1276305Sngie/*	$NetBSD: util.c,v 1.54 2013/11/26 13:44:41 joerg Exp $	*/
2236769Sobrien
3236769Sobrien/*
4236769Sobrien * Missing stuff from OS's
5236769Sobrien *
6276305Sngie *	$Id: util.c,v 1.33 2014/01/02 02:29:49 sjg Exp $
7236769Sobrien */
8276305Sngie#if defined(__MINT__) || defined(__linux__)
9276305Sngie#include <signal.h>
10276305Sngie#endif
11236769Sobrien
12236769Sobrien#include "make.h"
13236769Sobrien
14236769Sobrien#ifndef MAKE_NATIVE
15276305Sngiestatic char rcsid[] = "$NetBSD: util.c,v 1.54 2013/11/26 13:44:41 joerg Exp $";
16236769Sobrien#else
17236769Sobrien#ifndef lint
18276305Sngie__RCSID("$NetBSD: util.c,v 1.54 2013/11/26 13:44:41 joerg Exp $");
19236769Sobrien#endif
20236769Sobrien#endif
21236769Sobrien
22236769Sobrien#include <errno.h>
23236769Sobrien#include <time.h>
24236769Sobrien#include <signal.h>
25236769Sobrien
26236769Sobrien#if !defined(HAVE_STRERROR)
27236769Sobrienextern int errno, sys_nerr;
28236769Sobrienextern char *sys_errlist[];
29236769Sobrien
30236769Sobrienchar *
31236769Sobrienstrerror(int e)
32236769Sobrien{
33236769Sobrien    static char buf[100];
34236769Sobrien    if (e < 0 || e >= sys_nerr) {
35236769Sobrien	snprintf(buf, sizeof(buf), "Unknown error %d", e);
36236769Sobrien	return buf;
37236769Sobrien    }
38236769Sobrien    else
39236769Sobrien	return sys_errlist[e];
40236769Sobrien}
41236769Sobrien#endif
42236769Sobrien
43236769Sobrien#if !defined(HAVE_GETENV) || !defined(HAVE_SETENV) || !defined(HAVE_UNSETENV)
44236769Sobrienextern char **environ;
45236769Sobrien
46236769Sobrienstatic char *
47236769Sobrienfindenv(const char *name, int *offset)
48236769Sobrien{
49236769Sobrien	size_t i, len;
50236769Sobrien	char *p, *q;
51236769Sobrien
52236769Sobrien	len = strlen(name);
53236769Sobrien	for (i = 0; (q = environ[i]); i++) {
54236769Sobrien		p = strchr(q, '=');
55236769Sobrien		if (p == NULL || p - q != len)
56236769Sobrien			continue;
57236769Sobrien		if (strncmp(name, q, len) == 0) {
58236769Sobrien			*offset = i;
59236769Sobrien			return q + len + 1;
60236769Sobrien		}
61236769Sobrien	}
62236769Sobrien	*offset = i;
63236769Sobrien	return NULL;
64236769Sobrien}
65236769Sobrien
66236769Sobrienchar *
67236769Sobriengetenv(const char *name)
68236769Sobrien{
69236769Sobrien    int offset;
70236769Sobrien
71236769Sobrien    return(findenv(name, &offset));
72236769Sobrien}
73236769Sobrien
74236769Sobrienint
75236769Sobrienunsetenv(const char *name)
76236769Sobrien{
77236769Sobrien	char **p;
78236769Sobrien	int offset;
79236769Sobrien
80236769Sobrien	if (name == NULL || *name == '\0' || strchr(name, '=') != NULL) {
81236769Sobrien		errno = EINVAL;
82236769Sobrien		return -1;
83236769Sobrien	}
84236769Sobrien
85236769Sobrien	while (findenv(name, &offset))	{ /* if set multiple times */
86236769Sobrien		for (p = &environ[offset];; ++p)
87236769Sobrien			if (!(*p = *(p + 1)))
88236769Sobrien				break;
89236769Sobrien	}
90236769Sobrien	return 0;
91236769Sobrien}
92236769Sobrien
93236769Sobrienint
94236769Sobriensetenv(const char *name, const char *value, int rewrite)
95236769Sobrien{
96236769Sobrien	char *c, **newenv;
97236769Sobrien	const char *cc;
98236769Sobrien	size_t l_value, size;
99236769Sobrien	int offset;
100236769Sobrien
101236769Sobrien	if (name == NULL || value == NULL) {
102236769Sobrien		errno = EINVAL;
103236769Sobrien		return -1;
104236769Sobrien	}
105236769Sobrien
106236769Sobrien	if (*value == '=')			/* no `=' in value */
107236769Sobrien		++value;
108236769Sobrien	l_value = strlen(value);
109236769Sobrien
110236769Sobrien	/* find if already exists */
111236769Sobrien	if ((c = findenv(name, &offset))) {
112236769Sobrien		if (!rewrite)
113236769Sobrien			return 0;
114236769Sobrien		if (strlen(c) >= l_value)	/* old larger; copy over */
115236769Sobrien			goto copy;
116236769Sobrien	} else {					/* create new slot */
117236769Sobrien		size = sizeof(char *) * (offset + 2);
118236769Sobrien		if (savedEnv == environ) {		/* just increase size */
119236769Sobrien			if ((newenv = realloc(savedEnv, size)) == NULL)
120236769Sobrien				return -1;
121236769Sobrien			savedEnv = newenv;
122236769Sobrien		} else {				/* get new space */
123236769Sobrien			/*
124236769Sobrien			 * We don't free here because we don't know if
125236769Sobrien			 * the first allocation is valid on all OS's
126236769Sobrien			 */
127236769Sobrien			if ((savedEnv = malloc(size)) == NULL)
128236769Sobrien				return -1;
129236769Sobrien			(void)memcpy(savedEnv, environ, size - sizeof(char *));
130236769Sobrien		}
131236769Sobrien		environ = savedEnv;
132236769Sobrien		environ[offset + 1] = NULL;
133236769Sobrien	}
134236769Sobrien	for (cc = name; *cc && *cc != '='; ++cc)	/* no `=' in name */
135236769Sobrien		continue;
136236769Sobrien	size = cc - name;
137236769Sobrien	/* name + `=' + value */
138236769Sobrien	if ((environ[offset] = malloc(size + l_value + 2)) == NULL)
139236769Sobrien		return -1;
140236769Sobrien	c = environ[offset];
141236769Sobrien	(void)memcpy(c, name, size);
142236769Sobrien	c += size;
143236769Sobrien	*c++ = '=';
144236769Sobriencopy:
145236769Sobrien	(void)memcpy(c, value, l_value + 1);
146236769Sobrien	return 0;
147236769Sobrien}
148236769Sobrien
149236769Sobrien#ifdef TEST
150236769Sobrienint
151236769Sobrienmain(int argc, char *argv[])
152236769Sobrien{
153236769Sobrien	setenv(argv[1], argv[2], 0);
154236769Sobrien	printf("%s\n", getenv(argv[1]));
155236769Sobrien	unsetenv(argv[1]);
156236769Sobrien	printf("%s\n", getenv(argv[1]));
157236769Sobrien	return 0;
158236769Sobrien}
159236769Sobrien#endif
160236769Sobrien
161236769Sobrien#endif
162236769Sobrien
163236769Sobrien
164236769Sobrien#if defined(__hpux__) || defined(__hpux)
165236769Sobrien/* strrcpy():
166236769Sobrien *	Like strcpy, going backwards and returning the new pointer
167236769Sobrien */
168236769Sobrienstatic char *
169236769Sobrienstrrcpy(char *ptr, char *str)
170236769Sobrien{
171236769Sobrien    int len = strlen(str);
172236769Sobrien
173236769Sobrien    while (len)
174236769Sobrien	*--ptr = str[--len];
175236769Sobrien
176236769Sobrien    return (ptr);
177236769Sobrien} /* end strrcpy */
178236769Sobrien
179236769Sobrien
180236769Sobrienchar    *sys_siglist[] = {
181236769Sobrien        "Signal 0",
182236769Sobrien        "Hangup",                       /* SIGHUP    */
183236769Sobrien        "Interrupt",                    /* SIGINT    */
184236769Sobrien        "Quit",                         /* SIGQUIT   */
185236769Sobrien        "Illegal instruction",          /* SIGILL    */
186236769Sobrien        "Trace/BPT trap",               /* SIGTRAP   */
187236769Sobrien        "IOT trap",                     /* SIGIOT    */
188236769Sobrien        "EMT trap",                     /* SIGEMT    */
189236769Sobrien        "Floating point exception",     /* SIGFPE    */
190236769Sobrien        "Killed",                       /* SIGKILL   */
191236769Sobrien        "Bus error",                    /* SIGBUS    */
192236769Sobrien        "Segmentation fault",           /* SIGSEGV   */
193236769Sobrien        "Bad system call",              /* SIGSYS    */
194236769Sobrien        "Broken pipe",                  /* SIGPIPE   */
195236769Sobrien        "Alarm clock",                  /* SIGALRM   */
196236769Sobrien        "Terminated",                   /* SIGTERM   */
197236769Sobrien        "User defined signal 1",        /* SIGUSR1   */
198236769Sobrien        "User defined signal 2",        /* SIGUSR2   */
199236769Sobrien        "Child exited",                 /* SIGCLD    */
200236769Sobrien        "Power-fail restart",           /* SIGPWR    */
201236769Sobrien        "Virtual timer expired",        /* SIGVTALRM */
202236769Sobrien        "Profiling timer expired",      /* SIGPROF   */
203236769Sobrien        "I/O possible",                 /* SIGIO     */
204236769Sobrien        "Window size changes",          /* SIGWINDOW */
205236769Sobrien        "Stopped (signal)",             /* SIGSTOP   */
206236769Sobrien        "Stopped",                      /* SIGTSTP   */
207236769Sobrien        "Continued",                    /* SIGCONT   */
208236769Sobrien        "Stopped (tty input)",          /* SIGTTIN   */
209236769Sobrien        "Stopped (tty output)",         /* SIGTTOU   */
210236769Sobrien        "Urgent I/O condition",         /* SIGURG    */
211236769Sobrien        "Remote lock lost (NFS)",       /* SIGLOST   */
212236769Sobrien        "Signal 31",                    /* reserved  */
213236769Sobrien        "DIL signal"                    /* SIGDIL    */
214236769Sobrien};
215236769Sobrien#endif /* __hpux__ || __hpux */
216236769Sobrien
217236769Sobrien#if defined(__hpux__) || defined(__hpux)
218236769Sobrien#include <sys/types.h>
219236769Sobrien#include <sys/syscall.h>
220236769Sobrien#include <sys/signal.h>
221236769Sobrien#include <sys/stat.h>
222236769Sobrien#include <dirent.h>
223236769Sobrien#include <sys/time.h>
224236769Sobrien#include <unistd.h>
225236769Sobrien
226236769Sobrienint
227236769Sobrienkillpg(int pid, int sig)
228236769Sobrien{
229236769Sobrien    return kill(-pid, sig);
230236769Sobrien}
231236769Sobrien
232236769Sobrien#if !defined(__hpux__) && !defined(__hpux)
233236769Sobrienvoid
234236769Sobriensrandom(long seed)
235236769Sobrien{
236236769Sobrien    srand48(seed);
237236769Sobrien}
238236769Sobrien
239236769Sobrienlong
240236769Sobrienrandom(void)
241236769Sobrien{
242236769Sobrien    return lrand48();
243236769Sobrien}
244236769Sobrien#endif
245236769Sobrien
246236769Sobrien#if !defined(__hpux__) && !defined(__hpux)
247236769Sobrienint
248236769Sobrienutimes(char *file, struct timeval tvp[2])
249236769Sobrien{
250236769Sobrien    struct utimbuf t;
251236769Sobrien
252236769Sobrien    t.actime  = tvp[0].tv_sec;
253236769Sobrien    t.modtime = tvp[1].tv_sec;
254236769Sobrien    return(utime(file, &t));
255236769Sobrien}
256236769Sobrien#endif
257236769Sobrien
258236769Sobrien#if !defined(BSD) && !defined(d_fileno)
259236769Sobrien# define d_fileno d_ino
260236769Sobrien#endif
261236769Sobrien
262236769Sobrien#ifndef DEV_DEV_COMPARE
263236769Sobrien# define DEV_DEV_COMPARE(a, b) ((a) == (b))
264236769Sobrien#endif
265236769Sobrien#define ISDOT(c) ((c)[0] == '.' && (((c)[1] == '\0') || ((c)[1] == '/')))
266236769Sobrien#define ISDOTDOT(c) ((c)[0] == '.' && ISDOT(&((c)[1])))
267236769Sobrien
268236769Sobrienchar *
269236769Sobriengetwd(char *pathname)
270236769Sobrien{
271236769Sobrien    DIR    *dp;
272236769Sobrien    struct dirent *d;
273236769Sobrien    extern int errno;
274236769Sobrien
275236769Sobrien    struct stat st_root, st_cur, st_next, st_dotdot;
276236769Sobrien    char    pathbuf[MAXPATHLEN], nextpathbuf[MAXPATHLEN * 2];
277236769Sobrien    char   *pathptr, *nextpathptr, *cur_name_add;
278236769Sobrien
279236769Sobrien    /* find the inode of root */
280236769Sobrien    if (stat("/", &st_root) == -1) {
281236769Sobrien	(void)sprintf(pathname,
282236769Sobrien			"getwd: Cannot stat \"/\" (%s)", strerror(errno));
283236769Sobrien	return NULL;
284236769Sobrien    }
285236769Sobrien    pathbuf[MAXPATHLEN - 1] = '\0';
286236769Sobrien    pathptr = &pathbuf[MAXPATHLEN - 1];
287236769Sobrien    nextpathbuf[MAXPATHLEN - 1] = '\0';
288236769Sobrien    cur_name_add = nextpathptr = &nextpathbuf[MAXPATHLEN - 1];
289236769Sobrien
290236769Sobrien    /* find the inode of the current directory */
291236769Sobrien    if (lstat(".", &st_cur) == -1) {
292236769Sobrien	(void)sprintf(pathname,
293236769Sobrien			"getwd: Cannot stat \".\" (%s)", strerror(errno));
294236769Sobrien	return NULL;
295236769Sobrien    }
296236769Sobrien    nextpathptr = strrcpy(nextpathptr, "../");
297236769Sobrien
298236769Sobrien    /* Descend to root */
299236769Sobrien    for (;;) {
300236769Sobrien
301236769Sobrien	/* look if we found root yet */
302236769Sobrien	if (st_cur.st_ino == st_root.st_ino &&
303236769Sobrien	    DEV_DEV_COMPARE(st_cur.st_dev, st_root.st_dev)) {
304236769Sobrien	    (void)strcpy(pathname, *pathptr != '/' ? "/" : pathptr);
305236769Sobrien	    return (pathname);
306236769Sobrien	}
307236769Sobrien
308236769Sobrien	/* open the parent directory */
309236769Sobrien	if (stat(nextpathptr, &st_dotdot) == -1) {
310236769Sobrien	    (void)sprintf(pathname,
311236769Sobrien			    "getwd: Cannot stat directory \"%s\" (%s)",
312236769Sobrien			    nextpathptr, strerror(errno));
313236769Sobrien	    return NULL;
314236769Sobrien	}
315236769Sobrien	if ((dp = opendir(nextpathptr)) == NULL) {
316236769Sobrien	    (void)sprintf(pathname,
317236769Sobrien			    "getwd: Cannot open directory \"%s\" (%s)",
318236769Sobrien			    nextpathptr, strerror(errno));
319236769Sobrien	    return NULL;
320236769Sobrien	}
321236769Sobrien
322236769Sobrien	/* look in the parent for the entry with the same inode */
323236769Sobrien	if (DEV_DEV_COMPARE(st_dotdot.st_dev, st_cur.st_dev)) {
324236769Sobrien	    /* Parent has same device. No need to stat every member */
325236769Sobrien	    for (d = readdir(dp); d != NULL; d = readdir(dp))
326236769Sobrien		if (d->d_fileno == st_cur.st_ino)
327236769Sobrien		    break;
328236769Sobrien	}
329236769Sobrien	else {
330236769Sobrien	    /*
331236769Sobrien	     * Parent has a different device. This is a mount point so we
332236769Sobrien	     * need to stat every member
333236769Sobrien	     */
334236769Sobrien	    for (d = readdir(dp); d != NULL; d = readdir(dp)) {
335236769Sobrien		if (ISDOT(d->d_name) || ISDOTDOT(d->d_name))
336236769Sobrien		    continue;
337236769Sobrien		(void)strcpy(cur_name_add, d->d_name);
338236769Sobrien		if (lstat(nextpathptr, &st_next) == -1) {
339236769Sobrien		    (void)sprintf(pathname,
340236769Sobrien			"getwd: Cannot stat \"%s\" (%s)",
341236769Sobrien			d->d_name, strerror(errno));
342236769Sobrien		    (void)closedir(dp);
343236769Sobrien		    return NULL;
344236769Sobrien		}
345236769Sobrien		/* check if we found it yet */
346236769Sobrien		if (st_next.st_ino == st_cur.st_ino &&
347236769Sobrien		    DEV_DEV_COMPARE(st_next.st_dev, st_cur.st_dev))
348236769Sobrien		    break;
349236769Sobrien	    }
350236769Sobrien	}
351236769Sobrien	if (d == NULL) {
352236769Sobrien	    (void)sprintf(pathname,
353236769Sobrien		"getwd: Cannot find \".\" in \"..\"");
354236769Sobrien	    (void)closedir(dp);
355236769Sobrien	    return NULL;
356236769Sobrien	}
357236769Sobrien	st_cur = st_dotdot;
358236769Sobrien	pathptr = strrcpy(pathptr, d->d_name);
359236769Sobrien	pathptr = strrcpy(pathptr, "/");
360236769Sobrien	nextpathptr = strrcpy(nextpathptr, "../");
361236769Sobrien	(void)closedir(dp);
362236769Sobrien	*cur_name_add = '\0';
363236769Sobrien    }
364236769Sobrien} /* end getwd */
365236769Sobrien
366236769Sobrien#endif /* __hpux */
367236769Sobrien
368236769Sobrien#if !defined(HAVE_GETCWD)
369236769Sobrienchar *
370236769Sobriengetcwd(path, sz)
371236769Sobrien     char *path;
372236769Sobrien     int sz;
373236769Sobrien{
374236769Sobrien	return getwd(path);
375236769Sobrien}
376236769Sobrien#endif
377236769Sobrien
378236769Sobrien/* force posix signals */
379236769Sobrienvoid (*
380236769Sobrienbmake_signal(int s, void (*a)(int)))(int)
381236769Sobrien{
382236769Sobrien    struct sigaction sa, osa;
383236769Sobrien
384236769Sobrien    sa.sa_handler = a;
385236769Sobrien    sigemptyset(&sa.sa_mask);
386236769Sobrien    sa.sa_flags = SA_RESTART;
387236769Sobrien
388236769Sobrien    if (sigaction(s, &sa, &osa) == -1)
389236769Sobrien	return SIG_ERR;
390236769Sobrien    else
391236769Sobrien	return osa.sa_handler;
392236769Sobrien}
393236769Sobrien
394236769Sobrien#if !defined(HAVE_VSNPRINTF) || !defined(HAVE_VASPRINTF)
395236769Sobrien#include <stdarg.h>
396236769Sobrien#endif
397236769Sobrien
398236769Sobrien#if !defined(HAVE_VSNPRINTF)
399236769Sobrien#if !defined(__osf__)
400236769Sobrien#ifdef _IOSTRG
401236769Sobrien#define STRFLAG	(_IOSTRG|_IOWRT)	/* no _IOWRT: avoid stdio bug */
402236769Sobrien#else
403236769Sobrien#if 0
404236769Sobrien#define STRFLAG	(_IOREAD)		/* XXX: Assume svr4 stdio */
405236769Sobrien#endif
406236769Sobrien#endif /* _IOSTRG */
407236769Sobrien#endif /* __osf__ */
408236769Sobrien
409236769Sobrienint
410236769Sobrienvsnprintf(char *s, size_t n, const char *fmt, va_list args)
411236769Sobrien{
412236769Sobrien#ifdef STRFLAG
413236769Sobrien	FILE fakebuf;
414236769Sobrien
415236769Sobrien	fakebuf._flag = STRFLAG;
416236769Sobrien	/*
417236769Sobrien	 * Some os's are char * _ptr, others are unsigned char *_ptr...
418236769Sobrien	 * We cast to void * to make everyone happy.
419236769Sobrien	 */
420236769Sobrien	fakebuf._ptr = (void *)s;
421236769Sobrien	fakebuf._cnt = n-1;
422236769Sobrien	fakebuf._file = -1;
423236769Sobrien	_doprnt(fmt, args, &fakebuf);
424236769Sobrien	fakebuf._cnt++;
425236769Sobrien	putc('\0', &fakebuf);
426236769Sobrien	if (fakebuf._cnt<0)
427236769Sobrien	    fakebuf._cnt = 0;
428236769Sobrien	return (n-fakebuf._cnt-1);
429236769Sobrien#else
430236769Sobrien#ifndef _PATH_DEVNULL
431236769Sobrien# define _PATH_DEVNULL "/dev/null"
432236769Sobrien#endif
433236769Sobrien	/*
434236769Sobrien	 * Rats... we don't want to clobber anything...
435236769Sobrien	 * do a printf to /dev/null to see how much space we need.
436236769Sobrien	 */
437236769Sobrien	static FILE *nullfp;
438236769Sobrien	int need = 0;			/* XXX what's a useful error return? */
439236769Sobrien
440236769Sobrien	if (!nullfp)
441236769Sobrien		nullfp = fopen(_PATH_DEVNULL, "w");
442236769Sobrien	if (nullfp) {
443236769Sobrien		need = vfprintf(nullfp, fmt, args);
444236769Sobrien		if (need < n)
445236769Sobrien			(void)vsprintf(s, fmt, args);
446236769Sobrien	}
447236769Sobrien	return need;
448236769Sobrien#endif
449236769Sobrien}
450236769Sobrien#endif
451236769Sobrien
452236769Sobrien#if !defined(HAVE_SNPRINTF)
453236769Sobrienint
454236769Sobriensnprintf(char *s, size_t n, const char *fmt, ...)
455236769Sobrien{
456236769Sobrien	va_list ap;
457236769Sobrien	int rv;
458236769Sobrien
459236769Sobrien	va_start(ap, fmt);
460236769Sobrien	rv = vsnprintf(s, n, fmt, ap);
461236769Sobrien	va_end(ap);
462236769Sobrien	return rv;
463236769Sobrien}
464236769Sobrien#endif
465236769Sobrien
466236769Sobrien#if !defined(HAVE_STRFTIME)
467236769Sobriensize_t
468236769Sobrienstrftime(char *buf, size_t len, const char *fmt, const struct tm *tm)
469236769Sobrien{
470236769Sobrien	static char months[][4] = {
471236769Sobrien		"Jan", "Feb", "Mar", "Apr", "May", "Jun",
472236769Sobrien		"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
473236769Sobrien	};
474236769Sobrien
475236769Sobrien	size_t s;
476236769Sobrien	char *b = buf;
477236769Sobrien
478236769Sobrien	while (*fmt) {
479236769Sobrien		if (len == 0)
480236769Sobrien			return buf - b;
481236769Sobrien		if (*fmt != '%') {
482236769Sobrien			*buf++ = *fmt++;
483236769Sobrien			len--;
484236769Sobrien			continue;
485236769Sobrien		}
486236769Sobrien		switch (*fmt++) {
487236769Sobrien		case '%':
488236769Sobrien			*buf++ = '%';
489236769Sobrien			len--;
490236769Sobrien			if (len == 0) return buf - b;
491236769Sobrien			/*FALLTHROUGH*/
492236769Sobrien		case '\0':
493236769Sobrien			*buf = '%';
494236769Sobrien			s = 1;
495236769Sobrien			break;
496236769Sobrien		case 'k':
497236769Sobrien			s = snprintf(buf, len, "%d", tm->tm_hour);
498236769Sobrien			break;
499236769Sobrien		case 'M':
500236769Sobrien			s = snprintf(buf, len, "%02d", tm->tm_min);
501236769Sobrien			break;
502236769Sobrien		case 'S':
503236769Sobrien			s = snprintf(buf, len, "%02d", tm->tm_sec);
504236769Sobrien			break;
505236769Sobrien		case 'b':
506236769Sobrien			if (tm->tm_mon >= 12)
507236769Sobrien				return buf - b;
508236769Sobrien			s = snprintf(buf, len, "%s", months[tm->tm_mon]);
509236769Sobrien			break;
510236769Sobrien		case 'd':
511236769Sobrien			s = snprintf(buf, len, "%02d", tm->tm_mday);
512236769Sobrien			break;
513236769Sobrien		case 'Y':
514236769Sobrien			s = snprintf(buf, len, "%d", 1900 + tm->tm_year);
515236769Sobrien			break;
516236769Sobrien		default:
517236769Sobrien			s = snprintf(buf, len, "Unsupported format %c",
518236769Sobrien			    fmt[-1]);
519236769Sobrien			break;
520236769Sobrien		}
521236769Sobrien		buf += s;
522236769Sobrien		len -= s;
523236769Sobrien	}
524236769Sobrien}
525236769Sobrien#endif
526236769Sobrien
527236769Sobrien#if !defined(HAVE_KILLPG)
528236769Sobrien#if !defined(__hpux__) && !defined(__hpux)
529236769Sobrienint
530236769Sobrienkillpg(int pid, int sig)
531236769Sobrien{
532236769Sobrien    return kill(-pid, sig);
533236769Sobrien}
534236769Sobrien#endif
535236769Sobrien#endif
536236769Sobrien
537236769Sobrien#if !defined(HAVE_WARNX)
538236769Sobrienstatic void
539236769Sobrienvwarnx(const char *fmt, va_list args)
540236769Sobrien{
541236769Sobrien	fprintf(stderr, "%s: ", progname);
542236769Sobrien	if ((fmt)) {
543236769Sobrien		vfprintf(stderr, fmt, args);
544236769Sobrien		fprintf(stderr, ": ");
545236769Sobrien	}
546236769Sobrien}
547236769Sobrien#endif
548236769Sobrien
549236769Sobrien#if !defined(HAVE_WARN)
550236769Sobrienstatic void
551236769Sobrienvwarn(const char *fmt, va_list args)
552236769Sobrien{
553236769Sobrien	vwarnx(fmt, args);
554236769Sobrien	fprintf(stderr, "%s\n", strerror(errno));
555236769Sobrien}
556236769Sobrien#endif
557236769Sobrien
558236769Sobrien#if !defined(HAVE_ERR)
559236769Sobrienstatic void
560236769Sobrienverr(int eval, const char *fmt, va_list args)
561236769Sobrien{
562236769Sobrien	vwarn(fmt, args);
563236769Sobrien	exit(eval);
564236769Sobrien}
565236769Sobrien#endif
566236769Sobrien
567236769Sobrien#if !defined(HAVE_ERRX)
568236769Sobrienstatic void
569236769Sobrienverrx(int eval, const char *fmt, va_list args)
570236769Sobrien{
571236769Sobrien	vwarnx(fmt, args);
572236769Sobrien	exit(eval);
573236769Sobrien}
574236769Sobrien#endif
575236769Sobrien
576236769Sobrien#if !defined(HAVE_ERR)
577236769Sobrienvoid
578236769Sobrienerr(int eval, const char *fmt, ...)
579236769Sobrien{
580236769Sobrien        va_list ap;
581236769Sobrien
582236769Sobrien        va_start(ap, fmt);
583236769Sobrien        verr(eval, fmt, ap);
584236769Sobrien        va_end(ap);
585236769Sobrien}
586236769Sobrien#endif
587236769Sobrien
588236769Sobrien#if !defined(HAVE_ERRX)
589236769Sobrienvoid
590236769Sobrienerrx(int eval, const char *fmt, ...)
591236769Sobrien{
592236769Sobrien        va_list ap;
593236769Sobrien
594236769Sobrien        va_start(ap, fmt);
595236769Sobrien        verrx(eval, fmt, ap);
596236769Sobrien        va_end(ap);
597236769Sobrien}
598236769Sobrien#endif
599236769Sobrien
600236769Sobrien#if !defined(HAVE_WARN)
601236769Sobrienvoid
602236769Sobrienwarn(const char *fmt, ...)
603236769Sobrien{
604236769Sobrien        va_list ap;
605236769Sobrien
606236769Sobrien        va_start(ap, fmt);
607236769Sobrien        vwarn(fmt, ap);
608236769Sobrien        va_end(ap);
609236769Sobrien}
610236769Sobrien#endif
611236769Sobrien
612236769Sobrien#if !defined(HAVE_WARNX)
613236769Sobrienvoid
614236769Sobrienwarnx(const char *fmt, ...)
615236769Sobrien{
616236769Sobrien        va_list ap;
617236769Sobrien
618236769Sobrien        va_start(ap, fmt);
619236769Sobrien        vwarnx(fmt, ap);
620236769Sobrien        va_end(ap);
621236769Sobrien}
622236769Sobrien#endif
623