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