Annotation of src/usr.bin/make/util.c, Revision 1.26
1.26 ! guenther 1: /* $OpenBSD: util.c,v 1.25 2010/07/19 19:46:44 espie Exp $ */
1.6 millert 2: /* $NetBSD: util.c,v 1.10 1996/12/31 17:56:04 christos Exp $ */
1.1 deraadt 3:
4: /*
1.16 espie 5: * Copyright (c) 2001 Marc Espie.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: *
16: * THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT AND CONTRIBUTORS
17: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OPENBSD
20: * PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27: */
28: /*
1.1 deraadt 29: * Missing stuff from OS's
30: */
31:
1.16 espie 32: #include <sys/param.h>
1.1 deraadt 33: #include <stdio.h>
1.16 espie 34: #include "config.h"
35: #include "defines.h"
1.13 espie 36:
1.1 deraadt 37: #ifdef sun
38:
39: extern int errno, sys_nerr;
40: extern char *sys_errlist[];
41:
42: char *
1.5 millert 43: strerror(e)
44: int e;
1.1 deraadt 45: {
46: static char buf[100];
47: if (e < 0 || e >= sys_nerr) {
1.18 deraadt 48: snprintf(buf, sizeof buf, "Unknown error %d", e);
1.1 deraadt 49: return buf;
50: }
51: else
52: return sys_errlist[e];
53: }
54: #endif
55:
1.4 briggs 56: #ifdef ultrix
57: #include <string.h>
58:
59: /* strdup
60: *
61: * Make a duplicate of a string.
62: * For systems which lack this function.
63: */
64: char *
65: strdup(str)
66: const char *str;
67: {
68: size_t len;
1.5 millert 69: char *p;
1.4 briggs 70:
71: if (str == NULL)
72: return NULL;
73: len = strlen(str) + 1;
74: if ((p = malloc(len)) == NULL)
75: return NULL;
76:
77: return memcpy(p, str, len);
78: }
79:
80: #endif
81:
82: #if defined(sun) || defined(__hpux) || defined(__sgi)
1.1 deraadt 83:
84: int
85: setenv(name, value, dum)
1.5 millert 86: const char *name;
1.1 deraadt 87: const char *value;
88: int dum;
89: {
1.14 espie 90: char *p;
1.1 deraadt 91: int len = strlen(name) + strlen(value) + 2; /* = \0 */
1.14 espie 92: char *ptr = (char*)malloc(len);
1.1 deraadt 93:
94: if (ptr == NULL)
95: return -1;
1.5 millert 96:
1.1 deraadt 97: p = ptr;
98:
1.5 millert 99: while (*name)
1.1 deraadt 100: *p++ = *name++;
101:
102: *p++ = '=';
103:
1.5 millert 104: while (*value)
1.1 deraadt 105: *p++ = *value++;
106:
107: *p = '\0';
108:
109: len = putenv(ptr);
110: /* free(ptr); */
111: return len;
112: }
113: #endif
114:
115: #ifdef __hpux
116: #include <sys/types.h>
117: #include <sys/param.h>
118: #include <sys/syscall.h>
119: #include <sys/signal.h>
120: #include <sys/stat.h>
121: #include <stdio.h>
122: #include <dirent.h>
123: #include <sys/time.h>
124: #include <time.h>
125: #include <unistd.h>
126:
127:
128: int
129: killpg(pid, sig)
130: int pid, sig;
131: {
132: return kill(-pid, sig);
133: }
134:
135: void
136: srandom(seed)
137: long seed;
138: {
139: srand48(seed);
140: }
141:
142: long
143: random()
144: {
145: return lrand48();
146: }
147:
148: /* turn into bsd signals */
149: void (*
1.14 espie 150: signal(s, a))()
1.1 deraadt 151: int s;
152: void (*a)();
153: {
154: struct sigvec osv, sv;
155:
1.14 espie 156: (void)sigvector(s, (struct sigvec *)0, &osv);
1.1 deraadt 157: sv = osv;
158: sv.sv_handler = a;
159: #ifdef SV_BSDSIG
160: sv.sv_flags = SV_BSDSIG;
161: #endif
162:
1.14 espie 163: if (sigvector(s, &sv, (struct sigvec *)0) == -1)
164: return SIG_ERR;
165: return osv.sv_handler;
1.1 deraadt 166: }
167:
168: #if !defined(BSD) && !defined(d_fileno)
169: # define d_fileno d_ino
170: #endif
171:
172: #ifndef DEV_DEV_COMPARE
173: # define DEV_DEV_COMPARE(a, b) ((a) == (b))
174: #endif
1.14 espie 175: #define ISDOT(c) ((c)[0] == '.' && ((c)[1] == '\0' || (c)[1] == '/'))
1.1 deraadt 176: #define ISDOTDOT(c) ((c)[0] == '.' && ISDOT(&((c)[1])))
177:
178:
179: /* strrcpy():
180: * Like strcpy, going backwards and returning the new pointer
181: */
182: static char *
183: strrcpy(ptr, str)
1.14 espie 184: char *ptr, *str;
1.1 deraadt 185: {
1.14 espie 186: size_t len = strlen(str);
1.1 deraadt 187:
188: while (len)
189: *--ptr = str[--len];
190:
1.14 espie 191: return ptr;
1.1 deraadt 192: } /* end strrcpy */
193:
194:
195: char *
196: getwd(pathname)
197: char *pathname;
198: {
199: DIR *dp;
200: struct dirent *d;
201: extern int errno;
202:
203: struct stat st_root, st_cur, st_next, st_dotdot;
204: char pathbuf[MAXPATHLEN], nextpathbuf[MAXPATHLEN * 2];
205: char *pathptr, *nextpathptr, *cur_name_add;
206:
207: /* find the inode of root */
208: if (stat("/", &st_root) == -1) {
1.23 espie 209: (void)snprintf(pathname, MAXPATHLEN,
1.18 deraadt 210: "getwd: Cannot stat \"/\" (%s)", strerror(errno));
1.14 espie 211: return NULL;
1.1 deraadt 212: }
213: pathbuf[MAXPATHLEN - 1] = '\0';
214: pathptr = &pathbuf[MAXPATHLEN - 1];
215: nextpathbuf[MAXPATHLEN - 1] = '\0';
216: cur_name_add = nextpathptr = &nextpathbuf[MAXPATHLEN - 1];
217:
218: /* find the inode of the current directory */
219: if (lstat(".", &st_cur) == -1) {
1.19 espie 220: (void)snprintf(pathname, MAXPATHLEN,
1.18 deraadt 221: "getwd: Cannot stat \".\" (%s)", strerror(errno));
1.14 espie 222: return NULL;
1.1 deraadt 223: }
224: nextpathptr = strrcpy(nextpathptr, "../");
225:
226: /* Descend to root */
227: for (;;) {
228:
229: /* look if we found root yet */
230: if (st_cur.st_ino == st_root.st_ino &&
231: DEV_DEV_COMPARE(st_cur.st_dev, st_root.st_dev)) {
1.19 espie 232: (void)strlcpy(pathname, *pathptr != '/' ? "/" : pathptr, MAXPATHLEN);
1.14 espie 233: return pathname;
1.1 deraadt 234: }
235:
236: /* open the parent directory */
237: if (stat(nextpathptr, &st_dotdot) == -1) {
1.19 espie 238: (void)snprintf(pathname, MAXPATHLEN,
1.18 deraadt 239: "getwd: Cannot stat directory \"%s\" (%s)",
240: nextpathptr, strerror(errno));
1.14 espie 241: return NULL;
1.1 deraadt 242: }
243: if ((dp = opendir(nextpathptr)) == NULL) {
1.19 espie 244: (void)snprintf(pathname, MAXPATHLEN,
1.18 deraadt 245: "getwd: Cannot open directory \"%s\" (%s)",
246: nextpathptr, strerror(errno));
1.14 espie 247: return NULL;
1.1 deraadt 248: }
249:
250: /* look in the parent for the entry with the same inode */
251: if (DEV_DEV_COMPARE(st_dotdot.st_dev, st_cur.st_dev)) {
252: /* Parent has same device. No need to stat every member */
1.5 millert 253: for (d = readdir(dp); d != NULL; d = readdir(dp))
1.1 deraadt 254: if (d->d_fileno == st_cur.st_ino)
255: break;
256: }
257: else {
1.5 millert 258: /*
259: * Parent has a different device. This is a mount point so we
260: * need to stat every member
1.1 deraadt 261: */
262: for (d = readdir(dp); d != NULL; d = readdir(dp)) {
263: if (ISDOT(d->d_name) || ISDOTDOT(d->d_name))
264: continue;
1.23 espie 265: (void)strlcpy(cur_name_add, d->d_name,
1.21 millert 266: sizeof(nextpathbuf) MAXPATHLEN - (MAXPATHLEN - 1));
1.1 deraadt 267: if (lstat(nextpathptr, &st_next) == -1) {
1.19 espie 268: (void)snprintf(pathname, MAXPATHLEN,
1.18 deraadt 269: "getwd: Cannot stat \"%s\" (%s)",
270: d->d_name, strerror(errno));
1.14 espie 271: (void)closedir(dp);
272: return NULL;
1.1 deraadt 273: }
274: /* check if we found it yet */
275: if (st_next.st_ino == st_cur.st_ino &&
1.5 millert 276: DEV_DEV_COMPARE(st_next.st_dev, st_cur.st_dev))
1.1 deraadt 277: break;
278: }
279: }
280: if (d == NULL) {
1.19 espie 281: (void)snprintf(pathname, MAXPATHLEN,
1.18 deraadt 282: "getwd: Cannot find \".\" in \"..\"");
1.14 espie 283: (void)closedir(dp);
284: return NULL;
1.1 deraadt 285: }
286: st_cur = st_dotdot;
287: pathptr = strrcpy(pathptr, d->d_name);
288: pathptr = strrcpy(pathptr, "/");
289: nextpathptr = strrcpy(nextpathptr, "../");
1.14 espie 290: (void)closedir(dp);
1.1 deraadt 291: *cur_name_add = '\0';
292: }
293: } /* end getwd */
294:
295:
1.14 espie 296: char *sys_siglist[] = {
297: "Signal 0",
298: "Hangup", /* SIGHUP */
299: "Interrupt", /* SIGINT */
300: "Quit", /* SIGQUIT */
301: "Illegal instruction", /* SIGILL */
302: "Trace/BPT trap", /* SIGTRAP */
303: "IOT trap", /* SIGIOT */
304: "EMT trap", /* SIGEMT */
305: "Floating point exception", /* SIGFPE */
306: "Killed", /* SIGKILL */
307: "Bus error", /* SIGBUS */
308: "Segmentation fault", /* SIGSEGV */
309: "Bad system call", /* SIGSYS */
310: "Broken pipe", /* SIGPIPE */
311: "Alarm clock", /* SIGALRM */
312: "Terminated", /* SIGTERM */
313: "User defined signal 1", /* SIGUSR1 */
314: "User defined signal 2", /* SIGUSR2 */
315: "Child exited", /* SIGCLD */
316: "Power-fail restart", /* SIGPWR */
317: "Virtual timer expired", /* SIGVTALRM */
318: "Profiling timer expired", /* SIGPROF */
319: "I/O possible", /* SIGIO */
320: "Window size changes", /* SIGWINDOW */
321: "Stopped (signal)", /* SIGSTOP */
322: "Stopped", /* SIGTSTP */
323: "Continued", /* SIGCONT */
324: "Stopped (tty input)", /* SIGTTIN */
325: "Stopped (tty output)", /* SIGTTOU */
326: "Urgent I/O condition", /* SIGURG */
327: "Remote lock lost (NFS)", /* SIGLOST */
328: "Signal 31", /* reserved */
329: "DIL signal" /* SIGDIL */
1.1 deraadt 330: };
331:
332: int
333: utimes(file, tvp)
334: char *file;
1.26 ! guenther 335: struct timeval *tvp;
1.1 deraadt 336: {
337: struct utimbuf t;
338:
1.26 ! guenther 339: if (tvp == NULL)
! 340: return utime(file, NULL);
1.1 deraadt 341: t.actime = tvp[0].tv_sec;
342: t.modtime = tvp[1].tv_sec;
1.14 espie 343: return utime(file, &t);
1.1 deraadt 344: }
345:
346:
347: #endif /* __hpux */
1.2 deraadt 348:
349: #if defined(sun) && defined(__svr4__)
350: #include <signal.h>
351:
352: /* turn into bsd signals */
353: void (*
1.14 espie 354: signal(s, a))()
1.2 deraadt 355: int s;
356: void (*a)();
357: {
358: struct sigaction sa, osa;
359:
1.8 deraadt 360: memset(&sa, 0, sizeof sa);
1.2 deraadt 361: sa.sa_handler = a;
362: sigemptyset(&sa.sa_mask);
363: sa.sa_flags = SA_RESTART;
364:
365: if (sigaction(s, &sa, &osa) == -1)
366: return SIG_ERR;
367: else
368: return osa.sa_handler;
369: }
370:
1.6 millert 371: #endif
372:
1.16 espie 373: #ifndef BSD4_4
1.6 millert 374: #include <stdarg.h>
375:
376: #ifdef _IOSTRG
1.14 espie 377: #define STRFLAG (_IOSTRG|_IOWRT) /* no _IOWRT: avoid stdio bug */
1.6 millert 378: #else
1.14 espie 379: #define STRFLAG (_IOREAD) /* XXX: Assume svr4 stdio */
1.6 millert 380: #endif
381:
382: int
383: vsnprintf(s, n, fmt, args)
384: char *s;
385: size_t n;
386: const char *fmt;
387: va_list args;
388: {
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: */
1.14 espie 396: fakebuf._ptr = (void *)s;
1.6 millert 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;
1.14 espie 404: return n-fakebuf._cnt-1;
1.6 millert 405: }
406:
407: int
408: snprintf(char *s, size_t n, const char *fmt, ...)
409: {
410: va_list ap;
411: int rv;
1.17 millert 412:
1.6 millert 413: va_start(ap, fmt);
414: rv = vsnprintf(s, n, fmt, ap);
415: va_end(ap);
416: return rv;
1.11 espie 417: }
418: #endif
419: #ifdef NEED_STRSTR
420: char *
421: strstr(string, substring)
422: const char *string; /* String to search. */
423: const char *substring; /* Substring to find in string */
424: {
425: const char *a, *b;
426:
427: /*
428: * First scan quickly through the two strings looking for a single-
429: * character match. When it's found, then compare the rest of the
430: * substring.
431: */
432:
1.22 espie 433: for (b = substring; *string != 0; string++) {
1.11 espie 434: if (*string != *b)
435: continue;
436: a = string;
437: for (;;) {
438: if (*b == 0)
439: return (char *)string;
440: if (*a++ != *b++)
441: break;
442: }
443: b = substring;
444: }
445: return NULL;
1.12 espie 446: }
447: #endif
448:
449: #ifdef NEED_FGETLN
450: char *
451: fgetln(stream, len)
452: FILE *stream;
453: size_t *len;
454: {
455: static char *buffer = NULL;
456: static size_t buflen = 0;
457:
458: if (buflen == 0) {
1.14 espie 459: buflen = 512;
1.12 espie 460: buffer = emalloc(buflen+1);
461: }
462: if (fgets(buffer, buflen+1, stream) == NULL)
463: return NULL;
464: *len = strlen(buffer);
465: while (*len == buflen && buffer[*len-1] != '\n') {
466: buffer = erealloc(buffer, 2*buflen + 1);
467: if (fgets(buffer + buflen, buflen + 1, stream) == NULL)
468: return NULL;
469: *len += strlen(buffer + buflen);
470: buflen *= 2;
471: }
472: return buffer;
1.6 millert 473: }
1.2 deraadt 474: #endif