1 /* $NetBSD: util.c,v 1.19 1998/11/06 23:31:09 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.19 1998/11/06 23:31:09 christos Exp $"; 9 #else 10 #include <sys/cdefs.h> 11 #ifndef lint 12 __RCSID("$NetBSD: util.c,v 1.19 1998/11/06 23:31:09 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 sprintf(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 if ((p = malloc(len)) == NULL) 66 return NULL; 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*) malloc(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) sprintf(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) sprintf(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) sprintf(pathname, 232 "getwd: Cannot stat directory \"%s\" (%s)", 233 nextpathptr, strerror(errno)); 234 return (NULL); 235 } 236 if ((dp = opendir(nextpathptr)) == NULL) { 237 (void) sprintf(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) sprintf(pathname, "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) sprintf(pathname, "getwd: Cannot find \".\" in \"..\""); 273 (void) closedir(dp); 274 return (NULL); 275 } 276 st_cur = st_dotdot; 277 pathptr = strrcpy(pathptr, d->d_name); 278 pathptr = strrcpy(pathptr, "/"); 279 nextpathptr = strrcpy(nextpathptr, "../"); 280 (void) closedir(dp); 281 *cur_name_add = '\0'; 282 } 283 } /* end getwd */ 284 285 286 char *sys_siglist[] = { 287 "Signal 0", 288 "Hangup", /* SIGHUP */ 289 "Interrupt", /* SIGINT */ 290 "Quit", /* SIGQUIT */ 291 "Illegal instruction", /* SIGILL */ 292 "Trace/BPT trap", /* SIGTRAP */ 293 "IOT trap", /* SIGIOT */ 294 "EMT trap", /* SIGEMT */ 295 "Floating point exception", /* SIGFPE */ 296 "Killed", /* SIGKILL */ 297 "Bus error", /* SIGBUS */ 298 "Segmentation fault", /* SIGSEGV */ 299 "Bad system call", /* SIGSYS */ 300 "Broken pipe", /* SIGPIPE */ 301 "Alarm clock", /* SIGALRM */ 302 "Terminated", /* SIGTERM */ 303 "User defined signal 1", /* SIGUSR1 */ 304 "User defined signal 2", /* SIGUSR2 */ 305 "Child exited", /* SIGCLD */ 306 "Power-fail restart", /* SIGPWR */ 307 "Virtual timer expired", /* SIGVTALRM */ 308 "Profiling timer expired", /* SIGPROF */ 309 "I/O possible", /* SIGIO */ 310 "Window size changes", /* SIGWINDOW */ 311 "Stopped (signal)", /* SIGSTOP */ 312 "Stopped", /* SIGTSTP */ 313 "Continued", /* SIGCONT */ 314 "Stopped (tty input)", /* SIGTTIN */ 315 "Stopped (tty output)", /* SIGTTOU */ 316 "Urgent I/O condition", /* SIGURG */ 317 "Remote lock lost (NFS)", /* SIGLOST */ 318 "Signal 31", /* reserved */ 319 "DIL signal" /* SIGDIL */ 320 }; 321 322 int 323 utimes(file, tvp) 324 char *file; 325 struct timeval tvp[2]; 326 { 327 struct utimbuf t; 328 329 t.actime = tvp[0].tv_sec; 330 t.modtime = tvp[1].tv_sec; 331 return(utime(file, &t)); 332 } 333 334 335 #endif /* __hpux */ 336 337 #if defined(sun) && defined(__svr4__) 338 #include <signal.h> 339 340 /* turn into bsd signals */ 341 void (* 342 signal(s, a)) __P((int)) 343 int s; 344 void (*a) __P((int)); 345 { 346 struct sigaction sa, osa; 347 348 sa.sa_handler = a; 349 sigemptyset(&sa.sa_mask); 350 sa.sa_flags = SA_RESTART; 351 352 if (sigaction(s, &sa, &osa) == -1) 353 return SIG_ERR; 354 else 355 return osa.sa_handler; 356 } 357 358 #endif 359 360 #ifndef BSD4_4 361 #ifdef __STDC__ 362 #include <stdarg.h> 363 #else 364 #include <varargs.h> 365 #endif 366 367 #ifdef _IOSTRG 368 #define STRFLAG (_IOSTRG|_IOWRT) /* no _IOWRT: avoid stdio bug */ 369 #else 370 #if 0 371 #define STRFLAG (_IOREAD) /* XXX: Assume svr4 stdio */ 372 #endif 373 #endif 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 #ifndef __SVR4 434 int 435 strftime(buf, len, fmt, tm) 436 char *buf; 437 size_t len; 438 const char *fmt; 439 const struct tm *tm; 440 { 441 static char months[][4] = { 442 "Jan", "Feb", "Mar", "Apr", "May", "Jun", 443 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" 444 }; 445 446 size_t s; 447 char *b = buf; 448 449 while (*fmt) { 450 if (len == 0) 451 return buf - b; 452 if (*fmt != '%') { 453 *buf++ = *fmt++; 454 len--; 455 continue; 456 } 457 switch (*fmt++) { 458 case '%': 459 *buf++ = '%'; 460 len--; 461 if (len == 0) return buf - b; 462 /*FALLTHROUGH*/ 463 case '\0': 464 *buf = '%'; 465 s = 1; 466 break; 467 case 'k': 468 s = snprintf(buf, len, "%d", tm->tm_hour); 469 break; 470 case 'M': 471 s = snprintf(buf, len, "%02d", tm->tm_min); 472 break; 473 case 'S': 474 s = snprintf(buf, len, "%02d", tm->tm_sec); 475 break; 476 case 'b': 477 if (tm->tm_mon >= 12) 478 return buf - b; 479 s = snprintf(buf, len, "%s", months[tm->tm_mon]); 480 break; 481 case 'd': 482 s = snprintf(buf, len, "%s", tm->tm_mday); 483 break; 484 case 'Y': 485 s = snprintf(buf, len, "%s", 1900 + tm->tm_year); 486 break; 487 default: 488 s = snprintf(buf, len, "Unsupported format %c", 489 fmt[-1]); 490 break; 491 } 492 buf += s; 493 len -= s; 494 } 495 } 496 #endif 497 #endif 498