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