Home | History | Annotate | Line # | Download | only in make
util.c revision 1.35
      1 /*	$NetBSD: util.c,v 1.35 2004/05/07 00:04:40 ross Exp $	*/
      2 
      3 /*
      4  * Missing stuff from OS's
      5  */
      6 
      7 #ifndef MAKE_NATIVE
      8 static char rcsid[] = "$NetBSD: util.c,v 1.35 2004/05/07 00:04:40 ross Exp $";
      9 #else
     10 #include <sys/cdefs.h>
     11 #ifndef lint
     12 __RCSID("$NetBSD: util.c,v 1.35 2004/05/07 00:04:40 ross Exp $");
     13 #endif
     14 #endif
     15 
     16 #include <sys/param.h>
     17 
     18 #include <errno.h>
     19 #include <stdio.h>
     20 #include <time.h>
     21 
     22 #include "make.h"
     23 
     24 #if !defined(MAKE_NATIVE) && !defined(HAVE_STRERROR)
     25 extern int errno, sys_nerr;
     26 extern char *sys_errlist[];
     27 
     28 char *
     29 strerror(int e)
     30 {
     31     static char buf[100];
     32     if (e < 0 || e >= sys_nerr) {
     33 	snprintf(buf, sizeof(buf), "Unknown error %d", e);
     34 	return buf;
     35     }
     36     else
     37 	return sys_errlist[e];
     38 }
     39 #endif
     40 
     41 #if !defined(MAKE_NATIVE) && !defined(HAVE_STRDUP)
     42 #include <string.h>
     43 
     44 /* strdup
     45  *
     46  * Make a duplicate of a string.
     47  * For systems which lack this function.
     48  */
     49 char *
     50 strdup(const char *str)
     51 {
     52     size_t len;
     53     char *p;
     54 
     55     if (str == NULL)
     56 	return NULL;
     57     len = strlen(str) + 1;
     58     p = emalloc(len);
     59 
     60     return memcpy(p, str, len);
     61 }
     62 #endif
     63 
     64 #if !defined(MAKE_NATIVE) && !defined(HAVE_SETENV)
     65 int
     66 setenv(const char *name, const char *value, int dum)
     67 {
     68     char *p;
     69     int len = strlen(name) + strlen(value) + 2; /* = \0 */
     70     char *ptr = (char*) emalloc(len);
     71 
     72     (void) dum;
     73 
     74     if (ptr == NULL)
     75 	return -1;
     76 
     77     p = ptr;
     78 
     79     while (*name)
     80 	*p++ = *name++;
     81 
     82     *p++ = '=';
     83 
     84     while (*value)
     85 	*p++ = *value++;
     86 
     87     *p = '\0';
     88 
     89     len = putenv(ptr);
     90 /*    free(ptr); */
     91     return len;
     92 }
     93 #endif
     94 
     95 #if defined(__hpux__) || defined(__hpux)
     96 /* strrcpy():
     97  *	Like strcpy, going backwards and returning the new pointer
     98  */
     99 static char *
    100 strrcpy(char *ptr, char *str)
    101 {
    102     int len = strlen(str);
    103 
    104     while (len)
    105 	*--ptr = str[--len];
    106 
    107     return (ptr);
    108 } /* end strrcpy */
    109 
    110 char    *sys_siglist[] = {
    111         "Signal 0",
    112         "Hangup",                       /* SIGHUP    */
    113         "Interrupt",                    /* SIGINT    */
    114         "Quit",                         /* SIGQUIT   */
    115         "Illegal instruction",          /* SIGILL    */
    116         "Trace/BPT trap",               /* SIGTRAP   */
    117         "IOT trap",                     /* SIGIOT    */
    118         "EMT trap",                     /* SIGEMT    */
    119         "Floating point exception",     /* SIGFPE    */
    120         "Killed",                       /* SIGKILL   */
    121         "Bus error",                    /* SIGBUS    */
    122         "Segmentation fault",           /* SIGSEGV   */
    123         "Bad system call",              /* SIGSYS    */
    124         "Broken pipe",                  /* SIGPIPE   */
    125         "Alarm clock",                  /* SIGALRM   */
    126         "Terminated",                   /* SIGTERM   */
    127         "User defined signal 1",        /* SIGUSR1   */
    128         "User defined signal 2",        /* SIGUSR2   */
    129         "Child exited",                 /* SIGCLD    */
    130         "Power-fail restart",           /* SIGPWR    */
    131         "Virtual timer expired",        /* SIGVTALRM */
    132         "Profiling timer expired",      /* SIGPROF   */
    133         "I/O possible",                 /* SIGIO     */
    134         "Window size changes",          /* SIGWINDOW */
    135         "Stopped (signal)",             /* SIGSTOP   */
    136         "Stopped",                      /* SIGTSTP   */
    137         "Continued",                    /* SIGCONT   */
    138         "Stopped (tty input)",          /* SIGTTIN   */
    139         "Stopped (tty output)",         /* SIGTTOU   */
    140         "Urgent I/O condition",         /* SIGURG    */
    141         "Remote lock lost (NFS)",       /* SIGLOST   */
    142         "Signal 31",                    /* reserved  */
    143         "DIL signal"                    /* SIGDIL    */
    144 };
    145 #endif /* __hpux__ || __hpux */
    146 
    147 #if defined(__hpux__) || defined(__hpux)
    148 #include <sys/types.h>
    149 #include <sys/param.h>
    150 #include <sys/syscall.h>
    151 #include <sys/signal.h>
    152 #include <sys/stat.h>
    153 #include <stdio.h>
    154 #include <dirent.h>
    155 #include <sys/time.h>
    156 #include <time.h>
    157 #include <unistd.h>
    158 
    159 int
    160 killpg(int pid, int sig)
    161 {
    162     return kill(-pid, sig);
    163 }
    164 
    165 #if !defined(__hpux__) && !defined(__hpux)
    166 void
    167 srandom(long seed)
    168 {
    169     srand48(seed);
    170 }
    171 
    172 long
    173 random(void)
    174 {
    175     return lrand48();
    176 }
    177 #endif
    178 
    179 /* turn into bsd signals */
    180 void (*
    181 signal(int s, void (*a)(int)))(int)
    182 {
    183     struct sigvec osv, sv;
    184 
    185     (void) sigvector(s, (struct sigvec *) 0, &osv);
    186     sv = osv;
    187     sv.sv_handler = a;
    188 #ifdef SV_BSDSIG
    189     sv.sv_flags = SV_BSDSIG;
    190 #endif
    191 
    192     if (sigvector(s, &sv, (struct sigvec *) 0) == -1)
    193         return (BADSIG);
    194     return (osv.sv_handler);
    195 }
    196 
    197 #if !defined(__hpux__) && !defined(__hpux)
    198 int
    199 utimes(char *file, struct timeval tvp[2])
    200 {
    201     struct utimbuf t;
    202 
    203     t.actime  = tvp[0].tv_sec;
    204     t.modtime = tvp[1].tv_sec;
    205     return(utime(file, &t));
    206 }
    207 #endif
    208 
    209 #if !defined(BSD) && !defined(d_fileno)
    210 # define d_fileno d_ino
    211 #endif
    212 
    213 #ifndef DEV_DEV_COMPARE
    214 # define DEV_DEV_COMPARE(a, b) ((a) == (b))
    215 #endif
    216 #define ISDOT(c) ((c)[0] == '.' && (((c)[1] == '\0') || ((c)[1] == '/')))
    217 #define ISDOTDOT(c) ((c)[0] == '.' && ISDOT(&((c)[1])))
    218 
    219 char *
    220 getwd(char *pathname)
    221 {
    222     DIR    *dp;
    223     struct dirent *d;
    224     extern int errno;
    225 
    226     struct stat st_root, st_cur, st_next, st_dotdot;
    227     char    pathbuf[MAXPATHLEN], nextpathbuf[MAXPATHLEN * 2];
    228     char   *pathptr, *nextpathptr, *cur_name_add;
    229 
    230     /* find the inode of root */
    231     if (stat("/", &st_root) == -1) {
    232 	(void) sprintf(pathname,
    233 			"getwd: Cannot stat \"/\" (%s)", strerror(errno));
    234 	return (NULL);
    235     }
    236     pathbuf[MAXPATHLEN - 1] = '\0';
    237     pathptr = &pathbuf[MAXPATHLEN - 1];
    238     nextpathbuf[MAXPATHLEN - 1] = '\0';
    239     cur_name_add = nextpathptr = &nextpathbuf[MAXPATHLEN - 1];
    240 
    241     /* find the inode of the current directory */
    242     if (lstat(".", &st_cur) == -1) {
    243 	(void) sprintf(pathname,
    244 			"getwd: Cannot stat \".\" (%s)", strerror(errno));
    245 	return (NULL);
    246     }
    247     nextpathptr = strrcpy(nextpathptr, "../");
    248 
    249     /* Descend to root */
    250     for (;;) {
    251 
    252 	/* look if we found root yet */
    253 	if (st_cur.st_ino == st_root.st_ino &&
    254 	    DEV_DEV_COMPARE(st_cur.st_dev, st_root.st_dev)) {
    255 	    (void) strcpy(pathname, *pathptr != '/' ? "/" : pathptr);
    256 	    return (pathname);
    257 	}
    258 
    259 	/* open the parent directory */
    260 	if (stat(nextpathptr, &st_dotdot) == -1) {
    261 	    (void) sprintf(pathname,
    262 			    "getwd: Cannot stat directory \"%s\" (%s)",
    263 			    nextpathptr, strerror(errno));
    264 	    return (NULL);
    265 	}
    266 	if ((dp = opendir(nextpathptr)) == NULL) {
    267 	    (void) sprintf(pathname,
    268 			    "getwd: Cannot open directory \"%s\" (%s)",
    269 			    nextpathptr, strerror(errno));
    270 	    return (NULL);
    271 	}
    272 
    273 	/* look in the parent for the entry with the same inode */
    274 	if (DEV_DEV_COMPARE(st_dotdot.st_dev, st_cur.st_dev)) {
    275 	    /* Parent has same device. No need to stat every member */
    276 	    for (d = readdir(dp); d != NULL; d = readdir(dp))
    277 		if (d->d_fileno == st_cur.st_ino)
    278 		    break;
    279 	}
    280 	else {
    281 	    /*
    282 	     * Parent has a different device. This is a mount point so we
    283 	     * need to stat every member
    284 	     */
    285 	    for (d = readdir(dp); d != NULL; d = readdir(dp)) {
    286 		if (ISDOT(d->d_name) || ISDOTDOT(d->d_name))
    287 		    continue;
    288 		(void) strcpy(cur_name_add, d->d_name);
    289 		if (lstat(nextpathptr, &st_next) == -1) {
    290 		    (void) sprintf(pathname,
    291 			"getwd: Cannot stat \"%s\" (%s)",
    292 			d->d_name, strerror(errno));
    293 		    (void) closedir(dp);
    294 		    return (NULL);
    295 		}
    296 		/* check if we found it yet */
    297 		if (st_next.st_ino == st_cur.st_ino &&
    298 		    DEV_DEV_COMPARE(st_next.st_dev, st_cur.st_dev))
    299 		    break;
    300 	    }
    301 	}
    302 	if (d == NULL) {
    303 	    (void) sprintf(pathname,
    304 		"getwd: Cannot find \".\" in \"..\"");
    305 	    (void) closedir(dp);
    306 	    return (NULL);
    307 	}
    308 	st_cur = st_dotdot;
    309 	pathptr = strrcpy(pathptr, d->d_name);
    310 	pathptr = strrcpy(pathptr, "/");
    311 	nextpathptr = strrcpy(nextpathptr, "../");
    312 	(void) closedir(dp);
    313 	*cur_name_add = '\0';
    314     }
    315 } /* end getwd */
    316 #endif /* __hpux */
    317 
    318 #if defined(sun) && defined(__svr4__)
    319 #include <signal.h>
    320 
    321 /* turn into bsd signals */
    322 void (*
    323 signal(int s, void (*a)(int)))(int)
    324 {
    325     struct sigaction sa, osa;
    326 
    327     sa.sa_handler = a;
    328     sigemptyset(&sa.sa_mask);
    329     sa.sa_flags = SA_RESTART;
    330 
    331     if (sigaction(s, &sa, &osa) == -1)
    332 	return SIG_ERR;
    333     else
    334 	return osa.sa_handler;
    335 }
    336 #endif
    337 
    338 #if !defined(MAKE_NATIVE) && !defined(HAVE_VSNPRINTF)
    339 #include <stdarg.h>
    340 
    341 #if !defined(__osf__)
    342 #ifdef _IOSTRG
    343 #define STRFLAG	(_IOSTRG|_IOWRT)	/* no _IOWRT: avoid stdio bug */
    344 #else
    345 #if 0
    346 #define STRFLAG	(_IOREAD)		/* XXX: Assume svr4 stdio */
    347 #endif
    348 #endif /* _IOSTRG */
    349 #endif /* __osf__ */
    350 
    351 int
    352 vsnprintf(char *s, size_t n, const char *fmt, va_list args)
    353 {
    354 #ifdef STRFLAG
    355 	FILE fakebuf;
    356 
    357 	fakebuf._flag = STRFLAG;
    358 	/*
    359 	 * Some os's are char * _ptr, others are unsigned char *_ptr...
    360 	 * We cast to void * to make everyone happy.
    361 	 */
    362 	fakebuf._ptr = (void *) s;
    363 	fakebuf._cnt = n-1;
    364 	fakebuf._file = -1;
    365 	_doprnt(fmt, args, &fakebuf);
    366 	fakebuf._cnt++;
    367 	putc('\0', &fakebuf);
    368 	if (fakebuf._cnt<0)
    369 	    fakebuf._cnt = 0;
    370 	return (n-fakebuf._cnt-1);
    371 #else
    372 	(void) vsprintf(s, fmt, args);
    373 	return strlen(s);
    374 #endif
    375 }
    376 
    377 int
    378 snprintf(char *s, size_t n, const char *fmt, ...)
    379 {
    380 	va_list ap;
    381 	int rv;
    382 
    383 	va_start(ap, fmt);
    384 	rv = vsnprintf(s, n, fmt, ap);
    385 	va_end(ap);
    386 	return rv;
    387 }
    388 
    389 #if !defined(MAKE_NATIVE) && !defined(HAVE_STRFTIME)
    390 size_t
    391 strftime(char *buf, size_t len, const char *fmt, const struct tm *tm)
    392 {
    393 	static char months[][4] = {
    394 		"Jan", "Feb", "Mar", "Apr", "May", "Jun",
    395 		"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
    396 	};
    397 
    398 	size_t s;
    399 	char *b = buf;
    400 
    401 	while (*fmt) {
    402 		if (len == 0)
    403 			return buf - b;
    404 		if (*fmt != '%') {
    405 			*buf++ = *fmt++;
    406 			len--;
    407 			continue;
    408 		}
    409 		switch (*fmt++) {
    410 		case '%':
    411 			*buf++ = '%';
    412 			len--;
    413 			if (len == 0) return buf - b;
    414 			/*FALLTHROUGH*/
    415 		case '\0':
    416 			*buf = '%';
    417 			s = 1;
    418 			break;
    419 		case 'k':
    420 			s = snprintf(buf, len, "%d", tm->tm_hour);
    421 			break;
    422 		case 'M':
    423 			s = snprintf(buf, len, "%02d", tm->tm_min);
    424 			break;
    425 		case 'S':
    426 			s = snprintf(buf, len, "%02d", tm->tm_sec);
    427 			break;
    428 		case 'b':
    429 			if (tm->tm_mon >= 12)
    430 				return buf - b;
    431 			s = snprintf(buf, len, "%s", months[tm->tm_mon]);
    432 			break;
    433 		case 'd':
    434 			s = snprintf(buf, len, "%s", tm->tm_mday);
    435 			break;
    436 		case 'Y':
    437 			s = snprintf(buf, len, "%s", 1900 + tm->tm_year);
    438 			break;
    439 		default:
    440 			s = snprintf(buf, len, "Unsupported format %c",
    441 			    fmt[-1]);
    442 			break;
    443 		}
    444 		buf += s;
    445 		len -= s;
    446 	}
    447 }
    448 #endif
    449 #endif
    450