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