1 /* -*- c-file-style: "java"; indent-tabs-mode: nil; fill-column: 78 -*-
2 *
3 * distcc -- A simple distributed compiler system
4 *
5 * Copyright (C) 2002, 2003, 2004 by Martin Pool <mbp@samba.org>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
20 * USA.
21 */
22
23
24
25 /*
26 * Utilities for dealing with argv[]-style strings.
27 *
28 * These rules might not yet be consistently applied in distcc, but they
29 * should be in the future:
30 *
31 * For simplicity in managing memory we try to keep all argv structures
32 * malloc'd, without any shared structure. It is then possible to just free
33 * the whole thing whenever we're finished with it.
34 *
35 * One exception is of course the argv used to invoke the program, which is
36 * treated as read-only.
37 */
38
39
40 #include <config.h>
41
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <unistd.h>
45 #include <string.h>
46 #include <fcntl.h>
47 #include <errno.h>
48
49 #include <sys/stat.h>
50
51 #include "distcc.h"
52 #include "trace.h"
53 #include "util.h"
54 #include "exitcode.h"
55
56
57 /**
58 * Return true if argv contains needle as an argument.
59 **/
dcc_argv_search(char ** a,const char * needle)60 int dcc_argv_search(char **a,
61 const char *needle)
62 {
63 for (; *a; a++)
64 if (!strcmp(*a, needle))
65 return 1;
66 return 0;
67 }
68
69
dcc_argv_len(char ** a)70 unsigned int dcc_argv_len(char **a)
71 {
72 unsigned int i;
73
74 for (i = 0; a[i]; i++)
75 ;
76 return i;
77 }
78
79
80 /* Free a malloc'd argv structure. Only safe when the array and all its
81 * components were malloc'd. */
dcc_free_argv(char ** argv)82 void dcc_free_argv(char **argv)
83 {
84 char **a;
85
86 for (a = argv; *a != NULL; a++)
87 free(*a);
88 free(argv);
89 }
90
91
92 /* Copy an argv array, adding extra NULL elements to the end to allow for
93 * adding more arguments later.
94 */
dcc_copy_argv(char ** from,char *** out,int delta)95 int dcc_copy_argv(char **from, char ***out, int delta)
96 {
97 char **b;
98 int l, i, k;
99
100 l = dcc_argv_len(from);
101 b = malloc((l+1+delta) * (sizeof from[0]));
102 if (b == NULL) {
103 rs_log_error("failed to allocate copy of argv");
104 return EXIT_OUT_OF_MEMORY;
105 }
106 for (i = 0; i < l; i++) {
107 if ((b[i] = strdup(from[i])) == NULL) {
108 rs_log_error("failed to duplicate element %d", i);
109 for(k = 0; k < i; k++)
110 free(b[k]);
111 free(b);
112 return EXIT_OUT_OF_MEMORY;
113 }
114 }
115 b[l] = NULL;
116
117 *out = b;
118
119 return 0;
120 }
121
122
123
124 /**
125 * Convert an argv array to printable form for debugging output.
126 *
127 * @note The result is not necessarily properly quoted for passing to
128 * shells.
129 *
130 * @return newly-allocated string containing representation of
131 * arguments.
132 **/
dcc_argv_tostr(char ** a)133 char *dcc_argv_tostr(char **a)
134 {
135 int l, i;
136 char *s, *ss;
137
138 /* calculate total length */
139 for (l = 0, i = 0; a[i]; i++) {
140 l += strlen(a[i]) + 3; /* two quotes and space */
141 }
142
143 ss = s = malloc((size_t) l + 1);
144 if (!s) {
145 rs_log_crit("failed to allocate %d bytes", l+1);
146 exit(EXIT_OUT_OF_MEMORY);
147 }
148
149 for (i = 0; a[i]; i++) {
150 /* kind of half-assed quoting; won't handle strings containing
151 * quotes properly, but good enough for debug messages for the
152 * moment. */
153 int needs_quotes = !*a[i] || (strpbrk(a[i], " \t\n\"\';") != NULL);
154 if (i)
155 *ss++ = ' ';
156 if (needs_quotes)
157 *ss++ = '"';
158 strcpy(ss, a[i]);
159 ss += strlen(a[i]);
160 if (needs_quotes)
161 *ss++ = '"';
162 }
163 *ss = '\0';
164
165 return s;
166 }
167