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