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