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