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