diff options
Diffstat (limited to 'fonts/utilities/mff-29/fx.c')
-rw-r--r-- | fonts/utilities/mff-29/fx.c | 310 |
1 files changed, 310 insertions, 0 deletions
diff --git a/fonts/utilities/mff-29/fx.c b/fonts/utilities/mff-29/fx.c new file mode 100644 index 0000000000..86935452e6 --- /dev/null +++ b/fonts/utilities/mff-29/fx.c @@ -0,0 +1,310 @@ +/* fx.c 2.9.0 92/07/06 - the simple fork-and-exec function used in mff.c + * + * The only f&x needed is calling up METAFONT and GFtoPK, + * and these programs take only one argument. It is convenient + * to allow the templates given to include spaces, e.g., + * `-M "jobserver -q cmmf"' actually runs `jobserver'. + * + * I have ignored the "struct wait" nonsense -- Edition 7 all the way! :-) + * + * ATARI ST (and presumablu MS-DOS?) modification -- pdc 25 Jul 91 + * There is no fork-&-exec in TOS; Use spawnvp instead. + * +----------------------------------------------------------------------- + This software module copyright (c) 1990, 1991 Damian Cugley. + It is provided for free on an "as-is" basis. + See the file COPYING for more information. +----------------------------------------------------------------------- + * Created - pdc Mon 15 Jan 1990 + */ + +#include "config.h" + +#ifndef NO_EXEC_USE_SPAWN +# include <signal.h> /* NSIG */ +#else +# include <process.h> /* P_WAIT */ +#endif /* no_exec_use_spawn */ + +#include <errno.h> + +#include "stdc.h" +#include "xstdio.h" /* <stdio.h> plus prototypes */ +#include "fatal.h" /* how to error messages */ +#include "strmisc.h" /* incl. <string(s).h> */ +#include "fx.h" + +NONRETURNING void exit ARGS((int)); + +#define TRUE 1 +#define FALSE 0 + + +#ifndef lint +addr realloc ARGS((addr, sizeof_t)); +#else +# define realloc(P,S) 0 +#endif + +#define MORE 16 +/* + * generate more argv slots in batches of 16 + * (I will be surprised if 16 are needed!) + */ + +/* + * Construct an argv vector for the child process. + * + * |command| is pointer to zero-terminated string of characters; + * it is broken up as per strword(3) into separate arguments. + * |arg| is a final argument to append to the |argv| vector; + * it is *not* broken into words. + */ +static inline char ** +construct_args(command, argc, argv) + int argc; + char *command, **argv; +{ + int num_args = 0, max_args = MORE + argc; + char **nargv = (char **)xmalloc(max_args * sizeof(char *)), + *p, *strword_state; + + if (!(p = strword(command, &strword_state))) + syntaxf("command string is empty!"); + /* There should always be at least one word */ + do + { + if (max_args - num_args == 1 + argc) /* always two spare arg slots */ + { + /* try to make some more room */ + nargv = (char **) + xrealloc(nargv, (max_args += MORE) * sizeof (char *)); + } + nargv[num_args++] = p; + p = strword((char *)NULL, &strword_state); + } while (p); + + /* There are always two free slots in the |nargv| array: */ + while (argc-- > 0) + nargv[num_args++] = *argv++; + + nargv[num_args] = (char *)NULL; + return nargv; +} + + +/* + * fx -- run a subprocess and wait for it to finish + */ + +#ifdef NO_EXEC_USE_SPAWN + +void +fx(char *command, int argc, char **argv) +{ + char **argv = construct_args(command, argc, argv); + int exit_code = spawnvp(P_WAIT, argv[0], argv); + + xfree((addr)argv); + if (exit_code < 0) /* I am guessing positive exit codes are OK */ + fatalf("%s terminated with exit code %d\n", command, exit_code); +} + +#else /* EXEC is available: */ + +#ifdef BSD +# ifndef vfork +# define fork vfork +/* + * use vfork in preference to fork -- unless vfork has been #defined + * to fork (which might be expected on post-VM-problems UNIXes + */ +# endif +#endif + +int wait ARGS((int *)); +int fork ARGS((void)); +int execvp ARGS((const char *, const char **)); +void NONRETURNING _exit ARGS((int)); + +#ifdef NO_SIGLIST + +/* + * Must supply own list of signal names: + */ +static const char *sys_siglist[] = +{ + "shookum hip RALLO dine!", /* there is no signal 0 */ + "hangup", + "interrupt", + "quit", + "illegal instruction", + "trace trap", /* 5 */ + "IOT Trap", + "EMT trap", + "arithmetic exception", + "kill -KILL", + "bus error", /* 10 */ + "violation of segments", + "bad argument to system call", + "unrequited pipe", + "alarm clock", + "software terminate -- from kill(2)", /* 15 */ + /* that was the Edition 7 signals (0-15)... */ +#ifdef USG + "user-defined signal number 1", /* 16 */ + "user-defined signal number 2", /* 17 */ + "lonely child process", /* 18 */ + "death! death! death!", /* 19 -- power failure */ + /* + * For other systems (4.1 BSD?), signals > 15 + * will be reported numerically. + */ +#endif /* USG */ +}; + +/* define NSIG to be # of messages in above: */ +# undef NSIG +# define NSIG ((sizeof sys_siglist)/sizeof (char *)) + +#else /* have siglist */ + extern const char *sys_siglist[]; +#endif + +extern char *sys_errlist[]; +extern int sys_nerr; + + +/* + * classic fork and exec -- |command| and |arg| as above. + * Waits for child to finish. + */ +void /* aborts if can't exec */ +fx(command, argc, argv) + int argc; + char *command, **argv; +{ + int pid, t; + int status, /* status word from wait() */ + exit_code; /* exit code of child */ + + argv = construct_args(command, argc, argv); + + if ((pid = fork()) < 0) pfatalf("fork"); + else if (pid == 0) + { + /* This is the child */ + (void)execvp((const char *)argv[0], (const char **)argv); + /* If we get here, something's gone wrong: */ + perrorf(argv[0]); + _exit(1); /* don't use exit() in child */ + } + + /* This is the parent process */ +#ifdef BSD + t = wait(&status); +#else + while ((t = wait(&status)) < 0 && errno == EINTR) + ; +#endif + if (t != pid) pfatalf("very surprised because wait returned %d", t); + xfree((addr)argv); + + if ((status & 0xFF) != 0) + { + /* Terminated by signal: */ + int sig = status & 0x7F; + + fprintf(stderr, "%s killed by signal %d", command, sig); + if (sig < NSIG) + fprintf(stderr, " (%s)\n", sys_siglist[sig]); + if (status & 0x80) + fprintf(stderr, "Wow, coredump city.\n"); + exit(1); + } + else if (exit_code = status >> 8 & 0xFF) + { + fprintf(stderr, "%s terminated with exit code %d.\n", + command, exit_code); + exit(1); + } +} + + +#ifdef NO_EXECVP +/* + * This is intended as a version of execvp for systems that don't have it. + * (V7, BSD 4.2?) + * + * If an executable file is found for which execv() fails, + * it is assumed to be a shellscript and /bin/sh is invoked with + * its full pathname as first argument. + * + * pdc Thur. 27 June 1991 + */ + +#include <sys/param.h> +#ifndef MAXPATHLEN +# define MAXPATHLEN 1024 +#endif +#include "strmisc.h" +#include "searchpath.h" /* might as well use that */ + +int /* returns -1 if fails */ +execvp(progname, argv) + const char *progname; /* name of prog to search for */ + const char *argv[]; /* vector of arguments */ +{ + const char *getenv ARGS((const char *)); + int execv ARGS((const char *, const char *[])); + + char scratch[MAXPATHLEN]; + const char *path = getenv("PATH"); + + if (!path) path = ""; /* for mad people who like PATH-free shells */ + + if (findfile(scratch, progname, path, (char *)0)) + { + if (execv(scratch, argv), errno == ENOEXEC) + { + /* + * a /bin/sh command file + * Substitute pathname of file as 1st argument to sh: + * execvp("fo", {"fo","arg","brg",0}) -> + * /bin/sh /usr/local/bin/fo arg brg + */ + const char **nargv; /* ptr to vect of ptrs to vects of const char */ + int argc; + + /* + * count args: + */ + { + register const char **t = argv; + while (*t) ++t; + argc = (t - argv); + } + + /* allocate room for 1 more arg & the NULL */ + /* copy the NULL and the args except the 0'th arg */ + nargv = (const char **)xmalloc(sizeof (char *) * (argc + 2)); + bcopy((addr)(argv + 1), (addr)(nargv + 2), + argc*(sizeof (char *))); + nargv[0] = "/bin/sh"; + nargv[1] = scratch; + execv(nargv[0], nargv); + + /* failed -- */ + xfree((addr)nargv); + } + } + else + { + /* findfile returned FALSE */ + errno = ENOENT; + } + + return -1; +} +#endif /* NO_EXECVP */ +#endif /* NO_EXEC_USE_SPAWN */ |