source: trunk/src/gmake/misc.c@ 429

Last change on this file since 429 was 429, checked in by bird, 19 years ago

optimizing for the libc project.

  • Property svn:eol-style set to native
File size: 18.5 KB
Line 
1/* Miscellaneous generic support functions for GNU Make.
2Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1997,
32002 Free Software Foundation, Inc.
4This file is part of GNU Make.
5
6GNU Make is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11GNU Make is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Make; see the file COPYING. If not, write to
18the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA. */
20
21#include "make.h"
22#include "dep.h"
23#include "debug.h"
24
25#ifdef __EMX__ /* saves 5-10ms on libc */
26# define bcopy(src, dst, size) __builtin_memcpy((dst), (src), (size))
27#endif
28
29/* Variadic functions. We go through contortions to allow proper function
30 prototypes for both ANSI and pre-ANSI C compilers, and also for those
31 which support stdarg.h vs. varargs.h, and finally those which have
32 vfprintf(), etc. and those who have _doprnt... or nothing.
33
34 This fancy stuff all came from GNU fileutils, except for the VA_PRINTF and
35 VA_END macros used here since we have multiple print functions. */
36
37#if USE_VARIADIC
38# if HAVE_STDARG_H
39# include <stdarg.h>
40# define VA_START(args, lastarg) va_start(args, lastarg)
41# else
42# include <varargs.h>
43# define VA_START(args, lastarg) va_start(args)
44# endif
45# if HAVE_VPRINTF
46# define VA_PRINTF(fp, lastarg, args) vfprintf((fp), (lastarg), (args))
47# else
48# define VA_PRINTF(fp, lastarg, args) _doprnt((lastarg), (args), (fp))
49# endif
50# define VA_END(args) va_end(args)
51#else
52/* We can't use any variadic interface! */
53# define va_alist a1, a2, a3, a4, a5, a6, a7, a8
54# define va_dcl char *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8;
55# define VA_START(args, lastarg)
56# define VA_PRINTF(fp, lastarg, args) fprintf((fp), (lastarg), va_alist)
57# define VA_END(args)
58#endif
59
60
61/* Compare strings *S1 and *S2.
62 Return negative if the first is less, positive if it is greater,
63 zero if they are equal. */
64
65int
66alpha_compare (const void *v1, const void *v2)
67{
68 const char *s1 = *((char **)v1);
69 const char *s2 = *((char **)v2);
70
71 if (*s1 != *s2)
72 return *s1 - *s2;
73 return strcmp (s1, s2);
74}
75
76
77/* Discard each backslash-newline combination from LINE.
78 Backslash-backslash-newline combinations become backslash-newlines.
79 This is done by copying the text at LINE into itself. */
80
81void
82collapse_continuations (char *line)
83{
84 register char *in, *out, *p;
85 register int backslash;
86 register unsigned int bs_write;
87
88 in = strchr (line, '\n');
89 if (in == 0)
90 return;
91
92 out = in;
93 while (out > line && out[-1] == '\\')
94 --out;
95
96 while (*in != '\0')
97 {
98 /* BS_WRITE gets the number of quoted backslashes at
99 the end just before IN, and BACKSLASH gets nonzero
100 if the next character is quoted. */
101 backslash = 0;
102 bs_write = 0;
103 for (p = in - 1; p >= line && *p == '\\'; --p)
104 {
105 if (backslash)
106 ++bs_write;
107 backslash = !backslash;
108
109 /* It should be impossible to go back this far without exiting,
110 but if we do, we can't get the right answer. */
111 if (in == out - 1)
112 abort ();
113 }
114
115 /* Output the appropriate number of backslashes. */
116 while (bs_write-- > 0)
117 *out++ = '\\';
118
119 /* Skip the newline. */
120 ++in;
121
122 /* If the newline is quoted, discard following whitespace
123 and any preceding whitespace; leave just one space. */
124 if (backslash)
125 {
126 in = next_token (in);
127 while (out > line && isblank ((unsigned char)out[-1]))
128 --out;
129 *out++ = ' ';
130 }
131 else
132 /* If the newline isn't quoted, put it in the output. */
133 *out++ = '\n';
134
135 /* Now copy the following line to the output.
136 Stop when we find backslashes followed by a newline. */
137 while (*in != '\0')
138 if (*in == '\\')
139 {
140 p = in + 1;
141 while (*p == '\\')
142 ++p;
143 if (*p == '\n')
144 {
145 in = p;
146 break;
147 }
148 while (in < p)
149 *out++ = *in++;
150 }
151 else
152 *out++ = *in++;
153 }
154
155 *out = '\0';
156}
157
158
159/* Remove comments from LINE.
160 This is done by copying the text at LINE onto itself. */
161
162void
163remove_comments (char *line)
164{
165 char *comment;
166
167 comment = find_char_unquote (line, '#', 0, 0);
168
169 if (comment != 0)
170 /* Cut off the line at the #. */
171 *comment = '\0';
172}
173
174
175/* Print N spaces (used in debug for target-depth). */
176
177void
178print_spaces (unsigned int n)
179{
180 while (n-- > 0)
181 putchar (' ');
182}
183
184
185
186/* Return a newly-allocated string whose contents
187 concatenate those of s1, s2, s3. */
188
189char *
190concat (const char *s1, const char *s2, const char *s3)
191{
192 unsigned int len1, len2, len3;
193 char *result;
194
195 len1 = *s1 != '\0' ? strlen (s1) : 0;
196 len2 = *s2 != '\0' ? strlen (s2) : 0;
197 len3 = *s3 != '\0' ? strlen (s3) : 0;
198
199 result = (char *) xmalloc (len1 + len2 + len3 + 1);
200
201 if (*s1 != '\0')
202 bcopy (s1, result, len1);
203 if (*s2 != '\0')
204 bcopy (s2, result + len1, len2);
205 if (*s3 != '\0')
206 bcopy (s3, result + len1 + len2, len3);
207 *(result + len1 + len2 + len3) = '\0';
208
209 return result;
210}
211
212
213/* Print a message on stdout. */
214
215void
216#if HAVE_ANSI_COMPILER && USE_VARIADIC && HAVE_STDARG_H
217message (int prefix, const char *fmt, ...)
218#else
219message (prefix, fmt, va_alist)
220 int prefix;
221 const char *fmt;
222 va_dcl
223#endif
224{
225#if USE_VARIADIC
226 va_list args;
227#endif
228
229 log_working_directory (1);
230
231 if (fmt != 0)
232 {
233 if (prefix)
234 {
235 if (makelevel == 0)
236 printf ("%s: ", program);
237 else
238 printf ("%s[%u]: ", program, makelevel);
239 }
240 VA_START (args, fmt);
241 VA_PRINTF (stdout, fmt, args);
242 VA_END (args);
243 putchar ('\n');
244 }
245
246 fflush (stdout);
247}
248
249/* Print an error message. */
250
251void
252#if HAVE_ANSI_COMPILER && USE_VARIADIC && HAVE_STDARG_H
253error (const struct floc *flocp, const char *fmt, ...)
254#else
255error (flocp, fmt, va_alist)
256 const struct floc *flocp;
257 const char *fmt;
258 va_dcl
259#endif
260{
261#if USE_VARIADIC
262 va_list args;
263#endif
264
265 log_working_directory (1);
266
267 if (flocp && flocp->filenm)
268 fprintf (stderr, "%s:%lu: ", flocp->filenm, flocp->lineno);
269 else if (makelevel == 0)
270 fprintf (stderr, "%s: ", program);
271 else
272 fprintf (stderr, "%s[%u]: ", program, makelevel);
273
274 VA_START(args, fmt);
275 VA_PRINTF (stderr, fmt, args);
276 VA_END (args);
277
278 putc ('\n', stderr);
279 fflush (stderr);
280}
281
282/* Print an error message and exit. */
283
284void
285#if HAVE_ANSI_COMPILER && USE_VARIADIC && HAVE_STDARG_H
286fatal (const struct floc *flocp, const char *fmt, ...)
287#else
288fatal (flocp, fmt, va_alist)
289 const struct floc *flocp;
290 const char *fmt;
291 va_dcl
292#endif
293{
294#if USE_VARIADIC
295 va_list args;
296#endif
297
298 log_working_directory (1);
299
300 if (flocp && flocp->filenm)
301 fprintf (stderr, "%s:%lu: *** ", flocp->filenm, flocp->lineno);
302 else if (makelevel == 0)
303 fprintf (stderr, "%s: *** ", program);
304 else
305 fprintf (stderr, "%s[%u]: *** ", program, makelevel);
306
307 VA_START(args, fmt);
308 VA_PRINTF (stderr, fmt, args);
309 VA_END (args);
310
311 fputs (_(". Stop.\n"), stderr);
312
313 die (2);
314}
315
316#ifndef HAVE_STRERROR
317
318#undef strerror
319
320char *
321strerror (int errnum)
322{
323 extern int errno, sys_nerr;
324#ifndef __DECC
325 extern char *sys_errlist[];
326#endif
327 static char buf[] = "Unknown error 12345678901234567890";
328
329 if (errno < sys_nerr)
330 return sys_errlist[errnum];
331
332 sprintf (buf, _("Unknown error %d"), errnum);
333 return buf;
334}
335#endif
336
337/* Print an error message from errno. */
338
339void
340perror_with_name (const char *str, const char *name)
341{
342 error (NILF, _("%s%s: %s"), str, name, strerror (errno));
343}
344
345/* Print an error message from errno and exit. */
346
347void
348pfatal_with_name (const char *name)
349{
350 fatal (NILF, _("%s: %s"), name, strerror (errno));
351
352 /* NOTREACHED */
353}
354
355
356/* Like malloc but get fatal error if memory is exhausted. */
357/* Don't bother if we're using dmalloc; it provides these for us. */
358
359#ifndef HAVE_DMALLOC_H
360
361#undef xmalloc
362#undef xrealloc
363#undef xstrdup
364
365char *
366xmalloc (unsigned int size)
367{
368 /* Make sure we don't allocate 0, for pre-ANSI libraries. */
369 char *result = (char *) malloc (size ? size : 1);
370 if (result == 0)
371 fatal (NILF, _("virtual memory exhausted"));
372 return result;
373}
374
375
376char *
377xrealloc (char *ptr, unsigned int size)
378{
379 char *result;
380
381 /* Some older implementations of realloc() don't conform to ANSI. */
382 if (! size)
383 size = 1;
384 result = ptr ? realloc (ptr, size) : malloc (size);
385 if (result == 0)
386 fatal (NILF, _("virtual memory exhausted"));
387 return result;
388}
389
390
391char *
392xstrdup (const char *ptr)
393{
394 char *result;
395
396#ifdef HAVE_STRDUP
397 result = strdup (ptr);
398#else
399 result = (char *) malloc (strlen (ptr) + 1);
400#endif
401
402 if (result == 0)
403 fatal (NILF, _("virtual memory exhausted"));
404
405#ifdef HAVE_STRDUP
406 return result;
407#else
408 return strcpy(result, ptr);
409#endif
410}
411
412#endif /* HAVE_DMALLOC_H */
413
414char *
415savestring (const char *str, unsigned int length)
416{
417 register char *out = (char *) xmalloc (length + 1);
418 if (length > 0)
419 bcopy (str, out, length);
420 out[length] = '\0';
421 return out;
422}
423
424
425
426#ifndef KMK /* This is really a reimplemntation of memchr. */
427/* Limited INDEX:
428 Search through the string STRING, which ends at LIMIT, for the character C.
429 Returns a pointer to the first occurrence, or nil if none is found.
430 Like INDEX except that the string searched ends where specified
431 instead of at the first null. */
432
433char *
434lindex (const char *s, const char *limit, int c)
435{
436 while (s < limit)
437 if (*s++ == c)
438 return (char *)(s - 1);
439
440 return 0;
441}
442#endif
443
444
445/* Return the address of the first whitespace or null in the string S. */
446
447char *
448end_of_token (const char *s)
449{
450 while (*s != '\0' && !isblank ((unsigned char)*s))
451 ++s;
452 return (char *)s;
453}
454
455#ifdef WINDOWS32
456/*
457 * Same as end_of_token, but take into account a stop character
458 */
459char *
460end_of_token_w32 (char *s, char stopchar)
461{
462 register char *p = s;
463 register int backslash = 0;
464
465 while (*p != '\0' && *p != stopchar
466 && (backslash || !isblank ((unsigned char)*p)))
467 {
468 if (*p++ == '\\')
469 {
470 backslash = !backslash;
471 while (*p == '\\')
472 {
473 backslash = !backslash;
474 ++p;
475 }
476 }
477 else
478 backslash = 0;
479 }
480
481 return p;
482}
483#endif
484
485/* Return the address of the first nonwhitespace or null in the string S. */
486
487char *
488next_token (const char *s)
489{
490 while (isblank ((unsigned char)*s))
491 ++s;
492 return (char *)s;
493}
494
495/* Find the next token in PTR; return the address of it, and store the
496 length of the token into *LENGTHPTR if LENGTHPTR is not nil. */
497
498char *
499find_next_token (char **ptr, unsigned int *lengthptr)
500{
501 char *p = next_token (*ptr);
502 char *end;
503
504 if (*p == '\0')
505 return 0;
506
507 *ptr = end = end_of_token (p);
508 if (lengthptr != 0)
509 *lengthptr = end - p;
510 return p;
511}
512
513
514/* Copy a chain of `struct dep', making a new chain
515 with the same contents as the old one. */
516
517struct dep *
518copy_dep_chain (struct dep *d)
519{
520 register struct dep *c;
521 struct dep *firstnew = 0;
522 struct dep *lastnew = 0;
523
524 while (d != 0)
525 {
526 c = (struct dep *) xmalloc (sizeof (struct dep));
527 bcopy ((char *) d, (char *) c, sizeof (struct dep));
528 if (c->name != 0)
529 c->name = xstrdup (c->name);
530 c->next = 0;
531 if (firstnew == 0)
532 firstnew = lastnew = c;
533 else
534 lastnew = lastnew->next = c;
535
536 d = d->next;
537 }
538
539 return firstnew;
540}
541
542
543/* Free a chain of `struct nameseq'. Each nameseq->name is freed
544 as well. Can be used on `struct dep' chains.*/
545
546void
547free_ns_chain (struct nameseq *n)
548{
549 register struct nameseq *tmp;
550
551 while (n != 0)
552 {
553 if (n->name != 0)
554 free (n->name);
555
556 tmp = n;
557
558 n = n->next;
559
560 free (tmp);
561 }
562
563}
564
565#ifdef iAPX286
566/* The losing compiler on this machine can't handle this macro. */
567
568char *
569dep_name (struct dep *dep)
570{
571 return dep->name == 0 ? dep->file->name : dep->name;
572}
573#endif
574
575
576#ifdef GETLOADAVG_PRIVILEGED
577
578#ifdef POSIX
579
580/* Hopefully if a system says it's POSIX.1 and has the setuid and setgid
581 functions, they work as POSIX.1 says. Some systems (Alpha OSF/1 1.2,
582 for example) which claim to be POSIX.1 also have the BSD setreuid and
583 setregid functions, but they don't work as in BSD and only the POSIX.1
584 way works. */
585
586#undef HAVE_SETREUID
587#undef HAVE_SETREGID
588
589#else /* Not POSIX. */
590
591/* Some POSIX.1 systems have the seteuid and setegid functions. In a
592 POSIX-like system, they are the best thing to use. However, some
593 non-POSIX systems have them too but they do not work in the POSIX style
594 and we must use setreuid and setregid instead. */
595
596#undef HAVE_SETEUID
597#undef HAVE_SETEGID
598
599#endif /* POSIX. */
600
601#ifndef HAVE_UNISTD_H
602extern int getuid (), getgid (), geteuid (), getegid ();
603extern int setuid (), setgid ();
604#ifdef HAVE_SETEUID
605extern int seteuid ();
606#else
607#ifdef HAVE_SETREUID
608extern int setreuid ();
609#endif /* Have setreuid. */
610#endif /* Have seteuid. */
611#ifdef HAVE_SETEGID
612extern int setegid ();
613#else
614#ifdef HAVE_SETREGID
615extern int setregid ();
616#endif /* Have setregid. */
617#endif /* Have setegid. */
618#endif /* No <unistd.h>. */
619
620/* Keep track of the user and group IDs for user- and make- access. */
621static int user_uid = -1, user_gid = -1, make_uid = -1, make_gid = -1;
622#define access_inited (user_uid != -1)
623static enum { make, user } current_access;
624
625
626/* Under -d, write a message describing the current IDs. */
627
628static void
629log_access (char *flavor)
630{
631 if (! ISDB (DB_JOBS))
632 return;
633
634 /* All the other debugging messages go to stdout,
635 but we write this one to stderr because it might be
636 run in a child fork whose stdout is piped. */
637
638 fprintf (stderr, _("%s: user %lu (real %lu), group %lu (real %lu)\n"),
639 flavor, (unsigned long) geteuid (), (unsigned long) getuid (),
640 (unsigned long) getegid (), (unsigned long) getgid ());
641 fflush (stderr);
642}
643
644
645static void
646init_access (void)
647{
648#ifndef VMS
649 user_uid = getuid ();
650 user_gid = getgid ();
651
652 make_uid = geteuid ();
653 make_gid = getegid ();
654
655 /* Do these ever fail? */
656 if (user_uid == -1 || user_gid == -1 || make_uid == -1 || make_gid == -1)
657 pfatal_with_name ("get{e}[gu]id");
658
659 log_access (_("Initialized access"));
660
661 current_access = make;
662#endif
663}
664
665#endif /* GETLOADAVG_PRIVILEGED */
666
667/* Give the process appropriate permissions for access to
668 user data (i.e., to stat files, or to spawn a child process). */
669void
670user_access (void)
671{
672#ifdef GETLOADAVG_PRIVILEGED
673
674 if (!access_inited)
675 init_access ();
676
677 if (current_access == user)
678 return;
679
680 /* We are in "make access" mode. This means that the effective user and
681 group IDs are those of make (if it was installed setuid or setgid).
682 We now want to set the effective user and group IDs to the real IDs,
683 which are the IDs of the process that exec'd make. */
684
685#ifdef HAVE_SETEUID
686
687 /* Modern systems have the seteuid/setegid calls which set only the
688 effective IDs, which is ideal. */
689
690 if (seteuid (user_uid) < 0)
691 pfatal_with_name ("user_access: seteuid");
692
693#else /* Not HAVE_SETEUID. */
694
695#ifndef HAVE_SETREUID
696
697 /* System V has only the setuid/setgid calls to set user/group IDs.
698 There is an effective ID, which can be set by setuid/setgid.
699 It can be set (unless you are root) only to either what it already is
700 (returned by geteuid/getegid, now in make_uid/make_gid),
701 the real ID (return by getuid/getgid, now in user_uid/user_gid),
702 or the saved set ID (what the effective ID was before this set-ID
703 executable (make) was exec'd). */
704
705 if (setuid (user_uid) < 0)
706 pfatal_with_name ("user_access: setuid");
707
708#else /* HAVE_SETREUID. */
709
710 /* In 4BSD, the setreuid/setregid calls set both the real and effective IDs.
711 They may be set to themselves or each other. So you have two alternatives
712 at any one time. If you use setuid/setgid, the effective will be set to
713 the real, leaving only one alternative. Using setreuid/setregid, however,
714 you can toggle between your two alternatives by swapping the values in a
715 single setreuid or setregid call. */
716
717 if (setreuid (make_uid, user_uid) < 0)
718 pfatal_with_name ("user_access: setreuid");
719
720#endif /* Not HAVE_SETREUID. */
721#endif /* HAVE_SETEUID. */
722
723#ifdef HAVE_SETEGID
724 if (setegid (user_gid) < 0)
725 pfatal_with_name ("user_access: setegid");
726#else
727#ifndef HAVE_SETREGID
728 if (setgid (user_gid) < 0)
729 pfatal_with_name ("user_access: setgid");
730#else
731 if (setregid (make_gid, user_gid) < 0)
732 pfatal_with_name ("user_access: setregid");
733#endif
734#endif
735
736 current_access = user;
737
738 log_access (_("User access"));
739
740#endif /* GETLOADAVG_PRIVILEGED */
741}
742
743/* Give the process appropriate permissions for access to
744 make data (i.e., the load average). */
745void
746make_access (void)
747{
748#ifdef GETLOADAVG_PRIVILEGED
749
750 if (!access_inited)
751 init_access ();
752
753 if (current_access == make)
754 return;
755
756 /* See comments in user_access, above. */
757
758#ifdef HAVE_SETEUID
759 if (seteuid (make_uid) < 0)
760 pfatal_with_name ("make_access: seteuid");
761#else
762#ifndef HAVE_SETREUID
763 if (setuid (make_uid) < 0)
764 pfatal_with_name ("make_access: setuid");
765#else
766 if (setreuid (user_uid, make_uid) < 0)
767 pfatal_with_name ("make_access: setreuid");
768#endif
769#endif
770
771#ifdef HAVE_SETEGID
772 if (setegid (make_gid) < 0)
773 pfatal_with_name ("make_access: setegid");
774#else
775#ifndef HAVE_SETREGID
776 if (setgid (make_gid) < 0)
777 pfatal_with_name ("make_access: setgid");
778#else
779 if (setregid (user_gid, make_gid) < 0)
780 pfatal_with_name ("make_access: setregid");
781#endif
782#endif
783
784 current_access = make;
785
786 log_access (_("Make access"));
787
788#endif /* GETLOADAVG_PRIVILEGED */
789}
790
791/* Give the process appropriate permissions for a child process.
792 This is like user_access, but you can't get back to make_access. */
793void
794child_access (void)
795{
796#ifdef GETLOADAVG_PRIVILEGED
797
798 if (!access_inited)
799 abort ();
800
801 /* Set both the real and effective UID and GID to the user's.
802 They cannot be changed back to make's. */
803
804#ifndef HAVE_SETREUID
805 if (setuid (user_uid) < 0)
806 pfatal_with_name ("child_access: setuid");
807#else
808 if (setreuid (user_uid, user_uid) < 0)
809 pfatal_with_name ("child_access: setreuid");
810#endif
811
812#ifndef HAVE_SETREGID
813 if (setgid (user_gid) < 0)
814 pfatal_with_name ("child_access: setgid");
815#else
816 if (setregid (user_gid, user_gid) < 0)
817 pfatal_with_name ("child_access: setregid");
818#endif
819
820 log_access (_("Child access"));
821
822#endif /* GETLOADAVG_PRIVILEGED */
823}
824
825
826#ifdef NEED_GET_PATH_MAX
827unsigned int
828get_path_max (void)
829{
830 static unsigned int value;
831
832 if (value == 0)
833 {
834 long int x = pathconf ("/", _PC_PATH_MAX);
835 if (x > 0)
836 value = x;
837 else
838 return MAXPATHLEN;
839 }
840
841 return value;
842}
843#endif
Note: See TracBrowser for help on using the repository browser.