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