1 /* $NetBSD: util.c,v 1.20 1999/03/19 16:11:02 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.20 1999/03/19 16:11:02 christos Exp $"; 9 #else 10 #include <sys/cdefs.h> 11 #ifndef lint 12 __RCSID("$NetBSD: util.c,v 1.20 1999/03/19 16:11:02 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 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) sprintf(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) sprintf(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) sprintf(pathname, 231 "getwd: Cannot stat directory \"%s\" (%s)", 232 nextpathptr, strerror(errno)); 233 return (NULL); 234 } 235 if ((dp = opendir(nextpathptr)) == NULL) { 236 (void) sprintf(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) sprintf(pathname, "getwd: Cannot stat \"%s\" (%s)", 260 d->d_name, strerror(errno)); 261 (void) closedir(dp); 262 return (NULL); 263 } 264 /* check if we found it yet */ 265 if (st_next.st_ino == st_cur.st_ino && 266 DEV_DEV_COMPARE(st_next.st_dev, st_cur.st_dev)) 267 break; 268 } 269 } 270 if (d == NULL) { 271 (void) sprintf(pathname, "getwd: Cannot find \".\" in \"..\""); 272 (void) closedir(dp); 273 return (NULL); 274 } 275 st_cur = st_dotdot; 276 pathptr = strrcpy(pathptr, d->d_name); 277 pathptr = strrcpy(pathptr, "/"); 278 nextpathptr = strrcpy(nextpathptr, "../"); 279 (void) closedir(dp); 280 *cur_name_add = '\0'; 281 } 282 } /* end getwd */ 283 284 285 char *sys_siglist[] = { 286 "Signal 0", 287 "Hangup", /* SIGHUP */ 288 "Interrupt", /* SIGINT */ 289 "Quit", /* SIGQUIT */ 290 "Illegal instruction", /* SIGILL */ 291 "Trace/BPT trap", /* SIGTRAP */ 292 "IOT trap", /* SIGIOT */ 293 "EMT trap", /* SIGEMT */ 294 "Floating point exception", /* SIGFPE */ 295 "Killed", /* SIGKILL */ 296 "Bus error", /* SIGBUS */ 297 "Segmentation fault", /* SIGSEGV */ 298 "Bad system call", /* SIGSYS */ 299 "Broken pipe", /* SIGPIPE */ 300 "Alarm clock", /* SIGALRM */ 301 "Terminated", /* SIGTERM */ 302 "User defined signal 1", /* SIGUSR1 */ 303 "User defined signal 2", /* SIGUSR2 */ 304 "Child exited", /* SIGCLD */ 305 "Power-fail restart", /* SIGPWR */ 306 "Virtual timer expired", /* SIGVTALRM */ 307 "Profiling timer expired", /* SIGPROF */ 308 "I/O possible", /* SIGIO */ 309 "Window size changes", /* SIGWINDOW */ 310 "Stopped (signal)", /* SIGSTOP */ 311 "Stopped", /* SIGTSTP */ 312 "Continued", /* SIGCONT */ 313 "Stopped (tty input)", /* SIGTTIN */ 314 "Stopped (tty output)", /* SIGTTOU */ 315 "Urgent I/O condition", /* SIGURG */ 316 "Remote lock lost (NFS)", /* SIGLOST */ 317 "Signal 31", /* reserved */ 318 "DIL signal" /* SIGDIL */ 319 }; 320 321 int 322 utimes(file, tvp) 323 char *file; 324 struct timeval tvp[2]; 325 { 326 struct utimbuf t; 327 328 t.actime = tvp[0].tv_sec; 329 t.modtime = tvp[1].tv_sec; 330 return(utime(file, &t)); 331 } 332 333 334 #endif /* __hpux */ 335 336 #if defined(sun) && defined(__svr4__) 337 #include <signal.h> 338 339 /* turn into bsd signals */ 340 void (* 341 signal(s, a)) __P((int)) 342 int s; 343 void (*a) __P((int)); 344 { 345 struct sigaction sa, osa; 346 347 sa.sa_handler = a; 348 sigemptyset(&sa.sa_mask); 349 sa.sa_flags = SA_RESTART; 350 351 if (sigaction(s, &sa, &osa) == -1) 352 return SIG_ERR; 353 else 354 return osa.sa_handler; 355 } 356 357 #endif 358 359 #ifndef BSD4_4 360 #ifdef __STDC__ 361 #include <stdarg.h> 362 #else 363 #include <varargs.h> 364 #endif 365 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 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 #ifndef __SVR4 433 int 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