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