1*6a54128fSAndroid Build Coastguard Worker /*
2*6a54128fSAndroid Build Coastguard Worker * subst.c --- substitution program
3*6a54128fSAndroid Build Coastguard Worker *
4*6a54128fSAndroid Build Coastguard Worker * Subst is used as a quickie program to do @ substitutions
5*6a54128fSAndroid Build Coastguard Worker *
6*6a54128fSAndroid Build Coastguard Worker */
7*6a54128fSAndroid Build Coastguard Worker
8*6a54128fSAndroid Build Coastguard Worker #ifdef HAVE_CONFIG_H
9*6a54128fSAndroid Build Coastguard Worker #include "config.h"
10*6a54128fSAndroid Build Coastguard Worker #else
11*6a54128fSAndroid Build Coastguard Worker #define HAVE_SYS_STAT_H
12*6a54128fSAndroid Build Coastguard Worker #define HAVE_SYS_TIME_H
13*6a54128fSAndroid Build Coastguard Worker #endif
14*6a54128fSAndroid Build Coastguard Worker #include <stdio.h>
15*6a54128fSAndroid Build Coastguard Worker #include <errno.h>
16*6a54128fSAndroid Build Coastguard Worker #include <stdlib.h>
17*6a54128fSAndroid Build Coastguard Worker #include <unistd.h>
18*6a54128fSAndroid Build Coastguard Worker #include <string.h>
19*6a54128fSAndroid Build Coastguard Worker #include <ctype.h>
20*6a54128fSAndroid Build Coastguard Worker #ifdef HAVE_SYS_TIME_H
21*6a54128fSAndroid Build Coastguard Worker #include <sys/time.h>
22*6a54128fSAndroid Build Coastguard Worker #endif
23*6a54128fSAndroid Build Coastguard Worker #ifdef HAVE_SYS_TYPES_H
24*6a54128fSAndroid Build Coastguard Worker #include <sys/types.h>
25*6a54128fSAndroid Build Coastguard Worker #endif
26*6a54128fSAndroid Build Coastguard Worker #ifdef HAVE_SYS_STAT_H
27*6a54128fSAndroid Build Coastguard Worker #include <sys/stat.h>
28*6a54128fSAndroid Build Coastguard Worker #endif
29*6a54128fSAndroid Build Coastguard Worker #include <fcntl.h>
30*6a54128fSAndroid Build Coastguard Worker #include <time.h>
31*6a54128fSAndroid Build Coastguard Worker #include <utime.h>
32*6a54128fSAndroid Build Coastguard Worker #ifdef HAVE_SYS_TIME_H
33*6a54128fSAndroid Build Coastguard Worker #include <sys/time.h>
34*6a54128fSAndroid Build Coastguard Worker #endif
35*6a54128fSAndroid Build Coastguard Worker
36*6a54128fSAndroid Build Coastguard Worker #ifdef HAVE_GETOPT_H
37*6a54128fSAndroid Build Coastguard Worker #include <getopt.h>
38*6a54128fSAndroid Build Coastguard Worker #else
39*6a54128fSAndroid Build Coastguard Worker extern char *optarg;
40*6a54128fSAndroid Build Coastguard Worker extern int optind;
41*6a54128fSAndroid Build Coastguard Worker #endif
42*6a54128fSAndroid Build Coastguard Worker
43*6a54128fSAndroid Build Coastguard Worker
44*6a54128fSAndroid Build Coastguard Worker struct subst_entry {
45*6a54128fSAndroid Build Coastguard Worker char *name;
46*6a54128fSAndroid Build Coastguard Worker char *value;
47*6a54128fSAndroid Build Coastguard Worker struct subst_entry *next;
48*6a54128fSAndroid Build Coastguard Worker };
49*6a54128fSAndroid Build Coastguard Worker
50*6a54128fSAndroid Build Coastguard Worker static struct subst_entry *subst_table = 0;
51*6a54128fSAndroid Build Coastguard Worker
add_subst(char * name,char * value)52*6a54128fSAndroid Build Coastguard Worker static int add_subst(char *name, char *value)
53*6a54128fSAndroid Build Coastguard Worker {
54*6a54128fSAndroid Build Coastguard Worker struct subst_entry *ent = 0;
55*6a54128fSAndroid Build Coastguard Worker
56*6a54128fSAndroid Build Coastguard Worker ent = (struct subst_entry *) malloc(sizeof(struct subst_entry));
57*6a54128fSAndroid Build Coastguard Worker if (!ent)
58*6a54128fSAndroid Build Coastguard Worker goto fail;
59*6a54128fSAndroid Build Coastguard Worker ent->name = (char *) malloc(strlen(name)+1);
60*6a54128fSAndroid Build Coastguard Worker if (!ent->name)
61*6a54128fSAndroid Build Coastguard Worker goto fail;
62*6a54128fSAndroid Build Coastguard Worker ent->value = (char *) malloc(strlen(value)+1);
63*6a54128fSAndroid Build Coastguard Worker if (!ent->value)
64*6a54128fSAndroid Build Coastguard Worker goto fail;
65*6a54128fSAndroid Build Coastguard Worker strcpy(ent->name, name);
66*6a54128fSAndroid Build Coastguard Worker strcpy(ent->value, value);
67*6a54128fSAndroid Build Coastguard Worker ent->next = subst_table;
68*6a54128fSAndroid Build Coastguard Worker subst_table = ent;
69*6a54128fSAndroid Build Coastguard Worker return 0;
70*6a54128fSAndroid Build Coastguard Worker fail:
71*6a54128fSAndroid Build Coastguard Worker if (ent) {
72*6a54128fSAndroid Build Coastguard Worker free(ent->name);
73*6a54128fSAndroid Build Coastguard Worker free(ent);
74*6a54128fSAndroid Build Coastguard Worker }
75*6a54128fSAndroid Build Coastguard Worker return ENOMEM;
76*6a54128fSAndroid Build Coastguard Worker }
77*6a54128fSAndroid Build Coastguard Worker
fetch_subst_entry(char * name)78*6a54128fSAndroid Build Coastguard Worker static struct subst_entry *fetch_subst_entry(char *name)
79*6a54128fSAndroid Build Coastguard Worker {
80*6a54128fSAndroid Build Coastguard Worker struct subst_entry *ent;
81*6a54128fSAndroid Build Coastguard Worker
82*6a54128fSAndroid Build Coastguard Worker for (ent = subst_table; ent; ent = ent->next) {
83*6a54128fSAndroid Build Coastguard Worker if (strcmp(name, ent->name) == 0)
84*6a54128fSAndroid Build Coastguard Worker break;
85*6a54128fSAndroid Build Coastguard Worker }
86*6a54128fSAndroid Build Coastguard Worker return ent;
87*6a54128fSAndroid Build Coastguard Worker }
88*6a54128fSAndroid Build Coastguard Worker
89*6a54128fSAndroid Build Coastguard Worker /*
90*6a54128fSAndroid Build Coastguard Worker * Given the starting and ending position of the replacement name,
91*6a54128fSAndroid Build Coastguard Worker * check to see if it is valid, and pull it out if it is.
92*6a54128fSAndroid Build Coastguard Worker */
get_subst_symbol(const char * begin,size_t len,char prefix)93*6a54128fSAndroid Build Coastguard Worker static char *get_subst_symbol(const char *begin, size_t len, char prefix)
94*6a54128fSAndroid Build Coastguard Worker {
95*6a54128fSAndroid Build Coastguard Worker static char replace_name[128];
96*6a54128fSAndroid Build Coastguard Worker char *cp, *start;
97*6a54128fSAndroid Build Coastguard Worker
98*6a54128fSAndroid Build Coastguard Worker start = replace_name;
99*6a54128fSAndroid Build Coastguard Worker if (prefix)
100*6a54128fSAndroid Build Coastguard Worker *start++ = prefix;
101*6a54128fSAndroid Build Coastguard Worker
102*6a54128fSAndroid Build Coastguard Worker if (len > sizeof(replace_name)-2)
103*6a54128fSAndroid Build Coastguard Worker return NULL;
104*6a54128fSAndroid Build Coastguard Worker memcpy(start, begin, len);
105*6a54128fSAndroid Build Coastguard Worker start[len] = 0;
106*6a54128fSAndroid Build Coastguard Worker
107*6a54128fSAndroid Build Coastguard Worker /*
108*6a54128fSAndroid Build Coastguard Worker * The substitution variable must all be in the of [0-9A-Za-z_].
109*6a54128fSAndroid Build Coastguard Worker * If it isn't, this must be an invalid symbol name.
110*6a54128fSAndroid Build Coastguard Worker */
111*6a54128fSAndroid Build Coastguard Worker for (cp = start; *cp; cp++) {
112*6a54128fSAndroid Build Coastguard Worker if (!(*cp >= 'a' && *cp <= 'z') &&
113*6a54128fSAndroid Build Coastguard Worker !(*cp >= 'A' && *cp <= 'Z') &&
114*6a54128fSAndroid Build Coastguard Worker !(*cp >= '0' && *cp <= '9') &&
115*6a54128fSAndroid Build Coastguard Worker !(*cp == '_'))
116*6a54128fSAndroid Build Coastguard Worker return NULL;
117*6a54128fSAndroid Build Coastguard Worker }
118*6a54128fSAndroid Build Coastguard Worker return (replace_name);
119*6a54128fSAndroid Build Coastguard Worker }
120*6a54128fSAndroid Build Coastguard Worker
replace_string(char * begin,char * end,char * newstr)121*6a54128fSAndroid Build Coastguard Worker static void replace_string(char *begin, char *end, char *newstr)
122*6a54128fSAndroid Build Coastguard Worker {
123*6a54128fSAndroid Build Coastguard Worker int replace_len, len;
124*6a54128fSAndroid Build Coastguard Worker
125*6a54128fSAndroid Build Coastguard Worker replace_len = strlen(newstr);
126*6a54128fSAndroid Build Coastguard Worker len = end - begin;
127*6a54128fSAndroid Build Coastguard Worker if (replace_len == 0)
128*6a54128fSAndroid Build Coastguard Worker memmove(begin, end+1, strlen(end)+1);
129*6a54128fSAndroid Build Coastguard Worker else if (replace_len != len+1)
130*6a54128fSAndroid Build Coastguard Worker memmove(end+(replace_len-len-1), end,
131*6a54128fSAndroid Build Coastguard Worker strlen(end)+1);
132*6a54128fSAndroid Build Coastguard Worker memcpy(begin, newstr, replace_len);
133*6a54128fSAndroid Build Coastguard Worker }
134*6a54128fSAndroid Build Coastguard Worker
substitute_line(char * line)135*6a54128fSAndroid Build Coastguard Worker static void substitute_line(char *line)
136*6a54128fSAndroid Build Coastguard Worker {
137*6a54128fSAndroid Build Coastguard Worker char *ptr, *name_ptr, *end_ptr;
138*6a54128fSAndroid Build Coastguard Worker struct subst_entry *ent;
139*6a54128fSAndroid Build Coastguard Worker char *replace_name;
140*6a54128fSAndroid Build Coastguard Worker size_t len;
141*6a54128fSAndroid Build Coastguard Worker
142*6a54128fSAndroid Build Coastguard Worker /*
143*6a54128fSAndroid Build Coastguard Worker * Expand all @FOO@ substitutions
144*6a54128fSAndroid Build Coastguard Worker */
145*6a54128fSAndroid Build Coastguard Worker ptr = line;
146*6a54128fSAndroid Build Coastguard Worker while (ptr) {
147*6a54128fSAndroid Build Coastguard Worker name_ptr = strchr(ptr, '@');
148*6a54128fSAndroid Build Coastguard Worker if (!name_ptr)
149*6a54128fSAndroid Build Coastguard Worker break; /* No more */
150*6a54128fSAndroid Build Coastguard Worker if (*(++name_ptr) == '@') {
151*6a54128fSAndroid Build Coastguard Worker /*
152*6a54128fSAndroid Build Coastguard Worker * Handle tytso@@mit.edu --> [email protected]
153*6a54128fSAndroid Build Coastguard Worker */
154*6a54128fSAndroid Build Coastguard Worker memmove(name_ptr-1, name_ptr, strlen(name_ptr)+1);
155*6a54128fSAndroid Build Coastguard Worker ptr = name_ptr+1;
156*6a54128fSAndroid Build Coastguard Worker continue;
157*6a54128fSAndroid Build Coastguard Worker }
158*6a54128fSAndroid Build Coastguard Worker end_ptr = strchr(name_ptr, '@');
159*6a54128fSAndroid Build Coastguard Worker if (!end_ptr)
160*6a54128fSAndroid Build Coastguard Worker break;
161*6a54128fSAndroid Build Coastguard Worker len = end_ptr - name_ptr;
162*6a54128fSAndroid Build Coastguard Worker replace_name = get_subst_symbol(name_ptr, len, 0);
163*6a54128fSAndroid Build Coastguard Worker if (!replace_name) {
164*6a54128fSAndroid Build Coastguard Worker ptr = name_ptr;
165*6a54128fSAndroid Build Coastguard Worker continue;
166*6a54128fSAndroid Build Coastguard Worker }
167*6a54128fSAndroid Build Coastguard Worker ent = fetch_subst_entry(replace_name);
168*6a54128fSAndroid Build Coastguard Worker if (!ent) {
169*6a54128fSAndroid Build Coastguard Worker fprintf(stderr, "Unfound expansion: '%s'\n",
170*6a54128fSAndroid Build Coastguard Worker replace_name);
171*6a54128fSAndroid Build Coastguard Worker ptr = end_ptr + 1;
172*6a54128fSAndroid Build Coastguard Worker continue;
173*6a54128fSAndroid Build Coastguard Worker }
174*6a54128fSAndroid Build Coastguard Worker #if 0
175*6a54128fSAndroid Build Coastguard Worker fprintf(stderr, "Replace name = '%s' with '%s'\n",
176*6a54128fSAndroid Build Coastguard Worker replace_name, ent->value);
177*6a54128fSAndroid Build Coastguard Worker #endif
178*6a54128fSAndroid Build Coastguard Worker ptr = name_ptr-1;
179*6a54128fSAndroid Build Coastguard Worker replace_string(ptr, end_ptr, ent->value);
180*6a54128fSAndroid Build Coastguard Worker if ((ent->value[0] == '@') &&
181*6a54128fSAndroid Build Coastguard Worker (strlen(replace_name) == strlen(ent->value)-2) &&
182*6a54128fSAndroid Build Coastguard Worker !strncmp(replace_name, ent->value+1,
183*6a54128fSAndroid Build Coastguard Worker strlen(ent->value)-2))
184*6a54128fSAndroid Build Coastguard Worker /* avoid an infinite loop */
185*6a54128fSAndroid Build Coastguard Worker ptr += strlen(ent->value);
186*6a54128fSAndroid Build Coastguard Worker }
187*6a54128fSAndroid Build Coastguard Worker /*
188*6a54128fSAndroid Build Coastguard Worker * Now do a second pass to expand ${FOO}
189*6a54128fSAndroid Build Coastguard Worker */
190*6a54128fSAndroid Build Coastguard Worker ptr = line;
191*6a54128fSAndroid Build Coastguard Worker while (ptr) {
192*6a54128fSAndroid Build Coastguard Worker name_ptr = strchr(ptr, '$');
193*6a54128fSAndroid Build Coastguard Worker if (!name_ptr)
194*6a54128fSAndroid Build Coastguard Worker break; /* No more */
195*6a54128fSAndroid Build Coastguard Worker if (*(++name_ptr) != '{') {
196*6a54128fSAndroid Build Coastguard Worker ptr = name_ptr;
197*6a54128fSAndroid Build Coastguard Worker continue;
198*6a54128fSAndroid Build Coastguard Worker }
199*6a54128fSAndroid Build Coastguard Worker name_ptr++;
200*6a54128fSAndroid Build Coastguard Worker end_ptr = strchr(name_ptr, '}');
201*6a54128fSAndroid Build Coastguard Worker if (!end_ptr)
202*6a54128fSAndroid Build Coastguard Worker break;
203*6a54128fSAndroid Build Coastguard Worker len = end_ptr - name_ptr;
204*6a54128fSAndroid Build Coastguard Worker replace_name = get_subst_symbol(name_ptr, len, '$');
205*6a54128fSAndroid Build Coastguard Worker if (!replace_name) {
206*6a54128fSAndroid Build Coastguard Worker ptr = name_ptr;
207*6a54128fSAndroid Build Coastguard Worker continue;
208*6a54128fSAndroid Build Coastguard Worker }
209*6a54128fSAndroid Build Coastguard Worker ent = fetch_subst_entry(replace_name);
210*6a54128fSAndroid Build Coastguard Worker if (!ent) {
211*6a54128fSAndroid Build Coastguard Worker ptr = end_ptr + 1;
212*6a54128fSAndroid Build Coastguard Worker continue;
213*6a54128fSAndroid Build Coastguard Worker }
214*6a54128fSAndroid Build Coastguard Worker #if 0
215*6a54128fSAndroid Build Coastguard Worker fprintf(stderr, "Replace name = '%s' with '%s'\n",
216*6a54128fSAndroid Build Coastguard Worker replace_name, ent->value);
217*6a54128fSAndroid Build Coastguard Worker #endif
218*6a54128fSAndroid Build Coastguard Worker ptr = name_ptr-2;
219*6a54128fSAndroid Build Coastguard Worker replace_string(ptr, end_ptr, ent->value);
220*6a54128fSAndroid Build Coastguard Worker }
221*6a54128fSAndroid Build Coastguard Worker }
222*6a54128fSAndroid Build Coastguard Worker
parse_config_file(FILE * f)223*6a54128fSAndroid Build Coastguard Worker static void parse_config_file(FILE *f)
224*6a54128fSAndroid Build Coastguard Worker {
225*6a54128fSAndroid Build Coastguard Worker char line[2048];
226*6a54128fSAndroid Build Coastguard Worker char *cp, *ptr;
227*6a54128fSAndroid Build Coastguard Worker
228*6a54128fSAndroid Build Coastguard Worker while (!feof(f)) {
229*6a54128fSAndroid Build Coastguard Worker memset(line, 0, sizeof(line));
230*6a54128fSAndroid Build Coastguard Worker if (fgets(line, sizeof(line), f) == NULL)
231*6a54128fSAndroid Build Coastguard Worker break;
232*6a54128fSAndroid Build Coastguard Worker /*
233*6a54128fSAndroid Build Coastguard Worker * Strip newlines and comments.
234*6a54128fSAndroid Build Coastguard Worker */
235*6a54128fSAndroid Build Coastguard Worker cp = strchr(line, '\n');
236*6a54128fSAndroid Build Coastguard Worker if (cp)
237*6a54128fSAndroid Build Coastguard Worker *cp = 0;
238*6a54128fSAndroid Build Coastguard Worker cp = strchr(line, '#');
239*6a54128fSAndroid Build Coastguard Worker if (cp)
240*6a54128fSAndroid Build Coastguard Worker *cp = 0;
241*6a54128fSAndroid Build Coastguard Worker /*
242*6a54128fSAndroid Build Coastguard Worker * Skip trailing and leading whitespace
243*6a54128fSAndroid Build Coastguard Worker */
244*6a54128fSAndroid Build Coastguard Worker for (cp = line + strlen(line) - 1; cp >= line; cp--) {
245*6a54128fSAndroid Build Coastguard Worker if (*cp == ' ' || *cp == '\t')
246*6a54128fSAndroid Build Coastguard Worker *cp = 0;
247*6a54128fSAndroid Build Coastguard Worker else
248*6a54128fSAndroid Build Coastguard Worker break;
249*6a54128fSAndroid Build Coastguard Worker }
250*6a54128fSAndroid Build Coastguard Worker cp = line;
251*6a54128fSAndroid Build Coastguard Worker while (*cp && isspace(*cp))
252*6a54128fSAndroid Build Coastguard Worker cp++;
253*6a54128fSAndroid Build Coastguard Worker ptr = cp;
254*6a54128fSAndroid Build Coastguard Worker /*
255*6a54128fSAndroid Build Coastguard Worker * Skip empty lines
256*6a54128fSAndroid Build Coastguard Worker */
257*6a54128fSAndroid Build Coastguard Worker if (*ptr == 0)
258*6a54128fSAndroid Build Coastguard Worker continue;
259*6a54128fSAndroid Build Coastguard Worker /*
260*6a54128fSAndroid Build Coastguard Worker * Ignore future extensions
261*6a54128fSAndroid Build Coastguard Worker */
262*6a54128fSAndroid Build Coastguard Worker if (*ptr == '@')
263*6a54128fSAndroid Build Coastguard Worker continue;
264*6a54128fSAndroid Build Coastguard Worker /*
265*6a54128fSAndroid Build Coastguard Worker * Parse substitutions
266*6a54128fSAndroid Build Coastguard Worker */
267*6a54128fSAndroid Build Coastguard Worker for (cp = ptr; *cp; cp++)
268*6a54128fSAndroid Build Coastguard Worker if (isspace(*cp))
269*6a54128fSAndroid Build Coastguard Worker break;
270*6a54128fSAndroid Build Coastguard Worker *cp = 0;
271*6a54128fSAndroid Build Coastguard Worker for (cp++; *cp; cp++)
272*6a54128fSAndroid Build Coastguard Worker if (!isspace(*cp))
273*6a54128fSAndroid Build Coastguard Worker break;
274*6a54128fSAndroid Build Coastguard Worker #if 0
275*6a54128fSAndroid Build Coastguard Worker printf("Substitute: '%s' for '%s'\n", ptr, cp ? cp : "<NULL>");
276*6a54128fSAndroid Build Coastguard Worker #endif
277*6a54128fSAndroid Build Coastguard Worker add_subst(ptr, cp);
278*6a54128fSAndroid Build Coastguard Worker }
279*6a54128fSAndroid Build Coastguard Worker }
280*6a54128fSAndroid Build Coastguard Worker
281*6a54128fSAndroid Build Coastguard Worker /*
282*6a54128fSAndroid Build Coastguard Worker * Return 0 if the files are different, 1 if the files are the same.
283*6a54128fSAndroid Build Coastguard Worker */
compare_file(FILE * old_f,FILE * new_f)284*6a54128fSAndroid Build Coastguard Worker static int compare_file(FILE *old_f, FILE *new_f)
285*6a54128fSAndroid Build Coastguard Worker {
286*6a54128fSAndroid Build Coastguard Worker char oldbuf[2048], newbuf[2048], *oldcp, *newcp;
287*6a54128fSAndroid Build Coastguard Worker int retval;
288*6a54128fSAndroid Build Coastguard Worker
289*6a54128fSAndroid Build Coastguard Worker while (1) {
290*6a54128fSAndroid Build Coastguard Worker oldcp = fgets(oldbuf, sizeof(oldbuf), old_f);
291*6a54128fSAndroid Build Coastguard Worker newcp = fgets(newbuf, sizeof(newbuf), new_f);
292*6a54128fSAndroid Build Coastguard Worker if (!oldcp && !newcp) {
293*6a54128fSAndroid Build Coastguard Worker retval = 1;
294*6a54128fSAndroid Build Coastguard Worker break;
295*6a54128fSAndroid Build Coastguard Worker }
296*6a54128fSAndroid Build Coastguard Worker if (!oldcp || !newcp || strcmp(oldbuf, newbuf)) {
297*6a54128fSAndroid Build Coastguard Worker retval = 0;
298*6a54128fSAndroid Build Coastguard Worker break;
299*6a54128fSAndroid Build Coastguard Worker }
300*6a54128fSAndroid Build Coastguard Worker }
301*6a54128fSAndroid Build Coastguard Worker return retval;
302*6a54128fSAndroid Build Coastguard Worker }
303*6a54128fSAndroid Build Coastguard Worker
set_utimes(const char * filename,int fd,const struct timeval times[2])304*6a54128fSAndroid Build Coastguard Worker void set_utimes(const char *filename, int fd, const struct timeval times[2])
305*6a54128fSAndroid Build Coastguard Worker {
306*6a54128fSAndroid Build Coastguard Worker #ifdef HAVE_FUTIMES
307*6a54128fSAndroid Build Coastguard Worker if (futimes(fd, times) < 0)
308*6a54128fSAndroid Build Coastguard Worker perror("futimes");
309*6a54128fSAndroid Build Coastguard Worker #elif HAVE_UTIMES
310*6a54128fSAndroid Build Coastguard Worker if (utimes(filename, times) < 0)
311*6a54128fSAndroid Build Coastguard Worker perror("utimes");
312*6a54128fSAndroid Build Coastguard Worker #else
313*6a54128fSAndroid Build Coastguard Worker struct utimbuf ut;
314*6a54128fSAndroid Build Coastguard Worker
315*6a54128fSAndroid Build Coastguard Worker ut.actime = times[0].tv_sec;
316*6a54128fSAndroid Build Coastguard Worker ut.modtime = times[1].tv_sec;
317*6a54128fSAndroid Build Coastguard Worker if (utime(filename, &ut) < 0)
318*6a54128fSAndroid Build Coastguard Worker perror("utime");
319*6a54128fSAndroid Build Coastguard Worker #endif
320*6a54128fSAndroid Build Coastguard Worker }
321*6a54128fSAndroid Build Coastguard Worker
322*6a54128fSAndroid Build Coastguard Worker
main(int argc,char ** argv)323*6a54128fSAndroid Build Coastguard Worker int main(int argc, char **argv)
324*6a54128fSAndroid Build Coastguard Worker {
325*6a54128fSAndroid Build Coastguard Worker char line[2048];
326*6a54128fSAndroid Build Coastguard Worker int c;
327*6a54128fSAndroid Build Coastguard Worker int fd, ofd = -1;
328*6a54128fSAndroid Build Coastguard Worker FILE *in, *out, *old = NULL;
329*6a54128fSAndroid Build Coastguard Worker char *outfn = NULL, *newfn = NULL;
330*6a54128fSAndroid Build Coastguard Worker int verbose = 0;
331*6a54128fSAndroid Build Coastguard Worker int adjust_timestamp = 0;
332*6a54128fSAndroid Build Coastguard Worker int got_atime = 0;
333*6a54128fSAndroid Build Coastguard Worker struct stat stbuf;
334*6a54128fSAndroid Build Coastguard Worker struct timeval tv[2];
335*6a54128fSAndroid Build Coastguard Worker
336*6a54128fSAndroid Build Coastguard Worker while ((c = getopt (argc, argv, "f:tv")) != EOF) {
337*6a54128fSAndroid Build Coastguard Worker switch (c) {
338*6a54128fSAndroid Build Coastguard Worker case 'f':
339*6a54128fSAndroid Build Coastguard Worker in = fopen(optarg, "r");
340*6a54128fSAndroid Build Coastguard Worker if (!in) {
341*6a54128fSAndroid Build Coastguard Worker perror(optarg);
342*6a54128fSAndroid Build Coastguard Worker exit(1);
343*6a54128fSAndroid Build Coastguard Worker }
344*6a54128fSAndroid Build Coastguard Worker parse_config_file(in);
345*6a54128fSAndroid Build Coastguard Worker fclose(in);
346*6a54128fSAndroid Build Coastguard Worker break;
347*6a54128fSAndroid Build Coastguard Worker case 't':
348*6a54128fSAndroid Build Coastguard Worker adjust_timestamp++;
349*6a54128fSAndroid Build Coastguard Worker break;
350*6a54128fSAndroid Build Coastguard Worker case 'v':
351*6a54128fSAndroid Build Coastguard Worker verbose++;
352*6a54128fSAndroid Build Coastguard Worker break;
353*6a54128fSAndroid Build Coastguard Worker default:
354*6a54128fSAndroid Build Coastguard Worker fprintf(stderr, "%s: [-f config-file] [file]\n",
355*6a54128fSAndroid Build Coastguard Worker argv[0]);
356*6a54128fSAndroid Build Coastguard Worker break;
357*6a54128fSAndroid Build Coastguard Worker }
358*6a54128fSAndroid Build Coastguard Worker }
359*6a54128fSAndroid Build Coastguard Worker if (optind < argc) {
360*6a54128fSAndroid Build Coastguard Worker in = fopen(argv[optind], "r");
361*6a54128fSAndroid Build Coastguard Worker if (!in) {
362*6a54128fSAndroid Build Coastguard Worker perror(argv[optind]);
363*6a54128fSAndroid Build Coastguard Worker exit(1);
364*6a54128fSAndroid Build Coastguard Worker }
365*6a54128fSAndroid Build Coastguard Worker optind++;
366*6a54128fSAndroid Build Coastguard Worker } else
367*6a54128fSAndroid Build Coastguard Worker in = stdin;
368*6a54128fSAndroid Build Coastguard Worker
369*6a54128fSAndroid Build Coastguard Worker if (optind < argc) {
370*6a54128fSAndroid Build Coastguard Worker outfn = argv[optind];
371*6a54128fSAndroid Build Coastguard Worker newfn = (char *) malloc(strlen(outfn)+20);
372*6a54128fSAndroid Build Coastguard Worker if (!newfn) {
373*6a54128fSAndroid Build Coastguard Worker fprintf(stderr, "Memory error! Exiting.\n");
374*6a54128fSAndroid Build Coastguard Worker exit(1);
375*6a54128fSAndroid Build Coastguard Worker }
376*6a54128fSAndroid Build Coastguard Worker strcpy(newfn, outfn);
377*6a54128fSAndroid Build Coastguard Worker strcat(newfn, ".new");
378*6a54128fSAndroid Build Coastguard Worker ofd = open(newfn, O_CREAT|O_TRUNC|O_RDWR, 0644);
379*6a54128fSAndroid Build Coastguard Worker if (ofd < 0) {
380*6a54128fSAndroid Build Coastguard Worker perror(newfn);
381*6a54128fSAndroid Build Coastguard Worker exit(1);
382*6a54128fSAndroid Build Coastguard Worker }
383*6a54128fSAndroid Build Coastguard Worker out = fdopen(ofd, "w+");
384*6a54128fSAndroid Build Coastguard Worker if (!out) {
385*6a54128fSAndroid Build Coastguard Worker perror("fdopen");
386*6a54128fSAndroid Build Coastguard Worker exit(1);
387*6a54128fSAndroid Build Coastguard Worker }
388*6a54128fSAndroid Build Coastguard Worker
389*6a54128fSAndroid Build Coastguard Worker fd = open(outfn, O_RDONLY);
390*6a54128fSAndroid Build Coastguard Worker if (fd > 0) {
391*6a54128fSAndroid Build Coastguard Worker /* save the original atime, if possible */
392*6a54128fSAndroid Build Coastguard Worker if (fstat(fd, &stbuf) == 0) {
393*6a54128fSAndroid Build Coastguard Worker #if HAVE_STRUCT_STAT_ST_ATIM
394*6a54128fSAndroid Build Coastguard Worker tv[0].tv_sec = stbuf.st_atim.tv_sec;
395*6a54128fSAndroid Build Coastguard Worker tv[0].tv_usec = stbuf.st_atim.tv_nsec / 1000;
396*6a54128fSAndroid Build Coastguard Worker #else
397*6a54128fSAndroid Build Coastguard Worker tv[0].tv_sec = stbuf.st_atime;
398*6a54128fSAndroid Build Coastguard Worker tv[0].tv_usec = 0;
399*6a54128fSAndroid Build Coastguard Worker #endif
400*6a54128fSAndroid Build Coastguard Worker got_atime = 1;
401*6a54128fSAndroid Build Coastguard Worker }
402*6a54128fSAndroid Build Coastguard Worker old = fdopen(fd, "r");
403*6a54128fSAndroid Build Coastguard Worker if (!old)
404*6a54128fSAndroid Build Coastguard Worker close(fd);
405*6a54128fSAndroid Build Coastguard Worker }
406*6a54128fSAndroid Build Coastguard Worker } else {
407*6a54128fSAndroid Build Coastguard Worker out = stdout;
408*6a54128fSAndroid Build Coastguard Worker outfn = 0;
409*6a54128fSAndroid Build Coastguard Worker }
410*6a54128fSAndroid Build Coastguard Worker
411*6a54128fSAndroid Build Coastguard Worker while (!feof(in)) {
412*6a54128fSAndroid Build Coastguard Worker if (fgets(line, sizeof(line), in) == NULL)
413*6a54128fSAndroid Build Coastguard Worker break;
414*6a54128fSAndroid Build Coastguard Worker substitute_line(line);
415*6a54128fSAndroid Build Coastguard Worker fputs(line, out);
416*6a54128fSAndroid Build Coastguard Worker }
417*6a54128fSAndroid Build Coastguard Worker fclose(in);
418*6a54128fSAndroid Build Coastguard Worker if (outfn) {
419*6a54128fSAndroid Build Coastguard Worker fflush(out);
420*6a54128fSAndroid Build Coastguard Worker rewind(out);
421*6a54128fSAndroid Build Coastguard Worker if (old && compare_file(old, out)) {
422*6a54128fSAndroid Build Coastguard Worker if (verbose)
423*6a54128fSAndroid Build Coastguard Worker printf("No change, keeping %s.\n", outfn);
424*6a54128fSAndroid Build Coastguard Worker if (adjust_timestamp) {
425*6a54128fSAndroid Build Coastguard Worker if (verbose)
426*6a54128fSAndroid Build Coastguard Worker printf("Updating modtime for %s\n", outfn);
427*6a54128fSAndroid Build Coastguard Worker if (gettimeofday(&tv[1], NULL) < 0) {
428*6a54128fSAndroid Build Coastguard Worker perror("gettimeofday");
429*6a54128fSAndroid Build Coastguard Worker exit(1);
430*6a54128fSAndroid Build Coastguard Worker }
431*6a54128fSAndroid Build Coastguard Worker if (got_atime == 0)
432*6a54128fSAndroid Build Coastguard Worker tv[0] = tv[1];
433*6a54128fSAndroid Build Coastguard Worker else if (verbose)
434*6a54128fSAndroid Build Coastguard Worker printf("Using original atime\n");
435*6a54128fSAndroid Build Coastguard Worker set_utimes(outfn, fileno(old), tv);
436*6a54128fSAndroid Build Coastguard Worker }
437*6a54128fSAndroid Build Coastguard Worker #ifndef _WIN32
438*6a54128fSAndroid Build Coastguard Worker if (ofd >= 0)
439*6a54128fSAndroid Build Coastguard Worker (void) fchmod(ofd, 0444);
440*6a54128fSAndroid Build Coastguard Worker #endif
441*6a54128fSAndroid Build Coastguard Worker fclose(out);
442*6a54128fSAndroid Build Coastguard Worker if (unlink(newfn) < 0)
443*6a54128fSAndroid Build Coastguard Worker perror("unlink");
444*6a54128fSAndroid Build Coastguard Worker } else {
445*6a54128fSAndroid Build Coastguard Worker if (verbose)
446*6a54128fSAndroid Build Coastguard Worker printf("Creating or replacing %s.\n", outfn);
447*6a54128fSAndroid Build Coastguard Worker #ifndef _WIN32
448*6a54128fSAndroid Build Coastguard Worker if (ofd >= 0)
449*6a54128fSAndroid Build Coastguard Worker (void) fchmod(ofd, 0444);
450*6a54128fSAndroid Build Coastguard Worker #endif
451*6a54128fSAndroid Build Coastguard Worker fclose(out);
452*6a54128fSAndroid Build Coastguard Worker if (old)
453*6a54128fSAndroid Build Coastguard Worker fclose(old);
454*6a54128fSAndroid Build Coastguard Worker old = NULL;
455*6a54128fSAndroid Build Coastguard Worker if (rename(newfn, outfn) < 0) {
456*6a54128fSAndroid Build Coastguard Worker perror("rename");
457*6a54128fSAndroid Build Coastguard Worker exit(1);
458*6a54128fSAndroid Build Coastguard Worker }
459*6a54128fSAndroid Build Coastguard Worker }
460*6a54128fSAndroid Build Coastguard Worker }
461*6a54128fSAndroid Build Coastguard Worker if (old)
462*6a54128fSAndroid Build Coastguard Worker fclose(old);
463*6a54128fSAndroid Build Coastguard Worker if (newfn)
464*6a54128fSAndroid Build Coastguard Worker free(newfn);
465*6a54128fSAndroid Build Coastguard Worker return (0);
466*6a54128fSAndroid Build Coastguard Worker }
467*6a54128fSAndroid Build Coastguard Worker
468*6a54128fSAndroid Build Coastguard Worker
469