iso9660fs: initialize buffer cache
[minix.git] / usr.bin / make / util.c
blobe50f2a3b4f276dfb06aba25f55ac84fb684e39d1
1 /* $NetBSD: util.c,v 1.51 2011/04/02 07:58:30 mbalmer Exp $ */
3 /*
4 * Missing stuff from OS's
5 */
7 #ifndef MAKE_NATIVE
8 static char rcsid[] = "$NetBSD: util.c,v 1.51 2011/04/02 07:58:30 mbalmer Exp $";
9 #else
10 #include <sys/cdefs.h>
11 #ifndef lint
12 __RCSID("$NetBSD: util.c,v 1.51 2011/04/02 07:58:30 mbalmer Exp $");
13 #endif
14 #endif
16 #include <sys/param.h>
18 #include <errno.h>
19 #include <stdio.h>
20 #include <time.h>
21 #include <signal.h>
23 #include "make.h"
25 #if !defined(MAKE_NATIVE) && !defined(HAVE_STRERROR)
26 extern int errno, sys_nerr;
27 extern char *sys_errlist[];
29 char *
30 strerror(int e)
32 static char buf[100];
33 if (e < 0 || e >= sys_nerr) {
34 snprintf(buf, sizeof(buf), "Unknown error %d", e);
35 return buf;
37 else
38 return sys_errlist[e];
40 #endif
42 #if !defined(MAKE_NATIVE) && !defined(HAVE_SETENV)
43 extern char **environ;
45 static char *
46 findenv(const char *name, int *offset)
48 size_t i, len;
49 char *p, *q;
51 for (i = 0; (q = environ[i]); i++) {
52 p = strchr(q, '=');
53 if (p == NULL)
54 continue;
55 if (strncmp(name, q, len = p - q) == 0) {
56 *offset = i;
57 return q + len + 1;
60 *offset = i;
61 return NULL;
64 int
65 unsetenv(const char *name)
67 char **p;
68 int offset;
70 if (name == NULL || *name == '\0' || strchr(name, '=') != NULL) {
71 errno = EINVAL;
72 return -1;
75 while (findenv(name, &offset)) { /* if set multiple times */
76 for (p = &environ[offset];; ++p)
77 if (!(*p = *(p + 1)))
78 break;
80 return 0;
83 int
84 setenv(const char *name, const char *value, int rewrite)
86 static char **saveenv; /* copy of previously allocated space */
87 char *c, **newenv;
88 const char *cc;
89 size_t l_value, size;
90 int offset;
92 if (name == NULL || value == NULL) {
93 errno = EINVAL;
94 return -1;
97 if (*value == '=') /* no `=' in value */
98 ++value;
99 l_value = strlen(value);
101 /* find if already exists */
102 if ((c = findenv(name, &offset))) {
103 if (!rewrite)
104 return 0;
105 if (strlen(c) >= l_value) /* old larger; copy over */
106 goto copy;
107 } else { /* create new slot */
108 size = sizeof(char *) * (offset + 2);
109 if (saveenv == environ) { /* just increase size */
110 if ((newenv = realloc(saveenv, size)) == NULL)
111 return -1;
112 saveenv = newenv;
113 } else { /* get new space */
115 * We don't free here because we don't know if
116 * the first allocation is valid on all OS's
118 if ((saveenv = malloc(size)) == NULL)
119 return -1;
120 (void)memcpy(saveenv, environ, size - sizeof(char *));
122 environ = saveenv;
123 environ[offset + 1] = NULL;
125 for (cc = name; *cc && *cc != '='; ++cc) /* no `=' in name */
126 continue;
127 size = cc - name;
128 /* name + `=' + value */
129 if ((environ[offset] = malloc(size + l_value + 2)) == NULL)
130 return -1;
131 c = environ[offset];
132 (void)memcpy(c, name, size);
133 c += size;
134 *c++ = '=';
135 copy:
136 (void)memcpy(c, value, l_value + 1);
137 return 0;
140 #ifdef TEST
142 main(int argc, char *argv[])
144 setenv(argv[1], argv[2], 0);
145 printf("%s\n", getenv(argv[1]));
146 unsetenv(argv[1]);
147 printf("%s\n", getenv(argv[1]));
148 return 0;
150 #endif
152 #endif
154 #if defined(__hpux__) || defined(__hpux)
155 /* strrcpy():
156 * Like strcpy, going backwards and returning the new pointer
158 static char *
159 strrcpy(char *ptr, char *str)
161 int len = strlen(str);
163 while (len)
164 *--ptr = str[--len];
166 return (ptr);
167 } /* end strrcpy */
169 char *sys_siglist[] = {
170 "Signal 0",
171 "Hangup", /* SIGHUP */
172 "Interrupt", /* SIGINT */
173 "Quit", /* SIGQUIT */
174 "Illegal instruction", /* SIGILL */
175 "Trace/BPT trap", /* SIGTRAP */
176 "IOT trap", /* SIGIOT */
177 "EMT trap", /* SIGEMT */
178 "Floating point exception", /* SIGFPE */
179 "Killed", /* SIGKILL */
180 "Bus error", /* SIGBUS */
181 "Segmentation fault", /* SIGSEGV */
182 "Bad system call", /* SIGSYS */
183 "Broken pipe", /* SIGPIPE */
184 "Alarm clock", /* SIGALRM */
185 "Terminated", /* SIGTERM */
186 "User defined signal 1", /* SIGUSR1 */
187 "User defined signal 2", /* SIGUSR2 */
188 "Child exited", /* SIGCLD */
189 "Power-fail restart", /* SIGPWR */
190 "Virtual timer expired", /* SIGVTALRM */
191 "Profiling timer expired", /* SIGPROF */
192 "I/O possible", /* SIGIO */
193 "Window size changes", /* SIGWINDOW */
194 "Stopped (signal)", /* SIGSTOP */
195 "Stopped", /* SIGTSTP */
196 "Continued", /* SIGCONT */
197 "Stopped (tty input)", /* SIGTTIN */
198 "Stopped (tty output)", /* SIGTTOU */
199 "Urgent I/O condition", /* SIGURG */
200 "Remote lock lost (NFS)", /* SIGLOST */
201 "Signal 31", /* reserved */
202 "DIL signal" /* SIGDIL */
204 #endif /* __hpux__ || __hpux */
206 #if defined(__hpux__) || defined(__hpux)
207 #include <sys/types.h>
208 #include <sys/syscall.h>
209 #include <sys/signal.h>
210 #include <sys/stat.h>
211 #include <dirent.h>
212 #include <sys/time.h>
213 #include <unistd.h>
216 killpg(int pid, int sig)
218 return kill(-pid, sig);
221 #if !defined(__hpux__) && !defined(__hpux)
222 void
223 srandom(long seed)
225 srand48(seed);
228 long
229 random(void)
231 return lrand48();
233 #endif
235 #if !defined(__hpux__) && !defined(__hpux)
237 utimes(char *file, struct timeval tvp[2])
239 struct utimbuf t;
241 t.actime = tvp[0].tv_sec;
242 t.modtime = tvp[1].tv_sec;
243 return(utime(file, &t));
245 #endif
247 #if !defined(BSD) && !defined(d_fileno)
248 # define d_fileno d_ino
249 #endif
251 #ifndef DEV_DEV_COMPARE
252 # define DEV_DEV_COMPARE(a, b) ((a) == (b))
253 #endif
254 #define ISDOT(c) ((c)[0] == '.' && (((c)[1] == '\0') || ((c)[1] == '/')))
255 #define ISDOTDOT(c) ((c)[0] == '.' && ISDOT(&((c)[1])))
257 char *
258 getwd(char *pathname)
260 DIR *dp;
261 struct dirent *d;
262 extern int errno;
264 struct stat st_root, st_cur, st_next, st_dotdot;
265 char pathbuf[MAXPATHLEN], nextpathbuf[MAXPATHLEN * 2];
266 char *pathptr, *nextpathptr, *cur_name_add;
268 /* find the inode of root */
269 if (stat("/", &st_root) == -1) {
270 (void)sprintf(pathname,
271 "getwd: Cannot stat \"/\" (%s)", strerror(errno));
272 return NULL;
274 pathbuf[MAXPATHLEN - 1] = '\0';
275 pathptr = &pathbuf[MAXPATHLEN - 1];
276 nextpathbuf[MAXPATHLEN - 1] = '\0';
277 cur_name_add = nextpathptr = &nextpathbuf[MAXPATHLEN - 1];
279 /* find the inode of the current directory */
280 if (lstat(".", &st_cur) == -1) {
281 (void)sprintf(pathname,
282 "getwd: Cannot stat \".\" (%s)", strerror(errno));
283 return NULL;
285 nextpathptr = strrcpy(nextpathptr, "../");
287 /* Descend to root */
288 for (;;) {
290 /* look if we found root yet */
291 if (st_cur.st_ino == st_root.st_ino &&
292 DEV_DEV_COMPARE(st_cur.st_dev, st_root.st_dev)) {
293 (void)strcpy(pathname, *pathptr != '/' ? "/" : pathptr);
294 return (pathname);
297 /* open the parent directory */
298 if (stat(nextpathptr, &st_dotdot) == -1) {
299 (void)sprintf(pathname,
300 "getwd: Cannot stat directory \"%s\" (%s)",
301 nextpathptr, strerror(errno));
302 return NULL;
304 if ((dp = opendir(nextpathptr)) == NULL) {
305 (void)sprintf(pathname,
306 "getwd: Cannot open directory \"%s\" (%s)",
307 nextpathptr, strerror(errno));
308 return NULL;
311 /* look in the parent for the entry with the same inode */
312 if (DEV_DEV_COMPARE(st_dotdot.st_dev, st_cur.st_dev)) {
313 /* Parent has same device. No need to stat every member */
314 for (d = readdir(dp); d != NULL; d = readdir(dp))
315 if (d->d_fileno == st_cur.st_ino)
316 break;
318 else {
320 * Parent has a different device. This is a mount point so we
321 * need to stat every member
323 for (d = readdir(dp); d != NULL; d = readdir(dp)) {
324 if (ISDOT(d->d_name) || ISDOTDOT(d->d_name))
325 continue;
326 (void)strcpy(cur_name_add, d->d_name);
327 if (lstat(nextpathptr, &st_next) == -1) {
328 (void)sprintf(pathname,
329 "getwd: Cannot stat \"%s\" (%s)",
330 d->d_name, strerror(errno));
331 (void)closedir(dp);
332 return NULL;
334 /* check if we found it yet */
335 if (st_next.st_ino == st_cur.st_ino &&
336 DEV_DEV_COMPARE(st_next.st_dev, st_cur.st_dev))
337 break;
340 if (d == NULL) {
341 (void)sprintf(pathname,
342 "getwd: Cannot find \".\" in \"..\"");
343 (void)closedir(dp);
344 return NULL;
346 st_cur = st_dotdot;
347 pathptr = strrcpy(pathptr, d->d_name);
348 pathptr = strrcpy(pathptr, "/");
349 nextpathptr = strrcpy(nextpathptr, "../");
350 (void)closedir(dp);
351 *cur_name_add = '\0';
353 } /* end getwd */
354 #endif /* __hpux */
356 /* force posix signals */
357 void (*
358 bmake_signal(int s, void (*a)(int)))(int)
360 struct sigaction sa, osa;
362 sa.sa_handler = a;
363 sigemptyset(&sa.sa_mask);
364 sa.sa_flags = SA_RESTART;
366 if (sigaction(s, &sa, &osa) == -1)
367 return SIG_ERR;
368 else
369 return osa.sa_handler;
372 #if !defined(MAKE_NATIVE) && !defined(HAVE_VSNPRINTF)
373 #include <stdarg.h>
375 #if !defined(__osf__)
376 #ifdef _IOSTRG
377 #define STRFLAG (_IOSTRG|_IOWRT) /* no _IOWRT: avoid stdio bug */
378 #else
379 #if 0
380 #define STRFLAG (_IOREAD) /* XXX: Assume svr4 stdio */
381 #endif
382 #endif /* _IOSTRG */
383 #endif /* __osf__ */
386 vsnprintf(char *s, size_t n, const char *fmt, va_list args)
388 #ifdef STRFLAG
389 FILE fakebuf;
391 fakebuf._flag = STRFLAG;
393 * Some os's are char * _ptr, others are unsigned char *_ptr...
394 * We cast to void * to make everyone happy.
396 fakebuf._ptr = (void *)s;
397 fakebuf._cnt = n-1;
398 fakebuf._file = -1;
399 _doprnt(fmt, args, &fakebuf);
400 fakebuf._cnt++;
401 putc('\0', &fakebuf);
402 if (fakebuf._cnt<0)
403 fakebuf._cnt = 0;
404 return (n-fakebuf._cnt-1);
405 #else
406 (void)vsprintf(s, fmt, args);
407 return strlen(s);
408 #endif
412 snprintf(char *s, size_t n, const char *fmt, ...)
414 va_list ap;
415 int rv;
417 va_start(ap, fmt);
418 rv = vsnprintf(s, n, fmt, ap);
419 va_end(ap);
420 return rv;
423 #if !defined(MAKE_NATIVE) && !defined(HAVE_STRFTIME)
424 size_t
425 strftime(char *buf, size_t len, const char *fmt, const struct tm *tm)
427 static char months[][4] = {
428 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
429 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
432 size_t s;
433 char *b = buf;
435 while (*fmt) {
436 if (len == 0)
437 return buf - b;
438 if (*fmt != '%') {
439 *buf++ = *fmt++;
440 len--;
441 continue;
443 switch (*fmt++) {
444 case '%':
445 *buf++ = '%';
446 len--;
447 if (len == 0) return buf - b;
448 /*FALLTHROUGH*/
449 case '\0':
450 *buf = '%';
451 s = 1;
452 break;
453 case 'k':
454 s = snprintf(buf, len, "%d", tm->tm_hour);
455 break;
456 case 'M':
457 s = snprintf(buf, len, "%02d", tm->tm_min);
458 break;
459 case 'S':
460 s = snprintf(buf, len, "%02d", tm->tm_sec);
461 break;
462 case 'b':
463 if (tm->tm_mon >= 12)
464 return buf - b;
465 s = snprintf(buf, len, "%s", months[tm->tm_mon]);
466 break;
467 case 'd':
468 s = snprintf(buf, len, "%02d", tm->tm_mday);
469 break;
470 case 'Y':
471 s = snprintf(buf, len, "%d", 1900 + tm->tm_year);
472 break;
473 default:
474 s = snprintf(buf, len, "Unsupported format %c",
475 fmt[-1]);
476 break;
478 buf += s;
479 len -= s;
482 #endif
483 #endif