xref: /freebsd/contrib/bmake/util.c (revision 3841c287170be8b1cba4d9adf8e727ecaeb64518)
1*3841c287SSimon J. Gerraty /*	$NetBSD: util.c,v 1.57 2020/07/03 08:13:23 rillig Exp $	*/
23955d011SMarcel Moolenaar 
33955d011SMarcel Moolenaar /*
43955d011SMarcel Moolenaar  * Missing stuff from OS's
53955d011SMarcel Moolenaar  *
6*3841c287SSimon J. Gerraty  *	$Id: util.c,v 1.35 2020/07/04 18:16:55 sjg Exp $
73955d011SMarcel Moolenaar  */
80dede8b0SSimon J. Gerraty #if defined(__MINT__) || defined(__linux__)
90dede8b0SSimon J. Gerraty #include <signal.h>
100dede8b0SSimon J. Gerraty #endif
113955d011SMarcel Moolenaar 
123955d011SMarcel Moolenaar #include "make.h"
133955d011SMarcel Moolenaar 
143955d011SMarcel Moolenaar #ifndef MAKE_NATIVE
15*3841c287SSimon J. Gerraty static char rcsid[] = "$NetBSD: util.c,v 1.57 2020/07/03 08:13:23 rillig Exp $";
163955d011SMarcel Moolenaar #else
173955d011SMarcel Moolenaar #ifndef lint
18*3841c287SSimon J. Gerraty __RCSID("$NetBSD: util.c,v 1.57 2020/07/03 08:13:23 rillig Exp $");
193955d011SMarcel Moolenaar #endif
203955d011SMarcel Moolenaar #endif
213955d011SMarcel Moolenaar 
223955d011SMarcel Moolenaar #include <errno.h>
233955d011SMarcel Moolenaar #include <time.h>
243955d011SMarcel Moolenaar #include <signal.h>
253955d011SMarcel Moolenaar 
263955d011SMarcel Moolenaar #if !defined(HAVE_STRERROR)
273955d011SMarcel Moolenaar extern int errno, sys_nerr;
283955d011SMarcel Moolenaar extern char *sys_errlist[];
293955d011SMarcel Moolenaar 
303955d011SMarcel Moolenaar char *
313955d011SMarcel Moolenaar strerror(int e)
323955d011SMarcel Moolenaar {
333955d011SMarcel Moolenaar     static char buf[100];
343955d011SMarcel Moolenaar     if (e < 0 || e >= sys_nerr) {
353955d011SMarcel Moolenaar 	snprintf(buf, sizeof(buf), "Unknown error %d", e);
363955d011SMarcel Moolenaar 	return buf;
373955d011SMarcel Moolenaar     }
383955d011SMarcel Moolenaar     else
393955d011SMarcel Moolenaar 	return sys_errlist[e];
403955d011SMarcel Moolenaar }
413955d011SMarcel Moolenaar #endif
423955d011SMarcel Moolenaar 
433955d011SMarcel Moolenaar #if !defined(HAVE_GETENV) || !defined(HAVE_SETENV) || !defined(HAVE_UNSETENV)
443955d011SMarcel Moolenaar extern char **environ;
453955d011SMarcel Moolenaar 
463955d011SMarcel Moolenaar static char *
473955d011SMarcel Moolenaar findenv(const char *name, int *offset)
483955d011SMarcel Moolenaar {
493955d011SMarcel Moolenaar 	size_t i, len;
503955d011SMarcel Moolenaar 	char *p, *q;
513955d011SMarcel Moolenaar 
523955d011SMarcel Moolenaar 	len = strlen(name);
533955d011SMarcel Moolenaar 	for (i = 0; (q = environ[i]); i++) {
543955d011SMarcel Moolenaar 		p = strchr(q, '=');
553955d011SMarcel Moolenaar 		if (p == NULL || p - q != len)
563955d011SMarcel Moolenaar 			continue;
573955d011SMarcel Moolenaar 		if (strncmp(name, q, len) == 0) {
583955d011SMarcel Moolenaar 			*offset = i;
593955d011SMarcel Moolenaar 			return q + len + 1;
603955d011SMarcel Moolenaar 		}
613955d011SMarcel Moolenaar 	}
623955d011SMarcel Moolenaar 	*offset = i;
633955d011SMarcel Moolenaar 	return NULL;
643955d011SMarcel Moolenaar }
653955d011SMarcel Moolenaar 
663955d011SMarcel Moolenaar char *
673955d011SMarcel Moolenaar getenv(const char *name)
683955d011SMarcel Moolenaar {
693955d011SMarcel Moolenaar     int offset;
703955d011SMarcel Moolenaar 
71*3841c287SSimon J. Gerraty     return findenv(name, &offset);
723955d011SMarcel Moolenaar }
733955d011SMarcel Moolenaar 
743955d011SMarcel Moolenaar int
753955d011SMarcel Moolenaar unsetenv(const char *name)
763955d011SMarcel Moolenaar {
773955d011SMarcel Moolenaar 	char **p;
783955d011SMarcel Moolenaar 	int offset;
793955d011SMarcel Moolenaar 
803955d011SMarcel Moolenaar 	if (name == NULL || *name == '\0' || strchr(name, '=') != NULL) {
813955d011SMarcel Moolenaar 		errno = EINVAL;
823955d011SMarcel Moolenaar 		return -1;
833955d011SMarcel Moolenaar 	}
843955d011SMarcel Moolenaar 
853955d011SMarcel Moolenaar 	while (findenv(name, &offset))	{ /* if set multiple times */
863955d011SMarcel Moolenaar 		for (p = &environ[offset];; ++p)
873955d011SMarcel Moolenaar 			if (!(*p = *(p + 1)))
883955d011SMarcel Moolenaar 				break;
893955d011SMarcel Moolenaar 	}
903955d011SMarcel Moolenaar 	return 0;
913955d011SMarcel Moolenaar }
923955d011SMarcel Moolenaar 
933955d011SMarcel Moolenaar int
943955d011SMarcel Moolenaar setenv(const char *name, const char *value, int rewrite)
953955d011SMarcel Moolenaar {
963955d011SMarcel Moolenaar 	char *c, **newenv;
973955d011SMarcel Moolenaar 	const char *cc;
983955d011SMarcel Moolenaar 	size_t l_value, size;
993955d011SMarcel Moolenaar 	int offset;
1003955d011SMarcel Moolenaar 
1013955d011SMarcel Moolenaar 	if (name == NULL || value == NULL) {
1023955d011SMarcel Moolenaar 		errno = EINVAL;
1033955d011SMarcel Moolenaar 		return -1;
1043955d011SMarcel Moolenaar 	}
1053955d011SMarcel Moolenaar 
1063955d011SMarcel Moolenaar 	if (*value == '=')			/* no `=' in value */
1073955d011SMarcel Moolenaar 		++value;
1083955d011SMarcel Moolenaar 	l_value = strlen(value);
1093955d011SMarcel Moolenaar 
1103955d011SMarcel Moolenaar 	/* find if already exists */
1113955d011SMarcel Moolenaar 	if ((c = findenv(name, &offset))) {
1123955d011SMarcel Moolenaar 		if (!rewrite)
1133955d011SMarcel Moolenaar 			return 0;
1143955d011SMarcel Moolenaar 		if (strlen(c) >= l_value)	/* old larger; copy over */
1153955d011SMarcel Moolenaar 			goto copy;
1163955d011SMarcel Moolenaar 	} else {					/* create new slot */
1173955d011SMarcel Moolenaar 		size = sizeof(char *) * (offset + 2);
1183955d011SMarcel Moolenaar 		if (savedEnv == environ) {		/* just increase size */
1193955d011SMarcel Moolenaar 			if ((newenv = realloc(savedEnv, size)) == NULL)
1203955d011SMarcel Moolenaar 				return -1;
1213955d011SMarcel Moolenaar 			savedEnv = newenv;
1223955d011SMarcel Moolenaar 		} else {				/* get new space */
1233955d011SMarcel Moolenaar 			/*
1243955d011SMarcel Moolenaar 			 * We don't free here because we don't know if
1253955d011SMarcel Moolenaar 			 * the first allocation is valid on all OS's
1263955d011SMarcel Moolenaar 			 */
1273955d011SMarcel Moolenaar 			if ((savedEnv = malloc(size)) == NULL)
1283955d011SMarcel Moolenaar 				return -1;
1293955d011SMarcel Moolenaar 			(void)memcpy(savedEnv, environ, size - sizeof(char *));
1303955d011SMarcel Moolenaar 		}
1313955d011SMarcel Moolenaar 		environ = savedEnv;
1323955d011SMarcel Moolenaar 		environ[offset + 1] = NULL;
1333955d011SMarcel Moolenaar 	}
1343955d011SMarcel Moolenaar 	for (cc = name; *cc && *cc != '='; ++cc)	/* no `=' in name */
1353955d011SMarcel Moolenaar 		continue;
1363955d011SMarcel Moolenaar 	size = cc - name;
1373955d011SMarcel Moolenaar 	/* name + `=' + value */
1383955d011SMarcel Moolenaar 	if ((environ[offset] = malloc(size + l_value + 2)) == NULL)
1393955d011SMarcel Moolenaar 		return -1;
1403955d011SMarcel Moolenaar 	c = environ[offset];
1413955d011SMarcel Moolenaar 	(void)memcpy(c, name, size);
1423955d011SMarcel Moolenaar 	c += size;
1433955d011SMarcel Moolenaar 	*c++ = '=';
1443955d011SMarcel Moolenaar copy:
1453955d011SMarcel Moolenaar 	(void)memcpy(c, value, l_value + 1);
1463955d011SMarcel Moolenaar 	return 0;
1473955d011SMarcel Moolenaar }
1483955d011SMarcel Moolenaar 
1493955d011SMarcel Moolenaar #ifdef TEST
1503955d011SMarcel Moolenaar int
1513955d011SMarcel Moolenaar main(int argc, char *argv[])
1523955d011SMarcel Moolenaar {
1533955d011SMarcel Moolenaar 	setenv(argv[1], argv[2], 0);
1543955d011SMarcel Moolenaar 	printf("%s\n", getenv(argv[1]));
1553955d011SMarcel Moolenaar 	unsetenv(argv[1]);
1563955d011SMarcel Moolenaar 	printf("%s\n", getenv(argv[1]));
1573955d011SMarcel Moolenaar 	return 0;
1583955d011SMarcel Moolenaar }
1593955d011SMarcel Moolenaar #endif
1603955d011SMarcel Moolenaar 
1613955d011SMarcel Moolenaar #endif
1623955d011SMarcel Moolenaar 
1633955d011SMarcel Moolenaar 
1643955d011SMarcel Moolenaar #if defined(__hpux__) || defined(__hpux)
1653955d011SMarcel Moolenaar /* strrcpy():
1663955d011SMarcel Moolenaar  *	Like strcpy, going backwards and returning the new pointer
1673955d011SMarcel Moolenaar  */
1683955d011SMarcel Moolenaar static char *
1693955d011SMarcel Moolenaar strrcpy(char *ptr, char *str)
1703955d011SMarcel Moolenaar {
1713955d011SMarcel Moolenaar     int len = strlen(str);
1723955d011SMarcel Moolenaar 
1733955d011SMarcel Moolenaar     while (len)
1743955d011SMarcel Moolenaar 	*--ptr = str[--len];
1753955d011SMarcel Moolenaar 
176*3841c287SSimon J. Gerraty     return ptr;
1773955d011SMarcel Moolenaar } /* end strrcpy */
1783955d011SMarcel Moolenaar 
1793955d011SMarcel Moolenaar 
1803955d011SMarcel Moolenaar char    *sys_siglist[] = {
1813955d011SMarcel Moolenaar         "Signal 0",
1823955d011SMarcel Moolenaar         "Hangup",                       /* SIGHUP    */
1833955d011SMarcel Moolenaar         "Interrupt",                    /* SIGINT    */
1843955d011SMarcel Moolenaar         "Quit",                         /* SIGQUIT   */
1853955d011SMarcel Moolenaar         "Illegal instruction",          /* SIGILL    */
1863955d011SMarcel Moolenaar         "Trace/BPT trap",               /* SIGTRAP   */
1873955d011SMarcel Moolenaar         "IOT trap",                     /* SIGIOT    */
1883955d011SMarcel Moolenaar         "EMT trap",                     /* SIGEMT    */
1893955d011SMarcel Moolenaar         "Floating point exception",     /* SIGFPE    */
1903955d011SMarcel Moolenaar         "Killed",                       /* SIGKILL   */
1913955d011SMarcel Moolenaar         "Bus error",                    /* SIGBUS    */
1923955d011SMarcel Moolenaar         "Segmentation fault",           /* SIGSEGV   */
1933955d011SMarcel Moolenaar         "Bad system call",              /* SIGSYS    */
1943955d011SMarcel Moolenaar         "Broken pipe",                  /* SIGPIPE   */
1953955d011SMarcel Moolenaar         "Alarm clock",                  /* SIGALRM   */
1963955d011SMarcel Moolenaar         "Terminated",                   /* SIGTERM   */
1973955d011SMarcel Moolenaar         "User defined signal 1",        /* SIGUSR1   */
1983955d011SMarcel Moolenaar         "User defined signal 2",        /* SIGUSR2   */
1993955d011SMarcel Moolenaar         "Child exited",                 /* SIGCLD    */
2003955d011SMarcel Moolenaar         "Power-fail restart",           /* SIGPWR    */
2013955d011SMarcel Moolenaar         "Virtual timer expired",        /* SIGVTALRM */
2023955d011SMarcel Moolenaar         "Profiling timer expired",      /* SIGPROF   */
2033955d011SMarcel Moolenaar         "I/O possible",                 /* SIGIO     */
2043955d011SMarcel Moolenaar         "Window size changes",          /* SIGWINDOW */
2053955d011SMarcel Moolenaar         "Stopped (signal)",             /* SIGSTOP   */
2063955d011SMarcel Moolenaar         "Stopped",                      /* SIGTSTP   */
2073955d011SMarcel Moolenaar         "Continued",                    /* SIGCONT   */
2083955d011SMarcel Moolenaar         "Stopped (tty input)",          /* SIGTTIN   */
2093955d011SMarcel Moolenaar         "Stopped (tty output)",         /* SIGTTOU   */
2103955d011SMarcel Moolenaar         "Urgent I/O condition",         /* SIGURG    */
2113955d011SMarcel Moolenaar         "Remote lock lost (NFS)",       /* SIGLOST   */
2123955d011SMarcel Moolenaar         "Signal 31",                    /* reserved  */
2133955d011SMarcel Moolenaar         "DIL signal"                    /* SIGDIL    */
2143955d011SMarcel Moolenaar };
2153955d011SMarcel Moolenaar #endif /* __hpux__ || __hpux */
2163955d011SMarcel Moolenaar 
2173955d011SMarcel Moolenaar #if defined(__hpux__) || defined(__hpux)
2183955d011SMarcel Moolenaar #include <sys/types.h>
2193955d011SMarcel Moolenaar #include <sys/syscall.h>
2203955d011SMarcel Moolenaar #include <sys/signal.h>
2213955d011SMarcel Moolenaar #include <sys/stat.h>
2223955d011SMarcel Moolenaar #include <dirent.h>
2233955d011SMarcel Moolenaar #include <sys/time.h>
2243955d011SMarcel Moolenaar #include <unistd.h>
2253955d011SMarcel Moolenaar 
2263955d011SMarcel Moolenaar int
2273955d011SMarcel Moolenaar killpg(int pid, int sig)
2283955d011SMarcel Moolenaar {
2293955d011SMarcel Moolenaar     return kill(-pid, sig);
2303955d011SMarcel Moolenaar }
2313955d011SMarcel Moolenaar 
2323955d011SMarcel Moolenaar #if !defined(BSD) && !defined(d_fileno)
2333955d011SMarcel Moolenaar # define d_fileno d_ino
2343955d011SMarcel Moolenaar #endif
2353955d011SMarcel Moolenaar 
2363955d011SMarcel Moolenaar #ifndef DEV_DEV_COMPARE
2373955d011SMarcel Moolenaar # define DEV_DEV_COMPARE(a, b) ((a) == (b))
2383955d011SMarcel Moolenaar #endif
2393955d011SMarcel Moolenaar #define ISDOT(c) ((c)[0] == '.' && (((c)[1] == '\0') || ((c)[1] == '/')))
2403955d011SMarcel Moolenaar #define ISDOTDOT(c) ((c)[0] == '.' && ISDOT(&((c)[1])))
2413955d011SMarcel Moolenaar 
2423955d011SMarcel Moolenaar char *
2433955d011SMarcel Moolenaar getwd(char *pathname)
2443955d011SMarcel Moolenaar {
2453955d011SMarcel Moolenaar     DIR    *dp;
2463955d011SMarcel Moolenaar     struct dirent *d;
2473955d011SMarcel Moolenaar     extern int errno;
2483955d011SMarcel Moolenaar 
2493955d011SMarcel Moolenaar     struct stat st_root, st_cur, st_next, st_dotdot;
2503955d011SMarcel Moolenaar     char    pathbuf[MAXPATHLEN], nextpathbuf[MAXPATHLEN * 2];
2513955d011SMarcel Moolenaar     char   *pathptr, *nextpathptr, *cur_name_add;
2523955d011SMarcel Moolenaar 
2533955d011SMarcel Moolenaar     /* find the inode of root */
2543955d011SMarcel Moolenaar     if (stat("/", &st_root) == -1) {
2553955d011SMarcel Moolenaar 	(void)sprintf(pathname,
2563955d011SMarcel Moolenaar 			"getwd: Cannot stat \"/\" (%s)", strerror(errno));
2573955d011SMarcel Moolenaar 	return NULL;
2583955d011SMarcel Moolenaar     }
2593955d011SMarcel Moolenaar     pathbuf[MAXPATHLEN - 1] = '\0';
2603955d011SMarcel Moolenaar     pathptr = &pathbuf[MAXPATHLEN - 1];
2613955d011SMarcel Moolenaar     nextpathbuf[MAXPATHLEN - 1] = '\0';
2623955d011SMarcel Moolenaar     cur_name_add = nextpathptr = &nextpathbuf[MAXPATHLEN - 1];
2633955d011SMarcel Moolenaar 
2643955d011SMarcel Moolenaar     /* find the inode of the current directory */
2653955d011SMarcel Moolenaar     if (lstat(".", &st_cur) == -1) {
2663955d011SMarcel Moolenaar 	(void)sprintf(pathname,
2673955d011SMarcel Moolenaar 			"getwd: Cannot stat \".\" (%s)", strerror(errno));
2683955d011SMarcel Moolenaar 	return NULL;
2693955d011SMarcel Moolenaar     }
2703955d011SMarcel Moolenaar     nextpathptr = strrcpy(nextpathptr, "../");
2713955d011SMarcel Moolenaar 
2723955d011SMarcel Moolenaar     /* Descend to root */
2733955d011SMarcel Moolenaar     for (;;) {
2743955d011SMarcel Moolenaar 
2753955d011SMarcel Moolenaar 	/* look if we found root yet */
2763955d011SMarcel Moolenaar 	if (st_cur.st_ino == st_root.st_ino &&
2773955d011SMarcel Moolenaar 	    DEV_DEV_COMPARE(st_cur.st_dev, st_root.st_dev)) {
2783955d011SMarcel Moolenaar 	    (void)strcpy(pathname, *pathptr != '/' ? "/" : pathptr);
279*3841c287SSimon J. Gerraty 	    return pathname;
2803955d011SMarcel Moolenaar 	}
2813955d011SMarcel Moolenaar 
2823955d011SMarcel Moolenaar 	/* open the parent directory */
2833955d011SMarcel Moolenaar 	if (stat(nextpathptr, &st_dotdot) == -1) {
2843955d011SMarcel Moolenaar 	    (void)sprintf(pathname,
2853955d011SMarcel Moolenaar 			    "getwd: Cannot stat directory \"%s\" (%s)",
2863955d011SMarcel Moolenaar 			    nextpathptr, strerror(errno));
2873955d011SMarcel Moolenaar 	    return NULL;
2883955d011SMarcel Moolenaar 	}
2893955d011SMarcel Moolenaar 	if ((dp = opendir(nextpathptr)) == NULL) {
2903955d011SMarcel Moolenaar 	    (void)sprintf(pathname,
2913955d011SMarcel Moolenaar 			    "getwd: Cannot open directory \"%s\" (%s)",
2923955d011SMarcel Moolenaar 			    nextpathptr, strerror(errno));
2933955d011SMarcel Moolenaar 	    return NULL;
2943955d011SMarcel Moolenaar 	}
2953955d011SMarcel Moolenaar 
2963955d011SMarcel Moolenaar 	/* look in the parent for the entry with the same inode */
2973955d011SMarcel Moolenaar 	if (DEV_DEV_COMPARE(st_dotdot.st_dev, st_cur.st_dev)) {
2983955d011SMarcel Moolenaar 	    /* Parent has same device. No need to stat every member */
2993955d011SMarcel Moolenaar 	    for (d = readdir(dp); d != NULL; d = readdir(dp))
3003955d011SMarcel Moolenaar 		if (d->d_fileno == st_cur.st_ino)
3013955d011SMarcel Moolenaar 		    break;
3023955d011SMarcel Moolenaar 	}
3033955d011SMarcel Moolenaar 	else {
3043955d011SMarcel Moolenaar 	    /*
3053955d011SMarcel Moolenaar 	     * Parent has a different device. This is a mount point so we
3063955d011SMarcel Moolenaar 	     * need to stat every member
3073955d011SMarcel Moolenaar 	     */
3083955d011SMarcel Moolenaar 	    for (d = readdir(dp); d != NULL; d = readdir(dp)) {
3093955d011SMarcel Moolenaar 		if (ISDOT(d->d_name) || ISDOTDOT(d->d_name))
3103955d011SMarcel Moolenaar 		    continue;
3113955d011SMarcel Moolenaar 		(void)strcpy(cur_name_add, d->d_name);
3123955d011SMarcel Moolenaar 		if (lstat(nextpathptr, &st_next) == -1) {
3133955d011SMarcel Moolenaar 		    (void)sprintf(pathname,
3143955d011SMarcel Moolenaar 			"getwd: Cannot stat \"%s\" (%s)",
3153955d011SMarcel Moolenaar 			d->d_name, strerror(errno));
3163955d011SMarcel Moolenaar 		    (void)closedir(dp);
3173955d011SMarcel Moolenaar 		    return NULL;
3183955d011SMarcel Moolenaar 		}
3193955d011SMarcel Moolenaar 		/* check if we found it yet */
3203955d011SMarcel Moolenaar 		if (st_next.st_ino == st_cur.st_ino &&
3213955d011SMarcel Moolenaar 		    DEV_DEV_COMPARE(st_next.st_dev, st_cur.st_dev))
3223955d011SMarcel Moolenaar 		    break;
3233955d011SMarcel Moolenaar 	    }
3243955d011SMarcel Moolenaar 	}
3253955d011SMarcel Moolenaar 	if (d == NULL) {
3263955d011SMarcel Moolenaar 	    (void)sprintf(pathname,
3273955d011SMarcel Moolenaar 		"getwd: Cannot find \".\" in \"..\"");
3283955d011SMarcel Moolenaar 	    (void)closedir(dp);
3293955d011SMarcel Moolenaar 	    return NULL;
3303955d011SMarcel Moolenaar 	}
3313955d011SMarcel Moolenaar 	st_cur = st_dotdot;
3323955d011SMarcel Moolenaar 	pathptr = strrcpy(pathptr, d->d_name);
3333955d011SMarcel Moolenaar 	pathptr = strrcpy(pathptr, "/");
3343955d011SMarcel Moolenaar 	nextpathptr = strrcpy(nextpathptr, "../");
3353955d011SMarcel Moolenaar 	(void)closedir(dp);
3363955d011SMarcel Moolenaar 	*cur_name_add = '\0';
3373955d011SMarcel Moolenaar     }
3383955d011SMarcel Moolenaar } /* end getwd */
3393955d011SMarcel Moolenaar 
3403955d011SMarcel Moolenaar #endif /* __hpux */
3413955d011SMarcel Moolenaar 
3423955d011SMarcel Moolenaar #if !defined(HAVE_GETCWD)
3433955d011SMarcel Moolenaar char *
3443955d011SMarcel Moolenaar getcwd(path, sz)
3453955d011SMarcel Moolenaar      char *path;
3463955d011SMarcel Moolenaar      int sz;
3473955d011SMarcel Moolenaar {
3483955d011SMarcel Moolenaar 	return getwd(path);
3493955d011SMarcel Moolenaar }
3503955d011SMarcel Moolenaar #endif
3513955d011SMarcel Moolenaar 
3523955d011SMarcel Moolenaar /* force posix signals */
3533955d011SMarcel Moolenaar void (*
3543955d011SMarcel Moolenaar bmake_signal(int s, void (*a)(int)))(int)
3553955d011SMarcel Moolenaar {
3563955d011SMarcel Moolenaar     struct sigaction sa, osa;
3573955d011SMarcel Moolenaar 
3583955d011SMarcel Moolenaar     sa.sa_handler = a;
3593955d011SMarcel Moolenaar     sigemptyset(&sa.sa_mask);
3603955d011SMarcel Moolenaar     sa.sa_flags = SA_RESTART;
3613955d011SMarcel Moolenaar 
3623955d011SMarcel Moolenaar     if (sigaction(s, &sa, &osa) == -1)
3633955d011SMarcel Moolenaar 	return SIG_ERR;
3643955d011SMarcel Moolenaar     else
3653955d011SMarcel Moolenaar 	return osa.sa_handler;
3663955d011SMarcel Moolenaar }
3673955d011SMarcel Moolenaar 
3683955d011SMarcel Moolenaar #if !defined(HAVE_VSNPRINTF) || !defined(HAVE_VASPRINTF)
3693955d011SMarcel Moolenaar #include <stdarg.h>
3703955d011SMarcel Moolenaar #endif
3713955d011SMarcel Moolenaar 
3723955d011SMarcel Moolenaar #if !defined(HAVE_VSNPRINTF)
3733955d011SMarcel Moolenaar #if !defined(__osf__)
3743955d011SMarcel Moolenaar #ifdef _IOSTRG
3753955d011SMarcel Moolenaar #define STRFLAG	(_IOSTRG|_IOWRT)	/* no _IOWRT: avoid stdio bug */
3763955d011SMarcel Moolenaar #else
3773955d011SMarcel Moolenaar #if 0
3783955d011SMarcel Moolenaar #define STRFLAG	(_IOREAD)		/* XXX: Assume svr4 stdio */
3793955d011SMarcel Moolenaar #endif
3803955d011SMarcel Moolenaar #endif /* _IOSTRG */
3813955d011SMarcel Moolenaar #endif /* __osf__ */
3823955d011SMarcel Moolenaar 
3833955d011SMarcel Moolenaar int
3843955d011SMarcel Moolenaar vsnprintf(char *s, size_t n, const char *fmt, va_list args)
3853955d011SMarcel Moolenaar {
3863955d011SMarcel Moolenaar #ifdef STRFLAG
3873955d011SMarcel Moolenaar 	FILE fakebuf;
3883955d011SMarcel Moolenaar 
3893955d011SMarcel Moolenaar 	fakebuf._flag = STRFLAG;
3903955d011SMarcel Moolenaar 	/*
3913955d011SMarcel Moolenaar 	 * Some os's are char * _ptr, others are unsigned char *_ptr...
3923955d011SMarcel Moolenaar 	 * We cast to void * to make everyone happy.
3933955d011SMarcel Moolenaar 	 */
3943955d011SMarcel Moolenaar 	fakebuf._ptr = (void *)s;
3953955d011SMarcel Moolenaar 	fakebuf._cnt = n-1;
3963955d011SMarcel Moolenaar 	fakebuf._file = -1;
3973955d011SMarcel Moolenaar 	_doprnt(fmt, args, &fakebuf);
3983955d011SMarcel Moolenaar 	fakebuf._cnt++;
3993955d011SMarcel Moolenaar 	putc('\0', &fakebuf);
4003955d011SMarcel Moolenaar 	if (fakebuf._cnt<0)
4013955d011SMarcel Moolenaar 	    fakebuf._cnt = 0;
402*3841c287SSimon J. Gerraty 	return n-fakebuf._cnt-1;
4033955d011SMarcel Moolenaar #else
4043955d011SMarcel Moolenaar #ifndef _PATH_DEVNULL
4053955d011SMarcel Moolenaar # define _PATH_DEVNULL "/dev/null"
4063955d011SMarcel Moolenaar #endif
4073955d011SMarcel Moolenaar 	/*
4083955d011SMarcel Moolenaar 	 * Rats... we don't want to clobber anything...
4093955d011SMarcel Moolenaar 	 * do a printf to /dev/null to see how much space we need.
4103955d011SMarcel Moolenaar 	 */
4113955d011SMarcel Moolenaar 	static FILE *nullfp;
4123955d011SMarcel Moolenaar 	int need = 0;			/* XXX what's a useful error return? */
4133955d011SMarcel Moolenaar 
4143955d011SMarcel Moolenaar 	if (!nullfp)
4153955d011SMarcel Moolenaar 		nullfp = fopen(_PATH_DEVNULL, "w");
4163955d011SMarcel Moolenaar 	if (nullfp) {
4173955d011SMarcel Moolenaar 		need = vfprintf(nullfp, fmt, args);
4183955d011SMarcel Moolenaar 		if (need < n)
4193955d011SMarcel Moolenaar 			(void)vsprintf(s, fmt, args);
4203955d011SMarcel Moolenaar 	}
4213955d011SMarcel Moolenaar 	return need;
4223955d011SMarcel Moolenaar #endif
4233955d011SMarcel Moolenaar }
4243955d011SMarcel Moolenaar #endif
4253955d011SMarcel Moolenaar 
4263955d011SMarcel Moolenaar #if !defined(HAVE_SNPRINTF)
4273955d011SMarcel Moolenaar int
4283955d011SMarcel Moolenaar snprintf(char *s, size_t n, const char *fmt, ...)
4293955d011SMarcel Moolenaar {
4303955d011SMarcel Moolenaar 	va_list ap;
4313955d011SMarcel Moolenaar 	int rv;
4323955d011SMarcel Moolenaar 
4333955d011SMarcel Moolenaar 	va_start(ap, fmt);
4343955d011SMarcel Moolenaar 	rv = vsnprintf(s, n, fmt, ap);
4353955d011SMarcel Moolenaar 	va_end(ap);
4363955d011SMarcel Moolenaar 	return rv;
4373955d011SMarcel Moolenaar }
4383955d011SMarcel Moolenaar #endif
4393955d011SMarcel Moolenaar 
4403955d011SMarcel Moolenaar #if !defined(HAVE_STRFTIME)
4413955d011SMarcel Moolenaar size_t
4423955d011SMarcel Moolenaar strftime(char *buf, size_t len, const char *fmt, const struct tm *tm)
4433955d011SMarcel Moolenaar {
4443955d011SMarcel Moolenaar 	static char months[][4] = {
4453955d011SMarcel Moolenaar 		"Jan", "Feb", "Mar", "Apr", "May", "Jun",
4463955d011SMarcel Moolenaar 		"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
4473955d011SMarcel Moolenaar 	};
4483955d011SMarcel Moolenaar 
4493955d011SMarcel Moolenaar 	size_t s;
4503955d011SMarcel Moolenaar 	char *b = buf;
4513955d011SMarcel Moolenaar 
4523955d011SMarcel Moolenaar 	while (*fmt) {
4533955d011SMarcel Moolenaar 		if (len == 0)
4543955d011SMarcel Moolenaar 			return buf - b;
4553955d011SMarcel Moolenaar 		if (*fmt != '%') {
4563955d011SMarcel Moolenaar 			*buf++ = *fmt++;
4573955d011SMarcel Moolenaar 			len--;
4583955d011SMarcel Moolenaar 			continue;
4593955d011SMarcel Moolenaar 		}
4603955d011SMarcel Moolenaar 		switch (*fmt++) {
4613955d011SMarcel Moolenaar 		case '%':
4623955d011SMarcel Moolenaar 			*buf++ = '%';
4633955d011SMarcel Moolenaar 			len--;
4643955d011SMarcel Moolenaar 			if (len == 0) return buf - b;
4653955d011SMarcel Moolenaar 			/*FALLTHROUGH*/
4663955d011SMarcel Moolenaar 		case '\0':
4673955d011SMarcel Moolenaar 			*buf = '%';
4683955d011SMarcel Moolenaar 			s = 1;
4693955d011SMarcel Moolenaar 			break;
4703955d011SMarcel Moolenaar 		case 'k':
4713955d011SMarcel Moolenaar 			s = snprintf(buf, len, "%d", tm->tm_hour);
4723955d011SMarcel Moolenaar 			break;
4733955d011SMarcel Moolenaar 		case 'M':
4743955d011SMarcel Moolenaar 			s = snprintf(buf, len, "%02d", tm->tm_min);
4753955d011SMarcel Moolenaar 			break;
4763955d011SMarcel Moolenaar 		case 'S':
4773955d011SMarcel Moolenaar 			s = snprintf(buf, len, "%02d", tm->tm_sec);
4783955d011SMarcel Moolenaar 			break;
4793955d011SMarcel Moolenaar 		case 'b':
4803955d011SMarcel Moolenaar 			if (tm->tm_mon >= 12)
4813955d011SMarcel Moolenaar 				return buf - b;
4823955d011SMarcel Moolenaar 			s = snprintf(buf, len, "%s", months[tm->tm_mon]);
4833955d011SMarcel Moolenaar 			break;
4843955d011SMarcel Moolenaar 		case 'd':
4853955d011SMarcel Moolenaar 			s = snprintf(buf, len, "%02d", tm->tm_mday);
4863955d011SMarcel Moolenaar 			break;
4873955d011SMarcel Moolenaar 		case 'Y':
4883955d011SMarcel Moolenaar 			s = snprintf(buf, len, "%d", 1900 + tm->tm_year);
4893955d011SMarcel Moolenaar 			break;
4903955d011SMarcel Moolenaar 		default:
4913955d011SMarcel Moolenaar 			s = snprintf(buf, len, "Unsupported format %c",
4923955d011SMarcel Moolenaar 			    fmt[-1]);
4933955d011SMarcel Moolenaar 			break;
4943955d011SMarcel Moolenaar 		}
4953955d011SMarcel Moolenaar 		buf += s;
4963955d011SMarcel Moolenaar 		len -= s;
4973955d011SMarcel Moolenaar 	}
4983955d011SMarcel Moolenaar }
4993955d011SMarcel Moolenaar #endif
5003955d011SMarcel Moolenaar 
5013955d011SMarcel Moolenaar #if !defined(HAVE_KILLPG)
5023955d011SMarcel Moolenaar #if !defined(__hpux__) && !defined(__hpux)
5033955d011SMarcel Moolenaar int
5043955d011SMarcel Moolenaar killpg(int pid, int sig)
5053955d011SMarcel Moolenaar {
5063955d011SMarcel Moolenaar     return kill(-pid, sig);
5073955d011SMarcel Moolenaar }
5083955d011SMarcel Moolenaar #endif
5093955d011SMarcel Moolenaar #endif
5103955d011SMarcel Moolenaar 
5113955d011SMarcel Moolenaar #if !defined(HAVE_WARNX)
5123955d011SMarcel Moolenaar static void
5133955d011SMarcel Moolenaar vwarnx(const char *fmt, va_list args)
5143955d011SMarcel Moolenaar {
5153955d011SMarcel Moolenaar 	fprintf(stderr, "%s: ", progname);
5163955d011SMarcel Moolenaar 	if ((fmt)) {
5173955d011SMarcel Moolenaar 		vfprintf(stderr, fmt, args);
5183955d011SMarcel Moolenaar 		fprintf(stderr, ": ");
5193955d011SMarcel Moolenaar 	}
5203955d011SMarcel Moolenaar }
5213955d011SMarcel Moolenaar #endif
5223955d011SMarcel Moolenaar 
5233955d011SMarcel Moolenaar #if !defined(HAVE_WARN)
5243955d011SMarcel Moolenaar static void
5253955d011SMarcel Moolenaar vwarn(const char *fmt, va_list args)
5263955d011SMarcel Moolenaar {
5273955d011SMarcel Moolenaar 	vwarnx(fmt, args);
5283955d011SMarcel Moolenaar 	fprintf(stderr, "%s\n", strerror(errno));
5293955d011SMarcel Moolenaar }
5303955d011SMarcel Moolenaar #endif
5313955d011SMarcel Moolenaar 
5323955d011SMarcel Moolenaar #if !defined(HAVE_ERR)
5333955d011SMarcel Moolenaar static void
5343955d011SMarcel Moolenaar verr(int eval, const char *fmt, va_list args)
5353955d011SMarcel Moolenaar {
5363955d011SMarcel Moolenaar 	vwarn(fmt, args);
5373955d011SMarcel Moolenaar 	exit(eval);
5383955d011SMarcel Moolenaar }
5393955d011SMarcel Moolenaar #endif
5403955d011SMarcel Moolenaar 
5413955d011SMarcel Moolenaar #if !defined(HAVE_ERRX)
5423955d011SMarcel Moolenaar static void
5433955d011SMarcel Moolenaar verrx(int eval, const char *fmt, va_list args)
5443955d011SMarcel Moolenaar {
5453955d011SMarcel Moolenaar 	vwarnx(fmt, args);
5463955d011SMarcel Moolenaar 	exit(eval);
5473955d011SMarcel Moolenaar }
5483955d011SMarcel Moolenaar #endif
5493955d011SMarcel Moolenaar 
5503955d011SMarcel Moolenaar #if !defined(HAVE_ERR)
5513955d011SMarcel Moolenaar void
5523955d011SMarcel Moolenaar err(int eval, const char *fmt, ...)
5533955d011SMarcel Moolenaar {
5543955d011SMarcel Moolenaar         va_list ap;
5553955d011SMarcel Moolenaar 
5563955d011SMarcel Moolenaar         va_start(ap, fmt);
5573955d011SMarcel Moolenaar         verr(eval, fmt, ap);
5583955d011SMarcel Moolenaar         va_end(ap);
5593955d011SMarcel Moolenaar }
5603955d011SMarcel Moolenaar #endif
5613955d011SMarcel Moolenaar 
5623955d011SMarcel Moolenaar #if !defined(HAVE_ERRX)
5633955d011SMarcel Moolenaar void
5643955d011SMarcel Moolenaar errx(int eval, const char *fmt, ...)
5653955d011SMarcel Moolenaar {
5663955d011SMarcel Moolenaar         va_list ap;
5673955d011SMarcel Moolenaar 
5683955d011SMarcel Moolenaar         va_start(ap, fmt);
5693955d011SMarcel Moolenaar         verrx(eval, fmt, ap);
5703955d011SMarcel Moolenaar         va_end(ap);
5713955d011SMarcel Moolenaar }
5723955d011SMarcel Moolenaar #endif
5733955d011SMarcel Moolenaar 
5743955d011SMarcel Moolenaar #if !defined(HAVE_WARN)
5753955d011SMarcel Moolenaar void
5763955d011SMarcel Moolenaar warn(const char *fmt, ...)
5773955d011SMarcel Moolenaar {
5783955d011SMarcel Moolenaar         va_list ap;
5793955d011SMarcel Moolenaar 
5803955d011SMarcel Moolenaar         va_start(ap, fmt);
5813955d011SMarcel Moolenaar         vwarn(fmt, ap);
5823955d011SMarcel Moolenaar         va_end(ap);
5833955d011SMarcel Moolenaar }
5843955d011SMarcel Moolenaar #endif
5853955d011SMarcel Moolenaar 
5863955d011SMarcel Moolenaar #if !defined(HAVE_WARNX)
5873955d011SMarcel Moolenaar void
5883955d011SMarcel Moolenaar warnx(const char *fmt, ...)
5893955d011SMarcel Moolenaar {
5903955d011SMarcel Moolenaar         va_list ap;
5913955d011SMarcel Moolenaar 
5923955d011SMarcel Moolenaar         va_start(ap, fmt);
5933955d011SMarcel Moolenaar         vwarnx(fmt, ap);
5943955d011SMarcel Moolenaar         va_end(ap);
5953955d011SMarcel Moolenaar }
5963955d011SMarcel Moolenaar #endif
597