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