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