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