1 /*-
2 * Copyright (c) 2002 Juli Mallett. All rights reserved.
3 * Copyright (c) 1988, 1989, 1990, 1993
4 * The Regents of the University of California. All rights reserved.
5 * Copyright (c) 1989 by Berkeley Softworks
6 * All rights reserved.
7 *
8 * This code is derived from software contributed to Berkeley by
9 * Adam de Boor.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by the University of
22 * California, Berkeley and its contributors.
23 * 4. Neither the name of the University nor the names of its contributors
24 * may be used to endorse or promote products derived from this software
25 * without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 * SUCH DAMAGE.
38 *
39 * @(#)main.c 8.3 (Berkeley) 3/19/94
40 */
41
42 #include <sys/cdefs.h>
43
44 /*-
45 * util.c --
46 * General utilitarian routines for make(1).
47 */
48
49 #include <sys/types.h>
50 #include <sys/stat.h>
51 #include <err.h>
52 #include <errno.h>
53 #include <stdarg.h>
54 #include <stdlib.h>
55 #include <string.h>
56 #include <unistd.h>
57
58 #include "globals.h"
59 #include "job.h"
60 #include "targ.h"
61 #include "util.h"
62
63 static void enomem(void) __dead2;
64
65 /*-
66 * Debug --
67 * Print a debugging message given its format.
68 *
69 * Results:
70 * None.
71 *
72 * Side Effects:
73 * The message is printed.
74 */
75 /* VARARGS */
76 void
Debug(const char * fmt,...)77 Debug(const char *fmt, ...)
78 {
79 va_list ap;
80
81 va_start(ap, fmt);
82 vfprintf(stderr, fmt, ap);
83 va_end(ap);
84 fflush(stderr);
85 }
86
87 /*-
88 * Print a debugging message given its format and append the current
89 * errno description. Terminate with a newline.
90 */
91 /* VARARGS */
92 void
DebugM(const char * fmt,...)93 DebugM(const char *fmt, ...)
94 {
95 va_list ap;
96 int e = errno;
97
98 va_start(ap, fmt);
99 vfprintf(stderr, fmt, ap);
100 fprintf(stderr, ": %s\n", strerror(e));
101 va_end(ap);
102 fflush(stderr);
103 }
104
105 /*-
106 * Error --
107 * Print an error message given its format.
108 *
109 * Results:
110 * None.
111 *
112 * Side Effects:
113 * The message is printed.
114 */
115 /* VARARGS */
116 void
Error(const char * fmt,...)117 Error(const char *fmt, ...)
118 {
119 va_list ap;
120
121 va_start(ap, fmt);
122 vfprintf(stderr, fmt, ap);
123 va_end(ap);
124 fprintf(stderr, "\n");
125 fflush(stderr);
126 }
127
128 /*-
129 * Fatal --
130 * Produce a Fatal error message. If jobs are running, waits for them
131 * to finish.
132 *
133 * Results:
134 * None
135 *
136 * Side Effects:
137 * The program exits
138 */
139 /* VARARGS */
140 void
Fatal(const char * fmt,...)141 Fatal(const char *fmt, ...)
142 {
143 va_list ap;
144
145 va_start(ap, fmt);
146 if (jobsRunning)
147 Job_Wait();
148
149 vfprintf(stderr, fmt, ap);
150 va_end(ap);
151 fprintf(stderr, "\n");
152 fflush(stderr);
153
154 if (DEBUG(GRAPH2))
155 Targ_PrintGraph(2);
156 exit(2); /* Not 1 so -q can distinguish error */
157 }
158
159 /*
160 * Punt --
161 * Major exception once jobs are being created. Kills all jobs, prints
162 * a message and exits.
163 *
164 * Results:
165 * None
166 *
167 * Side Effects:
168 * All children are killed indiscriminately and the program Lib_Exits
169 */
170 /* VARARGS */
171 void
Punt(const char * fmt,...)172 Punt(const char *fmt, ...)
173 {
174 va_list ap;
175
176 va_start(ap, fmt);
177 fprintf(stderr, "make: ");
178 vfprintf(stderr, fmt, ap);
179 va_end(ap);
180 fprintf(stderr, "\n");
181 fflush(stderr);
182
183 DieHorribly();
184 }
185
186 /*-
187 * DieHorribly --
188 * Exit without giving a message.
189 *
190 * Results:
191 * None
192 *
193 * Side Effects:
194 * A big one...
195 */
196 void
DieHorribly(void)197 DieHorribly(void)
198 {
199 if (jobsRunning)
200 Job_AbortAll();
201 if (DEBUG(GRAPH2))
202 Targ_PrintGraph(2);
203 exit(2); /* Not 1, so -q can distinguish error */
204 }
205
206 /*
207 * Finish --
208 * Called when aborting due to errors in child shell to signal
209 * abnormal exit, with the number of errors encountered in Make_Make.
210 *
211 * Results:
212 * None
213 *
214 * Side Effects:
215 * The program exits
216 */
217 void
Finish(int errors)218 Finish(int errors)
219 {
220
221 Fatal("%d error%s", errors, errors == 1 ? "" : "s");
222 }
223
224 /*
225 * emalloc --
226 * malloc, but die on error.
227 */
228 void *
emalloc(size_t len)229 emalloc(size_t len)
230 {
231 void *p;
232
233 if ((p = malloc(len)) == NULL)
234 enomem();
235 return (p);
236 }
237
238 /*
239 * estrdup --
240 * strdup, but die on error.
241 */
242 char *
estrdup(const char * str)243 estrdup(const char *str)
244 {
245 char *p;
246
247 if ((p = strdup(str)) == NULL)
248 enomem();
249 return (p);
250 }
251
252 /*
253 * erealloc --
254 * realloc, but die on error.
255 */
256 void *
erealloc(void * ptr,size_t size)257 erealloc(void *ptr, size_t size)
258 {
259
260 if ((ptr = realloc(ptr, size)) == NULL)
261 enomem();
262 return (ptr);
263 }
264
265 /*
266 * enomem --
267 * die when out of memory.
268 */
269 static void
enomem(void)270 enomem(void)
271 {
272 err(2, NULL);
273 }
274
275 /*
276 * enunlink --
277 * Remove a file carefully, avoiding directories.
278 */
279 int
eunlink(const char * file)280 eunlink(const char *file)
281 {
282 struct stat st;
283
284 if (lstat(file, &st) == -1)
285 return (-1);
286
287 if (S_ISDIR(st.st_mode)) {
288 errno = EISDIR;
289 return (-1);
290 }
291 return (unlink(file));
292 }
293
294 /*
295 * Convert a flag word to a printable thing and print it
296 */
297 void
print_flags(FILE * fp,const struct flag2str * tab,u_int flags,int par)298 print_flags(FILE *fp, const struct flag2str *tab, u_int flags, int par)
299 {
300 int first = 1;
301
302 if (par)
303 fprintf(fp, "(");
304 while (tab->str != NULL) {
305 if (flags & tab->flag) {
306 if (!first)
307 fprintf(fp, par ? "|" : " ");
308 first = 0;
309 fprintf(fp, "%s", tab->str);
310 }
311 tab++;
312 }
313 if (par)
314 fprintf(fp, ")");
315 }
316