Patrick Welche <prlw1@cam.ac.uk>
[netbsd-mini2440.git] / usr.bin / make / util.c
blobc9b5351c928a23a31cd55d6d4c312c353f8b571b
1 /* $NetBSD: util.c,v 1.47 2008/12/13 15:19:29 dsl Exp $ */
3 /*
4 * Missing stuff from OS's
5 */
7 #ifndef MAKE_NATIVE
8 static char rcsid[] = "$NetBSD: util.c,v 1.47 2008/12/13 15:19:29 dsl Exp $";
9 #else
10 #include <sys/cdefs.h>
11 #ifndef lint
12 __RCSID("$NetBSD: util.c,v 1.47 2008/12/13 15:19:29 dsl Exp $");
13 #endif
14 #endif
16 #include <sys/param.h>
18 #include <errno.h>
19 #include <stdio.h>
20 #include <time.h>
22 #include "make.h"
24 #if !defined(MAKE_NATIVE) && !defined(HAVE_STRERROR)
25 extern int errno, sys_nerr;
26 extern char *sys_errlist[];
28 char *
29 strerror(int e)
31 static char buf[100];
32 if (e < 0 || e >= sys_nerr) {
33 snprintf(buf, sizeof(buf), "Unknown error %d", e);
34 return buf;
36 else
37 return sys_errlist[e];
39 #endif
41 #if !defined(MAKE_NATIVE) && !defined(HAVE_SETENV)
42 extern char **environ;
44 static char *
45 findenv(const char *name, int *offset)
47 size_t i, len;
48 char *p, *q;
50 for (i = 0; (q = environ[i]); i++) {
51 char *p = strchr(q, '=');
52 if (p == NULL)
53 continue;
54 if (strncmp(name, q, len = p - q) == 0) {
55 *offset = i;
56 return q + len + 1;
59 *offset = i;
60 return NULL;
63 int
64 unsetenv(const char *name)
66 char **p;
67 int offset;
69 if (name == NULL || *name == '\0' || strchr(name, '=') != NULL) {
70 errno = EINVAL;
71 return -1;
74 while (findenv(name, &offset)) { /* if set multiple times */
75 for (p = &environ[offset];; ++p)
76 if (!(*p = *(p + 1)))
77 break;
79 return 0;
82 int
83 setenv(const char *name, const char *value, int rewrite)
85 static char **saveenv; /* copy of previously allocated space */
86 char *c, **newenv;
87 const char *cc;
88 size_t l_value, size;
89 int offset;
91 if (name == NULL || value == NULL) {
92 errno = EINVAL;
93 return -1;
96 if (*value == '=') /* no `=' in value */
97 ++value;
98 l_value = strlen(value);
100 /* find if already exists */
101 if ((c = findenv(name, &offset))) {
102 if (!rewrite)
103 return 0;
104 if (strlen(c) >= l_value) /* old larger; copy over */
105 goto copy;
106 } else { /* create new slot */
107 size = sizeof(char *) * (offset + 2);
108 if (saveenv == environ) { /* just increase size */
109 if ((newenv = realloc(saveenv, size)) == NULL)
110 return -1;
111 saveenv = newenv;
112 } else { /* get new space */
114 * We don't free here because we don't know if
115 * the first allocation is valid on all OS's
117 if ((saveenv = malloc(size)) == NULL)
118 return -1;
119 (void)memcpy(saveenv, environ, size - sizeof(char *));
121 environ = saveenv;
122 environ[offset + 1] = NULL;
124 for (cc = name; *cc && *cc != '='; ++cc) /* no `=' in name */
125 continue;
126 size = cc - name;
127 /* name + `=' + value */
128 if ((environ[offset] = malloc(size + l_value + 2)) == NULL)
129 return -1;
130 c = environ[offset];
131 (void)memcpy(c, name, size);
132 c += size;
133 *c++ = '=';
134 copy:
135 (void)memcpy(c, value, l_value + 1);
136 return 0;
139 #ifdef TEST
141 main(int argc, char *argv[])
143 setenv(argv[1], argv[2], 0);
144 printf("%s\n", getenv(argv[1]));
145 unsetenv(argv[1]);
146 printf("%s\n", getenv(argv[1]));
147 return 0;
149 #endif
151 #endif
153 #if defined(__hpux__) || defined(__hpux)
154 /* strrcpy():
155 * Like strcpy, going backwards and returning the new pointer
157 static char *
158 strrcpy(char *ptr, char *str)
160 int len = strlen(str);
162 while (len)
163 *--ptr = str[--len];
165 return (ptr);
166 } /* end strrcpy */
168 char *sys_siglist[] = {
169 "Signal 0",
170 "Hangup", /* SIGHUP */
171 "Interrupt", /* SIGINT */
172 "Quit", /* SIGQUIT */
173 "Illegal instruction", /* SIGILL */
174 "Trace/BPT trap", /* SIGTRAP */
175 "IOT trap", /* SIGIOT */
176 "EMT trap", /* SIGEMT */
177 "Floating point exception", /* SIGFPE */
178 "Killed", /* SIGKILL */
179 "Bus error", /* SIGBUS */
180 "Segmentation fault", /* SIGSEGV */
181 "Bad system call", /* SIGSYS */
182 "Broken pipe", /* SIGPIPE */
183 "Alarm clock", /* SIGALRM */
184 "Terminated", /* SIGTERM */
185 "User defined signal 1", /* SIGUSR1 */
186 "User defined signal 2", /* SIGUSR2 */
187 "Child exited", /* SIGCLD */
188 "Power-fail restart", /* SIGPWR */
189 "Virtual timer expired", /* SIGVTALRM */
190 "Profiling timer expired", /* SIGPROF */
191 "I/O possible", /* SIGIO */
192 "Window size changes", /* SIGWINDOW */
193 "Stopped (signal)", /* SIGSTOP */
194 "Stopped", /* SIGTSTP */
195 "Continued", /* SIGCONT */
196 "Stopped (tty input)", /* SIGTTIN */
197 "Stopped (tty output)", /* SIGTTOU */
198 "Urgent I/O condition", /* SIGURG */
199 "Remote lock lost (NFS)", /* SIGLOST */
200 "Signal 31", /* reserved */
201 "DIL signal" /* SIGDIL */
203 #endif /* __hpux__ || __hpux */
205 #if defined(__hpux__) || defined(__hpux)
206 #include <sys/types.h>
207 #include <sys/syscall.h>
208 #include <sys/signal.h>
209 #include <sys/stat.h>
210 #include <dirent.h>
211 #include <sys/time.h>
212 #include <unistd.h>
215 killpg(int pid, int sig)
217 return kill(-pid, sig);
220 #if !defined(__hpux__) && !defined(__hpux)
221 void
222 srandom(long seed)
224 srand48(seed);
227 long
228 random(void)
230 return lrand48();
232 #endif
234 /* turn into bsd signals */
235 void (*
236 signal(int s, void (*a)(int)))(int)
238 struct sigvec osv, sv;
240 (void)sigvector(s, NULL, &osv);
241 sv = osv;
242 sv.sv_handler = a;
243 #ifdef SV_BSDSIG
244 sv.sv_flags = SV_BSDSIG;
245 #endif
247 if (sigvector(s, &sv, NULL) == -1)
248 return (BADSIG);
249 return (osv.sv_handler);
252 #if !defined(__hpux__) && !defined(__hpux)
254 utimes(char *file, struct timeval tvp[2])
256 struct utimbuf t;
258 t.actime = tvp[0].tv_sec;
259 t.modtime = tvp[1].tv_sec;
260 return(utime(file, &t));
262 #endif
264 #if !defined(BSD) && !defined(d_fileno)
265 # define d_fileno d_ino
266 #endif
268 #ifndef DEV_DEV_COMPARE
269 # define DEV_DEV_COMPARE(a, b) ((a) == (b))
270 #endif
271 #define ISDOT(c) ((c)[0] == '.' && (((c)[1] == '\0') || ((c)[1] == '/')))
272 #define ISDOTDOT(c) ((c)[0] == '.' && ISDOT(&((c)[1])))
274 char *
275 getwd(char *pathname)
277 DIR *dp;
278 struct dirent *d;
279 extern int errno;
281 struct stat st_root, st_cur, st_next, st_dotdot;
282 char pathbuf[MAXPATHLEN], nextpathbuf[MAXPATHLEN * 2];
283 char *pathptr, *nextpathptr, *cur_name_add;
285 /* find the inode of root */
286 if (stat("/", &st_root) == -1) {
287 (void)sprintf(pathname,
288 "getwd: Cannot stat \"/\" (%s)", strerror(errno));
289 return NULL;
291 pathbuf[MAXPATHLEN - 1] = '\0';
292 pathptr = &pathbuf[MAXPATHLEN - 1];
293 nextpathbuf[MAXPATHLEN - 1] = '\0';
294 cur_name_add = nextpathptr = &nextpathbuf[MAXPATHLEN - 1];
296 /* find the inode of the current directory */
297 if (lstat(".", &st_cur) == -1) {
298 (void)sprintf(pathname,
299 "getwd: Cannot stat \".\" (%s)", strerror(errno));
300 return NULL;
302 nextpathptr = strrcpy(nextpathptr, "../");
304 /* Descend to root */
305 for (;;) {
307 /* look if we found root yet */
308 if (st_cur.st_ino == st_root.st_ino &&
309 DEV_DEV_COMPARE(st_cur.st_dev, st_root.st_dev)) {
310 (void)strcpy(pathname, *pathptr != '/' ? "/" : pathptr);
311 return (pathname);
314 /* open the parent directory */
315 if (stat(nextpathptr, &st_dotdot) == -1) {
316 (void)sprintf(pathname,
317 "getwd: Cannot stat directory \"%s\" (%s)",
318 nextpathptr, strerror(errno));
319 return NULL;
321 if ((dp = opendir(nextpathptr)) == NULL) {
322 (void)sprintf(pathname,
323 "getwd: Cannot open directory \"%s\" (%s)",
324 nextpathptr, strerror(errno));
325 return NULL;
328 /* look in the parent for the entry with the same inode */
329 if (DEV_DEV_COMPARE(st_dotdot.st_dev, st_cur.st_dev)) {
330 /* Parent has same device. No need to stat every member */
331 for (d = readdir(dp); d != NULL; d = readdir(dp))
332 if (d->d_fileno == st_cur.st_ino)
333 break;
335 else {
337 * Parent has a different device. This is a mount point so we
338 * need to stat every member
340 for (d = readdir(dp); d != NULL; d = readdir(dp)) {
341 if (ISDOT(d->d_name) || ISDOTDOT(d->d_name))
342 continue;
343 (void)strcpy(cur_name_add, d->d_name);
344 if (lstat(nextpathptr, &st_next) == -1) {
345 (void)sprintf(pathname,
346 "getwd: Cannot stat \"%s\" (%s)",
347 d->d_name, strerror(errno));
348 (void)closedir(dp);
349 return NULL;
351 /* check if we found it yet */
352 if (st_next.st_ino == st_cur.st_ino &&
353 DEV_DEV_COMPARE(st_next.st_dev, st_cur.st_dev))
354 break;
357 if (d == NULL) {
358 (void)sprintf(pathname,
359 "getwd: Cannot find \".\" in \"..\"");
360 (void)closedir(dp);
361 return NULL;
363 st_cur = st_dotdot;
364 pathptr = strrcpy(pathptr, d->d_name);
365 pathptr = strrcpy(pathptr, "/");
366 nextpathptr = strrcpy(nextpathptr, "../");
367 (void)closedir(dp);
368 *cur_name_add = '\0';
370 } /* end getwd */
371 #endif /* __hpux */
373 #if defined(sun) && defined(__svr4__)
374 #include <signal.h>
376 /* turn into bsd signals */
377 void (*
378 signal(int s, void (*a)(int)))(int)
380 struct sigaction sa, osa;
382 sa.sa_handler = a;
383 sigemptyset(&sa.sa_mask);
384 sa.sa_flags = SA_RESTART;
386 if (sigaction(s, &sa, &osa) == -1)
387 return SIG_ERR;
388 else
389 return osa.sa_handler;
391 #endif
393 #if !defined(MAKE_NATIVE) && !defined(HAVE_VSNPRINTF)
394 #include <stdarg.h>
396 #if !defined(__osf__)
397 #ifdef _IOSTRG
398 #define STRFLAG (_IOSTRG|_IOWRT) /* no _IOWRT: avoid stdio bug */
399 #else
400 #if 0
401 #define STRFLAG (_IOREAD) /* XXX: Assume svr4 stdio */
402 #endif
403 #endif /* _IOSTRG */
404 #endif /* __osf__ */
407 vsnprintf(char *s, size_t n, const char *fmt, va_list args)
409 #ifdef STRFLAG
410 FILE fakebuf;
412 fakebuf._flag = STRFLAG;
414 * Some os's are char * _ptr, others are unsigned char *_ptr...
415 * We cast to void * to make everyone happy.
417 fakebuf._ptr = (void *)s;
418 fakebuf._cnt = n-1;
419 fakebuf._file = -1;
420 _doprnt(fmt, args, &fakebuf);
421 fakebuf._cnt++;
422 putc('\0', &fakebuf);
423 if (fakebuf._cnt<0)
424 fakebuf._cnt = 0;
425 return (n-fakebuf._cnt-1);
426 #else
427 (void)vsprintf(s, fmt, args);
428 return strlen(s);
429 #endif
433 snprintf(char *s, size_t n, const char *fmt, ...)
435 va_list ap;
436 int rv;
438 va_start(ap, fmt);
439 rv = vsnprintf(s, n, fmt, ap);
440 va_end(ap);
441 return rv;
444 #if !defined(MAKE_NATIVE) && !defined(HAVE_STRFTIME)
445 size_t
446 strftime(char *buf, size_t len, const char *fmt, const struct tm *tm)
448 static char months[][4] = {
449 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
450 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
453 size_t s;
454 char *b = buf;
456 while (*fmt) {
457 if (len == 0)
458 return buf - b;
459 if (*fmt != '%') {
460 *buf++ = *fmt++;
461 len--;
462 continue;
464 switch (*fmt++) {
465 case '%':
466 *buf++ = '%';
467 len--;
468 if (len == 0) return buf - b;
469 /*FALLTHROUGH*/
470 case '\0':
471 *buf = '%';
472 s = 1;
473 break;
474 case 'k':
475 s = snprintf(buf, len, "%d", tm->tm_hour);
476 break;
477 case 'M':
478 s = snprintf(buf, len, "%02d", tm->tm_min);
479 break;
480 case 'S':
481 s = snprintf(buf, len, "%02d", tm->tm_sec);
482 break;
483 case 'b':
484 if (tm->tm_mon >= 12)
485 return buf - b;
486 s = snprintf(buf, len, "%s", months[tm->tm_mon]);
487 break;
488 case 'd':
489 s = snprintf(buf, len, "%02d", tm->tm_mday);
490 break;
491 case 'Y':
492 s = snprintf(buf, len, "%d", 1900 + tm->tm_year);
493 break;
494 default:
495 s = snprintf(buf, len, "Unsupported format %c",
496 fmt[-1]);
497 break;
499 buf += s;
500 len -= s;
503 #endif
504 #endif