VirtualBox

source: kBuild/vendor/gnumake/current/misc.c@ 3387

Last change on this file since 3387 was 3138, checked in by bird, 6 years ago

Imported make 4.2.1 (2e55f5e4abdc0e38c1d64be703b446695e70b3b6) from https://git.savannah.gnu.org/git/make.git.

  • Property svn:eol-style set to native
File size: 16.0 KB
Line 
1/* Miscellaneous generic support functions for GNU Make.
2Copyright (C) 1988-2016 Free Software Foundation, Inc.
3This file is part of GNU Make.
4
5GNU Make is free software; you can redistribute it and/or modify it under the
6terms of the GNU General Public License as published by the Free Software
7Foundation; either version 3 of the License, or (at your option) any later
8version.
9
10GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
11WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License along with
15this program. If not, see <http://www.gnu.org/licenses/>. */
16
17#include "makeint.h"
18#include "filedef.h"
19#include "dep.h"
20#include "debug.h"
21
22/* GNU make no longer supports pre-ANSI89 environments. */
23
24#include <stdarg.h>
25
26#ifdef HAVE_FCNTL_H
27# include <fcntl.h>
28#else
29# include <sys/file.h>
30#endif
31
32/* Compare strings *S1 and *S2.
33 Return negative if the first is less, positive if it is greater,
34 zero if they are equal. */
35
36int
37alpha_compare (const void *v1, const void *v2)
38{
39 const char *s1 = *((char **)v1);
40 const char *s2 = *((char **)v2);
41
42 if (*s1 != *s2)
43 return *s1 - *s2;
44 return strcmp (s1, s2);
45}
46
47
48/* Discard each backslash-newline combination from LINE.
49 Backslash-backslash-newline combinations become backslash-newlines.
50 This is done by copying the text at LINE into itself. */
51
52void
53collapse_continuations (char *line)
54{
55 char *in, *out, *p;
56
57 in = strchr (line, '\n');
58 if (in == 0)
59 return;
60
61 out = in;
62 while (out > line && out[-1] == '\\')
63 --out;
64
65 while (*in != '\0')
66 {
67 /* BS_WRITE gets the number of quoted backslashes at
68 the end just before IN, and BACKSLASH gets nonzero
69 if the next character is quoted. */
70 unsigned int backslash = 0;
71 unsigned int bs_write = 0;
72 for (p = in - 1; p >= line && *p == '\\'; --p)
73 {
74 if (backslash)
75 ++bs_write;
76 backslash = !backslash;
77
78 /* It should be impossible to go back this far without exiting,
79 but if we do, we can't get the right answer. */
80 if (in == out - 1)
81 abort ();
82 }
83
84 /* Output the appropriate number of backslashes. */
85 while (bs_write-- > 0)
86 *out++ = '\\';
87
88 /* Skip the newline. */
89 ++in;
90
91 if (backslash)
92 {
93 /* Backslash/newline handling:
94 In traditional GNU make all trailing whitespace, consecutive
95 backslash/newlines, and any leading non-newline whitespace on the
96 next line is reduced to a single space.
97 In POSIX, each backslash/newline and is replaced by a space. */
98 while (ISBLANK (*in))
99 ++in;
100 if (! posix_pedantic)
101 while (out > line && ISBLANK (out[-1]))
102 --out;
103 *out++ = ' ';
104 }
105 else
106 /* If the newline isn't quoted, put it in the output. */
107 *out++ = '\n';
108
109 /* Now copy the following line to the output.
110 Stop when we find backslashes followed by a newline. */
111 while (*in != '\0')
112 if (*in == '\\')
113 {
114 p = in + 1;
115 while (*p == '\\')
116 ++p;
117 if (*p == '\n')
118 {
119 in = p;
120 break;
121 }
122 while (in < p)
123 *out++ = *in++;
124 }
125 else
126 *out++ = *in++;
127 }
128
129 *out = '\0';
130}
131
132
133/* Print N spaces (used in debug for target-depth). */
134
135void
136print_spaces (unsigned int n)
137{
138 while (n-- > 0)
139 putchar (' ');
140}
141
142
143
144/* Return a string whose contents concatenate the NUM strings provided
145 This string lives in static, re-used memory. */
146
147const char *
148concat (unsigned int num, ...)
149{
150 static unsigned int rlen = 0;
151 static char *result = NULL;
152 unsigned int ri = 0;
153 va_list args;
154
155 va_start (args, num);
156
157 while (num-- > 0)
158 {
159 const char *s = va_arg (args, const char *);
160 unsigned int l = xstrlen (s);
161
162 if (l == 0)
163 continue;
164
165 if (ri + l > rlen)
166 {
167 rlen = ((rlen ? rlen : 60) + l) * 2;
168 result = xrealloc (result, rlen);
169 }
170
171 memcpy (result + ri, s, l);
172 ri += l;
173 }
174
175 va_end (args);
176
177 /* Get some more memory if we don't have enough space for the
178 terminating '\0'. */
179 if (ri == rlen)
180 {
181 rlen = (rlen ? rlen : 60) * 2;
182 result = xrealloc (result, rlen);
183 }
184
185 result[ri] = '\0';
186
187 return result;
188}
189
190
191
192#ifndef HAVE_STRERROR
193#undef strerror
194char *
195strerror (int errnum)
196{
197 extern int errno, sys_nerr;
198#ifndef __DECC
199 extern char *sys_errlist[];
200#endif
201 static char buf[] = "Unknown error 12345678901234567890";
202
203 if (errno < sys_nerr)
204 return sys_errlist[errnum];
205
206 sprintf (buf, _("Unknown error %d"), errnum);
207 return buf;
208}
209#endif
210
211
212/* Like malloc but get fatal error if memory is exhausted. */
213/* Don't bother if we're using dmalloc; it provides these for us. */
214
215#ifndef HAVE_DMALLOC_H
216
217#undef xmalloc
218#undef xcalloc
219#undef xrealloc
220#undef xstrdup
221
222void *
223xmalloc (unsigned int size)
224{
225 /* Make sure we don't allocate 0, for pre-ISO implementations. */
226 void *result = malloc (size ? size : 1);
227 if (result == 0)
228 OUT_OF_MEM();
229 return result;
230}
231
232
233void *
234xcalloc (unsigned int size)
235{
236 /* Make sure we don't allocate 0, for pre-ISO implementations. */
237 void *result = calloc (size ? size : 1, 1);
238 if (result == 0)
239 OUT_OF_MEM();
240 return result;
241}
242
243
244void *
245xrealloc (void *ptr, unsigned int size)
246{
247 void *result;
248
249 /* Some older implementations of realloc() don't conform to ISO. */
250 if (! size)
251 size = 1;
252 result = ptr ? realloc (ptr, size) : malloc (size);
253 if (result == 0)
254 OUT_OF_MEM();
255 return result;
256}
257
258
259char *
260xstrdup (const char *ptr)
261{
262 char *result;
263
264#ifdef HAVE_STRDUP
265 result = strdup (ptr);
266#else
267 result = malloc (strlen (ptr) + 1);
268#endif
269
270 if (result == 0)
271 OUT_OF_MEM();
272
273#ifdef HAVE_STRDUP
274 return result;
275#else
276 return strcpy (result, ptr);
277#endif
278}
279
280#endif /* HAVE_DMALLOC_H */
281
282char *
283xstrndup (const char *str, unsigned int length)
284{
285 char *result;
286
287#ifdef HAVE_STRNDUP
288 result = strndup (str, length);
289 if (result == 0)
290 OUT_OF_MEM();
291#else
292 result = xmalloc (length + 1);
293 if (length > 0)
294 strncpy (result, str, length);
295 result[length] = '\0';
296#endif
297
298 return result;
299}
300
301
302
303/* Limited INDEX:
304 Search through the string STRING, which ends at LIMIT, for the character C.
305 Returns a pointer to the first occurrence, or nil if none is found.
306 Like INDEX except that the string searched ends where specified
307 instead of at the first null. */
308
309char *
310lindex (const char *s, const char *limit, int c)
311{
312 while (s < limit)
313 if (*s++ == c)
314 return (char *)(s - 1);
315
316 return 0;
317}
318
319
320/* Return the address of the first whitespace or null in the string S. */
321
322char *
323end_of_token (const char *s)
324{
325 END_OF_TOKEN (s);
326 return (char *)s;
327}
328
329/* Return the address of the first nonwhitespace or null in the string S. */
330
331char *
332next_token (const char *s)
333{
334 NEXT_TOKEN (s);
335 return (char *)s;
336}
337
338/* Find the next token in PTR; return the address of it, and store the length
339 of the token into *LENGTHPTR if LENGTHPTR is not nil. Set *PTR to the end
340 of the token, so this function can be called repeatedly in a loop. */
341
342char *
343find_next_token (const char **ptr, unsigned int *lengthptr)
344{
345 const char *p = next_token (*ptr);
346
347 if (*p == '\0')
348 return 0;
349
350 *ptr = end_of_token (p);
351 if (lengthptr != 0)
352 *lengthptr = *ptr - p;
353
354 return (char *)p;
355}
356
357
358
359/* Copy a chain of 'struct dep'. For 2nd expansion deps, dup the name. */
360
361struct dep *
362copy_dep_chain (const struct dep *d)
363{
364 struct dep *firstnew = 0;
365 struct dep *lastnew = 0;
366
367 while (d != 0)
368 {
369 struct dep *c = xmalloc (sizeof (struct dep));
370 memcpy (c, d, sizeof (struct dep));
371
372 if (c->need_2nd_expansion)
373 c->name = xstrdup (c->name);
374
375 c->next = 0;
376 if (firstnew == 0)
377 firstnew = lastnew = c;
378 else
379 lastnew = lastnew->next = c;
380
381 d = d->next;
382 }
383
384 return firstnew;
385}
386
387/* Free a chain of struct nameseq.
388 For struct dep chains use free_dep_chain. */
389
390void
391free_ns_chain (struct nameseq *ns)
392{
393 while (ns != 0)
394 {
395 struct nameseq *t = ns;
396 ns = ns->next;
397 free_ns (t);
398 }
399}
400
401
402
403#if !HAVE_STRCASECMP && !HAVE_STRICMP && !HAVE_STRCMPI
404/* If we don't have strcasecmp() (from POSIX), or anything that can substitute
405 for it, define our own version. */
406
407int
408strcasecmp (const char *s1, const char *s2)
409{
410 while (1)
411 {
412 int c1 = (int) *(s1++);
413 int c2 = (int) *(s2++);
414
415 if (isalpha (c1))
416 c1 = tolower (c1);
417 if (isalpha (c2))
418 c2 = tolower (c2);
419
420 if (c1 != '\0' && c1 == c2)
421 continue;
422
423 return (c1 - c2);
424 }
425}
426#endif
427
428#if !HAVE_STRNCASECMP && !HAVE_STRNICMP && !HAVE_STRNCMPI
429/* If we don't have strncasecmp() (from POSIX), or anything that can
430 substitute for it, define our own version. */
431
432int
433strncasecmp (const char *s1, const char *s2, int n)
434{
435 while (n-- > 0)
436 {
437 int c1 = (int) *(s1++);
438 int c2 = (int) *(s2++);
439
440 if (isalpha (c1))
441 c1 = tolower (c1);
442 if (isalpha (c2))
443 c2 = tolower (c2);
444
445 if (c1 != '\0' && c1 == c2)
446 continue;
447
448 return (c1 - c2);
449 }
450
451 return 0;
452}
453#endif
454
455
456#ifdef GETLOADAVG_PRIVILEGED
457
458#ifdef POSIX
459
460/* Hopefully if a system says it's POSIX.1 and has the setuid and setgid
461 functions, they work as POSIX.1 says. Some systems (Alpha OSF/1 1.2,
462 for example) which claim to be POSIX.1 also have the BSD setreuid and
463 setregid functions, but they don't work as in BSD and only the POSIX.1
464 way works. */
465
466#undef HAVE_SETREUID
467#undef HAVE_SETREGID
468
469#else /* Not POSIX. */
470
471/* Some POSIX.1 systems have the seteuid and setegid functions. In a
472 POSIX-like system, they are the best thing to use. However, some
473 non-POSIX systems have them too but they do not work in the POSIX style
474 and we must use setreuid and setregid instead. */
475
476#undef HAVE_SETEUID
477#undef HAVE_SETEGID
478
479#endif /* POSIX. */
480
481#ifndef HAVE_UNISTD_H
482extern int getuid (), getgid (), geteuid (), getegid ();
483extern int setuid (), setgid ();
484#ifdef HAVE_SETEUID
485extern int seteuid ();
486#else
487#ifdef HAVE_SETREUID
488extern int setreuid ();
489#endif /* Have setreuid. */
490#endif /* Have seteuid. */
491#ifdef HAVE_SETEGID
492extern int setegid ();
493#else
494#ifdef HAVE_SETREGID
495extern int setregid ();
496#endif /* Have setregid. */
497#endif /* Have setegid. */
498#endif /* No <unistd.h>. */
499
500/* Keep track of the user and group IDs for user- and make- access. */
501static int user_uid = -1, user_gid = -1, make_uid = -1, make_gid = -1;
502#define access_inited (user_uid != -1)
503static enum { make, user } current_access;
504
505
506/* Under -d, write a message describing the current IDs. */
507
508static void
509log_access (const char *flavor)
510{
511 if (! ISDB (DB_JOBS))
512 return;
513
514 /* All the other debugging messages go to stdout,
515 but we write this one to stderr because it might be
516 run in a child fork whose stdout is piped. */
517
518 fprintf (stderr, _("%s: user %lu (real %lu), group %lu (real %lu)\n"),
519 flavor, (unsigned long) geteuid (), (unsigned long) getuid (),
520 (unsigned long) getegid (), (unsigned long) getgid ());
521 fflush (stderr);
522}
523
524
525static void
526init_access (void)
527{
528#ifndef VMS
529 user_uid = getuid ();
530 user_gid = getgid ();
531
532 make_uid = geteuid ();
533 make_gid = getegid ();
534
535 /* Do these ever fail? */
536 if (user_uid == -1 || user_gid == -1 || make_uid == -1 || make_gid == -1)
537 pfatal_with_name ("get{e}[gu]id");
538
539 log_access (_("Initialized access"));
540
541 current_access = make;
542#endif
543}
544
545#endif /* GETLOADAVG_PRIVILEGED */
546
547/* Give the process appropriate permissions for access to
548 user data (i.e., to stat files, or to spawn a child process). */
549void
550user_access (void)
551{
552#ifdef GETLOADAVG_PRIVILEGED
553
554 if (!access_inited)
555 init_access ();
556
557 if (current_access == user)
558 return;
559
560 /* We are in "make access" mode. This means that the effective user and
561 group IDs are those of make (if it was installed setuid or setgid).
562 We now want to set the effective user and group IDs to the real IDs,
563 which are the IDs of the process that exec'd make. */
564
565#ifdef HAVE_SETEUID
566
567 /* Modern systems have the seteuid/setegid calls which set only the
568 effective IDs, which is ideal. */
569
570 if (seteuid (user_uid) < 0)
571 pfatal_with_name ("user_access: seteuid");
572
573#else /* Not HAVE_SETEUID. */
574
575#ifndef HAVE_SETREUID
576
577 /* System V has only the setuid/setgid calls to set user/group IDs.
578 There is an effective ID, which can be set by setuid/setgid.
579 It can be set (unless you are root) only to either what it already is
580 (returned by geteuid/getegid, now in make_uid/make_gid),
581 the real ID (return by getuid/getgid, now in user_uid/user_gid),
582 or the saved set ID (what the effective ID was before this set-ID
583 executable (make) was exec'd). */
584
585 if (setuid (user_uid) < 0)
586 pfatal_with_name ("user_access: setuid");
587
588#else /* HAVE_SETREUID. */
589
590 /* In 4BSD, the setreuid/setregid calls set both the real and effective IDs.
591 They may be set to themselves or each other. So you have two alternatives
592 at any one time. If you use setuid/setgid, the effective will be set to
593 the real, leaving only one alternative. Using setreuid/setregid, however,
594 you can toggle between your two alternatives by swapping the values in a
595 single setreuid or setregid call. */
596
597 if (setreuid (make_uid, user_uid) < 0)
598 pfatal_with_name ("user_access: setreuid");
599
600#endif /* Not HAVE_SETREUID. */
601#endif /* HAVE_SETEUID. */
602
603#ifdef HAVE_SETEGID
604 if (setegid (user_gid) < 0)
605 pfatal_with_name ("user_access: setegid");
606#else
607#ifndef HAVE_SETREGID
608 if (setgid (user_gid) < 0)
609 pfatal_with_name ("user_access: setgid");
610#else
611 if (setregid (make_gid, user_gid) < 0)
612 pfatal_with_name ("user_access: setregid");
613#endif
614#endif
615
616 current_access = user;
617
618 log_access (_("User access"));
619
620#endif /* GETLOADAVG_PRIVILEGED */
621}
622
623/* Give the process appropriate permissions for access to
624 make data (i.e., the load average). */
625void
626make_access (void)
627{
628#ifdef GETLOADAVG_PRIVILEGED
629
630 if (!access_inited)
631 init_access ();
632
633 if (current_access == make)
634 return;
635
636 /* See comments in user_access, above. */
637
638#ifdef HAVE_SETEUID
639 if (seteuid (make_uid) < 0)
640 pfatal_with_name ("make_access: seteuid");
641#else
642#ifndef HAVE_SETREUID
643 if (setuid (make_uid) < 0)
644 pfatal_with_name ("make_access: setuid");
645#else
646 if (setreuid (user_uid, make_uid) < 0)
647 pfatal_with_name ("make_access: setreuid");
648#endif
649#endif
650
651#ifdef HAVE_SETEGID
652 if (setegid (make_gid) < 0)
653 pfatal_with_name ("make_access: setegid");
654#else
655#ifndef HAVE_SETREGID
656 if (setgid (make_gid) < 0)
657 pfatal_with_name ("make_access: setgid");
658#else
659 if (setregid (user_gid, make_gid) < 0)
660 pfatal_with_name ("make_access: setregid");
661#endif
662#endif
663
664 current_access = make;
665
666 log_access (_("Make access"));
667
668#endif /* GETLOADAVG_PRIVILEGED */
669}
670
671/* Give the process appropriate permissions for a child process.
672 This is like user_access, but you can't get back to make_access. */
673void
674child_access (void)
675{
676#ifdef GETLOADAVG_PRIVILEGED
677
678 if (!access_inited)
679 abort ();
680
681 /* Set both the real and effective UID and GID to the user's.
682 They cannot be changed back to make's. */
683
684#ifndef HAVE_SETREUID
685 if (setuid (user_uid) < 0)
686 pfatal_with_name ("child_access: setuid");
687#else
688 if (setreuid (user_uid, user_uid) < 0)
689 pfatal_with_name ("child_access: setreuid");
690#endif
691
692#ifndef HAVE_SETREGID
693 if (setgid (user_gid) < 0)
694 pfatal_with_name ("child_access: setgid");
695#else
696 if (setregid (user_gid, user_gid) < 0)
697 pfatal_with_name ("child_access: setregid");
698#endif
699
700 log_access (_("Child access"));
701
702#endif /* GETLOADAVG_PRIVILEGED */
703}
704
705#ifdef NEED_GET_PATH_MAX
706unsigned int
707get_path_max (void)
708{
709 static unsigned int value;
710
711 if (value == 0)
712 {
713 long int x = pathconf ("/", _PC_PATH_MAX);
714 if (x > 0)
715 value = x;
716 else
717 return MAXPATHLEN;
718 }
719
720 return value;
721}
722#endif
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use