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