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