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