/* $NetBSD: run.c,v 1.6 1998/08/10 02:23:45 perry Exp $ */ /* * Copyright 1997 Piermont Information Systems Inc. * All rights reserved. * * Written by Philip A. Nelson for Piermont Information Systems Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software develooped for the NetBSD Project by * Piermont Information Systems Inc. * 4. The name of Piermont Information Systems Inc. may not be used to endorse * or promote products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY PIERMONT INFORMATION SYSTEMS INC. ``AS IS'' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL PIERMONT INFORMATION SYSTEMS INC. BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. * */ /* run.c -- routines to interact with other programs. */ #include #include #include #include #include #include "defs.h" #include "msg_defs.h" #ifdef DEBUG #define Xsystem(y) printf ("%s\n", y), 0 #else #define Xsystem(y) system(y) #endif /* * local prototypes */ int do_system __P((const char *cmdstr)); char* va_prog_cmdstr __P((char *cmd, va_list ap)); #define BUFSIZE 4096 int collect(int kind, char **buffer, const char *name, ...) { size_t nbytes; /* Number of bytes in buffer. */ size_t fbytes; /* Number of bytes in file. */ struct stat st; /* stat information. */ int ch; FILE *f; char fileorcmd [STRSIZE]; va_list ap; va_start(ap, name); vsnprintf(fileorcmd, STRSIZE, name, ap); va_end(ap); if (kind == T_FILE) { /* Get the file information. */ if (stat(fileorcmd, &st)) { *buffer = NULL; return -1; } fbytes = (size_t)st.st_size; /* Open the file. */ f = fopen(fileorcmd, "r"); if (f == NULL) { *buffer = NULL; return -1; } } else { /* Open the program. */ f = popen(fileorcmd, "r"); if (f == NULL) { *buffer = NULL; return -1; } fbytes = BUFSIZE; } if (fbytes == 0) fbytes = BUFSIZE; /* Allocate the buffer size. */ *buffer = (char *)malloc(fbytes + 1); if (!*buffer) return -1; /* Read the buffer. */ nbytes = 0; while (nbytes < fbytes && (ch = fgetc(f)) != EOF) (*buffer)[nbytes++] = ch; (*buffer)[nbytes] = 0; if (kind == T_FILE) fclose(f); else pclose(f); return nbytes; } /* * system(3), but with a debug wrapper. */ int do_system(execstr) const char *execstr; { register int ret; /* * The following may be more than one function call. Can't just * "return Xsystem (command);" */ ret = Xsystem(execstr); return (ret); } /* * build command tring for do_system() from anonymous args. * XXX return result is in a static buffer. */ char * va_prog_cmdstr(char *cmd, va_list ap) { static char command[STRSIZE]; memset(command, 0, STRSIZE); (void)vsnprintf(command, STRSIZE, cmd, ap); return (command); } /* * run a program. The caller handles any and all errors. */ int run_prog (char *cmd, ...) { va_list ap; int ret; va_start(ap, cmd); ret = do_system(va_prog_cmdstr(cmd, ap)); va_end(ap); return (ret); } /* * run a program where no errors are expected. * Like run_prog, except print a generic warning if the return is nonzero. * Used where sysinst doesn't yet know how to recover from an error, * but where an error is not completely catastrophic. * Use stderr/stdin since we want the user to see any messages * from the command before we go back into curses. */ int run_prog_or_continue(char *cmd, ...) { va_list ap; int ret; const char *execstr; va_start(ap, cmd); execstr = va_prog_cmdstr(cmd, ap); ret = do_system(execstr); va_end(ap); /* Warn copiously about any errors. */ if (ret) { /* XXX use messages instead */ printf(msg_string(MSG_anonprogfailed), execstr, strerror(ret)); fgetc(stdin); } return ret; } /* * run a program. Die if there are any errors. */ void run_prog_or_die (char *cmd, ...) { va_list ap; int ret; const char *execstr; va_start(ap, cmd); execstr = va_prog_cmdstr(cmd, ap); ret = do_system(execstr); if (ret) { printf(msg_string(MSG_progdie), execstr, strerror(ret)); exit(ret); } }