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