1 /* $NetBSD: util.c,v 1.27 2001/12/11 20:37:24 tv Exp $ */ 2 3 /* 4 * Missing stuff from OS's 5 */ 6 7 #ifdef MAKE_BOOTSTRAP 8 static char rcsid[] = "$NetBSD: util.c,v 1.27 2001/12/11 20:37:24 tv Exp $"; 9 #else 10 #include <sys/cdefs.h> 11 #ifndef lint 12 __RCSID("$NetBSD: util.c,v 1.27 2001/12/11 20:37:24 tv 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 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 #ifdef ultrix 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 69 #endif 70 71 #if defined(sun) || defined(__hpux__) || defined(__sgi) || defined(__hpux) 72 73 int 74 setenv(name, value, dum) 75 const char *name; 76 const char *value; 77 int dum; 78 { 79 register char *p; 80 int len = strlen(name) + strlen(value) + 2; /* = \0 */ 81 char *ptr = (char*) emalloc(len); 82 83 (void) dum; 84 85 if (ptr == NULL) 86 return -1; 87 88 p = ptr; 89 90 while (*name) 91 *p++ = *name++; 92 93 *p++ = '='; 94 95 while (*value) 96 *p++ = *value++; 97 98 *p = '\0'; 99 100 len = putenv(ptr); 101 /* free(ptr); */ 102 return len; 103 } 104 #endif 105 106 #if defined(__hpux__) || defined(__hpux) 107 108 /* strrcpy(): 109 * Like strcpy, going backwards and returning the new pointer 110 */ 111 static char * 112 strrcpy(ptr, str) 113 register char *ptr, *str; 114 { 115 register int len = strlen(str); 116 117 while (len) 118 *--ptr = str[--len]; 119 120 return (ptr); 121 } /* end strrcpy */ 122 123 char *sys_siglist[] = { 124 "Signal 0", 125 "Hangup", /* SIGHUP */ 126 "Interrupt", /* SIGINT */ 127 "Quit", /* SIGQUIT */ 128 "Illegal instruction", /* SIGILL */ 129 "Trace/BPT trap", /* SIGTRAP */ 130 "IOT trap", /* SIGIOT */ 131 "EMT trap", /* SIGEMT */ 132 "Floating point exception", /* SIGFPE */ 133 "Killed", /* SIGKILL */ 134 "Bus error", /* SIGBUS */ 135 "Segmentation fault", /* SIGSEGV */ 136 "Bad system call", /* SIGSYS */ 137 "Broken pipe", /* SIGPIPE */ 138 "Alarm clock", /* SIGALRM */ 139 "Terminated", /* SIGTERM */ 140 "User defined signal 1", /* SIGUSR1 */ 141 "User defined signal 2", /* SIGUSR2 */ 142 "Child exited", /* SIGCLD */ 143 "Power-fail restart", /* SIGPWR */ 144 "Virtual timer expired", /* SIGVTALRM */ 145 "Profiling timer expired", /* SIGPROF */ 146 "I/O possible", /* SIGIO */ 147 "Window size changes", /* SIGWINDOW */ 148 "Stopped (signal)", /* SIGSTOP */ 149 "Stopped", /* SIGTSTP */ 150 "Continued", /* SIGCONT */ 151 "Stopped (tty input)", /* SIGTTIN */ 152 "Stopped (tty output)", /* SIGTTOU */ 153 "Urgent I/O condition", /* SIGURG */ 154 "Remote lock lost (NFS)", /* SIGLOST */ 155 "Signal 31", /* reserved */ 156 "DIL signal" /* SIGDIL */ 157 }; 158 #endif /* __hpux__ || __hpux */ 159 160 161 #ifdef __hpux 162 #include <sys/types.h> 163 #include <sys/param.h> 164 #include <sys/syscall.h> 165 #include <sys/signal.h> 166 #include <sys/stat.h> 167 #include <stdio.h> 168 #include <dirent.h> 169 #include <sys/time.h> 170 #include <time.h> 171 #include <unistd.h> 172 173 int 174 killpg(pid, sig) 175 int pid, sig; 176 { 177 return kill(-pid, sig); 178 } 179 180 void 181 srandom(seed) 182 long seed; 183 { 184 srand48(seed); 185 } 186 187 long 188 random() 189 { 190 return lrand48(); 191 } 192 193 /* turn into bsd signals */ 194 void (* 195 signal(s, a)) __P((int)) 196 int s; 197 void (*a) __P((int)); 198 { 199 struct sigvec osv, sv; 200 201 (void) sigvector(s, (struct sigvec *) 0, &osv); 202 sv = osv; 203 sv.sv_handler = a; 204 #ifdef SV_BSDSIG 205 sv.sv_flags = SV_BSDSIG; 206 #endif 207 208 if (sigvector(s, &sv, (struct sigvec *) 0) == -1) 209 return (BADSIG); 210 return (osv.sv_handler); 211 } 212 213 int 214 utimes(file, tvp) 215 char *file; 216 struct timeval tvp[2]; 217 { 218 struct utimbuf t; 219 220 t.actime = tvp[0].tv_sec; 221 t.modtime = tvp[1].tv_sec; 222 return(utime(file, &t)); 223 } 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 356 #endif 357 358 #if !defined(BSD4_4) && !defined(SUNOS_5_7) && !defined(__linux__) 359 #ifdef __STDC__ 360 #include <stdarg.h> 361 #else 362 #include <varargs.h> 363 #endif 364 365 #if !defined(__osf__) 366 #ifdef _IOSTRG 367 #define STRFLAG (_IOSTRG|_IOWRT) /* no _IOWRT: avoid stdio bug */ 368 #else 369 #if 0 370 #define STRFLAG (_IOREAD) /* XXX: Assume svr4 stdio */ 371 #endif 372 #endif /* _IOSTRG */ 373 #endif /* __osf__ */ 374 375 int 376 vsnprintf(s, n, fmt, args) 377 char *s; 378 size_t n; 379 const char *fmt; 380 va_list args; 381 { 382 #ifdef STRFLAG 383 FILE fakebuf; 384 385 fakebuf._flag = STRFLAG; 386 /* 387 * Some os's are char * _ptr, others are unsigned char *_ptr... 388 * We cast to void * to make everyone happy. 389 */ 390 fakebuf._ptr = (void *) s; 391 fakebuf._cnt = n-1; 392 fakebuf._file = -1; 393 _doprnt(fmt, args, &fakebuf); 394 fakebuf._cnt++; 395 putc('\0', &fakebuf); 396 if (fakebuf._cnt<0) 397 fakebuf._cnt = 0; 398 return (n-fakebuf._cnt-1); 399 #else 400 (void) vsprintf(s, fmt, args); 401 return strlen(s); 402 #endif 403 } 404 405 int 406 #ifdef __STDC__ 407 snprintf(char *s, size_t n, const char *fmt, ...) 408 #else 409 snprintf(va_alist) 410 va_dcl 411 #endif 412 { 413 va_list ap; 414 int rv; 415 #ifdef __STDC__ 416 va_start(ap, fmt); 417 #else 418 char *s; 419 size_t n; 420 const char *fmt; 421 422 va_start(ap); 423 424 s = va_arg(ap, char *); 425 n = va_arg(ap, size_t); 426 fmt = va_arg(ap, const char *); 427 #endif 428 rv = vsnprintf(s, n, fmt, ap); 429 va_end(ap); 430 return rv; 431 } 432 433 #if !defined(__SVR4) && !defined(__linux__) && !defined(ultrix) \ 434 && !defined(__sgi) && !defined(__osf__) && !defined(__hpux__) \ 435 && !defined(__CYGWIN__) 436 437 int 438 strftime(buf, len, fmt, tm) 439 char *buf; 440 size_t len; 441 const char *fmt; 442 const struct tm *tm; 443 { 444 static char months[][4] = { 445 "Jan", "Feb", "Mar", "Apr", "May", "Jun", 446 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" 447 }; 448 449 size_t s; 450 char *b = buf; 451 452 while (*fmt) { 453 if (len == 0) 454 return buf - b; 455 if (*fmt != '%') { 456 *buf++ = *fmt++; 457 len--; 458 continue; 459 } 460 switch (*fmt++) { 461 case '%': 462 *buf++ = '%'; 463 len--; 464 if (len == 0) return buf - b; 465 /*FALLTHROUGH*/ 466 case '\0': 467 *buf = '%'; 468 s = 1; 469 break; 470 case 'k': 471 s = snprintf(buf, len, "%d", tm->tm_hour); 472 break; 473 case 'M': 474 s = snprintf(buf, len, "%02d", tm->tm_min); 475 break; 476 case 'S': 477 s = snprintf(buf, len, "%02d", tm->tm_sec); 478 break; 479 case 'b': 480 if (tm->tm_mon >= 12) 481 return buf - b; 482 s = snprintf(buf, len, "%s", months[tm->tm_mon]); 483 break; 484 case 'd': 485 s = snprintf(buf, len, "%s", tm->tm_mday); 486 break; 487 case 'Y': 488 s = snprintf(buf, len, "%s", 1900 + tm->tm_year); 489 break; 490 default: 491 s = snprintf(buf, len, "Unsupported format %c", 492 fmt[-1]); 493 break; 494 } 495 buf += s; 496 len -= s; 497 } 498 } 499 #endif 500 #endif 501