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