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