/* util.c -- general utility routines shared by multiple components */ #include #include #include #include /* needed by HP-UX */ #include /* needed by HP-UX */ #include "gen.h" #include "util.h" #include "paths.h" #include "config.h" /****************************** error exits ******************************/ char *xprefix = 0; /* set this to prefix messages with arg0 or whatever */ /* mexit(s) -- exit immediately, with message */ void mexit (s) char *s; { fflush (stdout); if (xprefix) fprintf (stderr, "%s: ", xprefix); fprintf (stderr, "%s\n", s); exit (1); } /* pexit(s) -- call perror(s) and exit immediately */ void pexit (s) char *s; { fflush (stdout); if (xprefix) fprintf (stderr, "%s: ", xprefix); perror (s); exit (1); } /*************************** memory allocation ***************************/ /* alloc(n) -- allocate n bytes, with success guaranteed */ char * alloc (n) int n; { char *s; s = malloc ((unsigned) n); if (!s) mexit ("out of memory"); return s; } /* salloc(s) -- allocate and initialize string, with success guaranteed */ char * salloc (s) char *s; { return strcpy (alloc (strlen (s) + 1), s); } /**************************** string checking ****************************/ /* strtail(s,t) -- return pointer to tail substring t of s, or 0 if no match */ char * strtail (s, t) char *s, *t; { int ls = strlen (s); int lt = strlen (t); if (ls < lt) return 0; s = s + ls - lt; if (strcmp (s, t) == 0) return s; else return 0; } /**************************** file handling ****************************/ /* mustopen(filename,type) -- fopen() with guaranteed success */ FILE * mustopen (filename, type) char *filename, *type; { FILE *fp; fp = fopen (filename, type); if (!fp) pexit (filename); return fp; } /* modtime(filename) -- return modification time of a file, or 0 if no file */ long modtime (filename) char *filename; { struct stat status; if (stat (filename, &status) != 0) return 0; else return (long) status.st_mtime; } /**************************** exec assistance ****************************/ int trcexec; /* if set, trace execs on standard error output */ /* spawn(argv,dir) -- vfork, chdir, exec, wait */ int spawn (argv, dir) char *argv[]; char *dir; { int status; int pid; fflush (stdout); fflush (stderr); pid = vfork (); if (pid < 0) pexit ("can't fork"); else if (pid == 0) { /* we're the child process */ if (dir) /* change current directory if specified */ if (chdir (dir) != 0) pexit (dir); doexec (argv); /* exec the program */ perror (argv[0]); /* diagnose error if exec failed */ exit (1); } wait (&status); return status; } /* doexec(argv) -- trace if requested, exec program, abort on error */ void doexec (argv) char *argv[]; { char **argp; fflush (stdout); if (trcexec) { fprintf (stderr, "+"); for (argp = argv; *argp; argp++) fprintf (stderr, " %s", *argp); fprintf (stderr, "\n"); } fflush (stderr); execv (argv[0], argv); pexit (argv[0]); } /**************************** path searching ****************************/ static char *searchpath; /* setpath(ifdir,expt) -- set path for future searches */ void setpath (ifdir, expt) char *ifdir; int expt; { char *evpath; evpath = getenv ("MPD_PATH"); if (evpath == NULL) evpath = ""; searchpath = alloc (strlen (evpath) + strlen (ifdir) + 100); if (expt) sprintf (searchpath, "%s:.:%s:%s/links", evpath, ifdir, MPDSRC); else sprintf (searchpath, "%s:.:%s:%s", evpath, ifdir, MPDLIB); } /* pathopen(filename,suffix,buf) -- search path and open file for reading * * If the file is found, its name is left in buf. */ FILE * pathopen (filename, suffix, buf) char *filename, *suffix, *buf; { FILE *fp; char *p, *q; if (strchr(filename, '/')) { /* if absolute path */ sprintf(buf, "%s%s", filename, suffix); return fopen(buf, "r"); } p = searchpath; for (;;) { while (*p == ':') p++; if (*p == '\0') break; while (p[0] == '.' && p[1] == '/' && p[2] != ':' && p[2] != '\0') p += 2; q = buf; while (*p != '\0' && *p != ':') *q++ = *p++; sprintf (q, "/%s%s", filename, suffix); if ((fp = fopen (buf, "r")) != NULL) return fp; } sprintf (buf, "%s%s", filename, suffix); return NULL; }