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