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