xref: /minix3/usr.bin/make/util.c (revision 2bc7c627ace37c52ea76fc2f2c700c563df69735)
1*2bc7c627SLionel Sambuc /*	$NetBSD: util.c,v 1.53 2012/06/04 22:45:05 sjg Exp $	*/
22e2caf59SThomas Veerman 
32e2caf59SThomas Veerman /*
42e2caf59SThomas Veerman  * Missing stuff from OS's
52e2caf59SThomas Veerman  */
62e2caf59SThomas Veerman 
72e2caf59SThomas Veerman #ifndef MAKE_NATIVE
8*2bc7c627SLionel Sambuc static char rcsid[] = "$NetBSD: util.c,v 1.53 2012/06/04 22:45:05 sjg Exp $";
92e2caf59SThomas Veerman #else
102e2caf59SThomas Veerman #include <sys/cdefs.h>
112e2caf59SThomas Veerman #ifndef lint
12*2bc7c627SLionel Sambuc __RCSID("$NetBSD: util.c,v 1.53 2012/06/04 22:45:05 sjg Exp $");
132e2caf59SThomas Veerman #endif
142e2caf59SThomas Veerman #endif
152e2caf59SThomas Veerman 
162e2caf59SThomas Veerman #include <sys/param.h>
172e2caf59SThomas Veerman 
182e2caf59SThomas Veerman #include <errno.h>
192e2caf59SThomas Veerman #include <stdio.h>
202e2caf59SThomas Veerman #include <time.h>
212e2caf59SThomas Veerman #include <signal.h>
222e2caf59SThomas Veerman 
232e2caf59SThomas Veerman #include "make.h"
242e2caf59SThomas Veerman 
252e2caf59SThomas Veerman #if !defined(MAKE_NATIVE) && !defined(HAVE_STRERROR)
262e2caf59SThomas Veerman extern int errno, sys_nerr;
272e2caf59SThomas Veerman extern char *sys_errlist[];
282e2caf59SThomas Veerman 
292e2caf59SThomas Veerman char *
302e2caf59SThomas Veerman strerror(int e)
312e2caf59SThomas Veerman {
322e2caf59SThomas Veerman     static char buf[100];
332e2caf59SThomas Veerman     if (e < 0 || e >= sys_nerr) {
342e2caf59SThomas Veerman 	snprintf(buf, sizeof(buf), "Unknown error %d", e);
352e2caf59SThomas Veerman 	return buf;
362e2caf59SThomas Veerman     }
372e2caf59SThomas Veerman     else
382e2caf59SThomas Veerman 	return sys_errlist[e];
392e2caf59SThomas Veerman }
402e2caf59SThomas Veerman #endif
412e2caf59SThomas Veerman 
422e2caf59SThomas Veerman #if !defined(MAKE_NATIVE) && !defined(HAVE_SETENV)
432e2caf59SThomas Veerman extern char **environ;
442e2caf59SThomas Veerman 
452e2caf59SThomas Veerman static char *
462e2caf59SThomas Veerman findenv(const char *name, int *offset)
472e2caf59SThomas Veerman {
482e2caf59SThomas Veerman 	size_t i, len;
492e2caf59SThomas Veerman 	char *p, *q;
502e2caf59SThomas Veerman 
51*2bc7c627SLionel Sambuc 	len = strlen(name);
522e2caf59SThomas Veerman 	for (i = 0; (q = environ[i]); i++) {
532e2caf59SThomas Veerman 		p = strchr(q, '=');
54*2bc7c627SLionel Sambuc 		if (p == NULL || p - q != len)
552e2caf59SThomas Veerman 			continue;
56*2bc7c627SLionel Sambuc 		if (strncmp(name, q, len) == 0) {
572e2caf59SThomas Veerman 			*offset = i;
582e2caf59SThomas Veerman 			return q + len + 1;
592e2caf59SThomas Veerman 		}
602e2caf59SThomas Veerman 	}
612e2caf59SThomas Veerman 	*offset = i;
622e2caf59SThomas Veerman 	return NULL;
632e2caf59SThomas Veerman }
642e2caf59SThomas Veerman 
65*2bc7c627SLionel Sambuc char *
66*2bc7c627SLionel Sambuc getenv(const char *name)
67*2bc7c627SLionel Sambuc {
68*2bc7c627SLionel Sambuc     int offset;
69*2bc7c627SLionel Sambuc 
70*2bc7c627SLionel Sambuc     return(findenv(name, &offset));
71*2bc7c627SLionel Sambuc }
72*2bc7c627SLionel Sambuc 
732e2caf59SThomas Veerman int
742e2caf59SThomas Veerman unsetenv(const char *name)
752e2caf59SThomas Veerman {
762e2caf59SThomas Veerman 	char **p;
772e2caf59SThomas Veerman 	int offset;
782e2caf59SThomas Veerman 
792e2caf59SThomas Veerman 	if (name == NULL || *name == '\0' || strchr(name, '=') != NULL) {
802e2caf59SThomas Veerman 		errno = EINVAL;
812e2caf59SThomas Veerman 		return -1;
822e2caf59SThomas Veerman 	}
832e2caf59SThomas Veerman 
842e2caf59SThomas Veerman 	while (findenv(name, &offset))	{ /* if set multiple times */
852e2caf59SThomas Veerman 		for (p = &environ[offset];; ++p)
862e2caf59SThomas Veerman 			if (!(*p = *(p + 1)))
872e2caf59SThomas Veerman 				break;
882e2caf59SThomas Veerman 	}
892e2caf59SThomas Veerman 	return 0;
902e2caf59SThomas Veerman }
912e2caf59SThomas Veerman 
922e2caf59SThomas Veerman int
932e2caf59SThomas Veerman setenv(const char *name, const char *value, int rewrite)
942e2caf59SThomas Veerman {
952e2caf59SThomas Veerman 	char *c, **newenv;
962e2caf59SThomas Veerman 	const char *cc;
972e2caf59SThomas Veerman 	size_t l_value, size;
982e2caf59SThomas Veerman 	int offset;
992e2caf59SThomas Veerman 
1002e2caf59SThomas Veerman 	if (name == NULL || value == NULL) {
1012e2caf59SThomas Veerman 		errno = EINVAL;
1022e2caf59SThomas Veerman 		return -1;
1032e2caf59SThomas Veerman 	}
1042e2caf59SThomas Veerman 
1052e2caf59SThomas Veerman 	if (*value == '=')			/* no `=' in value */
1062e2caf59SThomas Veerman 		++value;
1072e2caf59SThomas Veerman 	l_value = strlen(value);
1082e2caf59SThomas Veerman 
1092e2caf59SThomas Veerman 	/* find if already exists */
1102e2caf59SThomas Veerman 	if ((c = findenv(name, &offset))) {
1112e2caf59SThomas Veerman 		if (!rewrite)
1122e2caf59SThomas Veerman 			return 0;
1132e2caf59SThomas Veerman 		if (strlen(c) >= l_value)	/* old larger; copy over */
1142e2caf59SThomas Veerman 			goto copy;
1152e2caf59SThomas Veerman 	} else {					/* create new slot */
1162e2caf59SThomas Veerman 		size = sizeof(char *) * (offset + 2);
117*2bc7c627SLionel Sambuc 		if (savedEnv == environ) {		/* just increase size */
118*2bc7c627SLionel Sambuc 			if ((newenv = realloc(savedEnv, size)) == NULL)
1192e2caf59SThomas Veerman 				return -1;
120*2bc7c627SLionel Sambuc 			savedEnv = newenv;
1212e2caf59SThomas Veerman 		} else {				/* get new space */
1222e2caf59SThomas Veerman 			/*
1232e2caf59SThomas Veerman 			 * We don't free here because we don't know if
1242e2caf59SThomas Veerman 			 * the first allocation is valid on all OS's
1252e2caf59SThomas Veerman 			 */
126*2bc7c627SLionel Sambuc 			if ((savedEnv = malloc(size)) == NULL)
1272e2caf59SThomas Veerman 				return -1;
128*2bc7c627SLionel Sambuc 			(void)memcpy(savedEnv, environ, size - sizeof(char *));
1292e2caf59SThomas Veerman 		}
130*2bc7c627SLionel Sambuc 		environ = savedEnv;
1312e2caf59SThomas Veerman 		environ[offset + 1] = NULL;
1322e2caf59SThomas Veerman 	}
1332e2caf59SThomas Veerman 	for (cc = name; *cc && *cc != '='; ++cc)	/* no `=' in name */
1342e2caf59SThomas Veerman 		continue;
1352e2caf59SThomas Veerman 	size = cc - name;
1362e2caf59SThomas Veerman 	/* name + `=' + value */
1372e2caf59SThomas Veerman 	if ((environ[offset] = malloc(size + l_value + 2)) == NULL)
1382e2caf59SThomas Veerman 		return -1;
1392e2caf59SThomas Veerman 	c = environ[offset];
1402e2caf59SThomas Veerman 	(void)memcpy(c, name, size);
1412e2caf59SThomas Veerman 	c += size;
1422e2caf59SThomas Veerman 	*c++ = '=';
1432e2caf59SThomas Veerman copy:
1442e2caf59SThomas Veerman 	(void)memcpy(c, value, l_value + 1);
1452e2caf59SThomas Veerman 	return 0;
1462e2caf59SThomas Veerman }
1472e2caf59SThomas Veerman 
1482e2caf59SThomas Veerman #ifdef TEST
1492e2caf59SThomas Veerman int
1502e2caf59SThomas Veerman main(int argc, char *argv[])
1512e2caf59SThomas Veerman {
1522e2caf59SThomas Veerman 	setenv(argv[1], argv[2], 0);
1532e2caf59SThomas Veerman 	printf("%s\n", getenv(argv[1]));
1542e2caf59SThomas Veerman 	unsetenv(argv[1]);
1552e2caf59SThomas Veerman 	printf("%s\n", getenv(argv[1]));
1562e2caf59SThomas Veerman 	return 0;
1572e2caf59SThomas Veerman }
1582e2caf59SThomas Veerman #endif
1592e2caf59SThomas Veerman 
1602e2caf59SThomas Veerman #endif
1612e2caf59SThomas Veerman 
1622e2caf59SThomas Veerman #if defined(__hpux__) || defined(__hpux)
1632e2caf59SThomas Veerman /* strrcpy():
1642e2caf59SThomas Veerman  *	Like strcpy, going backwards and returning the new pointer
1652e2caf59SThomas Veerman  */
1662e2caf59SThomas Veerman static char *
1672e2caf59SThomas Veerman strrcpy(char *ptr, char *str)
1682e2caf59SThomas Veerman {
1692e2caf59SThomas Veerman     int len = strlen(str);
1702e2caf59SThomas Veerman 
1712e2caf59SThomas Veerman     while (len)
1722e2caf59SThomas Veerman 	*--ptr = str[--len];
1732e2caf59SThomas Veerman 
1742e2caf59SThomas Veerman     return (ptr);
1752e2caf59SThomas Veerman } /* end strrcpy */
1762e2caf59SThomas Veerman 
1772e2caf59SThomas Veerman char    *sys_siglist[] = {
1782e2caf59SThomas Veerman         "Signal 0",
1792e2caf59SThomas Veerman         "Hangup",                       /* SIGHUP    */
1802e2caf59SThomas Veerman         "Interrupt",                    /* SIGINT    */
1812e2caf59SThomas Veerman         "Quit",                         /* SIGQUIT   */
1822e2caf59SThomas Veerman         "Illegal instruction",          /* SIGILL    */
1832e2caf59SThomas Veerman         "Trace/BPT trap",               /* SIGTRAP   */
1842e2caf59SThomas Veerman         "IOT trap",                     /* SIGIOT    */
1852e2caf59SThomas Veerman         "EMT trap",                     /* SIGEMT    */
1862e2caf59SThomas Veerman         "Floating point exception",     /* SIGFPE    */
1872e2caf59SThomas Veerman         "Killed",                       /* SIGKILL   */
1882e2caf59SThomas Veerman         "Bus error",                    /* SIGBUS    */
1892e2caf59SThomas Veerman         "Segmentation fault",           /* SIGSEGV   */
1902e2caf59SThomas Veerman         "Bad system call",              /* SIGSYS    */
1912e2caf59SThomas Veerman         "Broken pipe",                  /* SIGPIPE   */
1922e2caf59SThomas Veerman         "Alarm clock",                  /* SIGALRM   */
1932e2caf59SThomas Veerman         "Terminated",                   /* SIGTERM   */
1942e2caf59SThomas Veerman         "User defined signal 1",        /* SIGUSR1   */
1952e2caf59SThomas Veerman         "User defined signal 2",        /* SIGUSR2   */
1962e2caf59SThomas Veerman         "Child exited",                 /* SIGCLD    */
1972e2caf59SThomas Veerman         "Power-fail restart",           /* SIGPWR    */
1982e2caf59SThomas Veerman         "Virtual timer expired",        /* SIGVTALRM */
1992e2caf59SThomas Veerman         "Profiling timer expired",      /* SIGPROF   */
2002e2caf59SThomas Veerman         "I/O possible",                 /* SIGIO     */
2012e2caf59SThomas Veerman         "Window size changes",          /* SIGWINDOW */
2022e2caf59SThomas Veerman         "Stopped (signal)",             /* SIGSTOP   */
2032e2caf59SThomas Veerman         "Stopped",                      /* SIGTSTP   */
2042e2caf59SThomas Veerman         "Continued",                    /* SIGCONT   */
2052e2caf59SThomas Veerman         "Stopped (tty input)",          /* SIGTTIN   */
2062e2caf59SThomas Veerman         "Stopped (tty output)",         /* SIGTTOU   */
2072e2caf59SThomas Veerman         "Urgent I/O condition",         /* SIGURG    */
2082e2caf59SThomas Veerman         "Remote lock lost (NFS)",       /* SIGLOST   */
2092e2caf59SThomas Veerman         "Signal 31",                    /* reserved  */
2102e2caf59SThomas Veerman         "DIL signal"                    /* SIGDIL    */
2112e2caf59SThomas Veerman };
2122e2caf59SThomas Veerman #endif /* __hpux__ || __hpux */
2132e2caf59SThomas Veerman 
2142e2caf59SThomas Veerman #if defined(__hpux__) || defined(__hpux)
2152e2caf59SThomas Veerman #include <sys/types.h>
2162e2caf59SThomas Veerman #include <sys/syscall.h>
2172e2caf59SThomas Veerman #include <sys/signal.h>
2182e2caf59SThomas Veerman #include <sys/stat.h>
2192e2caf59SThomas Veerman #include <dirent.h>
2202e2caf59SThomas Veerman #include <sys/time.h>
2212e2caf59SThomas Veerman #include <unistd.h>
2222e2caf59SThomas Veerman 
2232e2caf59SThomas Veerman int
2242e2caf59SThomas Veerman killpg(int pid, int sig)
2252e2caf59SThomas Veerman {
2262e2caf59SThomas Veerman     return kill(-pid, sig);
2272e2caf59SThomas Veerman }
2282e2caf59SThomas Veerman 
2292e2caf59SThomas Veerman #if !defined(__hpux__) && !defined(__hpux)
2302e2caf59SThomas Veerman void
2312e2caf59SThomas Veerman srandom(long seed)
2322e2caf59SThomas Veerman {
2332e2caf59SThomas Veerman     srand48(seed);
2342e2caf59SThomas Veerman }
2352e2caf59SThomas Veerman 
2362e2caf59SThomas Veerman long
2372e2caf59SThomas Veerman random(void)
2382e2caf59SThomas Veerman {
2392e2caf59SThomas Veerman     return lrand48();
2402e2caf59SThomas Veerman }
2412e2caf59SThomas Veerman #endif
2422e2caf59SThomas Veerman 
2432e2caf59SThomas Veerman #if !defined(__hpux__) && !defined(__hpux)
2442e2caf59SThomas Veerman int
2452e2caf59SThomas Veerman utimes(char *file, struct timeval tvp[2])
2462e2caf59SThomas Veerman {
2472e2caf59SThomas Veerman     struct utimbuf t;
2482e2caf59SThomas Veerman 
2492e2caf59SThomas Veerman     t.actime  = tvp[0].tv_sec;
2502e2caf59SThomas Veerman     t.modtime = tvp[1].tv_sec;
2512e2caf59SThomas Veerman     return(utime(file, &t));
2522e2caf59SThomas Veerman }
2532e2caf59SThomas Veerman #endif
2542e2caf59SThomas Veerman 
2552e2caf59SThomas Veerman #if !defined(BSD) && !defined(d_fileno)
2562e2caf59SThomas Veerman # define d_fileno d_ino
2572e2caf59SThomas Veerman #endif
2582e2caf59SThomas Veerman 
2592e2caf59SThomas Veerman #ifndef DEV_DEV_COMPARE
2602e2caf59SThomas Veerman # define DEV_DEV_COMPARE(a, b) ((a) == (b))
2612e2caf59SThomas Veerman #endif
2622e2caf59SThomas Veerman #define ISDOT(c) ((c)[0] == '.' && (((c)[1] == '\0') || ((c)[1] == '/')))
2632e2caf59SThomas Veerman #define ISDOTDOT(c) ((c)[0] == '.' && ISDOT(&((c)[1])))
2642e2caf59SThomas Veerman 
2652e2caf59SThomas Veerman char *
2662e2caf59SThomas Veerman getwd(char *pathname)
2672e2caf59SThomas Veerman {
2682e2caf59SThomas Veerman     DIR    *dp;
2692e2caf59SThomas Veerman     struct dirent *d;
2702e2caf59SThomas Veerman     extern int errno;
2712e2caf59SThomas Veerman 
2722e2caf59SThomas Veerman     struct stat st_root, st_cur, st_next, st_dotdot;
2732e2caf59SThomas Veerman     char    pathbuf[MAXPATHLEN], nextpathbuf[MAXPATHLEN * 2];
2742e2caf59SThomas Veerman     char   *pathptr, *nextpathptr, *cur_name_add;
2752e2caf59SThomas Veerman 
2762e2caf59SThomas Veerman     /* find the inode of root */
2772e2caf59SThomas Veerman     if (stat("/", &st_root) == -1) {
2782e2caf59SThomas Veerman 	(void)sprintf(pathname,
2792e2caf59SThomas Veerman 			"getwd: Cannot stat \"/\" (%s)", strerror(errno));
2802e2caf59SThomas Veerman 	return NULL;
2812e2caf59SThomas Veerman     }
2822e2caf59SThomas Veerman     pathbuf[MAXPATHLEN - 1] = '\0';
2832e2caf59SThomas Veerman     pathptr = &pathbuf[MAXPATHLEN - 1];
2842e2caf59SThomas Veerman     nextpathbuf[MAXPATHLEN - 1] = '\0';
2852e2caf59SThomas Veerman     cur_name_add = nextpathptr = &nextpathbuf[MAXPATHLEN - 1];
2862e2caf59SThomas Veerman 
2872e2caf59SThomas Veerman     /* find the inode of the current directory */
2882e2caf59SThomas Veerman     if (lstat(".", &st_cur) == -1) {
2892e2caf59SThomas Veerman 	(void)sprintf(pathname,
2902e2caf59SThomas Veerman 			"getwd: Cannot stat \".\" (%s)", strerror(errno));
2912e2caf59SThomas Veerman 	return NULL;
2922e2caf59SThomas Veerman     }
2932e2caf59SThomas Veerman     nextpathptr = strrcpy(nextpathptr, "../");
2942e2caf59SThomas Veerman 
2952e2caf59SThomas Veerman     /* Descend to root */
2962e2caf59SThomas Veerman     for (;;) {
2972e2caf59SThomas Veerman 
2982e2caf59SThomas Veerman 	/* look if we found root yet */
2992e2caf59SThomas Veerman 	if (st_cur.st_ino == st_root.st_ino &&
3002e2caf59SThomas Veerman 	    DEV_DEV_COMPARE(st_cur.st_dev, st_root.st_dev)) {
3012e2caf59SThomas Veerman 	    (void)strcpy(pathname, *pathptr != '/' ? "/" : pathptr);
3022e2caf59SThomas Veerman 	    return (pathname);
3032e2caf59SThomas Veerman 	}
3042e2caf59SThomas Veerman 
3052e2caf59SThomas Veerman 	/* open the parent directory */
3062e2caf59SThomas Veerman 	if (stat(nextpathptr, &st_dotdot) == -1) {
3072e2caf59SThomas Veerman 	    (void)sprintf(pathname,
3082e2caf59SThomas Veerman 			    "getwd: Cannot stat directory \"%s\" (%s)",
3092e2caf59SThomas Veerman 			    nextpathptr, strerror(errno));
3102e2caf59SThomas Veerman 	    return NULL;
3112e2caf59SThomas Veerman 	}
3122e2caf59SThomas Veerman 	if ((dp = opendir(nextpathptr)) == NULL) {
3132e2caf59SThomas Veerman 	    (void)sprintf(pathname,
3142e2caf59SThomas Veerman 			    "getwd: Cannot open directory \"%s\" (%s)",
3152e2caf59SThomas Veerman 			    nextpathptr, strerror(errno));
3162e2caf59SThomas Veerman 	    return NULL;
3172e2caf59SThomas Veerman 	}
3182e2caf59SThomas Veerman 
3192e2caf59SThomas Veerman 	/* look in the parent for the entry with the same inode */
3202e2caf59SThomas Veerman 	if (DEV_DEV_COMPARE(st_dotdot.st_dev, st_cur.st_dev)) {
3212e2caf59SThomas Veerman 	    /* Parent has same device. No need to stat every member */
3222e2caf59SThomas Veerman 	    for (d = readdir(dp); d != NULL; d = readdir(dp))
3232e2caf59SThomas Veerman 		if (d->d_fileno == st_cur.st_ino)
3242e2caf59SThomas Veerman 		    break;
3252e2caf59SThomas Veerman 	}
3262e2caf59SThomas Veerman 	else {
3272e2caf59SThomas Veerman 	    /*
3282e2caf59SThomas Veerman 	     * Parent has a different device. This is a mount point so we
3292e2caf59SThomas Veerman 	     * need to stat every member
3302e2caf59SThomas Veerman 	     */
3312e2caf59SThomas Veerman 	    for (d = readdir(dp); d != NULL; d = readdir(dp)) {
3322e2caf59SThomas Veerman 		if (ISDOT(d->d_name) || ISDOTDOT(d->d_name))
3332e2caf59SThomas Veerman 		    continue;
3342e2caf59SThomas Veerman 		(void)strcpy(cur_name_add, d->d_name);
3352e2caf59SThomas Veerman 		if (lstat(nextpathptr, &st_next) == -1) {
3362e2caf59SThomas Veerman 		    (void)sprintf(pathname,
3372e2caf59SThomas Veerman 			"getwd: Cannot stat \"%s\" (%s)",
3382e2caf59SThomas Veerman 			d->d_name, strerror(errno));
3392e2caf59SThomas Veerman 		    (void)closedir(dp);
3402e2caf59SThomas Veerman 		    return NULL;
3412e2caf59SThomas Veerman 		}
3422e2caf59SThomas Veerman 		/* check if we found it yet */
3432e2caf59SThomas Veerman 		if (st_next.st_ino == st_cur.st_ino &&
3442e2caf59SThomas Veerman 		    DEV_DEV_COMPARE(st_next.st_dev, st_cur.st_dev))
3452e2caf59SThomas Veerman 		    break;
3462e2caf59SThomas Veerman 	    }
3472e2caf59SThomas Veerman 	}
3482e2caf59SThomas Veerman 	if (d == NULL) {
3492e2caf59SThomas Veerman 	    (void)sprintf(pathname,
3502e2caf59SThomas Veerman 		"getwd: Cannot find \".\" in \"..\"");
3512e2caf59SThomas Veerman 	    (void)closedir(dp);
3522e2caf59SThomas Veerman 	    return NULL;
3532e2caf59SThomas Veerman 	}
3542e2caf59SThomas Veerman 	st_cur = st_dotdot;
3552e2caf59SThomas Veerman 	pathptr = strrcpy(pathptr, d->d_name);
3562e2caf59SThomas Veerman 	pathptr = strrcpy(pathptr, "/");
3572e2caf59SThomas Veerman 	nextpathptr = strrcpy(nextpathptr, "../");
3582e2caf59SThomas Veerman 	(void)closedir(dp);
3592e2caf59SThomas Veerman 	*cur_name_add = '\0';
3602e2caf59SThomas Veerman     }
3612e2caf59SThomas Veerman } /* end getwd */
3622e2caf59SThomas Veerman #endif /* __hpux */
3632e2caf59SThomas Veerman 
3642e2caf59SThomas Veerman /* force posix signals */
3652e2caf59SThomas Veerman void (*
3662e2caf59SThomas Veerman bmake_signal(int s, void (*a)(int)))(int)
3672e2caf59SThomas Veerman {
3682e2caf59SThomas Veerman     struct sigaction sa, osa;
3692e2caf59SThomas Veerman 
3702e2caf59SThomas Veerman     sa.sa_handler = a;
3712e2caf59SThomas Veerman     sigemptyset(&sa.sa_mask);
3722e2caf59SThomas Veerman     sa.sa_flags = SA_RESTART;
3732e2caf59SThomas Veerman 
3742e2caf59SThomas Veerman     if (sigaction(s, &sa, &osa) == -1)
3752e2caf59SThomas Veerman 	return SIG_ERR;
3762e2caf59SThomas Veerman     else
3772e2caf59SThomas Veerman 	return osa.sa_handler;
3782e2caf59SThomas Veerman }
3792e2caf59SThomas Veerman 
3802e2caf59SThomas Veerman #if !defined(MAKE_NATIVE) && !defined(HAVE_VSNPRINTF)
3812e2caf59SThomas Veerman #include <stdarg.h>
3822e2caf59SThomas Veerman 
3832e2caf59SThomas Veerman #if !defined(__osf__)
3842e2caf59SThomas Veerman #ifdef _IOSTRG
3852e2caf59SThomas Veerman #define STRFLAG	(_IOSTRG|_IOWRT)	/* no _IOWRT: avoid stdio bug */
3862e2caf59SThomas Veerman #else
3872e2caf59SThomas Veerman #if 0
3882e2caf59SThomas Veerman #define STRFLAG	(_IOREAD)		/* XXX: Assume svr4 stdio */
3892e2caf59SThomas Veerman #endif
3902e2caf59SThomas Veerman #endif /* _IOSTRG */
3912e2caf59SThomas Veerman #endif /* __osf__ */
3922e2caf59SThomas Veerman 
3932e2caf59SThomas Veerman int
3942e2caf59SThomas Veerman vsnprintf(char *s, size_t n, const char *fmt, va_list args)
3952e2caf59SThomas Veerman {
3962e2caf59SThomas Veerman #ifdef STRFLAG
3972e2caf59SThomas Veerman 	FILE fakebuf;
3982e2caf59SThomas Veerman 
3992e2caf59SThomas Veerman 	fakebuf._flag = STRFLAG;
4002e2caf59SThomas Veerman 	/*
4012e2caf59SThomas Veerman 	 * Some os's are char * _ptr, others are unsigned char *_ptr...
4022e2caf59SThomas Veerman 	 * We cast to void * to make everyone happy.
4032e2caf59SThomas Veerman 	 */
4042e2caf59SThomas Veerman 	fakebuf._ptr = (void *)s;
4052e2caf59SThomas Veerman 	fakebuf._cnt = n-1;
4062e2caf59SThomas Veerman 	fakebuf._file = -1;
4072e2caf59SThomas Veerman 	_doprnt(fmt, args, &fakebuf);
4082e2caf59SThomas Veerman 	fakebuf._cnt++;
4092e2caf59SThomas Veerman 	putc('\0', &fakebuf);
4102e2caf59SThomas Veerman 	if (fakebuf._cnt<0)
4112e2caf59SThomas Veerman 	    fakebuf._cnt = 0;
4122e2caf59SThomas Veerman 	return (n-fakebuf._cnt-1);
4132e2caf59SThomas Veerman #else
4142e2caf59SThomas Veerman 	(void)vsprintf(s, fmt, args);
4152e2caf59SThomas Veerman 	return strlen(s);
4162e2caf59SThomas Veerman #endif
4172e2caf59SThomas Veerman }
4182e2caf59SThomas Veerman 
4192e2caf59SThomas Veerman int
4202e2caf59SThomas Veerman snprintf(char *s, size_t n, const char *fmt, ...)
4212e2caf59SThomas Veerman {
4222e2caf59SThomas Veerman 	va_list ap;
4232e2caf59SThomas Veerman 	int rv;
4242e2caf59SThomas Veerman 
4252e2caf59SThomas Veerman 	va_start(ap, fmt);
4262e2caf59SThomas Veerman 	rv = vsnprintf(s, n, fmt, ap);
4272e2caf59SThomas Veerman 	va_end(ap);
4282e2caf59SThomas Veerman 	return rv;
4292e2caf59SThomas Veerman }
4302e2caf59SThomas Veerman 
4312e2caf59SThomas Veerman #if !defined(MAKE_NATIVE) && !defined(HAVE_STRFTIME)
4322e2caf59SThomas Veerman size_t
4332e2caf59SThomas Veerman strftime(char *buf, size_t len, const char *fmt, const struct tm *tm)
4342e2caf59SThomas Veerman {
4352e2caf59SThomas Veerman 	static char months[][4] = {
4362e2caf59SThomas Veerman 		"Jan", "Feb", "Mar", "Apr", "May", "Jun",
4372e2caf59SThomas Veerman 		"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
4382e2caf59SThomas Veerman 	};
4392e2caf59SThomas Veerman 
4402e2caf59SThomas Veerman 	size_t s;
4412e2caf59SThomas Veerman 	char *b = buf;
4422e2caf59SThomas Veerman 
4432e2caf59SThomas Veerman 	while (*fmt) {
4442e2caf59SThomas Veerman 		if (len == 0)
4452e2caf59SThomas Veerman 			return buf - b;
4462e2caf59SThomas Veerman 		if (*fmt != '%') {
4472e2caf59SThomas Veerman 			*buf++ = *fmt++;
4482e2caf59SThomas Veerman 			len--;
4492e2caf59SThomas Veerman 			continue;
4502e2caf59SThomas Veerman 		}
4512e2caf59SThomas Veerman 		switch (*fmt++) {
4522e2caf59SThomas Veerman 		case '%':
4532e2caf59SThomas Veerman 			*buf++ = '%';
4542e2caf59SThomas Veerman 			len--;
4552e2caf59SThomas Veerman 			if (len == 0) return buf - b;
4562e2caf59SThomas Veerman 			/*FALLTHROUGH*/
4572e2caf59SThomas Veerman 		case '\0':
4582e2caf59SThomas Veerman 			*buf = '%';
4592e2caf59SThomas Veerman 			s = 1;
4602e2caf59SThomas Veerman 			break;
4612e2caf59SThomas Veerman 		case 'k':
4622e2caf59SThomas Veerman 			s = snprintf(buf, len, "%d", tm->tm_hour);
4632e2caf59SThomas Veerman 			break;
4642e2caf59SThomas Veerman 		case 'M':
4652e2caf59SThomas Veerman 			s = snprintf(buf, len, "%02d", tm->tm_min);
4662e2caf59SThomas Veerman 			break;
4672e2caf59SThomas Veerman 		case 'S':
4682e2caf59SThomas Veerman 			s = snprintf(buf, len, "%02d", tm->tm_sec);
4692e2caf59SThomas Veerman 			break;
4702e2caf59SThomas Veerman 		case 'b':
4712e2caf59SThomas Veerman 			if (tm->tm_mon >= 12)
4722e2caf59SThomas Veerman 				return buf - b;
4732e2caf59SThomas Veerman 			s = snprintf(buf, len, "%s", months[tm->tm_mon]);
4742e2caf59SThomas Veerman 			break;
4752e2caf59SThomas Veerman 		case 'd':
4762e2caf59SThomas Veerman 			s = snprintf(buf, len, "%02d", tm->tm_mday);
4772e2caf59SThomas Veerman 			break;
4782e2caf59SThomas Veerman 		case 'Y':
4792e2caf59SThomas Veerman 			s = snprintf(buf, len, "%d", 1900 + tm->tm_year);
4802e2caf59SThomas Veerman 			break;
4812e2caf59SThomas Veerman 		default:
4822e2caf59SThomas Veerman 			s = snprintf(buf, len, "Unsupported format %c",
4832e2caf59SThomas Veerman 			    fmt[-1]);
4842e2caf59SThomas Veerman 			break;
4852e2caf59SThomas Veerman 		}
4862e2caf59SThomas Veerman 		buf += s;
4872e2caf59SThomas Veerman 		len -= s;
4882e2caf59SThomas Veerman 	}
4892e2caf59SThomas Veerman }
4902e2caf59SThomas Veerman #endif
4912e2caf59SThomas Veerman #endif
492