fixincl.c revision 1.1.1.5 1 1.1 mrg /* Install modified versions of certain ANSI-incompatible system header
2 1.1 mrg files which are fixed to work correctly with ANSI C and placed in a
3 1.1 mrg directory that GCC will search.
4 1.1 mrg
5 1.1.1.2 mrg Copyright (C) 1997, 1998, 1999, 2000, 2004, 2009, 2012
6 1.1 mrg Free Software Foundation, Inc.
7 1.1 mrg
8 1.1 mrg This file is part of GCC.
9 1.1 mrg
10 1.1 mrg GCC is free software; you can redistribute it and/or modify
11 1.1 mrg it under the terms of the GNU General Public License as published by
12 1.1 mrg the Free Software Foundation; either version 3, or (at your option)
13 1.1 mrg any later version.
14 1.1 mrg
15 1.1 mrg GCC is distributed in the hope that it will be useful,
16 1.1 mrg but WITHOUT ANY WARRANTY; without even the implied warranty of
17 1.1 mrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 1.1 mrg GNU General Public License for more details.
19 1.1 mrg
20 1.1 mrg You should have received a copy of the GNU General Public License
21 1.1 mrg along with GCC; see the file COPYING3. If not see
22 1.1 mrg <http://www.gnu.org/licenses/>. */
23 1.1 mrg
24 1.1 mrg #include "fixlib.h"
25 1.1 mrg
26 1.1 mrg #include <fnmatch.h>
27 1.1 mrg #include <sys/stat.h>
28 1.1 mrg #ifndef SEPARATE_FIX_PROC
29 1.1 mrg #include <sys/wait.h>
30 1.1 mrg #endif
31 1.1 mrg
32 1.1 mrg #if defined( HAVE_MMAP_FILE )
33 1.1 mrg #include <sys/mman.h>
34 1.1 mrg #define BAD_ADDR ((void*)-1)
35 1.1 mrg #endif
36 1.1 mrg
37 1.1 mrg #ifndef SEPARATE_FIX_PROC
38 1.1 mrg #include "server.h"
39 1.1 mrg #endif
40 1.1 mrg
41 1.1 mrg /* The contents of this string are not very important. It is mostly
42 1.1 mrg just used as part of the "I am alive and working" test. */
43 1.1 mrg
44 1.1 mrg static const char program_id[] = "fixincl version 1.1";
45 1.1 mrg
46 1.1 mrg /* This format will be used at the start of every generated file */
47 1.1 mrg
48 1.1 mrg static const char z_std_preamble[] =
49 1.1 mrg "/* DO NOT EDIT THIS FILE.\n\n\
50 1.1 mrg It has been auto-edited by fixincludes from:\n\n\
51 1.1 mrg \t\"%s/%s\"\n\n\
52 1.1 mrg This had to be done to correct non-standard usages in the\n\
53 1.1 mrg original, manufacturer supplied header file. */\n\n";
54 1.1 mrg
55 1.1 mrg int find_base_len = 0;
56 1.1 mrg int have_tty = 0;
57 1.1 mrg
58 1.1 mrg pid_t process_chain_head = (pid_t) -1;
59 1.1 mrg
60 1.1 mrg char* pz_curr_file; /* name of the current file under test/fix */
61 1.1 mrg char* pz_curr_data; /* original contents of that file */
62 1.1 mrg char* pz_temp_file; /* for DOS, a place to stash the temporary
63 1.1 mrg fixed data between system(3) calls */
64 1.1 mrg t_bool curr_data_mapped;
65 1.1 mrg int data_map_fd;
66 1.1 mrg size_t data_map_size;
67 1.1 mrg size_t ttl_data_size = 0;
68 1.1 mrg
69 1.1 mrg #ifdef DO_STATS
70 1.1 mrg int process_ct = 0;
71 1.1 mrg int apply_ct = 0;
72 1.1 mrg int fixed_ct = 0;
73 1.1 mrg int altered_ct = 0;
74 1.1 mrg #endif /* DO_STATS */
75 1.1 mrg
76 1.1 mrg const char incl_quote_pat[] = "^[ \t]*#[ \t]*include[ \t]*\"[^/]";
77 1.1 mrg regex_t incl_quote_re;
78 1.1 mrg
79 1.1.1.4 mrg #ifndef SEPARATE_FIX_PROC
80 1.1.1.4 mrg tSCC z_fork_err[] = "Error %d (%s) starting filter process for %s\n";
81 1.1.1.4 mrg #endif
82 1.1.1.4 mrg
83 1.1 mrg static void do_version (void) ATTRIBUTE_NORETURN;
84 1.1 mrg char *load_file (const char *);
85 1.1 mrg void run_compiles (void);
86 1.1 mrg void initialize (int argc, char** argv);
87 1.1 mrg void process (void);
88 1.1 mrg
89 1.1 mrg /* External Source Code */
90 1.1 mrg
91 1.1 mrg #include "fixincl.x"
92 1.1 mrg
93 1.1 mrg /* * * * * * * * * * * * * * * * * * *
94 1.1 mrg *
95 1.1 mrg * MAIN ROUTINE
96 1.1 mrg */
97 1.1 mrg extern int main (int, char **);
98 1.1 mrg int
99 1.1 mrg main (int argc, char** argv)
100 1.1 mrg {
101 1.1 mrg char *file_name_buf;
102 1.1 mrg
103 1.1 mrg initialize ( argc, argv );
104 1.1 mrg
105 1.1 mrg have_tty = isatty (fileno (stderr));
106 1.1 mrg
107 1.1 mrg /* Before anything else, ensure we can allocate our file name buffer. */
108 1.1 mrg file_name_buf = load_file_data (stdin);
109 1.1 mrg
110 1.1 mrg /* Because of the way server shells work, you have to keep stdin, out
111 1.1 mrg and err open so that the proper input file does not get closed
112 1.1 mrg by accident */
113 1.1 mrg
114 1.1 mrg freopen ("/dev/null", "r", stdin);
115 1.1 mrg
116 1.1 mrg if (file_name_buf == (char *) NULL)
117 1.1 mrg {
118 1.1 mrg fputs ("No file names listed for fixing\n", stderr);
119 1.1 mrg exit (EXIT_FAILURE);
120 1.1 mrg }
121 1.1 mrg
122 1.1 mrg for (;;)
123 1.1 mrg {
124 1.1 mrg char* pz_end;
125 1.1 mrg
126 1.1 mrg /* skip to start of name, past any "./" prefixes */
127 1.1 mrg
128 1.1 mrg while (ISSPACE (*file_name_buf)) file_name_buf++;
129 1.1 mrg while ((file_name_buf[0] == '.') && (file_name_buf[1] == '/'))
130 1.1 mrg file_name_buf += 2;
131 1.1 mrg
132 1.1 mrg /* Check for end of list */
133 1.1 mrg
134 1.1 mrg if (*file_name_buf == NUL)
135 1.1 mrg break;
136 1.1 mrg
137 1.1 mrg /* Set global file name pointer and find end of name */
138 1.1 mrg
139 1.1 mrg pz_curr_file = file_name_buf;
140 1.1 mrg pz_end = strchr( pz_curr_file, '\n' );
141 1.1 mrg if (pz_end == (char*)NULL)
142 1.1 mrg pz_end = file_name_buf = pz_curr_file + strlen (pz_curr_file);
143 1.1 mrg else
144 1.1 mrg file_name_buf = pz_end + 1;
145 1.1 mrg
146 1.1 mrg while ((pz_end > pz_curr_file) && ISSPACE( pz_end[-1])) pz_end--;
147 1.1 mrg
148 1.1 mrg /* IF no name is found (blank line) or comment marker, skip line */
149 1.1 mrg
150 1.1 mrg if ((pz_curr_file == pz_end) || (*pz_curr_file == '#'))
151 1.1 mrg continue;
152 1.1 mrg *pz_end = NUL;
153 1.1 mrg
154 1.1 mrg process ();
155 1.1 mrg } /* for (;;) */
156 1.1 mrg
157 1.1 mrg #ifdef DO_STATS
158 1.1 mrg if (VLEVEL( VERB_PROGRESS )) {
159 1.1 mrg tSCC zFmt[] =
160 1.1 mrg "\
161 1.1 mrg Processed %5d files containing %d bytes \n\
162 1.1 mrg Applying %5d fixes to %d files\n\
163 1.1 mrg Altering %5d of them\n";
164 1.1 mrg
165 1.1 mrg fprintf (stderr, zFmt, process_ct, ttl_data_size, apply_ct,
166 1.1 mrg fixed_ct, altered_ct);
167 1.1 mrg }
168 1.1 mrg #endif /* DO_STATS */
169 1.1 mrg
170 1.1 mrg # ifdef SEPARATE_FIX_PROC
171 1.1 mrg unlink( pz_temp_file );
172 1.1 mrg # endif
173 1.1 mrg exit (EXIT_SUCCESS);
174 1.1 mrg }
175 1.1 mrg
176 1.1 mrg
177 1.1 mrg static void
178 1.1 mrg do_version (void)
179 1.1 mrg {
180 1.1 mrg static const char zFmt[] = "echo '%s'";
181 1.1 mrg char zBuf[ 1024 ];
182 1.1 mrg
183 1.1 mrg /* The 'version' option is really used to test that:
184 1.1 mrg 1. The program loads correctly (no missing libraries)
185 1.1 mrg 2. that we can compile all the regular expressions.
186 1.1 mrg 3. we can correctly run our server shell process
187 1.1 mrg */
188 1.1 mrg run_compiles ();
189 1.1 mrg sprintf (zBuf, zFmt, program_id);
190 1.1 mrg #ifndef SEPARATE_FIX_PROC
191 1.1 mrg puts (zBuf + 5);
192 1.1 mrg exit (strcmp (run_shell (zBuf), program_id));
193 1.1 mrg #else
194 1.1.1.4 mrg exit (system_with_shell (zBuf));
195 1.1 mrg #endif
196 1.1 mrg }
197 1.1 mrg
198 1.1 mrg /* * * * * * * * * * * * */
199 1.1 mrg
200 1.1 mrg void
201 1.1 mrg initialize ( int argc, char** argv )
202 1.1 mrg {
203 1.1 mrg xmalloc_set_program_name (argv[0]);
204 1.1 mrg
205 1.1 mrg switch (argc)
206 1.1 mrg {
207 1.1 mrg case 1:
208 1.1 mrg break;
209 1.1 mrg
210 1.1 mrg case 2:
211 1.1 mrg if (strcmp (argv[1], "-v") == 0)
212 1.1 mrg do_version ();
213 1.1 mrg if (freopen (argv[1], "r", stdin) == (FILE*)NULL)
214 1.1 mrg {
215 1.1 mrg fprintf (stderr, "Error %d (%s) reopening %s as stdin\n",
216 1.1 mrg errno, xstrerror (errno), argv[1] );
217 1.1 mrg exit (EXIT_FAILURE);
218 1.1 mrg }
219 1.1 mrg break;
220 1.1 mrg
221 1.1 mrg default:
222 1.1 mrg fputs ("fixincl ERROR: too many command line arguments\n", stderr);
223 1.1 mrg exit (EXIT_FAILURE);
224 1.1 mrg }
225 1.1 mrg
226 1.1 mrg #ifdef SIGCHLD
227 1.1 mrg /* We *MUST* set SIGCHLD to SIG_DFL so that the wait4() call will
228 1.1 mrg receive the signal. A different setting is inheritable */
229 1.1 mrg signal (SIGCHLD, SIG_DFL);
230 1.1 mrg #endif
231 1.1 mrg
232 1.1 mrg initialize_opts ();
233 1.1 mrg
234 1.1 mrg if (ISDIGIT ( *pz_verbose ))
235 1.1 mrg verbose_level = (te_verbose)atoi( pz_verbose );
236 1.1 mrg else
237 1.1 mrg switch (*pz_verbose) {
238 1.1 mrg case 's':
239 1.1 mrg case 'S':
240 1.1 mrg verbose_level = VERB_SILENT; break;
241 1.1 mrg
242 1.1 mrg case 'f':
243 1.1 mrg case 'F':
244 1.1 mrg verbose_level = VERB_FIXES; break;
245 1.1 mrg
246 1.1 mrg case 'a':
247 1.1 mrg case 'A':
248 1.1 mrg verbose_level = VERB_APPLIES; break;
249 1.1 mrg
250 1.1 mrg default:
251 1.1 mrg case 'p':
252 1.1 mrg case 'P':
253 1.1 mrg verbose_level = VERB_PROGRESS; break;
254 1.1 mrg
255 1.1 mrg case 't':
256 1.1 mrg case 'T':
257 1.1 mrg verbose_level = VERB_TESTS; break;
258 1.1 mrg
259 1.1 mrg case 'e':
260 1.1 mrg case 'E':
261 1.1 mrg verbose_level = VERB_EVERYTHING; break;
262 1.1 mrg }
263 1.1 mrg if (verbose_level >= VERB_EVERYTHING) {
264 1.1 mrg verbose_level = VERB_EVERYTHING;
265 1.1 mrg fputs ("fixinc verbosity: EVERYTHING\n", stderr);
266 1.1 mrg }
267 1.1 mrg while ((pz_find_base[0] == '.') && (pz_find_base[1] == '/'))
268 1.1 mrg pz_find_base += 2;
269 1.1 mrg if ((pz_find_base[0] != '.') || (pz_find_base[1] != NUL))
270 1.1 mrg find_base_len = strlen( pz_find_base );
271 1.1 mrg
272 1.1 mrg /* Compile all the regular expressions now.
273 1.1 mrg That way, it is done only once for the whole run.
274 1.1 mrg */
275 1.1 mrg run_compiles ();
276 1.1 mrg
277 1.1 mrg # ifdef SEPARATE_FIX_PROC
278 1.1 mrg /* NULL as the first argument to `tempnam' causes it to DTRT
279 1.1 mrg wrt the temporary directory where the file will be created. */
280 1.1 mrg pz_temp_file = tempnam( NULL, "fxinc" );
281 1.1.1.4 mrg
282 1.1.1.4 mrg #if defined(__MINGW32__)
283 1.1.1.4 mrg fix_path_separators (pz_temp_file);
284 1.1.1.4 mrg #endif
285 1.1.1.4 mrg
286 1.1 mrg # endif
287 1.1 mrg
288 1.1 mrg signal (SIGQUIT, SIG_IGN);
289 1.1 mrg signal (SIGIOT, SIG_IGN);
290 1.1 mrg signal (SIGPIPE, SIG_IGN);
291 1.1 mrg signal (SIGALRM, SIG_IGN);
292 1.1 mrg signal (SIGTERM, SIG_IGN);
293 1.1 mrg }
294 1.1 mrg
295 1.1 mrg /* * * * * * * * * * * * *
296 1.1 mrg
297 1.1 mrg load_file loads all the contents of a file into malloc-ed memory.
298 1.1 mrg Its argument is the name of the file to read in; the returned
299 1.1 mrg result is the NUL terminated contents of the file. The file
300 1.1 mrg is presumed to be an ASCII text file containing no NULs. */
301 1.1 mrg char *
302 1.1 mrg load_file ( const char* fname )
303 1.1 mrg {
304 1.1 mrg struct stat stbf;
305 1.1 mrg char* res;
306 1.1 mrg
307 1.1 mrg if (stat (fname, &stbf) != 0)
308 1.1 mrg {
309 1.1 mrg if (NOT_SILENT)
310 1.1 mrg fprintf (stderr, "error %d (%s) stat-ing %s\n",
311 1.1 mrg errno, xstrerror (errno), fname );
312 1.1 mrg return (char *) NULL;
313 1.1 mrg }
314 1.1 mrg if (stbf.st_size == 0)
315 1.1 mrg return (char*)NULL;
316 1.1 mrg
317 1.1 mrg /* Make the data map size one larger than the file size for documentation
318 1.1 mrg purposes. Truth is that there will be a following NUL character if
319 1.1 mrg the file size is not a multiple of the page size. If it is a multiple,
320 1.1 mrg then this adjustment sometimes fails anyway. */
321 1.1 mrg data_map_size = stbf.st_size+1;
322 1.1 mrg data_map_fd = open (fname, O_RDONLY);
323 1.1 mrg ttl_data_size += data_map_size-1;
324 1.1 mrg
325 1.1 mrg if (data_map_fd < 0)
326 1.1 mrg {
327 1.1 mrg if (NOT_SILENT)
328 1.1 mrg fprintf (stderr, "error %d (%s) opening %s for read\n",
329 1.1 mrg errno, xstrerror (errno), fname);
330 1.1 mrg return (char*)NULL;
331 1.1 mrg }
332 1.1 mrg
333 1.1 mrg #ifdef HAVE_MMAP_FILE
334 1.1 mrg curr_data_mapped = BOOL_TRUE;
335 1.1 mrg
336 1.1 mrg /* IF the file size is a multiple of the page size,
337 1.1 mrg THEN sometimes you will seg fault trying to access a trailing byte */
338 1.1 mrg if ((stbf.st_size & (getpagesize()-1)) == 0)
339 1.1 mrg res = (char*)BAD_ADDR;
340 1.1 mrg else
341 1.1 mrg res = (char*)mmap ((void*)NULL, data_map_size, PROT_READ,
342 1.1 mrg MAP_PRIVATE, data_map_fd, 0);
343 1.1 mrg if (res == (char*)BAD_ADDR)
344 1.1 mrg #endif
345 1.1 mrg {
346 1.1 mrg FILE* fp = fdopen (data_map_fd, "r");
347 1.1 mrg curr_data_mapped = BOOL_FALSE;
348 1.1 mrg res = load_file_data (fp);
349 1.1 mrg fclose (fp);
350 1.1 mrg }
351 1.1 mrg
352 1.1 mrg return res;
353 1.1 mrg }
354 1.1 mrg
355 1.1 mrg static int
356 1.1 mrg machine_matches( tFixDesc* p_fixd )
357 1.1 mrg {
358 1.1 mrg char const ** papz_machs = p_fixd->papz_machs;
359 1.1 mrg int have_match = BOOL_FALSE;
360 1.1 mrg
361 1.1 mrg for (;;)
362 1.1 mrg {
363 1.1 mrg char const * pz_mpat = *(papz_machs++);
364 1.1 mrg if (pz_mpat == NULL)
365 1.1 mrg break;
366 1.1 mrg if (fnmatch(pz_mpat, pz_machine, 0) == 0)
367 1.1 mrg {
368 1.1 mrg have_match = BOOL_TRUE;
369 1.1 mrg break;
370 1.1 mrg }
371 1.1 mrg }
372 1.1 mrg
373 1.1 mrg /* Check for sense inversion then set the "skip test" flag, if needed */
374 1.1 mrg if (p_fixd->fd_flags & FD_MACH_IFNOT)
375 1.1 mrg have_match = ! have_match;
376 1.1 mrg
377 1.1 mrg if (! have_match)
378 1.1 mrg p_fixd->fd_flags |= FD_SKIP_TEST;
379 1.1 mrg
380 1.1 mrg return have_match;
381 1.1 mrg }
382 1.1 mrg
383 1.1 mrg /* * * * * * * * * * * * *
384 1.1 mrg *
385 1.1 mrg * run_compiles run all the regexp compiles for all the fixes once.
386 1.1 mrg */
387 1.1 mrg void
388 1.1 mrg run_compiles (void)
389 1.1 mrg {
390 1.1 mrg tFixDesc *p_fixd = fixDescList;
391 1.1 mrg int fix_ct = FIX_COUNT;
392 1.1 mrg regex_t *p_re = XCNEWVEC (regex_t, REGEX_COUNT);
393 1.1 mrg
394 1.1 mrg /* Make sure compile_re does not stumble across invalid data */
395 1.1 mrg
396 1.1 mrg memset (&incl_quote_re, '\0', sizeof (regex_t));
397 1.1 mrg
398 1.1 mrg compile_re (incl_quote_pat, &incl_quote_re, 1,
399 1.1 mrg "quoted include", "run_compiles");
400 1.1 mrg
401 1.1 mrg /* Allow machine name tests to be ignored (testing, mainly) */
402 1.1 mrg
403 1.1 mrg if (pz_machine && ((*pz_machine == '\0') || (*pz_machine == '*')))
404 1.1 mrg pz_machine = (char*)NULL;
405 1.1 mrg
406 1.1 mrg /* FOR every fixup, ... */
407 1.1 mrg do
408 1.1 mrg {
409 1.1.1.2 mrg tTestDesc *p_test;
410 1.1.1.2 mrg int test_ct;
411 1.1.1.2 mrg
412 1.1.1.2 mrg if (fixinc_mode && (p_fixd->fd_flags & FD_REPLACEMENT))
413 1.1.1.2 mrg {
414 1.1.1.2 mrg p_fixd->fd_flags |= FD_SKIP_TEST;
415 1.1.1.2 mrg continue;
416 1.1.1.2 mrg }
417 1.1.1.2 mrg
418 1.1.1.2 mrg p_test = p_fixd->p_test_desc;
419 1.1.1.2 mrg test_ct = p_fixd->test_ct;
420 1.1 mrg
421 1.1 mrg /* IF the machine type pointer is not NULL (we are not in test mode)
422 1.1 mrg AND this test is for or not done on particular machines
423 1.1 mrg THEN ... */
424 1.1 mrg
425 1.1 mrg if ( (pz_machine != NULL)
426 1.1 mrg && (p_fixd->papz_machs != (const char**) NULL)
427 1.1 mrg && ! machine_matches (p_fixd) )
428 1.1 mrg continue;
429 1.1 mrg
430 1.1 mrg /* FOR every test for the fixup, ... */
431 1.1 mrg
432 1.1 mrg while (--test_ct >= 0)
433 1.1 mrg {
434 1.1 mrg switch (p_test->type)
435 1.1 mrg {
436 1.1 mrg case TT_EGREP:
437 1.1 mrg case TT_NEGREP:
438 1.1 mrg p_test->p_test_regex = p_re++;
439 1.1 mrg compile_re (p_test->pz_test_text, p_test->p_test_regex, 0,
440 1.1 mrg "select test", p_fixd->fix_name);
441 1.1 mrg default: break;
442 1.1 mrg }
443 1.1 mrg p_test++;
444 1.1 mrg }
445 1.1 mrg }
446 1.1 mrg while (p_fixd++, --fix_ct > 0);
447 1.1 mrg }
448 1.1 mrg
449 1.1 mrg
450 1.1 mrg /* * * * * * * * * * * * *
451 1.1 mrg
452 1.1 mrg create_file Create the output modified file.
453 1.1 mrg Input: the name of the file to create
454 1.1 mrg Returns: a file pointer to the new, open file */
455 1.1 mrg
456 1.1 mrg #if defined(S_IRUSR) && defined(S_IWUSR) && \
457 1.1 mrg defined(S_IRGRP) && defined(S_IROTH)
458 1.1 mrg
459 1.1 mrg # define S_IRALL (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
460 1.1 mrg #else
461 1.1 mrg # define S_IRALL 0644
462 1.1 mrg #endif
463 1.1 mrg
464 1.1 mrg #if defined(S_IRWXU) && defined(S_IRGRP) && defined(S_IXGRP) && \
465 1.1 mrg defined(S_IROTH) && defined(S_IXOTH)
466 1.1 mrg
467 1.1 mrg # define S_DIRALL (S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)
468 1.1 mrg #else
469 1.1 mrg # define S_DIRALL 0755
470 1.1 mrg #endif
471 1.1 mrg
472 1.1 mrg
473 1.1 mrg static FILE *
474 1.1 mrg create_file (void)
475 1.1 mrg {
476 1.1 mrg int fd;
477 1.1 mrg FILE *pf;
478 1.1 mrg char fname[MAXPATHLEN];
479 1.1 mrg
480 1.1 mrg sprintf (fname, "%s/%s", pz_dest_dir, pz_curr_file + find_base_len);
481 1.1 mrg
482 1.1 mrg fd = open (fname, O_WRONLY | O_CREAT | O_TRUNC, S_IRALL);
483 1.1 mrg
484 1.1 mrg /* We may need to create the directories needed... */
485 1.1 mrg if ((fd < 0) && (errno == ENOENT))
486 1.1 mrg {
487 1.1 mrg char *pz_dir = strchr (fname + 1, '/');
488 1.1 mrg struct stat stbf;
489 1.1 mrg
490 1.1 mrg while (pz_dir != (char *) NULL)
491 1.1 mrg {
492 1.1 mrg *pz_dir = NUL;
493 1.1 mrg if (stat (fname, &stbf) < 0)
494 1.1 mrg {
495 1.1 mrg #ifdef _WIN32
496 1.1 mrg mkdir (fname);
497 1.1 mrg #else
498 1.1 mrg mkdir (fname, S_IFDIR | S_DIRALL);
499 1.1 mrg #endif
500 1.1 mrg }
501 1.1 mrg
502 1.1 mrg *pz_dir = '/';
503 1.1 mrg pz_dir = strchr (pz_dir + 1, '/');
504 1.1 mrg }
505 1.1 mrg
506 1.1 mrg /* Now, lets try the open again... */
507 1.1 mrg fd = open (fname, O_WRONLY | O_CREAT | O_TRUNC, S_IRALL);
508 1.1 mrg }
509 1.1 mrg if (fd < 0)
510 1.1 mrg {
511 1.1 mrg fprintf (stderr, "Error %d (%s) creating %s\n",
512 1.1 mrg errno, xstrerror (errno), fname);
513 1.1 mrg exit (EXIT_FAILURE);
514 1.1 mrg }
515 1.1 mrg if (NOT_SILENT)
516 1.1 mrg fprintf (stderr, "Fixed: %s\n", pz_curr_file);
517 1.1 mrg pf = fdopen (fd, "w");
518 1.1 mrg
519 1.1 mrg /*
520 1.1 mrg * IF pz_machine is NULL, then we are in some sort of test mode.
521 1.1 mrg * Do not insert the current directory name. Use a constant string.
522 1.1 mrg */
523 1.1 mrg fprintf (pf, z_std_preamble,
524 1.1 mrg (pz_machine == NULL)
525 1.1 mrg ? "fixinc/tests/inc"
526 1.1 mrg : pz_input_dir,
527 1.1 mrg pz_curr_file);
528 1.1 mrg
529 1.1 mrg return pf;
530 1.1 mrg }
531 1.1 mrg
532 1.1 mrg
533 1.1 mrg /* * * * * * * * * * * * *
534 1.1 mrg
535 1.1 mrg test_test make sure a shell-style test expression passes.
536 1.1 mrg Input: a pointer to the descriptor of the test to run and
537 1.1 mrg the name of the file that we might want to fix
538 1.1 mrg Result: APPLY_FIX or SKIP_FIX, depending on the result of the
539 1.1 mrg shell script we run. */
540 1.1 mrg #ifndef SEPARATE_FIX_PROC
541 1.1 mrg static int
542 1.1 mrg test_test (tTestDesc* p_test, char* pz_test_file)
543 1.1 mrg {
544 1.1 mrg tSCC cmd_fmt[] =
545 1.1 mrg "file=%s\n\
546 1.1 mrg if ( test %s ) > /dev/null 2>&1\n\
547 1.1 mrg then echo TRUE\n\
548 1.1 mrg else echo FALSE\n\
549 1.1 mrg fi";
550 1.1 mrg
551 1.1 mrg char *pz_res;
552 1.1 mrg int res;
553 1.1 mrg
554 1.1 mrg static char cmd_buf[4096];
555 1.1 mrg
556 1.1 mrg sprintf (cmd_buf, cmd_fmt, pz_test_file, p_test->pz_test_text);
557 1.1 mrg pz_res = run_shell (cmd_buf);
558 1.1 mrg
559 1.1 mrg switch (*pz_res) {
560 1.1 mrg case 'T':
561 1.1 mrg res = APPLY_FIX;
562 1.1 mrg break;
563 1.1 mrg
564 1.1 mrg case 'F':
565 1.1 mrg res = SKIP_FIX;
566 1.1 mrg break;
567 1.1 mrg
568 1.1 mrg default:
569 1.1 mrg fprintf (stderr, "Script yielded bogus result of `%s':\n%s\n\n",
570 1.1 mrg pz_res, cmd_buf );
571 1.1 mrg res = SKIP_FIX;
572 1.1 mrg }
573 1.1 mrg
574 1.1 mrg free ((void *) pz_res);
575 1.1 mrg return res;
576 1.1 mrg }
577 1.1.1.4 mrg #elif defined(__MINGW32__) || defined(__DJGPP__)
578 1.1.1.4 mrg static int
579 1.1.1.4 mrg test_test (tTestDesc* p_test, char* pz_test_file)
580 1.1.1.4 mrg {
581 1.1.1.4 mrg tSCC cmd_fmt[] =
582 1.1.1.4 mrg #if defined(__DJGPP__)
583 1.1.1.4 mrg "file=%s; test %s >/dev/null 2>/dev/null";
584 1.1.1.4 mrg #else
585 1.1.1.4 mrg "file=%s; test %s > /dev/null 2>&1";
586 1.1.1.4 mrg #endif
587 1.1.1.4 mrg int res;
588 1.1.1.4 mrg
589 1.1.1.4 mrg char *cmd_buf = XNEWVEC (char, strlen(cmd_fmt) + strlen(pz_test_file) + strlen(p_test->pz_test_text));
590 1.1.1.4 mrg
591 1.1.1.4 mrg sprintf (cmd_buf, cmd_fmt, pz_test_file, p_test->pz_test_text);
592 1.1.1.4 mrg res = system_with_shell (cmd_buf);
593 1.1.1.4 mrg
594 1.1.1.4 mrg free (cmd_buf);
595 1.1.1.4 mrg return res ? SKIP_FIX : APPLY_FIX;
596 1.1.1.4 mrg }
597 1.1 mrg #else
598 1.1 mrg /*
599 1.1 mrg * IF we are in MS-DOS land, then whatever shell-type test is required
600 1.1 mrg * will, by definition, fail
601 1.1 mrg */
602 1.1 mrg #define test_test(t,tf) SKIP_FIX
603 1.1 mrg #endif
604 1.1 mrg
605 1.1 mrg /* * * * * * * * * * * * *
606 1.1 mrg
607 1.1 mrg egrep_test make sure an egrep expression is found in the file text.
608 1.1 mrg Input: a pointer to the descriptor of the test to run and
609 1.1 mrg the pointer to the contents of the file under suspicion
610 1.1 mrg Result: APPLY_FIX if the pattern is found, SKIP_FIX otherwise
611 1.1 mrg
612 1.1 mrg The caller may choose to reverse meaning if the sense of the test
613 1.1 mrg is inverted. */
614 1.1 mrg
615 1.1 mrg static int
616 1.1 mrg egrep_test (char* pz_data, tTestDesc* p_test)
617 1.1 mrg {
618 1.1 mrg #ifdef DEBUG
619 1.1 mrg if (p_test->p_test_regex == 0)
620 1.1 mrg fprintf (stderr, "fixincl ERROR RE not compiled: `%s'\n",
621 1.1 mrg p_test->pz_test_text);
622 1.1 mrg #endif
623 1.1 mrg if (xregexec (p_test->p_test_regex, pz_data, 0, 0, 0) == 0)
624 1.1 mrg return APPLY_FIX;
625 1.1 mrg return SKIP_FIX;
626 1.1 mrg }
627 1.1 mrg
628 1.1.1.3 mrg /* * * * * * * * * * * * *
629 1.1.1.3 mrg
630 1.1.1.3 mrg cksum_test check the sum of the candidate file
631 1.1.1.3 mrg Input: the original file contents and the file name
632 1.1.1.3 mrg Result: APPLY_FIX if the check sum matches, SKIP_FIX otherwise
633 1.1.1.3 mrg
634 1.1.1.3 mrg The caller may choose to reverse meaning if the sense of the test
635 1.1.1.3 mrg is inverted. */
636 1.1.1.3 mrg
637 1.1.1.3 mrg static int
638 1.1.1.3 mrg cksum_test (char * pz_data, tTestDesc * p_test, char * fname)
639 1.1.1.3 mrg {
640 1.1.1.3 mrg unsigned int cksum;
641 1.1.1.3 mrg
642 1.1.1.3 mrg /*
643 1.1.1.3 mrg * Testing is off in normal operation mode.
644 1.1.1.3 mrg * So, in testing mode, APPLY_FIX is always returned.
645 1.1.1.3 mrg */
646 1.1.1.3 mrg if (fixinc_mode != TESTING_OFF)
647 1.1.1.3 mrg return APPLY_FIX;
648 1.1.1.3 mrg
649 1.1.1.3 mrg {
650 1.1.1.3 mrg char * fnm = strrchr(fname, '/');
651 1.1.1.3 mrg if (fnm != NULL)
652 1.1.1.3 mrg fname = fnm + 1;
653 1.1.1.3 mrg
654 1.1.1.3 mrg errno = 0;
655 1.1.1.3 mrg cksum = (unsigned int)strtoul(p_test->pz_test_text, &fnm, 10);
656 1.1.1.3 mrg if (errno != 0)
657 1.1.1.3 mrg return SKIP_FIX;
658 1.1.1.3 mrg
659 1.1.1.3 mrg if (! ISSPACE(*fnm++))
660 1.1.1.3 mrg return SKIP_FIX;
661 1.1.1.3 mrg while (ISSPACE(*fnm)) fnm++;
662 1.1.1.3 mrg
663 1.1.1.3 mrg if (! ISDIGIT(*fnm++))
664 1.1.1.3 mrg return SKIP_FIX;
665 1.1.1.3 mrg while (ISDIGIT(*fnm)) fnm++;
666 1.1.1.3 mrg
667 1.1.1.3 mrg if (! ISSPACE(*fnm++))
668 1.1.1.3 mrg return SKIP_FIX;
669 1.1.1.3 mrg while (ISSPACE(*fnm)) fnm++;
670 1.1.1.3 mrg
671 1.1.1.3 mrg if (strcmp(fnm, fname) != 0)
672 1.1.1.3 mrg return SKIP_FIX;
673 1.1.1.3 mrg }
674 1.1.1.3 mrg
675 1.1.1.3 mrg {
676 1.1.1.3 mrg unsigned int sum = 0;
677 1.1.1.3 mrg while (*pz_data != NUL) {
678 1.1.1.3 mrg sum = (sum >> 1) + ((sum & 1) << 15) + (unsigned)(*pz_data++);
679 1.1.1.3 mrg sum &= 0xFFFF;
680 1.1.1.3 mrg }
681 1.1.1.3 mrg
682 1.1.1.3 mrg return (sum == cksum) ? APPLY_FIX : SKIP_FIX;
683 1.1.1.3 mrg }
684 1.1.1.3 mrg }
685 1.1 mrg
686 1.1 mrg /* * * * * * * * * * * * *
687 1.1 mrg
688 1.1 mrg quoted_file_exists Make sure that a file exists before we emit
689 1.1 mrg the file name. If we emit the name, our invoking shell will try
690 1.1 mrg to copy a non-existing file into the destination directory. */
691 1.1 mrg
692 1.1 mrg static int
693 1.1 mrg quoted_file_exists (const char* pz_src_path,
694 1.1 mrg const char* pz_file_path,
695 1.1 mrg const char* pz_file)
696 1.1 mrg {
697 1.1 mrg char z[ MAXPATHLEN ];
698 1.1 mrg char* pz;
699 1.1 mrg sprintf (z, "%s/%s/", pz_src_path, pz_file_path);
700 1.1 mrg pz = z + strlen ( z );
701 1.1 mrg
702 1.1 mrg for (;;) {
703 1.1 mrg char ch = *pz_file++;
704 1.1 mrg if (! ISGRAPH( ch ))
705 1.1 mrg return 0;
706 1.1 mrg if (ch == '"')
707 1.1 mrg break;
708 1.1 mrg *pz++ = ch;
709 1.1 mrg }
710 1.1 mrg *pz = '\0';
711 1.1 mrg {
712 1.1 mrg struct stat s;
713 1.1 mrg if (stat (z, &s) != 0)
714 1.1 mrg return 0;
715 1.1 mrg return S_ISREG( s.st_mode );
716 1.1 mrg }
717 1.1 mrg }
718 1.1 mrg
719 1.1 mrg
720 1.1 mrg /* * * * * * * * * * * * *
721 1.1 mrg *
722 1.1 mrg extract_quoted_files
723 1.1 mrg
724 1.1 mrg The syntax, `#include "file.h"' specifies that the compiler is to
725 1.1 mrg search the local directory of the current file before the include
726 1.1 mrg list. Consequently, if we have modified a header and stored it in
727 1.1 mrg another directory, any files that are included by that modified
728 1.1 mrg file in that fashion must also be copied into this new directory.
729 1.1 mrg This routine finds those flavors of #include and for each one found
730 1.1 mrg emits a triple of:
731 1.1 mrg
732 1.1 mrg 1. source directory of the original file
733 1.1 mrg 2. the relative path file name of the #includ-ed file
734 1.1 mrg 3. the full destination path for this file
735 1.1 mrg
736 1.1 mrg Input: the text of the file, the file name and a pointer to the
737 1.1 mrg match list where the match information was stored.
738 1.1 mrg Result: internally nothing. The results are written to stdout
739 1.1 mrg for interpretation by the invoking shell */
740 1.1 mrg
741 1.1 mrg
742 1.1 mrg static void
743 1.1 mrg extract_quoted_files (char* pz_data,
744 1.1 mrg const char* pz_fixed_file,
745 1.1 mrg regmatch_t* p_re_match)
746 1.1 mrg {
747 1.1 mrg char *pz_dir_end = strrchr (pz_fixed_file, '/');
748 1.1 mrg char *pz_incl_quot = pz_data;
749 1.1 mrg
750 1.1 mrg if (VLEVEL( VERB_APPLIES ))
751 1.1 mrg fprintf (stderr, "Quoted includes in %s\n", pz_fixed_file);
752 1.1 mrg
753 1.1 mrg /* Set "pz_fixed_file" to point to the containing subdirectory of the source
754 1.1 mrg If there is none, then it is in our current directory, ".". */
755 1.1 mrg
756 1.1 mrg if (pz_dir_end == (char *) NULL)
757 1.1 mrg pz_fixed_file = ".";
758 1.1 mrg else
759 1.1 mrg *pz_dir_end = '\0';
760 1.1 mrg
761 1.1 mrg for (;;)
762 1.1 mrg {
763 1.1 mrg pz_incl_quot += p_re_match->rm_so;
764 1.1 mrg
765 1.1 mrg /* Skip forward to the included file name */
766 1.1 mrg while (*pz_incl_quot != '"')
767 1.1 mrg pz_incl_quot++;
768 1.1 mrg
769 1.1 mrg if (quoted_file_exists (pz_src_dir, pz_fixed_file, pz_incl_quot))
770 1.1 mrg {
771 1.1 mrg /* Print the source directory and the subdirectory
772 1.1 mrg of the file in question. */
773 1.1 mrg printf ("%s %s/", pz_src_dir, pz_fixed_file);
774 1.1 mrg pz_dir_end = pz_incl_quot;
775 1.1 mrg
776 1.1 mrg /* Append to the directory the relative path of the desired file */
777 1.1 mrg while (*pz_incl_quot != '"')
778 1.1 mrg putc (*pz_incl_quot++, stdout);
779 1.1 mrg
780 1.1 mrg /* Now print the destination directory appended with the
781 1.1 mrg relative path of the desired file */
782 1.1 mrg printf (" %s/%s/", pz_dest_dir, pz_fixed_file);
783 1.1 mrg while (*pz_dir_end != '"')
784 1.1 mrg putc (*pz_dir_end++, stdout);
785 1.1 mrg
786 1.1 mrg /* End of entry */
787 1.1 mrg putc ('\n', stdout);
788 1.1 mrg }
789 1.1 mrg
790 1.1 mrg /* Find the next entry */
791 1.1 mrg if (xregexec (&incl_quote_re, pz_incl_quot, 1, p_re_match, 0) != 0)
792 1.1 mrg break;
793 1.1 mrg }
794 1.1 mrg }
795 1.1 mrg
796 1.1 mrg
797 1.1 mrg /* * * * * * * * * * * * *
798 1.1 mrg
799 1.1 mrg Somebody wrote a *_fix subroutine that we must call.
800 1.1 mrg */
801 1.1 mrg #ifndef SEPARATE_FIX_PROC
802 1.1 mrg static int
803 1.1 mrg internal_fix (int read_fd, tFixDesc* p_fixd)
804 1.1 mrg {
805 1.1 mrg int fd[2];
806 1.1 mrg
807 1.1 mrg if (pipe( fd ) != 0)
808 1.1 mrg {
809 1.1 mrg fprintf (stderr, "Error %d on pipe(2) call\n", errno );
810 1.1 mrg exit (EXIT_FAILURE);
811 1.1 mrg }
812 1.1 mrg
813 1.1 mrg for (;;)
814 1.1 mrg {
815 1.1 mrg pid_t childid = fork();
816 1.1 mrg
817 1.1 mrg switch (childid)
818 1.1 mrg {
819 1.1 mrg case -1:
820 1.1 mrg break;
821 1.1 mrg
822 1.1 mrg case 0:
823 1.1 mrg close (fd[0]);
824 1.1 mrg goto do_child_task;
825 1.1 mrg
826 1.1 mrg default:
827 1.1 mrg /*
828 1.1 mrg * Parent process
829 1.1 mrg */
830 1.1 mrg close (read_fd);
831 1.1 mrg close (fd[1]);
832 1.1 mrg return fd[0];
833 1.1 mrg }
834 1.1 mrg
835 1.1 mrg /*
836 1.1 mrg * Parent in error
837 1.1 mrg */
838 1.1 mrg fprintf (stderr, z_fork_err, errno, xstrerror (errno),
839 1.1 mrg p_fixd->fix_name);
840 1.1 mrg {
841 1.1 mrg static int failCt = 0;
842 1.1 mrg if ((errno != EAGAIN) || (++failCt > 10))
843 1.1 mrg exit (EXIT_FAILURE);
844 1.1 mrg sleep (1);
845 1.1 mrg }
846 1.1 mrg } do_child_task:;
847 1.1 mrg
848 1.1 mrg /*
849 1.1 mrg * Close our current stdin and stdout
850 1.1 mrg */
851 1.1 mrg close (STDIN_FILENO);
852 1.1 mrg close (STDOUT_FILENO);
853 1.1 mrg UNLOAD_DATA();
854 1.1 mrg
855 1.1 mrg /*
856 1.1 mrg * Make the fd passed in the stdin, and the write end of
857 1.1 mrg * the new pipe become the stdout.
858 1.1 mrg */
859 1.1 mrg dup2 (fd[1], STDOUT_FILENO);
860 1.1 mrg dup2 (read_fd, STDIN_FILENO);
861 1.1 mrg
862 1.1 mrg apply_fix (p_fixd, pz_curr_file);
863 1.1 mrg exit (0);
864 1.1 mrg }
865 1.1 mrg #endif /* !SEPARATE_FIX_PROC */
866 1.1 mrg
867 1.1 mrg
868 1.1 mrg #ifdef SEPARATE_FIX_PROC
869 1.1 mrg static void
870 1.1 mrg fix_with_system (tFixDesc* p_fixd,
871 1.1 mrg tCC* pz_fix_file,
872 1.1 mrg tCC* pz_file_source,
873 1.1 mrg tCC* pz_temp_file)
874 1.1 mrg {
875 1.1 mrg char* pz_cmd;
876 1.1 mrg char* pz_scan;
877 1.1 mrg size_t argsize;
878 1.1 mrg
879 1.1 mrg if (p_fixd->fd_flags & FD_SUBROUTINE)
880 1.1 mrg {
881 1.1 mrg static const char z_applyfix_prog[] =
882 1.1.1.3 mrg "/../fixincludes/applyfix" EXE_EXT;
883 1.1 mrg
884 1.1 mrg struct stat buf;
885 1.1 mrg argsize = 32
886 1.1 mrg + strlen (pz_orig_dir)
887 1.1 mrg + sizeof (z_applyfix_prog)
888 1.1 mrg + strlen (pz_fix_file)
889 1.1 mrg + strlen (pz_file_source)
890 1.1 mrg + strlen (pz_temp_file);
891 1.1 mrg
892 1.1 mrg /* Allocate something sure to be big enough for our purposes */
893 1.1 mrg pz_cmd = XNEWVEC (char, argsize);
894 1.1 mrg strcpy (pz_cmd, pz_orig_dir);
895 1.1 mrg pz_scan = pz_cmd + strlen (pz_orig_dir);
896 1.1 mrg
897 1.1 mrg strcpy (pz_scan, z_applyfix_prog);
898 1.1 mrg
899 1.1 mrg /* IF we can't find the "applyfix" executable file at the first guess,
900 1.1.1.3 mrg try one level higher up */
901 1.1 mrg if (stat (pz_cmd, &buf) == -1)
902 1.1.1.3 mrg {
903 1.1.1.3 mrg strcpy (pz_scan, "/..");
904 1.1.1.3 mrg strcpy (pz_scan+3, z_applyfix_prog);
905 1.1.1.3 mrg }
906 1.1 mrg
907 1.1 mrg pz_scan += strlen (pz_scan);
908 1.1 mrg
909 1.1 mrg /*
910 1.1 mrg * Now add the fix number and file names that may be needed
911 1.1 mrg */
912 1.1.1.2 mrg sprintf (pz_scan, " %ld '%s' '%s' '%s'", (long) (p_fixd - fixDescList),
913 1.1.1.3 mrg pz_fix_file, pz_file_source, pz_temp_file);
914 1.1 mrg }
915 1.1 mrg else /* NOT an "internal" fix: */
916 1.1 mrg {
917 1.1 mrg size_t parg_size;
918 1.1.1.4 mrg #if defined(__MSDOS__) && !defined(__DJGPP__)
919 1.1 mrg /* Don't use the "src > dstX; rm -f dst; mv -f dstX dst" trick:
920 1.1 mrg dst is a temporary file anyway, so we know there's no other
921 1.1 mrg file by that name; and DOS's system(3) doesn't mind to
922 1.1 mrg clobber existing file in redirection. Besides, with DOS 8+3
923 1.1 mrg limited file namespace, we can easily lose if dst already has
924 1.1 mrg an extension that is 3 or more characters long.
925 1.1 mrg
926 1.1 mrg I do not think the 8+3 issue is relevant because all the files
927 1.1 mrg we operate on are named "*.h", making 8+2 adequate. Anyway,
928 1.1 mrg the following bizarre use of 'cat' only works on DOS boxes.
929 1.1 mrg It causes the file to be dropped into a temporary file for
930 1.1 mrg 'cat' to read (pipes do not work on DOS). */
931 1.1 mrg tSCC z_cmd_fmt[] = " '%s' | cat > '%s'";
932 1.1 mrg #else
933 1.1 mrg /* Don't use positional formatting arguments because some lame-o
934 1.1 mrg implementations cannot cope :-(. */
935 1.1 mrg tSCC z_cmd_fmt[] = " %s > %sX ; rm -f %s; mv -f %sX %s";
936 1.1 mrg #endif
937 1.1.1.4 mrg tSCC z_subshell_start[] = "( ";
938 1.1.1.4 mrg tSCC z_subshell_end[] = " ) < ";
939 1.1 mrg tCC** ppArgs = p_fixd->patch_args;
940 1.1 mrg
941 1.1 mrg argsize = sizeof( z_cmd_fmt ) + strlen( pz_temp_file )
942 1.1 mrg + strlen( pz_file_source );
943 1.1 mrg parg_size = argsize;
944 1.1 mrg
945 1.1.1.4 mrg if (p_fixd->fd_flags & FD_SHELL_SCRIPT)
946 1.1.1.4 mrg {
947 1.1.1.4 mrg argsize += strlen( z_subshell_start ) + strlen ( z_subshell_end );
948 1.1.1.4 mrg }
949 1.1 mrg
950 1.1 mrg /*
951 1.1 mrg * Compute the size of the command line. Add lotsa extra space
952 1.1 mrg * because some of the args to sed use lotsa single quotes.
953 1.1 mrg * (This requires three extra bytes per quote. Here we allow
954 1.1 mrg * for up to 8 single quotes for each argument, including the
955 1.1 mrg * command name "sed" itself. Nobody will *ever* need more. :)
956 1.1 mrg */
957 1.1 mrg for (;;)
958 1.1 mrg {
959 1.1 mrg tCC* p_arg = *(ppArgs++);
960 1.1 mrg if (p_arg == NULL)
961 1.1 mrg break;
962 1.1 mrg argsize += 24 + strlen( p_arg );
963 1.1 mrg }
964 1.1 mrg
965 1.1 mrg /* Estimated buffer size we will need. */
966 1.1 mrg pz_scan = pz_cmd = XNEWVEC (char, argsize);
967 1.1 mrg /* How much of it do we allot to the program name and its
968 1.1 mrg arguments. */
969 1.1 mrg parg_size = argsize - parg_size;
970 1.1 mrg
971 1.1 mrg ppArgs = p_fixd->patch_args;
972 1.1 mrg
973 1.1 mrg /*
974 1.1.1.4 mrg * If it's shell script, enclose it in parentheses and skip "sh -c".
975 1.1.1.4 mrg */
976 1.1.1.4 mrg if (p_fixd->fd_flags & FD_SHELL_SCRIPT)
977 1.1.1.4 mrg {
978 1.1.1.4 mrg strcpy (pz_scan, z_subshell_start);
979 1.1.1.4 mrg pz_scan += strlen (z_subshell_start);
980 1.1.1.4 mrg ppArgs += 2;
981 1.1.1.4 mrg }
982 1.1.1.4 mrg
983 1.1.1.4 mrg /*
984 1.1 mrg * Copy the program name, unquoted
985 1.1 mrg */
986 1.1 mrg {
987 1.1 mrg tCC* pArg = *(ppArgs++);
988 1.1 mrg for (;;)
989 1.1 mrg {
990 1.1 mrg char ch = *(pArg++);
991 1.1 mrg if (ch == NUL)
992 1.1 mrg break;
993 1.1 mrg *(pz_scan++) = ch;
994 1.1 mrg }
995 1.1 mrg }
996 1.1 mrg
997 1.1 mrg /*
998 1.1 mrg * Copy the program arguments, quoted
999 1.1 mrg */
1000 1.1 mrg for (;;)
1001 1.1 mrg {
1002 1.1 mrg tCC* pArg = *(ppArgs++);
1003 1.1.1.3 mrg char* pz_scan_save;
1004 1.1 mrg if (pArg == NULL)
1005 1.1 mrg break;
1006 1.1 mrg *(pz_scan++) = ' ';
1007 1.1 mrg pz_scan = make_raw_shell_str( pz_scan_save = pz_scan, pArg,
1008 1.1.1.3 mrg parg_size - (pz_scan - pz_cmd) );
1009 1.1.1.3 mrg /*
1010 1.1.1.3 mrg * Make sure we don't overflow the buffer due to sloppy
1011 1.1.1.3 mrg * size estimation.
1012 1.1.1.3 mrg */
1013 1.1.1.3 mrg while (pz_scan == (char*)NULL)
1014 1.1.1.3 mrg {
1015 1.1.1.3 mrg size_t already_filled = pz_scan_save - pz_cmd;
1016 1.1.1.3 mrg pz_cmd = xrealloc (pz_cmd, argsize += 100);
1017 1.1.1.3 mrg pz_scan_save = pz_scan = pz_cmd + already_filled;
1018 1.1.1.3 mrg parg_size += 100;
1019 1.1.1.3 mrg pz_scan = make_raw_shell_str( pz_scan, pArg,
1020 1.1.1.3 mrg parg_size - (pz_scan - pz_cmd) );
1021 1.1.1.3 mrg }
1022 1.1 mrg }
1023 1.1 mrg
1024 1.1 mrg /*
1025 1.1.1.4 mrg * Close parenthesis if it's shell script.
1026 1.1.1.4 mrg */
1027 1.1.1.4 mrg if (p_fixd->fd_flags & FD_SHELL_SCRIPT)
1028 1.1.1.4 mrg {
1029 1.1.1.4 mrg strcpy (pz_scan, z_subshell_end);
1030 1.1.1.4 mrg pz_scan += strlen (z_subshell_end);
1031 1.1.1.4 mrg }
1032 1.1.1.4 mrg
1033 1.1.1.4 mrg /*
1034 1.1 mrg * add the file machinations.
1035 1.1 mrg */
1036 1.1.1.4 mrg #if defined(__MSDOS__) && !defined(__DJGPP__)
1037 1.1 mrg sprintf (pz_scan, z_cmd_fmt, pz_file_source, pz_temp_file );
1038 1.1 mrg #else
1039 1.1 mrg sprintf (pz_scan, z_cmd_fmt, pz_file_source, pz_temp_file,
1040 1.1 mrg pz_temp_file, pz_temp_file, pz_temp_file);
1041 1.1 mrg #endif
1042 1.1 mrg }
1043 1.1.1.4 mrg system_with_shell (pz_cmd);
1044 1.1.1.4 mrg free (pz_cmd);
1045 1.1 mrg }
1046 1.1 mrg
1047 1.1 mrg /* * * * * * * * * * * * *
1048 1.1 mrg
1049 1.1 mrg This loop should only cycle for 1/2 of one loop.
1050 1.1 mrg "chain_open" starts a process that uses "read_fd" as
1051 1.1 mrg its stdin and returns the new fd this process will use
1052 1.1 mrg for stdout. */
1053 1.1 mrg
1054 1.1 mrg #else /* is *NOT* SEPARATE_FIX_PROC */
1055 1.1 mrg static int
1056 1.1 mrg start_fixer (int read_fd, tFixDesc* p_fixd, char* pz_fix_file)
1057 1.1 mrg {
1058 1.1 mrg tCC* pz_cmd_save;
1059 1.1 mrg char* pz_cmd;
1060 1.1 mrg
1061 1.1 mrg if ((p_fixd->fd_flags & FD_SUBROUTINE) != 0)
1062 1.1 mrg return internal_fix (read_fd, p_fixd);
1063 1.1 mrg
1064 1.1 mrg if ((p_fixd->fd_flags & FD_SHELL_SCRIPT) == 0)
1065 1.1 mrg {
1066 1.1 mrg pz_cmd = NULL;
1067 1.1 mrg pz_cmd_save = NULL;
1068 1.1 mrg }
1069 1.1 mrg else
1070 1.1 mrg {
1071 1.1 mrg tSCC z_cmd_fmt[] = "file='%s'\n%s";
1072 1.1 mrg pz_cmd = XNEWVEC (char, strlen (p_fixd->patch_args[2])
1073 1.1.1.3 mrg + sizeof (z_cmd_fmt) + strlen (pz_fix_file));
1074 1.1 mrg sprintf (pz_cmd, z_cmd_fmt, pz_fix_file, p_fixd->patch_args[2]);
1075 1.1 mrg pz_cmd_save = p_fixd->patch_args[2];
1076 1.1 mrg p_fixd->patch_args[2] = pz_cmd;
1077 1.1 mrg }
1078 1.1 mrg
1079 1.1 mrg /* Start a fix process, handing off the previous read fd for its
1080 1.1 mrg stdin and getting a new fd that reads from the fix process' stdout.
1081 1.1 mrg We normally will not loop, but we will up to 10 times if we keep
1082 1.1 mrg getting "EAGAIN" errors.
1083 1.1 mrg
1084 1.1 mrg */
1085 1.1 mrg for (;;)
1086 1.1 mrg {
1087 1.1 mrg static int failCt = 0;
1088 1.1 mrg int fd;
1089 1.1 mrg
1090 1.1 mrg fd = chain_open (read_fd,
1091 1.1 mrg (tCC **) p_fixd->patch_args,
1092 1.1 mrg (process_chain_head == -1)
1093 1.1 mrg ? &process_chain_head : (pid_t *) NULL);
1094 1.1 mrg
1095 1.1 mrg if (fd != -1)
1096 1.1 mrg {
1097 1.1 mrg read_fd = fd;
1098 1.1 mrg break;
1099 1.1 mrg }
1100 1.1 mrg
1101 1.1 mrg fprintf (stderr, z_fork_err, errno, xstrerror (errno),
1102 1.1 mrg p_fixd->fix_name);
1103 1.1 mrg
1104 1.1 mrg if ((errno != EAGAIN) || (++failCt > 10))
1105 1.1 mrg exit (EXIT_FAILURE);
1106 1.1 mrg sleep (1);
1107 1.1 mrg }
1108 1.1 mrg
1109 1.1 mrg /* IF we allocated a shell script command,
1110 1.1 mrg THEN free it and restore the command format to the fix description */
1111 1.1 mrg if (pz_cmd != (char*)NULL)
1112 1.1 mrg {
1113 1.1 mrg free ((void*)pz_cmd);
1114 1.1 mrg p_fixd->patch_args[2] = pz_cmd_save;
1115 1.1 mrg }
1116 1.1 mrg
1117 1.1 mrg return read_fd;
1118 1.1 mrg }
1119 1.1 mrg #endif
1120 1.1.1.3 mrg #ifdef DEBUG
1121 1.1.1.3 mrg # define NOTE_SKIP(_ttyp) do { \
1122 1.1.1.3 mrg if (VLEVEL( VERB_EVERYTHING )) \
1123 1.1.1.3 mrg fprintf (stderr, z_failed, _ttyp, p_fixd->fix_name, \
1124 1.1.1.3 mrg pz_fname, p_fixd->test_ct - test_ct); \
1125 1.1.1.3 mrg } while (0)
1126 1.1.1.3 mrg #else
1127 1.1.1.3 mrg # define NOTE_SKIP(_ttyp)
1128 1.1.1.3 mrg #endif
1129 1.1 mrg
1130 1.1 mrg /* * * * * * * * * * * * *
1131 1.1 mrg *
1132 1.1 mrg * Process the potential fixes for a particular include file.
1133 1.1 mrg * Input: the original text of the file and the file's name
1134 1.1 mrg * Result: none. A new file may or may not be created.
1135 1.1 mrg */
1136 1.1 mrg static t_bool
1137 1.1 mrg fix_applies (tFixDesc* p_fixd)
1138 1.1 mrg {
1139 1.1 mrg const char *pz_fname = pz_curr_file;
1140 1.1 mrg const char *pz_scan = p_fixd->file_list;
1141 1.1 mrg int test_ct;
1142 1.1 mrg tTestDesc *p_test;
1143 1.1.1.3 mrg t_bool saw_sum_test = BOOL_FALSE;
1144 1.1.1.3 mrg t_bool one_sum_passed = BOOL_FALSE;
1145 1.1 mrg
1146 1.1.1.4 mrg #if defined(__MSDOS__) && !defined(__DJGPP__)
1147 1.1 mrg /*
1148 1.1 mrg * There is only one fix that uses a shell script as of this writing.
1149 1.1 mrg * I hope to nuke it anyway, it does not apply to DOS and it would
1150 1.1 mrg * be painful to implement. Therefore, no "shell" fixes for DOS.
1151 1.1 mrg */
1152 1.1 mrg if (p_fixd->fd_flags & (FD_SHELL_SCRIPT | FD_SKIP_TEST))
1153 1.1 mrg return BOOL_FALSE;
1154 1.1 mrg #else
1155 1.1 mrg if (p_fixd->fd_flags & FD_SKIP_TEST)
1156 1.1 mrg return BOOL_FALSE;
1157 1.1 mrg #endif
1158 1.1 mrg
1159 1.1 mrg /* IF there is a file name restriction,
1160 1.1 mrg THEN ensure the current file name matches one in the pattern */
1161 1.1 mrg
1162 1.1 mrg if (pz_scan != (char *) NULL)
1163 1.1 mrg {
1164 1.1 mrg while ((pz_fname[0] == '.') && (pz_fname[1] == '/'))
1165 1.1 mrg pz_fname += 2;
1166 1.1 mrg
1167 1.1 mrg for (;;)
1168 1.1 mrg {
1169 1.1 mrg if (fnmatch (pz_scan, pz_fname, 0) == 0)
1170 1.1 mrg break;
1171 1.1 mrg pz_scan += strlen (pz_scan) + 1;
1172 1.1 mrg if (*pz_scan == NUL)
1173 1.1 mrg return BOOL_FALSE;
1174 1.1 mrg }
1175 1.1 mrg }
1176 1.1 mrg
1177 1.1 mrg /* FOR each test, see if it fails.
1178 1.1.1.3 mrg "sum" fails only if all "sum" tests fail.
1179 1.1 mrg IF it does fail, then we go on to the next test */
1180 1.1 mrg
1181 1.1 mrg for (p_test = p_fixd->p_test_desc, test_ct = p_fixd->test_ct;
1182 1.1 mrg test_ct-- > 0;
1183 1.1 mrg p_test++)
1184 1.1 mrg {
1185 1.1 mrg switch (p_test->type)
1186 1.1 mrg {
1187 1.1 mrg case TT_TEST:
1188 1.1 mrg if (test_test (p_test, pz_curr_file) != APPLY_FIX) {
1189 1.1.1.3 mrg NOTE_SKIP("TEST");
1190 1.1 mrg return BOOL_FALSE;
1191 1.1 mrg }
1192 1.1 mrg break;
1193 1.1 mrg
1194 1.1 mrg case TT_EGREP:
1195 1.1 mrg if (egrep_test (pz_curr_data, p_test) != APPLY_FIX) {
1196 1.1.1.3 mrg NOTE_SKIP("EGREP");
1197 1.1 mrg return BOOL_FALSE;
1198 1.1 mrg }
1199 1.1 mrg break;
1200 1.1 mrg
1201 1.1 mrg case TT_NEGREP:
1202 1.1 mrg if (egrep_test (pz_curr_data, p_test) == APPLY_FIX) {
1203 1.1.1.3 mrg NOTE_SKIP("NEGREP");
1204 1.1 mrg /* Negated sense */
1205 1.1 mrg return BOOL_FALSE;
1206 1.1 mrg }
1207 1.1 mrg break;
1208 1.1 mrg
1209 1.1.1.3 mrg case TT_CKSUM:
1210 1.1.1.3 mrg if (one_sum_passed)
1211 1.1.1.3 mrg break; /* No need to check any more */
1212 1.1.1.3 mrg
1213 1.1.1.3 mrg saw_sum_test = BOOL_TRUE;
1214 1.1.1.3 mrg if (cksum_test (pz_curr_data, p_test, pz_curr_file) != APPLY_FIX) {
1215 1.1.1.3 mrg NOTE_SKIP("CKSUM");
1216 1.1.1.3 mrg } else {
1217 1.1.1.3 mrg one_sum_passed = BOOL_TRUE;
1218 1.1.1.3 mrg }
1219 1.1.1.3 mrg break;
1220 1.1.1.3 mrg
1221 1.1 mrg case TT_FUNCTION:
1222 1.1 mrg if (run_test (p_test->pz_test_text, pz_curr_file, pz_curr_data)
1223 1.1 mrg != APPLY_FIX) {
1224 1.1.1.3 mrg NOTE_SKIP("FTEST");
1225 1.1 mrg return BOOL_FALSE;
1226 1.1 mrg }
1227 1.1 mrg break;
1228 1.1 mrg }
1229 1.1 mrg }
1230 1.1 mrg
1231 1.1.1.3 mrg if (saw_sum_test)
1232 1.1.1.3 mrg return one_sum_passed;
1233 1.1.1.3 mrg
1234 1.1 mrg return BOOL_TRUE;
1235 1.1 mrg }
1236 1.1 mrg
1237 1.1 mrg
1238 1.1 mrg /* * * * * * * * * * * * *
1239 1.1 mrg
1240 1.1 mrg Write out a replacement file */
1241 1.1 mrg
1242 1.1 mrg static void
1243 1.1 mrg write_replacement (tFixDesc* p_fixd)
1244 1.1 mrg {
1245 1.1 mrg const char* pz_text = p_fixd->patch_args[0];
1246 1.1 mrg
1247 1.1 mrg if ((pz_text == (char*)NULL) || (*pz_text == NUL))
1248 1.1 mrg return;
1249 1.1 mrg
1250 1.1 mrg {
1251 1.1 mrg FILE* out_fp = create_file ();
1252 1.1 mrg size_t sz = strlen (pz_text);
1253 1.1 mrg fwrite (pz_text, sz, 1, out_fp);
1254 1.1 mrg if (pz_text[ sz-1 ] != '\n')
1255 1.1 mrg fputc ('\n', out_fp);
1256 1.1 mrg fclose (out_fp);
1257 1.1 mrg }
1258 1.1 mrg }
1259 1.1 mrg
1260 1.1 mrg
1261 1.1 mrg /* * * * * * * * * * * * *
1262 1.1 mrg
1263 1.1 mrg We have work to do. Read back in the output
1264 1.1 mrg of the filtering chain. Compare each byte as we read it with
1265 1.1 mrg the contents of the original file. As soon as we find any
1266 1.1 mrg difference, we will create the output file, write out all
1267 1.1 mrg the matched text and then copy any remaining data from the
1268 1.1 mrg output of the filter chain.
1269 1.1 mrg */
1270 1.1 mrg static void
1271 1.1 mrg test_for_changes (int read_fd)
1272 1.1 mrg {
1273 1.1 mrg FILE *in_fp = fdopen (read_fd, "r");
1274 1.1 mrg FILE *out_fp = (FILE *) NULL;
1275 1.1 mrg unsigned char *pz_cmp = (unsigned char*)pz_curr_data;
1276 1.1 mrg
1277 1.1 mrg #ifdef DO_STATS
1278 1.1 mrg fixed_ct++;
1279 1.1 mrg #endif
1280 1.1 mrg for (;;)
1281 1.1 mrg {
1282 1.1 mrg int ch;
1283 1.1 mrg
1284 1.1 mrg ch = getc (in_fp);
1285 1.1 mrg if (ch == EOF)
1286 1.1 mrg break;
1287 1.1 mrg ch &= 0xFF; /* all bytes are 8 bits */
1288 1.1 mrg
1289 1.1 mrg /* IF we are emitting the output
1290 1.1 mrg THEN emit this character, too.
1291 1.1 mrg */
1292 1.1 mrg if (out_fp != (FILE *) NULL)
1293 1.1 mrg putc (ch, out_fp);
1294 1.1 mrg
1295 1.1 mrg /* ELSE if this character does not match the original,
1296 1.1 mrg THEN now is the time to start the output.
1297 1.1 mrg */
1298 1.1 mrg else if (ch != *pz_cmp)
1299 1.1 mrg {
1300 1.1 mrg out_fp = create_file ();
1301 1.1 mrg
1302 1.1 mrg #ifdef DO_STATS
1303 1.1 mrg altered_ct++;
1304 1.1 mrg #endif
1305 1.1 mrg /* IF there are matched data, write the matched part now. */
1306 1.1 mrg if ((char*)pz_cmp != pz_curr_data)
1307 1.1 mrg fwrite (pz_curr_data, (size_t)((char*)pz_cmp - pz_curr_data),
1308 1.1.1.3 mrg 1, out_fp);
1309 1.1 mrg
1310 1.1 mrg /* Emit the current unmatching character */
1311 1.1 mrg putc (ch, out_fp);
1312 1.1 mrg }
1313 1.1 mrg else
1314 1.1 mrg /* ELSE the character matches. Advance the compare ptr */
1315 1.1 mrg pz_cmp++;
1316 1.1 mrg }
1317 1.1 mrg
1318 1.1 mrg /* IF we created the output file, ... */
1319 1.1 mrg if (out_fp != (FILE *) NULL)
1320 1.1 mrg {
1321 1.1 mrg regmatch_t match;
1322 1.1 mrg
1323 1.1 mrg /* Close the file and see if we have to worry about
1324 1.1 mrg `#include "file.h"' constructs. */
1325 1.1 mrg fclose (out_fp);
1326 1.1 mrg if (xregexec (&incl_quote_re, pz_curr_data, 1, &match, 0) == 0)
1327 1.1 mrg extract_quoted_files (pz_curr_data, pz_curr_file, &match);
1328 1.1 mrg }
1329 1.1 mrg
1330 1.1 mrg fclose (in_fp);
1331 1.1 mrg close (read_fd); /* probably redundant, but I'm paranoid */
1332 1.1 mrg }
1333 1.1 mrg
1334 1.1 mrg
1335 1.1 mrg /* * * * * * * * * * * * *
1336 1.1 mrg
1337 1.1 mrg Process the potential fixes for a particular include file.
1338 1.1 mrg Input: the original text of the file and the file's name
1339 1.1 mrg Result: none. A new file may or may not be created. */
1340 1.1 mrg
1341 1.1 mrg void
1342 1.1 mrg process (void)
1343 1.1 mrg {
1344 1.1 mrg tFixDesc *p_fixd = fixDescList;
1345 1.1 mrg int todo_ct = FIX_COUNT;
1346 1.1 mrg int read_fd = -1;
1347 1.1 mrg # ifndef SEPARATE_FIX_PROC
1348 1.1 mrg int num_children = 0;
1349 1.1 mrg # else /* is SEPARATE_FIX_PROC */
1350 1.1 mrg char* pz_file_source = pz_curr_file;
1351 1.1 mrg # endif
1352 1.1 mrg
1353 1.1 mrg if (access (pz_curr_file, R_OK) != 0)
1354 1.1 mrg {
1355 1.1.1.5 mrg /* It may happens if for e. g. the distro ships some broken symlinks
1356 1.1.1.5 mrg in /usr/include. */
1357 1.1.1.5 mrg
1358 1.1.1.5 mrg /* "INPUT" is exported in fixinc.sh, which is the pwd where fixincl
1359 1.1.1.5 mrg runs. It's used instead of getcwd to avoid allocating a buffer
1360 1.1.1.5 mrg with unknown length. */
1361 1.1.1.5 mrg const char *cwd = getenv ("INPUT");
1362 1.1.1.5 mrg if (!cwd)
1363 1.1.1.5 mrg cwd = "the working directory";
1364 1.1.1.5 mrg
1365 1.1.1.5 mrg fprintf (stderr, "Cannot access %s from %s: %s\n", pz_curr_file, cwd,
1366 1.1.1.5 mrg xstrerror (errno));
1367 1.1 mrg return;
1368 1.1 mrg }
1369 1.1 mrg
1370 1.1 mrg pz_curr_data = load_file (pz_curr_file);
1371 1.1 mrg if (pz_curr_data == (char *) NULL)
1372 1.1 mrg return;
1373 1.1 mrg
1374 1.1 mrg #ifdef DO_STATS
1375 1.1 mrg process_ct++;
1376 1.1 mrg #endif
1377 1.1 mrg if (VLEVEL( VERB_PROGRESS ) && have_tty)
1378 1.1 mrg fprintf (stderr, "%6lu %-50s \r",
1379 1.1.1.3 mrg (unsigned long) data_map_size, pz_curr_file);
1380 1.1 mrg
1381 1.1 mrg # ifndef SEPARATE_FIX_PROC
1382 1.1 mrg process_chain_head = NOPROCESS;
1383 1.1 mrg
1384 1.1 mrg /* For every fix in our fix list, ... */
1385 1.1 mrg for (; todo_ct > 0; p_fixd++, todo_ct--)
1386 1.1 mrg {
1387 1.1 mrg if (! fix_applies (p_fixd))
1388 1.1 mrg continue;
1389 1.1 mrg
1390 1.1 mrg if (VLEVEL( VERB_APPLIES ))
1391 1.1 mrg fprintf (stderr, "Applying %-24s to %s\n",
1392 1.1 mrg p_fixd->fix_name, pz_curr_file);
1393 1.1 mrg
1394 1.1 mrg if (p_fixd->fd_flags & FD_REPLACEMENT)
1395 1.1 mrg {
1396 1.1 mrg write_replacement (p_fixd);
1397 1.1 mrg UNLOAD_DATA();
1398 1.1 mrg return;
1399 1.1 mrg }
1400 1.1 mrg
1401 1.1 mrg /* IF we do not have a read pointer,
1402 1.1 mrg THEN this is the first fix for the current file.
1403 1.1 mrg Open the source file. That will be used as stdin for
1404 1.1 mrg the first fix. Any subsequent fixes will use the
1405 1.1 mrg stdout descriptor of the previous fix for its stdin. */
1406 1.1 mrg
1407 1.1 mrg if (read_fd == -1)
1408 1.1 mrg {
1409 1.1 mrg read_fd = open (pz_curr_file, O_RDONLY);
1410 1.1 mrg if (read_fd < 0)
1411 1.1 mrg {
1412 1.1 mrg fprintf (stderr, "Error %d (%s) opening %s\n", errno,
1413 1.1 mrg xstrerror (errno), pz_curr_file);
1414 1.1 mrg exit (EXIT_FAILURE);
1415 1.1 mrg }
1416 1.1 mrg
1417 1.1 mrg /* Ensure we do not get duplicate output */
1418 1.1 mrg
1419 1.1 mrg fflush (stdout);
1420 1.1 mrg }
1421 1.1 mrg
1422 1.1 mrg read_fd = start_fixer (read_fd, p_fixd, pz_curr_file);
1423 1.1 mrg num_children++;
1424 1.1 mrg }
1425 1.1 mrg
1426 1.1 mrg /* IF we have a read-back file descriptor,
1427 1.1 mrg THEN check for changes and write output if changed. */
1428 1.1 mrg
1429 1.1 mrg if (read_fd >= 0)
1430 1.1 mrg {
1431 1.1 mrg test_for_changes (read_fd);
1432 1.1 mrg #ifdef DO_STATS
1433 1.1 mrg apply_ct += num_children;
1434 1.1 mrg #endif
1435 1.1 mrg /* Wait for child processes created by chain_open()
1436 1.1 mrg to avoid leaving zombies. */
1437 1.1 mrg do {
1438 1.1 mrg wait ((int *) NULL);
1439 1.1 mrg } while (--num_children > 0);
1440 1.1 mrg }
1441 1.1 mrg
1442 1.1 mrg # else /* is SEPARATE_FIX_PROC */
1443 1.1 mrg
1444 1.1 mrg for (; todo_ct > 0; p_fixd++, todo_ct--)
1445 1.1 mrg {
1446 1.1 mrg if (! fix_applies (p_fixd))
1447 1.1 mrg continue;
1448 1.1 mrg
1449 1.1 mrg if (VLEVEL( VERB_APPLIES ))
1450 1.1 mrg fprintf (stderr, "Applying %-24s to %s\n",
1451 1.1 mrg p_fixd->fix_name, pz_curr_file);
1452 1.1 mrg
1453 1.1 mrg if (p_fixd->fd_flags & FD_REPLACEMENT)
1454 1.1 mrg {
1455 1.1 mrg write_replacement (p_fixd);
1456 1.1 mrg UNLOAD_DATA();
1457 1.1 mrg return;
1458 1.1 mrg }
1459 1.1 mrg fix_with_system (p_fixd, pz_curr_file, pz_file_source, pz_temp_file);
1460 1.1 mrg pz_file_source = pz_temp_file;
1461 1.1 mrg }
1462 1.1 mrg
1463 1.1 mrg read_fd = open (pz_temp_file, O_RDONLY);
1464 1.1 mrg if (read_fd < 0)
1465 1.1 mrg {
1466 1.1 mrg if (errno != ENOENT)
1467 1.1 mrg fprintf (stderr, "error %d (%s) opening output (%s) for read\n",
1468 1.1 mrg errno, xstrerror (errno), pz_temp_file);
1469 1.1 mrg }
1470 1.1 mrg else
1471 1.1 mrg {
1472 1.1 mrg test_for_changes (read_fd);
1473 1.1 mrg /* Unlinking a file while it is still open is a Bad Idea on
1474 1.1 mrg DOS/Windows. */
1475 1.1 mrg close (read_fd);
1476 1.1 mrg unlink (pz_temp_file);
1477 1.1 mrg }
1478 1.1 mrg
1479 1.1 mrg # endif
1480 1.1 mrg UNLOAD_DATA();
1481 1.1 mrg }
1482