1141104Sharti/*-
2104818Sjmallett * Copyright (c) 2002 Juli Mallett.  All rights reserved.
3104818Sjmallett * Copyright (c) 1988, 1989, 1990, 1993
4104818Sjmallett *	The Regents of the University of California.  All rights reserved.
5104818Sjmallett * Copyright (c) 1989 by Berkeley Softworks
6104818Sjmallett * All rights reserved.
7104818Sjmallett *
8104818Sjmallett * This code is derived from software contributed to Berkeley by
9104818Sjmallett * Adam de Boor.
10104818Sjmallett *
11104818Sjmallett * Redistribution and use in source and binary forms, with or without
12104818Sjmallett * modification, are permitted provided that the following conditions
13104818Sjmallett * are met:
14104818Sjmallett * 1. Redistributions of source code must retain the above copyright
15104818Sjmallett *    notice, this list of conditions and the following disclaimer.
16104818Sjmallett * 2. Redistributions in binary form must reproduce the above copyright
17104818Sjmallett *    notice, this list of conditions and the following disclaimer in the
18104818Sjmallett *    documentation and/or other materials provided with the distribution.
19104818Sjmallett * 3. All advertising materials mentioning features or use of this software
20104818Sjmallett *    must display the following acknowledgement:
21104818Sjmallett *	This product includes software developed by the University of
22104818Sjmallett *	California, Berkeley and its contributors.
23104818Sjmallett * 4. Neither the name of the University nor the names of its contributors
24104818Sjmallett *    may be used to endorse or promote products derived from this software
25104818Sjmallett *    without specific prior written permission.
26104818Sjmallett *
27104818Sjmallett * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28104818Sjmallett * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29104818Sjmallett * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30104818Sjmallett * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31104818Sjmallett * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32104818Sjmallett * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33104818Sjmallett * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34104818Sjmallett * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35104818Sjmallett * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36104818Sjmallett * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37104818Sjmallett * SUCH DAMAGE.
38104818Sjmallett *
39104818Sjmallett * @(#)main.c      8.3 (Berkeley) 3/19/94
40104818Sjmallett */
41104818Sjmallett
42104818Sjmallett#include <sys/cdefs.h>
43104818Sjmallett__FBSDID("$FreeBSD: releng/10.3/usr.bin/make/util.c 146184 2005-05-13 13:47:41Z harti $");
44104818Sjmallett
45104818Sjmallett/*-
46104818Sjmallett * util.c --
47104818Sjmallett *	General utilitarian routines for make(1).
48104818Sjmallett */
49104818Sjmallett
50104818Sjmallett#include <sys/types.h>
51104818Sjmallett#include <sys/stat.h>
52104818Sjmallett#include <err.h>
53104818Sjmallett#include <errno.h>
54104818Sjmallett#include <stdarg.h>
55141104Sharti#include <stdlib.h>
56141104Sharti#include <string.h>
57104818Sjmallett#include <unistd.h>
58104818Sjmallett
59141104Sharti#include "globals.h"
60104818Sjmallett#include "job.h"
61141104Sharti#include "targ.h"
62141104Sharti#include "util.h"
63104818Sjmallett
64141139Shartistatic void enomem(void) __dead2;
65141139Sharti
66104818Sjmallett/*-
67104818Sjmallett * Debug --
68104818Sjmallett *	Print a debugging message given its format.
69104818Sjmallett *
70104818Sjmallett * Results:
71104818Sjmallett *	None.
72104818Sjmallett *
73104818Sjmallett * Side Effects:
74104818Sjmallett *	The message is printed.
75104818Sjmallett */
76104818Sjmallett/* VARARGS */
77104818Sjmallettvoid
78104818SjmallettDebug(const char *fmt, ...)
79104818Sjmallett{
80104818Sjmallett	va_list ap;
81104818Sjmallett
82104818Sjmallett	va_start(ap, fmt);
83138232Sharti	vfprintf(stderr, fmt, ap);
84104818Sjmallett	va_end(ap);
85138232Sharti	fflush(stderr);
86104818Sjmallett}
87104818Sjmallett
88104818Sjmallett/*-
89143278Sharti * Print a debugging message given its format and append the current
90143278Sharti * errno description. Terminate with a newline.
91143278Sharti */
92143278Sharti/* VARARGS */
93143278Shartivoid
94143278ShartiDebugM(const char *fmt, ...)
95143278Sharti{
96143278Sharti	va_list	ap;
97143278Sharti	int e = errno;
98143278Sharti
99143278Sharti	va_start(ap, fmt);
100143278Sharti	vfprintf(stderr, fmt, ap);
101143278Sharti	fprintf(stderr, ": %s\n", strerror(e));
102143278Sharti	va_end(ap);
103143278Sharti	fflush(stderr);
104143278Sharti}
105143278Sharti
106143278Sharti/*-
107104818Sjmallett * Error --
108104818Sjmallett *	Print an error message given its format.
109104818Sjmallett *
110104818Sjmallett * Results:
111104818Sjmallett *	None.
112104818Sjmallett *
113104818Sjmallett * Side Effects:
114104818Sjmallett *	The message is printed.
115104818Sjmallett */
116104818Sjmallett/* VARARGS */
117104818Sjmallettvoid
118104818SjmallettError(const char *fmt, ...)
119104818Sjmallett{
120104818Sjmallett	va_list ap;
121104818Sjmallett
122104818Sjmallett	va_start(ap, fmt);
123138232Sharti	vfprintf(stderr, fmt, ap);
124104818Sjmallett	va_end(ap);
125138232Sharti	fprintf(stderr, "\n");
126138232Sharti	fflush(stderr);
127104818Sjmallett}
128104818Sjmallett
129104818Sjmallett/*-
130104818Sjmallett * Fatal --
131104818Sjmallett *	Produce a Fatal error message. If jobs are running, waits for them
132104818Sjmallett *	to finish.
133104818Sjmallett *
134104818Sjmallett * Results:
135104818Sjmallett *	None
136104818Sjmallett *
137104818Sjmallett * Side Effects:
138104818Sjmallett *	The program exits
139104818Sjmallett */
140104818Sjmallett/* VARARGS */
141104818Sjmallettvoid
142104818SjmallettFatal(const char *fmt, ...)
143104818Sjmallett{
144104818Sjmallett	va_list ap;
145104818Sjmallett
146104818Sjmallett	va_start(ap, fmt);
147104818Sjmallett	if (jobsRunning)
148104818Sjmallett		Job_Wait();
149104818Sjmallett
150138232Sharti	vfprintf(stderr, fmt, ap);
151104818Sjmallett	va_end(ap);
152138232Sharti	fprintf(stderr, "\n");
153138232Sharti	fflush(stderr);
154104818Sjmallett
155104818Sjmallett	if (DEBUG(GRAPH2))
156104818Sjmallett		Targ_PrintGraph(2);
157104818Sjmallett	exit(2);		/* Not 1 so -q can distinguish error */
158104818Sjmallett}
159104818Sjmallett
160104818Sjmallett/*
161104818Sjmallett * Punt --
162104818Sjmallett *	Major exception once jobs are being created. Kills all jobs, prints
163104818Sjmallett *	a message and exits.
164104818Sjmallett *
165104818Sjmallett * Results:
166104818Sjmallett *	None
167104818Sjmallett *
168104818Sjmallett * Side Effects:
169104818Sjmallett *	All children are killed indiscriminately and the program Lib_Exits
170104818Sjmallett */
171104818Sjmallett/* VARARGS */
172104818Sjmallettvoid
173104818SjmallettPunt(const char *fmt, ...)
174104818Sjmallett{
175104818Sjmallett	va_list ap;
176104818Sjmallett
177104818Sjmallett	va_start(ap, fmt);
178138232Sharti	fprintf(stderr, "make: ");
179138232Sharti	vfprintf(stderr, fmt, ap);
180104818Sjmallett	va_end(ap);
181138232Sharti	fprintf(stderr, "\n");
182138232Sharti	fflush(stderr);
183104818Sjmallett
184104818Sjmallett	DieHorribly();
185104818Sjmallett}
186104818Sjmallett
187104818Sjmallett/*-
188104818Sjmallett * DieHorribly --
189104818Sjmallett *	Exit without giving a message.
190104818Sjmallett *
191104818Sjmallett * Results:
192104818Sjmallett *	None
193104818Sjmallett *
194104818Sjmallett * Side Effects:
195104818Sjmallett *	A big one...
196104818Sjmallett */
197104818Sjmallettvoid
198104818SjmallettDieHorribly(void)
199104818Sjmallett{
200104818Sjmallett	if (jobsRunning)
201104818Sjmallett		Job_AbortAll();
202104818Sjmallett	if (DEBUG(GRAPH2))
203104818Sjmallett		Targ_PrintGraph(2);
204104818Sjmallett	exit(2);		/* Not 1, so -q can distinguish error */
205104818Sjmallett}
206104818Sjmallett
207104818Sjmallett/*
208104818Sjmallett * Finish --
209104818Sjmallett *	Called when aborting due to errors in child shell to signal
210104818Sjmallett *	abnormal exit, with the number of errors encountered in Make_Make.
211104818Sjmallett *
212104818Sjmallett * Results:
213104818Sjmallett *	None
214104818Sjmallett *
215104818Sjmallett * Side Effects:
216104818Sjmallett *	The program exits
217104818Sjmallett */
218104818Sjmallettvoid
219104818SjmallettFinish(int errors)
220104818Sjmallett{
221138232Sharti
222104818Sjmallett	Fatal("%d error%s", errors, errors == 1 ? "" : "s");
223104818Sjmallett}
224104818Sjmallett
225104818Sjmallett/*
226104818Sjmallett * emalloc --
227104818Sjmallett *	malloc, but die on error.
228104818Sjmallett */
229104818Sjmallettvoid *
230104818Sjmallettemalloc(size_t len)
231104818Sjmallett{
232104818Sjmallett	void *p;
233104818Sjmallett
234104818Sjmallett	if ((p = malloc(len)) == NULL)
235104818Sjmallett		enomem();
236138232Sharti	return (p);
237104818Sjmallett}
238104818Sjmallett
239104818Sjmallett/*
240104818Sjmallett * estrdup --
241104818Sjmallett *	strdup, but die on error.
242104818Sjmallett */
243104818Sjmallettchar *
244104818Sjmallettestrdup(const char *str)
245104818Sjmallett{
246104818Sjmallett	char *p;
247104818Sjmallett
248104818Sjmallett	if ((p = strdup(str)) == NULL)
249104818Sjmallett		enomem();
250138232Sharti	return (p);
251104818Sjmallett}
252104818Sjmallett
253104818Sjmallett/*
254104818Sjmallett * erealloc --
255104818Sjmallett *	realloc, but die on error.
256104818Sjmallett */
257104818Sjmallettvoid *
258104818Sjmalletterealloc(void *ptr, size_t size)
259104818Sjmallett{
260138232Sharti
261104818Sjmallett	if ((ptr = realloc(ptr, size)) == NULL)
262104818Sjmallett		enomem();
263138232Sharti	return (ptr);
264104818Sjmallett}
265104818Sjmallett
266104818Sjmallett/*
267104818Sjmallett * enomem --
268104818Sjmallett *	die when out of memory.
269104818Sjmallett */
270141139Shartistatic void
271104818Sjmallettenomem(void)
272104818Sjmallett{
273104818Sjmallett	err(2, NULL);
274104818Sjmallett}
275104818Sjmallett
276104818Sjmallett/*
277104818Sjmallett * enunlink --
278104818Sjmallett *	Remove a file carefully, avoiding directories.
279104818Sjmallett */
280104818Sjmallettint
281104818Sjmalletteunlink(const char *file)
282104818Sjmallett{
283104818Sjmallett	struct stat st;
284104818Sjmallett
285104818Sjmallett	if (lstat(file, &st) == -1)
286138232Sharti		return (-1);
287104818Sjmallett
288104818Sjmallett	if (S_ISDIR(st.st_mode)) {
289104818Sjmallett		errno = EISDIR;
290138232Sharti		return (-1);
291104818Sjmallett	}
292138232Sharti	return (unlink(file));
293104818Sjmallett}
294104818Sjmallett
295143414Sharti/*
296143414Sharti * Convert a flag word to a printable thing and print it
297143414Sharti */
298143414Shartivoid
299146184Shartiprint_flags(FILE *fp, const struct flag2str *tab, u_int flags, int par)
300143414Sharti{
301143414Sharti	int first = 1;
302143414Sharti
303146184Sharti	if (par)
304146184Sharti		fprintf(fp, "(");
305143414Sharti	while (tab->str != NULL) {
306143414Sharti		if (flags & tab->flag) {
307143414Sharti			if (!first)
308146184Sharti				fprintf(fp, par ? "|" : " ");
309143414Sharti			first = 0;
310143414Sharti			fprintf(fp, "%s", tab->str);
311143414Sharti		}
312143414Sharti		tab++;
313143414Sharti	}
314146184Sharti	if (par)
315146184Sharti		fprintf(fp, ")");
316143414Sharti}
317