Drop main() prototype. Syncs with NetBSD-8
[minix.git] / usr.bin / make / util.c
blob506fb4d9b280471d6403ec67a1cfac6d334ed0cb
1 /* $NetBSD: util.c,v 1.54 2013/11/26 13:44:41 joerg Exp $ */
3 /*
4 * Missing stuff from OS's
5 */
6 #if defined(__MINT__) || defined(__linux__)
7 #include <signal.h>
8 #endif
10 #ifndef MAKE_NATIVE
11 static char rcsid[] = "$NetBSD: util.c,v 1.54 2013/11/26 13:44:41 joerg Exp $";
12 #else
13 #include <sys/cdefs.h>
14 #ifndef lint
15 __RCSID("$NetBSD: util.c,v 1.54 2013/11/26 13:44:41 joerg Exp $");
16 #endif
17 #endif
19 #include <sys/param.h>
21 #include <errno.h>
22 #include <stdio.h>
23 #include <time.h>
24 #include <signal.h>
26 #include "make.h"
28 #if !defined(MAKE_NATIVE) && !defined(HAVE_STRERROR)
29 extern int errno, sys_nerr;
30 extern char *sys_errlist[];
32 char *
33 strerror(int e)
35 static char buf[100];
36 if (e < 0 || e >= sys_nerr) {
37 snprintf(buf, sizeof(buf), "Unknown error %d", e);
38 return buf;
40 else
41 return sys_errlist[e];
43 #endif
45 #if !defined(MAKE_NATIVE) && !defined(HAVE_SETENV)
46 extern char **environ;
48 static char *
49 findenv(const char *name, int *offset)
51 size_t i, len;
52 char *p, *q;
54 len = strlen(name);
55 for (i = 0; (q = environ[i]); i++) {
56 p = strchr(q, '=');
57 if (p == NULL || p - q != len)
58 continue;
59 if (strncmp(name, q, len) == 0) {
60 *offset = i;
61 return q + len + 1;
64 *offset = i;
65 return NULL;
68 char *
69 getenv(const char *name)
71 int offset;
73 return(findenv(name, &offset));
76 int
77 unsetenv(const char *name)
79 char **p;
80 int offset;
82 if (name == NULL || *name == '\0' || strchr(name, '=') != NULL) {
83 errno = EINVAL;
84 return -1;
87 while (findenv(name, &offset)) { /* if set multiple times */
88 for (p = &environ[offset];; ++p)
89 if (!(*p = *(p + 1)))
90 break;
92 return 0;
95 int
96 setenv(const char *name, const char *value, int rewrite)
98 char *c, **newenv;
99 const char *cc;
100 size_t l_value, size;
101 int offset;
103 if (name == NULL || value == NULL) {
104 errno = EINVAL;
105 return -1;
108 if (*value == '=') /* no `=' in value */
109 ++value;
110 l_value = strlen(value);
112 /* find if already exists */
113 if ((c = findenv(name, &offset))) {
114 if (!rewrite)
115 return 0;
116 if (strlen(c) >= l_value) /* old larger; copy over */
117 goto copy;
118 } else { /* create new slot */
119 size = sizeof(char *) * (offset + 2);
120 if (savedEnv == environ) { /* just increase size */
121 if ((newenv = realloc(savedEnv, size)) == NULL)
122 return -1;
123 savedEnv = newenv;
124 } else { /* get new space */
126 * We don't free here because we don't know if
127 * the first allocation is valid on all OS's
129 if ((savedEnv = malloc(size)) == NULL)
130 return -1;
131 (void)memcpy(savedEnv, environ, size - sizeof(char *));
133 environ = savedEnv;
134 environ[offset + 1] = NULL;
136 for (cc = name; *cc && *cc != '='; ++cc) /* no `=' in name */
137 continue;
138 size = cc - name;
139 /* name + `=' + value */
140 if ((environ[offset] = malloc(size + l_value + 2)) == NULL)
141 return -1;
142 c = environ[offset];
143 (void)memcpy(c, name, size);
144 c += size;
145 *c++ = '=';
146 copy:
147 (void)memcpy(c, value, l_value + 1);
148 return 0;
151 #ifdef TEST
153 main(int argc, char *argv[])
155 setenv(argv[1], argv[2], 0);
156 printf("%s\n", getenv(argv[1]));
157 unsetenv(argv[1]);
158 printf("%s\n", getenv(argv[1]));
159 return 0;
161 #endif
163 #endif
165 #if defined(__hpux__) || defined(__hpux)
166 /* strrcpy():
167 * Like strcpy, going backwards and returning the new pointer
169 static char *
170 strrcpy(char *ptr, char *str)
172 int len = strlen(str);
174 while (len)
175 *--ptr = str[--len];
177 return (ptr);
178 } /* end strrcpy */
180 char *sys_siglist[] = {
181 "Signal 0",
182 "Hangup", /* SIGHUP */
183 "Interrupt", /* SIGINT */
184 "Quit", /* SIGQUIT */
185 "Illegal instruction", /* SIGILL */
186 "Trace/BPT trap", /* SIGTRAP */
187 "IOT trap", /* SIGIOT */
188 "EMT trap", /* SIGEMT */
189 "Floating point exception", /* SIGFPE */
190 "Killed", /* SIGKILL */
191 "Bus error", /* SIGBUS */
192 "Segmentation fault", /* SIGSEGV */
193 "Bad system call", /* SIGSYS */
194 "Broken pipe", /* SIGPIPE */
195 "Alarm clock", /* SIGALRM */
196 "Terminated", /* SIGTERM */
197 "User defined signal 1", /* SIGUSR1 */
198 "User defined signal 2", /* SIGUSR2 */
199 "Child exited", /* SIGCLD */
200 "Power-fail restart", /* SIGPWR */
201 "Virtual timer expired", /* SIGVTALRM */
202 "Profiling timer expired", /* SIGPROF */
203 "I/O possible", /* SIGIO */
204 "Window size changes", /* SIGWINDOW */
205 "Stopped (signal)", /* SIGSTOP */
206 "Stopped", /* SIGTSTP */
207 "Continued", /* SIGCONT */
208 "Stopped (tty input)", /* SIGTTIN */
209 "Stopped (tty output)", /* SIGTTOU */
210 "Urgent I/O condition", /* SIGURG */
211 "Remote lock lost (NFS)", /* SIGLOST */
212 "Signal 31", /* reserved */
213 "DIL signal" /* SIGDIL */
215 #endif /* __hpux__ || __hpux */
217 #if defined(__hpux__) || defined(__hpux)
218 #include <sys/types.h>
219 #include <sys/syscall.h>
220 #include <sys/signal.h>
221 #include <sys/stat.h>
222 #include <dirent.h>
223 #include <sys/time.h>
224 #include <unistd.h>
227 killpg(int pid, int sig)
229 return kill(-pid, sig);
232 #if !defined(__hpux__) && !defined(__hpux)
233 void
234 srandom(long seed)
236 srand48(seed);
239 long
240 random(void)
242 return lrand48();
244 #endif
246 #if !defined(__hpux__) && !defined(__hpux)
248 utimes(char *file, struct timeval tvp[2])
250 struct utimbuf t;
252 t.actime = tvp[0].tv_sec;
253 t.modtime = tvp[1].tv_sec;
254 return(utime(file, &t));
256 #endif
258 #if !defined(BSD) && !defined(d_fileno)
259 # define d_fileno d_ino
260 #endif
262 #ifndef DEV_DEV_COMPARE
263 # define DEV_DEV_COMPARE(a, b) ((a) == (b))
264 #endif
265 #define ISDOT(c) ((c)[0] == '.' && (((c)[1] == '\0') || ((c)[1] == '/')))
266 #define ISDOTDOT(c) ((c)[0] == '.' && ISDOT(&((c)[1])))
268 char *
269 getwd(char *pathname)
271 DIR *dp;
272 struct dirent *d;
273 extern int errno;
275 struct stat st_root, st_cur, st_next, st_dotdot;
276 char pathbuf[MAXPATHLEN], nextpathbuf[MAXPATHLEN * 2];
277 char *pathptr, *nextpathptr, *cur_name_add;
279 /* find the inode of root */
280 if (stat("/", &st_root) == -1) {
281 (void)sprintf(pathname,
282 "getwd: Cannot stat \"/\" (%s)", strerror(errno));
283 return NULL;
285 pathbuf[MAXPATHLEN - 1] = '\0';
286 pathptr = &pathbuf[MAXPATHLEN - 1];
287 nextpathbuf[MAXPATHLEN - 1] = '\0';
288 cur_name_add = nextpathptr = &nextpathbuf[MAXPATHLEN - 1];
290 /* find the inode of the current directory */
291 if (lstat(".", &st_cur) == -1) {
292 (void)sprintf(pathname,
293 "getwd: Cannot stat \".\" (%s)", strerror(errno));
294 return NULL;
296 nextpathptr = strrcpy(nextpathptr, "../");
298 /* Descend to root */
299 for (;;) {
301 /* look if we found root yet */
302 if (st_cur.st_ino == st_root.st_ino &&
303 DEV_DEV_COMPARE(st_cur.st_dev, st_root.st_dev)) {
304 (void)strcpy(pathname, *pathptr != '/' ? "/" : pathptr);
305 return (pathname);
308 /* open the parent directory */
309 if (stat(nextpathptr, &st_dotdot) == -1) {
310 (void)sprintf(pathname,
311 "getwd: Cannot stat directory \"%s\" (%s)",
312 nextpathptr, strerror(errno));
313 return NULL;
315 if ((dp = opendir(nextpathptr)) == NULL) {
316 (void)sprintf(pathname,
317 "getwd: Cannot open directory \"%s\" (%s)",
318 nextpathptr, strerror(errno));
319 return NULL;
322 /* look in the parent for the entry with the same inode */
323 if (DEV_DEV_COMPARE(st_dotdot.st_dev, st_cur.st_dev)) {
324 /* Parent has same device. No need to stat every member */
325 for (d = readdir(dp); d != NULL; d = readdir(dp))
326 if (d->d_fileno == st_cur.st_ino)
327 break;
329 else {
331 * Parent has a different device. This is a mount point so we
332 * need to stat every member
334 for (d = readdir(dp); d != NULL; d = readdir(dp)) {
335 if (ISDOT(d->d_name) || ISDOTDOT(d->d_name))
336 continue;
337 (void)strcpy(cur_name_add, d->d_name);
338 if (lstat(nextpathptr, &st_next) == -1) {
339 (void)sprintf(pathname,
340 "getwd: Cannot stat \"%s\" (%s)",
341 d->d_name, strerror(errno));
342 (void)closedir(dp);
343 return NULL;
345 /* check if we found it yet */
346 if (st_next.st_ino == st_cur.st_ino &&
347 DEV_DEV_COMPARE(st_next.st_dev, st_cur.st_dev))
348 break;
351 if (d == NULL) {
352 (void)sprintf(pathname,
353 "getwd: Cannot find \".\" in \"..\"");
354 (void)closedir(dp);
355 return NULL;
357 st_cur = st_dotdot;
358 pathptr = strrcpy(pathptr, d->d_name);
359 pathptr = strrcpy(pathptr, "/");
360 nextpathptr = strrcpy(nextpathptr, "../");
361 (void)closedir(dp);
362 *cur_name_add = '\0';
364 } /* end getwd */
365 #endif /* __hpux */
367 /* force posix signals */
368 void (*
369 bmake_signal(int s, void (*a)(int)))(int)
371 struct sigaction sa, osa;
373 sa.sa_handler = a;
374 sigemptyset(&sa.sa_mask);
375 sa.sa_flags = SA_RESTART;
377 if (sigaction(s, &sa, &osa) == -1)
378 return SIG_ERR;
379 else
380 return osa.sa_handler;
383 #if !defined(MAKE_NATIVE) && !defined(HAVE_VSNPRINTF)
384 #include <stdarg.h>
386 #if !defined(__osf__)
387 #ifdef _IOSTRG
388 #define STRFLAG (_IOSTRG|_IOWRT) /* no _IOWRT: avoid stdio bug */
389 #else
390 #if 0
391 #define STRFLAG (_IOREAD) /* XXX: Assume svr4 stdio */
392 #endif
393 #endif /* _IOSTRG */
394 #endif /* __osf__ */
397 vsnprintf(char *s, size_t n, const char *fmt, va_list args)
399 #ifdef STRFLAG
400 FILE fakebuf;
402 fakebuf._flag = STRFLAG;
404 * Some os's are char * _ptr, others are unsigned char *_ptr...
405 * We cast to void * to make everyone happy.
407 fakebuf._ptr = (void *)s;
408 fakebuf._cnt = n-1;
409 fakebuf._file = -1;
410 _doprnt(fmt, args, &fakebuf);
411 fakebuf._cnt++;
412 putc('\0', &fakebuf);
413 if (fakebuf._cnt<0)
414 fakebuf._cnt = 0;
415 return (n-fakebuf._cnt-1);
416 #else
417 (void)vsprintf(s, fmt, args);
418 return strlen(s);
419 #endif
423 snprintf(char *s, size_t n, const char *fmt, ...)
425 va_list ap;
426 int rv;
428 va_start(ap, fmt);
429 rv = vsnprintf(s, n, fmt, ap);
430 va_end(ap);
431 return rv;
434 #if !defined(MAKE_NATIVE) && !defined(HAVE_STRFTIME)
435 size_t
436 strftime(char *buf, size_t len, const char *fmt, const struct tm *tm)
438 static char months[][4] = {
439 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
440 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
443 size_t s;
444 char *b = buf;
446 while (*fmt) {
447 if (len == 0)
448 return buf - b;
449 if (*fmt != '%') {
450 *buf++ = *fmt++;
451 len--;
452 continue;
454 switch (*fmt++) {
455 case '%':
456 *buf++ = '%';
457 len--;
458 if (len == 0) return buf - b;
459 /*FALLTHROUGH*/
460 case '\0':
461 *buf = '%';
462 s = 1;
463 break;
464 case 'k':
465 s = snprintf(buf, len, "%d", tm->tm_hour);
466 break;
467 case 'M':
468 s = snprintf(buf, len, "%02d", tm->tm_min);
469 break;
470 case 'S':
471 s = snprintf(buf, len, "%02d", tm->tm_sec);
472 break;
473 case 'b':
474 if (tm->tm_mon >= 12)
475 return buf - b;
476 s = snprintf(buf, len, "%s", months[tm->tm_mon]);
477 break;
478 case 'd':
479 s = snprintf(buf, len, "%02d", tm->tm_mday);
480 break;
481 case 'Y':
482 s = snprintf(buf, len, "%d", 1900 + tm->tm_year);
483 break;
484 default:
485 s = snprintf(buf, len, "Unsupported format %c",
486 fmt[-1]);
487 break;
489 buf += s;
490 len -= s;
493 #endif
494 #endif