util.c revision 1.30 1 /* $NetBSD: util.c,v 1.30 2002/03/02 03:56:02 tv Exp $ */
2
3 /*
4 * Missing stuff from OS's
5 */
6
7 #ifdef MAKE_BOOTSTRAP
8 static char rcsid[] = "$NetBSD: util.c,v 1.30 2002/03/02 03:56:02 tv Exp $";
9 #else
10 #include <sys/cdefs.h>
11 #ifndef lint
12 __RCSID("$NetBSD: util.c,v 1.30 2002/03/02 03:56:02 tv 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 void
177 srandom(seed)
178 long seed;
179 {
180 srand48(seed);
181 }
182
183 long
184 random()
185 {
186 return lrand48();
187 }
188
189 /* turn into bsd signals */
190 void (*
191 signal(s, a)) __P((int))
192 int s;
193 void (*a) __P((int));
194 {
195 struct sigvec osv, sv;
196
197 (void) sigvector(s, (struct sigvec *) 0, &osv);
198 sv = osv;
199 sv.sv_handler = a;
200 #ifdef SV_BSDSIG
201 sv.sv_flags = SV_BSDSIG;
202 #endif
203
204 if (sigvector(s, &sv, (struct sigvec *) 0) == -1)
205 return (BADSIG);
206 return (osv.sv_handler);
207 }
208
209 int
210 utimes(file, tvp)
211 char *file;
212 struct timeval tvp[2];
213 {
214 struct utimbuf t;
215
216 t.actime = tvp[0].tv_sec;
217 t.modtime = tvp[1].tv_sec;
218 return(utime(file, &t));
219 }
220
221 #if !defined(BSD) && !defined(d_fileno)
222 # define d_fileno d_ino
223 #endif
224
225 #ifndef DEV_DEV_COMPARE
226 # define DEV_DEV_COMPARE(a, b) ((a) == (b))
227 #endif
228 #define ISDOT(c) ((c)[0] == '.' && (((c)[1] == '\0') || ((c)[1] == '/')))
229 #define ISDOTDOT(c) ((c)[0] == '.' && ISDOT(&((c)[1])))
230
231 char *
232 getwd(pathname)
233 char *pathname;
234 {
235 DIR *dp;
236 struct dirent *d;
237 extern int errno;
238
239 struct stat st_root, st_cur, st_next, st_dotdot;
240 char pathbuf[MAXPATHLEN], nextpathbuf[MAXPATHLEN * 2];
241 char *pathptr, *nextpathptr, *cur_name_add;
242
243 /* find the inode of root */
244 if (stat("/", &st_root) == -1) {
245 (void) snprintf(pathname, sizeof(pathname),
246 "getwd: Cannot stat \"/\" (%s)", strerror(errno));
247 return (NULL);
248 }
249 pathbuf[MAXPATHLEN - 1] = '\0';
250 pathptr = &pathbuf[MAXPATHLEN - 1];
251 nextpathbuf[MAXPATHLEN - 1] = '\0';
252 cur_name_add = nextpathptr = &nextpathbuf[MAXPATHLEN - 1];
253
254 /* find the inode of the current directory */
255 if (lstat(".", &st_cur) == -1) {
256 (void) snprintf(pathname, sizeof(pathname),
257 "getwd: Cannot stat \".\" (%s)", strerror(errno));
258 return (NULL);
259 }
260 nextpathptr = strrcpy(nextpathptr, "../");
261
262 /* Descend to root */
263 for (;;) {
264
265 /* look if we found root yet */
266 if (st_cur.st_ino == st_root.st_ino &&
267 DEV_DEV_COMPARE(st_cur.st_dev, st_root.st_dev)) {
268 (void) strcpy(pathname, *pathptr != '/' ? "/" : pathptr);
269 return (pathname);
270 }
271
272 /* open the parent directory */
273 if (stat(nextpathptr, &st_dotdot) == -1) {
274 (void) snprintf(pathname, sizeof(pathname),
275 "getwd: Cannot stat directory \"%s\" (%s)",
276 nextpathptr, strerror(errno));
277 return (NULL);
278 }
279 if ((dp = opendir(nextpathptr)) == NULL) {
280 (void) snprintf(pathname, sizeof(pathname),
281 "getwd: Cannot open directory \"%s\" (%s)",
282 nextpathptr, strerror(errno));
283 return (NULL);
284 }
285
286 /* look in the parent for the entry with the same inode */
287 if (DEV_DEV_COMPARE(st_dotdot.st_dev, st_cur.st_dev)) {
288 /* Parent has same device. No need to stat every member */
289 for (d = readdir(dp); d != NULL; d = readdir(dp))
290 if (d->d_fileno == st_cur.st_ino)
291 break;
292 }
293 else {
294 /*
295 * Parent has a different device. This is a mount point so we
296 * need to stat every member
297 */
298 for (d = readdir(dp); d != NULL; d = readdir(dp)) {
299 if (ISDOT(d->d_name) || ISDOTDOT(d->d_name))
300 continue;
301 (void) strcpy(cur_name_add, d->d_name);
302 if (lstat(nextpathptr, &st_next) == -1) {
303 (void) snprintf(pathname, sizeof(pathname),
304 "getwd: Cannot stat \"%s\" (%s)",
305 d->d_name, strerror(errno));
306 (void) closedir(dp);
307 return (NULL);
308 }
309 /* check if we found it yet */
310 if (st_next.st_ino == st_cur.st_ino &&
311 DEV_DEV_COMPARE(st_next.st_dev, st_cur.st_dev))
312 break;
313 }
314 }
315 if (d == NULL) {
316 (void) snprintf(pathname, sizeof(pathname),
317 "getwd: Cannot find \".\" in \"..\"");
318 (void) closedir(dp);
319 return (NULL);
320 }
321 st_cur = st_dotdot;
322 pathptr = strrcpy(pathptr, d->d_name);
323 pathptr = strrcpy(pathptr, "/");
324 nextpathptr = strrcpy(nextpathptr, "../");
325 (void) closedir(dp);
326 *cur_name_add = '\0';
327 }
328 } /* end getwd */
329 #endif /* __hpux */
330
331 #if defined(sun) && defined(__svr4__)
332 #include <signal.h>
333
334 /* turn into bsd signals */
335 void (*
336 signal(s, a)) __P((int))
337 int s;
338 void (*a) __P((int));
339 {
340 struct sigaction sa, osa;
341
342 sa.sa_handler = a;
343 sigemptyset(&sa.sa_mask);
344 sa.sa_flags = SA_RESTART;
345
346 if (sigaction(s, &sa, &osa) == -1)
347 return SIG_ERR;
348 else
349 return osa.sa_handler;
350 }
351 #endif
352
353 #if defined(MAKE_BOOTSTRAP) && !defined(HAVE_VSNPRINTF)
354 #ifdef __STDC__
355 #include <stdarg.h>
356 #else
357 #include <varargs.h>
358 #endif
359
360 #if !defined(__osf__)
361 #ifdef _IOSTRG
362 #define STRFLAG (_IOSTRG|_IOWRT) /* no _IOWRT: avoid stdio bug */
363 #else
364 #if 0
365 #define STRFLAG (_IOREAD) /* XXX: Assume svr4 stdio */
366 #endif
367 #endif /* _IOSTRG */
368 #endif /* __osf__ */
369
370 int
371 vsnprintf(s, n, fmt, args)
372 char *s;
373 size_t n;
374 const char *fmt;
375 va_list args;
376 {
377 #ifdef STRFLAG
378 FILE fakebuf;
379
380 fakebuf._flag = STRFLAG;
381 /*
382 * Some os's are char * _ptr, others are unsigned char *_ptr...
383 * We cast to void * to make everyone happy.
384 */
385 fakebuf._ptr = (void *) s;
386 fakebuf._cnt = n-1;
387 fakebuf._file = -1;
388 _doprnt(fmt, args, &fakebuf);
389 fakebuf._cnt++;
390 putc('\0', &fakebuf);
391 if (fakebuf._cnt<0)
392 fakebuf._cnt = 0;
393 return (n-fakebuf._cnt-1);
394 #else
395 (void) vsprintf(s, fmt, args);
396 return strlen(s);
397 #endif
398 }
399
400 int
401 #ifdef __STDC__
402 snprintf(char *s, size_t n, const char *fmt, ...)
403 #else
404 snprintf(va_alist)
405 va_dcl
406 #endif
407 {
408 va_list ap;
409 int rv;
410 #ifdef __STDC__
411 va_start(ap, fmt);
412 #else
413 char *s;
414 size_t n;
415 const char *fmt;
416
417 va_start(ap);
418
419 s = va_arg(ap, char *);
420 n = va_arg(ap, size_t);
421 fmt = va_arg(ap, const char *);
422 #endif
423 rv = vsnprintf(s, n, fmt, ap);
424 va_end(ap);
425 return rv;
426 }
427
428 #if defined(MAKE_BOOTSTRAP) && !defined(HAVE_STRFTIME)
429 size_t
430 strftime(buf, len, fmt, tm)
431 char *buf;
432 size_t len;
433 const char *fmt;
434 const struct tm *tm;
435 {
436 static char months[][4] = {
437 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
438 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
439 };
440
441 size_t s;
442 char *b = buf;
443
444 while (*fmt) {
445 if (len == 0)
446 return buf - b;
447 if (*fmt != '%') {
448 *buf++ = *fmt++;
449 len--;
450 continue;
451 }
452 switch (*fmt++) {
453 case '%':
454 *buf++ = '%';
455 len--;
456 if (len == 0) return buf - b;
457 /*FALLTHROUGH*/
458 case '\0':
459 *buf = '%';
460 s = 1;
461 break;
462 case 'k':
463 s = snprintf(buf, len, "%d", tm->tm_hour);
464 break;
465 case 'M':
466 s = snprintf(buf, len, "%02d", tm->tm_min);
467 break;
468 case 'S':
469 s = snprintf(buf, len, "%02d", tm->tm_sec);
470 break;
471 case 'b':
472 if (tm->tm_mon >= 12)
473 return buf - b;
474 s = snprintf(buf, len, "%s", months[tm->tm_mon]);
475 break;
476 case 'd':
477 s = snprintf(buf, len, "%s", tm->tm_mday);
478 break;
479 case 'Y':
480 s = snprintf(buf, len, "%s", 1900 + tm->tm_year);
481 break;
482 default:
483 s = snprintf(buf, len, "Unsupported format %c",
484 fmt[-1]);
485 break;
486 }
487 buf += s;
488 len -= s;
489 }
490 }
491 #endif
492 #endif
493