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