00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "fixlib.h"
00025
00026 #include <sys/stat.h>
00027
00028 #if defined( HAVE_MMAP_FILE )
00029 #include <sys/mman.h>
00030 #define BAD_ADDR ((void*)-1)
00031 #endif
00032
00033 #ifndef SEPARATE_FIX_PROC
00034 #include "server.h"
00035 #endif
00036
00037
00038
00039
00040 static const char program_id[] = "fixincl version 1.1";
00041
00042
00043
00044 static const char z_std_preamble[] =
00045 "/* DO NOT EDIT THIS FILE.\n\n\
00046 It has been auto-edited by fixincludes from:\n\n\
00047 \t\"%s/%s\"\n\n\
00048 This had to be done to correct non-standard usages in the\n\
00049 original, manufacturer supplied header file. */\n\n";
00050
00051 int find_base_len = 0;
00052
00053 typedef enum {
00054 VERB_SILENT = 0,
00055 VERB_FIXES,
00056 VERB_APPLIES,
00057 VERB_PROGRESS,
00058 VERB_TESTS,
00059 VERB_EVERYTHING
00060 } te_verbose;
00061
00062 te_verbose verbose_level = VERB_PROGRESS;
00063 int have_tty = 0;
00064
00065 #define VLEVEL(l) ((unsigned int) verbose_level >= (unsigned int) l)
00066 #define NOT_SILENT VLEVEL(VERB_FIXES)
00067
00068 pid_t process_chain_head = (pid_t) -1;
00069
00070 char* pz_curr_file;
00071 char* pz_curr_data;
00072 char* pz_temp_file;
00073
00074 t_bool curr_data_mapped;
00075 int data_map_fd;
00076 size_t data_map_size;
00077 size_t ttl_data_size = 0;
00078
00079 #ifdef DO_STATS
00080 int process_ct = 0;
00081 int apply_ct = 0;
00082 int fixed_ct = 0;
00083 int altered_ct = 0;
00084 #endif
00085
00086 const char incl_quote_pat[] = "^[ \t]*#[ \t]*include[ \t]*\"[^/]";
00087 tSCC z_fork_err[] = "Error %d (%s) starting filter process for %s\n";
00088 regex_t incl_quote_re;
00089
00090 static void do_version (void) ATTRIBUTE_NORETURN;
00091 char *load_file (const char *);
00092 void run_compiles (void);
00093 void initialize (int argc, char** argv);
00094 void process (void);
00095
00096
00097
00098 #include "fixincl.x"
00099
00100
00101
00102
00103
00104 extern int main (int, char **);
00105 int
00106 main (int argc, char** argv)
00107 {
00108 char *file_name_buf;
00109
00110 initialize ( argc, argv );
00111
00112 have_tty = isatty (fileno (stderr));
00113
00114
00115 file_name_buf = load_file_data (stdin);
00116
00117
00118
00119
00120
00121 freopen ("/dev/null", "r", stdin);
00122
00123 if (file_name_buf == (char *) NULL)
00124 {
00125 fputs ("No file names listed for fixing\n", stderr);
00126 exit (EXIT_FAILURE);
00127 }
00128
00129 for (;;)
00130 {
00131 char* pz_end;
00132
00133
00134
00135 while (ISSPACE (*file_name_buf)) file_name_buf++;
00136 while ((file_name_buf[0] == '.') && (file_name_buf[1] == '/'))
00137 file_name_buf += 2;
00138
00139
00140
00141 if (*file_name_buf == NUL)
00142 break;
00143
00144
00145
00146 pz_curr_file = file_name_buf;
00147 pz_end = strchr( pz_curr_file, '\n' );
00148 if (pz_end == (char*)NULL)
00149 pz_end = file_name_buf = pz_curr_file + strlen (pz_curr_file);
00150 else
00151 file_name_buf = pz_end + 1;
00152
00153 while ((pz_end > pz_curr_file) && ISSPACE( pz_end[-1])) pz_end--;
00154
00155
00156
00157 if ((pz_curr_file == pz_end) || (*pz_curr_file == '#'))
00158 continue;
00159 *pz_end = NUL;
00160
00161 process ();
00162 }
00163
00164 #ifdef DO_STATS
00165 if (VLEVEL( VERB_PROGRESS )) {
00166 tSCC zFmt[] =
00167 "\
00168 Processed %5d files containing %d bytes \n\
00169 Applying %5d fixes to %d files\n\
00170 Altering %5d of them\n";
00171
00172 fprintf (stderr, zFmt, process_ct, ttl_data_size, apply_ct,
00173 fixed_ct, altered_ct);
00174 }
00175 #endif
00176
00177 # ifdef SEPARATE_FIX_PROC
00178 unlink( pz_temp_file );
00179 # endif
00180 exit (EXIT_SUCCESS);
00181 }
00182
00183
00184 static void
00185 do_version (void)
00186 {
00187 static const char zFmt[] = "echo '%s'";
00188 char zBuf[ 1024 ];
00189
00190
00191
00192
00193
00194
00195 run_compiles ();
00196 sprintf (zBuf, zFmt, program_id);
00197 #ifndef SEPARATE_FIX_PROC
00198 puts (zBuf + 5);
00199 exit (strcmp (run_shell (zBuf), program_id));
00200 #else
00201 exit (system (zBuf));
00202 #endif
00203 }
00204
00205
00206
00207 void
00208 initialize ( int argc, char** argv )
00209 {
00210 xmalloc_set_program_name (argv[0]);
00211
00212 switch (argc)
00213 {
00214 case 1:
00215 break;
00216
00217 case 2:
00218 if (strcmp (argv[1], "-v") == 0)
00219 do_version ();
00220 if (freopen (argv[1], "r", stdin) == (FILE*)NULL)
00221 {
00222 fprintf (stderr, "Error %d (%s) reopening %s as stdin\n",
00223 errno, xstrerror (errno), argv[1] );
00224 exit (EXIT_FAILURE);
00225 }
00226 break;
00227
00228 default:
00229 fputs ("fixincl ERROR: too many command line arguments\n", stderr);
00230 exit (EXIT_FAILURE);
00231 }
00232
00233 #ifdef SIGCHLD
00234
00235
00236 signal (SIGCHLD, SIG_DFL);
00237 #endif
00238
00239 initialize_opts ();
00240
00241 if (ISDIGIT ( *pz_verbose ))
00242 verbose_level = (te_verbose)atoi( pz_verbose );
00243 else
00244 switch (*pz_verbose) {
00245 case 's':
00246 case 'S':
00247 verbose_level = VERB_SILENT; break;
00248
00249 case 'f':
00250 case 'F':
00251 verbose_level = VERB_FIXES; break;
00252
00253 case 'a':
00254 case 'A':
00255 verbose_level = VERB_APPLIES; break;
00256
00257 default:
00258 case 'p':
00259 case 'P':
00260 verbose_level = VERB_PROGRESS; break;
00261
00262 case 't':
00263 case 'T':
00264 verbose_level = VERB_TESTS; break;
00265
00266 case 'e':
00267 case 'E':
00268 verbose_level = VERB_EVERYTHING; break;
00269 }
00270 if (verbose_level >= VERB_EVERYTHING) {
00271 verbose_level = VERB_EVERYTHING;
00272 fputs ("fixinc verbosity: EVERYTHING\n", stderr);
00273 }
00274 while ((pz_find_base[0] == '.') && (pz_find_base[1] == '/'))
00275 pz_find_base += 2;
00276 if ((pz_find_base[0] != '.') || (pz_find_base[1] != NUL))
00277 find_base_len = strlen( pz_find_base );
00278
00279
00280
00281
00282 run_compiles ();
00283
00284 # ifdef SEPARATE_FIX_PROC
00285
00286
00287 pz_temp_file = tempnam( NULL, "fxinc" );
00288 # endif
00289
00290 signal (SIGQUIT, SIG_IGN);
00291 signal (SIGIOT, SIG_IGN);
00292 signal (SIGPIPE, SIG_IGN);
00293 signal (SIGALRM, SIG_IGN);
00294 signal (SIGTERM, SIG_IGN);
00295 }
00296
00297
00298
00299
00300
00301
00302
00303 char *
00304 load_file ( const char* fname )
00305 {
00306 struct stat stbf;
00307 char* res;
00308
00309 if (stat (fname, &stbf) != 0)
00310 {
00311 if (NOT_SILENT)
00312 fprintf (stderr, "error %d (%s) stat-ing %s\n",
00313 errno, xstrerror (errno), fname );
00314 return (char *) NULL;
00315 }
00316 if (stbf.st_size == 0)
00317 return (char*)NULL;
00318
00319
00320
00321
00322
00323 data_map_size = stbf.st_size+1;
00324 data_map_fd = open (fname, O_RDONLY);
00325 ttl_data_size += data_map_size-1;
00326
00327 if (data_map_fd < 0)
00328 {
00329 if (NOT_SILENT)
00330 fprintf (stderr, "error %d (%s) opening %s for read\n",
00331 errno, xstrerror (errno), fname);
00332 return (char*)NULL;
00333 }
00334
00335 #ifdef HAVE_MMAP_FILE
00336 curr_data_mapped = BOOL_TRUE;
00337
00338
00339
00340 if ((stbf.st_size & (getpagesize()-1)) == 0)
00341 res = (char*)BAD_ADDR;
00342 else
00343 res = (char*)mmap ((void*)NULL, data_map_size, PROT_READ,
00344 MAP_PRIVATE, data_map_fd, 0);
00345 if (res == (char*)BAD_ADDR)
00346 #endif
00347 {
00348 FILE* fp = fdopen (data_map_fd, "r");
00349 curr_data_mapped = BOOL_FALSE;
00350 res = load_file_data (fp);
00351 fclose (fp);
00352 }
00353
00354 return res;
00355 }
00356
00357 static int
00358 machine_matches( tFixDesc* p_fixd )
00359 {
00360 # ifndef SEPARATE_FIX_PROC
00361 tSCC case_fmt[] = "case %s in\n";
00362 tSCC esac_fmt[] =
00363 " )\n echo %s ;;\n* ) echo %s ;;\nesac";
00364 tSCC skip[] = "skip";
00365 tSCC run[] = "run";
00366
00367
00368 const char **papz_machs = p_fixd->papz_machs;
00369 char *pz;
00370 const char *pz_sep = "";
00371 tCC *pz_if_true;
00372 tCC *pz_if_false;
00373 char cmd_buf[ MACH_LIST_SIZE_LIMIT ];
00374
00375
00376
00377 sprintf (cmd_buf, case_fmt, pz_machine);
00378 pz = cmd_buf + strlen (cmd_buf);
00379
00380
00381
00382 if (p_fixd->fd_flags & FD_MACH_IFNOT)
00383 {
00384 pz_if_true = skip;
00385 pz_if_false = run;
00386 }
00387 else
00388 {
00389 pz_if_true = run;
00390 pz_if_false = skip;
00391 }
00392
00393
00394
00395
00396 for (;;)
00397 {
00398 const char* pz_mach = *(papz_machs++);
00399
00400 if (pz_mach == (const char*) NULL)
00401 break;
00402 sprintf (pz, "%s%s", pz_sep, pz_mach);
00403 pz += strlen (pz);
00404 pz_sep = " | \\\n";
00405 }
00406
00407
00408
00409 sprintf (pz, esac_fmt, pz_if_true, pz_if_false);
00410
00411
00412
00413
00414 {
00415 int skip;
00416 pz = run_shell (cmd_buf);
00417 skip = (*pz == 's');
00418 free ( (void*)pz );
00419 if (skip)
00420 {
00421 p_fixd->fd_flags |= FD_SKIP_TEST;
00422 return BOOL_FALSE;
00423 }
00424 }
00425
00426 return BOOL_TRUE;
00427 # else
00428 const char **papz_machs = p_fixd->papz_machs;
00429 int invert = (p_fixd->fd_flags & FD_MACH_IFNOT) != 0;
00430 for (;;)
00431 {
00432 const char* pz_mach = *(papz_machs++);
00433
00434 if (pz_mach == (const char*) NULL)
00435 break;
00436 if (strstr (pz_mach, "dos") != NULL && !invert)
00437 return BOOL_TRUE;
00438 }
00439
00440 p_fixd->fd_flags |= FD_SKIP_TEST;
00441 return BOOL_FALSE;
00442 # endif
00443 }
00444
00445
00446
00447
00448
00449 void
00450 run_compiles (void)
00451 {
00452 tFixDesc *p_fixd = fixDescList;
00453 int fix_ct = FIX_COUNT;
00454 regex_t *p_re = xcalloc (REGEX_COUNT, sizeof (regex_t));
00455
00456
00457
00458 memset (&incl_quote_re, '\0', sizeof (regex_t));
00459
00460 compile_re (incl_quote_pat, &incl_quote_re, 1,
00461 "quoted include", "run_compiles");
00462
00463
00464
00465 if (pz_machine && ((*pz_machine == '\0') || (*pz_machine == '*')))
00466 pz_machine = (char*)NULL;
00467
00468
00469 do
00470 {
00471 tTestDesc *p_test = p_fixd->p_test_desc;
00472 int test_ct = p_fixd->test_ct;
00473
00474
00475
00476
00477
00478 if ( (pz_machine != NULL)
00479 && (p_fixd->papz_machs != (const char**) NULL)
00480 && ! machine_matches (p_fixd) )
00481 continue;
00482
00483
00484
00485 while (--test_ct >= 0)
00486 {
00487 switch (p_test->type)
00488 {
00489 case TT_EGREP:
00490 case TT_NEGREP:
00491 p_test->p_test_regex = p_re++;
00492 compile_re (p_test->pz_test_text, p_test->p_test_regex, 0,
00493 "select test", p_fixd->fix_name);
00494 default: break;
00495 }
00496 p_test++;
00497 }
00498 }
00499 while (p_fixd++, --fix_ct > 0);
00500 }
00501
00502
00503
00504
00505
00506
00507
00508
00509 #if defined(S_IRUSR) && defined(S_IWUSR) && \
00510 defined(S_IRGRP) && defined(S_IROTH)
00511
00512 # define S_IRALL (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
00513 #else
00514 # define S_IRALL 0644
00515 #endif
00516
00517 #if defined(S_IRWXU) && defined(S_IRGRP) && defined(S_IXGRP) && \
00518 defined(S_IROTH) && defined(S_IXOTH)
00519
00520 # define S_DIRALL (S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)
00521 #else
00522 # define S_DIRALL 0755
00523 #endif
00524
00525
00526 static FILE *
00527 create_file (void)
00528 {
00529 int fd;
00530 FILE *pf;
00531 char fname[MAXPATHLEN];
00532
00533 sprintf (fname, "%s/%s", pz_dest_dir, pz_curr_file + find_base_len);
00534
00535 fd = open (fname, O_WRONLY | O_CREAT | O_TRUNC, S_IRALL);
00536
00537
00538 if ((fd < 0) && (errno == ENOENT))
00539 {
00540 char *pz_dir = strchr (fname + 1, '/');
00541 struct stat stbf;
00542
00543 while (pz_dir != (char *) NULL)
00544 {
00545 *pz_dir = NUL;
00546 if (stat (fname, &stbf) < 0)
00547 {
00548 #ifdef _WIN32
00549 mkdir (fname);
00550 #else
00551 mkdir (fname, S_IFDIR | S_DIRALL);
00552 #endif
00553 }
00554
00555 *pz_dir = '/';
00556 pz_dir = strchr (pz_dir + 1, '/');
00557 }
00558
00559
00560 fd = open (fname, O_WRONLY | O_CREAT | O_TRUNC, S_IRALL);
00561 }
00562 if (fd < 0)
00563 {
00564 fprintf (stderr, "Error %d (%s) creating %s\n",
00565 errno, xstrerror (errno), fname);
00566 exit (EXIT_FAILURE);
00567 }
00568 if (NOT_SILENT)
00569 fprintf (stderr, "Fixed: %s\n", pz_curr_file);
00570 pf = fdopen (fd, "w");
00571
00572
00573
00574
00575
00576 fprintf (pf, z_std_preamble,
00577 (pz_machine == NULL)
00578 ? "fixinc/tests/inc"
00579 : pz_input_dir,
00580 pz_curr_file);
00581
00582 return pf;
00583 }
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593 #ifndef SEPARATE_FIX_PROC
00594 static int
00595 test_test (tTestDesc* p_test, char* pz_test_file)
00596 {
00597 tSCC cmd_fmt[] =
00598 "file=%s\n\
00599 if ( test %s ) > /dev/null 2>&1\n\
00600 then echo TRUE\n\
00601 else echo FALSE\n\
00602 fi";
00603
00604 char *pz_res;
00605 int res;
00606
00607 static char cmd_buf[4096];
00608
00609 sprintf (cmd_buf, cmd_fmt, pz_test_file, p_test->pz_test_text);
00610 pz_res = run_shell (cmd_buf);
00611
00612 switch (*pz_res) {
00613 case 'T':
00614 res = APPLY_FIX;
00615 break;
00616
00617 case 'F':
00618 res = SKIP_FIX;
00619 break;
00620
00621 default:
00622 fprintf (stderr, "Script yielded bogus result of `%s':\n%s\n\n",
00623 pz_res, cmd_buf );
00624 res = SKIP_FIX;
00625 }
00626
00627 free ((void *) pz_res);
00628 return res;
00629 }
00630 #else
00631
00632
00633
00634
00635 #define test_test(t,tf) SKIP_FIX
00636 #endif
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648 static int
00649 egrep_test (char* pz_data, tTestDesc* p_test)
00650 {
00651 #ifdef DEBUG
00652 if (p_test->p_test_regex == 0)
00653 fprintf (stderr, "fixincl ERROR RE not compiled: `%s'\n",
00654 p_test->pz_test_text);
00655 #endif
00656 if (xregexec (p_test->p_test_regex, pz_data, 0, 0, 0) == 0)
00657 return APPLY_FIX;
00658 return SKIP_FIX;
00659 }
00660
00661
00662
00663
00664
00665
00666
00667
00668 static int
00669 quoted_file_exists (const char* pz_src_path,
00670 const char* pz_file_path,
00671 const char* pz_file)
00672 {
00673 char z[ MAXPATHLEN ];
00674 char* pz;
00675 sprintf (z, "%s/%s/", pz_src_path, pz_file_path);
00676 pz = z + strlen ( z );
00677
00678 for (;;) {
00679 char ch = *pz_file++;
00680 if (! ISGRAPH( ch ))
00681 return 0;
00682 if (ch == '"')
00683 break;
00684 *pz++ = ch;
00685 }
00686 *pz = '\0';
00687 {
00688 struct stat s;
00689 if (stat (z, &s) != 0)
00690 return 0;
00691 return S_ISREG( s.st_mode );
00692 }
00693 }
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718 static void
00719 extract_quoted_files (char* pz_data,
00720 const char* pz_fixed_file,
00721 regmatch_t* p_re_match)
00722 {
00723 char *pz_dir_end = strrchr (pz_fixed_file, '/');
00724 char *pz_incl_quot = pz_data;
00725
00726 if (VLEVEL( VERB_APPLIES ))
00727 fprintf (stderr, "Quoted includes in %s\n", pz_fixed_file);
00728
00729
00730
00731
00732 if (pz_dir_end == (char *) NULL)
00733 pz_fixed_file = ".";
00734 else
00735 *pz_dir_end = '\0';
00736
00737 for (;;)
00738 {
00739 pz_incl_quot += p_re_match->rm_so;
00740
00741
00742 while (*pz_incl_quot != '"')
00743 pz_incl_quot++;
00744
00745 if (quoted_file_exists (pz_src_dir, pz_fixed_file, pz_incl_quot))
00746 {
00747
00748
00749 printf ("%s %s/", pz_src_dir, pz_fixed_file);
00750 pz_dir_end = pz_incl_quot;
00751
00752
00753 while (*pz_incl_quot != '"')
00754 putc (*pz_incl_quot++, stdout);
00755
00756
00757
00758 printf (" %s/%s/", pz_dest_dir, pz_fixed_file);
00759 while (*pz_dir_end != '"')
00760 putc (*pz_dir_end++, stdout);
00761
00762
00763 putc ('\n', stdout);
00764 }
00765
00766
00767 if (xregexec (&incl_quote_re, pz_incl_quot, 1, p_re_match, 0) != 0)
00768 break;
00769 }
00770 }
00771
00772
00773
00774
00775
00776
00777 #ifndef SEPARATE_FIX_PROC
00778 static int
00779 internal_fix (int read_fd, tFixDesc* p_fixd)
00780 {
00781 int fd[2];
00782
00783 if (pipe( fd ) != 0)
00784 {
00785 fprintf (stderr, "Error %d on pipe(2) call\n", errno );
00786 exit (EXIT_FAILURE);
00787 }
00788
00789 for (;;)
00790 {
00791 pid_t childid = fork();
00792
00793 switch (childid)
00794 {
00795 case -1:
00796 break;
00797
00798 case 0:
00799 close (fd[0]);
00800 goto do_child_task;
00801
00802 default:
00803
00804
00805
00806 close (read_fd);
00807 close (fd[1]);
00808 return fd[0];
00809 }
00810
00811
00812
00813
00814 fprintf (stderr, z_fork_err, errno, xstrerror (errno),
00815 p_fixd->fix_name);
00816 {
00817 static int failCt = 0;
00818 if ((errno != EAGAIN) || (++failCt > 10))
00819 exit (EXIT_FAILURE);
00820 sleep (1);
00821 }
00822 } do_child_task:;
00823
00824
00825
00826
00827 close (STDIN_FILENO);
00828 close (STDOUT_FILENO);
00829 UNLOAD_DATA();
00830
00831
00832
00833
00834
00835 dup2 (fd[1], STDOUT_FILENO);
00836 dup2 (read_fd, STDIN_FILENO);
00837
00838 apply_fix (p_fixd, pz_curr_file);
00839 exit (0);
00840 }
00841 #endif
00842
00843
00844 #ifdef SEPARATE_FIX_PROC
00845 static void
00846 fix_with_system (tFixDesc* p_fixd,
00847 tCC* pz_fix_file,
00848 tCC* pz_file_source,
00849 tCC* pz_temp_file)
00850 {
00851 char* pz_cmd;
00852 char* pz_scan;
00853 size_t argsize;
00854
00855 if (p_fixd->fd_flags & FD_SUBROUTINE)
00856 {
00857 static const char z_applyfix_prog[] =
00858 "/../fixincludes/applyfix" EXE_EXT;
00859
00860 struct stat buf;
00861 argsize = 32
00862 + strlen (pz_orig_dir)
00863 + sizeof (z_applyfix_prog)
00864 + strlen (pz_fix_file)
00865 + strlen (pz_file_source)
00866 + strlen (pz_temp_file);
00867
00868
00869 pz_cmd = xmalloc (argsize);
00870 strcpy (pz_cmd, pz_orig_dir);
00871 pz_scan = pz_cmd + strlen (pz_orig_dir);
00872
00873 strcpy (pz_scan, z_applyfix_prog);
00874
00875
00876
00877 if (stat (pz_cmd, &buf) == -1)
00878 {
00879 strcpy (pz_scan, "/..");
00880 strcpy (pz_scan+3, z_applyfix_prog);
00881 }
00882
00883 pz_scan += strlen (pz_scan);
00884
00885
00886
00887
00888 sprintf (pz_scan, " %ld '%s' '%s' '%s'", p_fixd - fixDescList,
00889 pz_fix_file, pz_file_source, pz_temp_file);
00890 }
00891 else
00892 {
00893 size_t parg_size;
00894 #ifdef __MSDOS__
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907 tSCC z_cmd_fmt[] = " '%s' | cat > '%s'";
00908 #else
00909
00910
00911 tSCC z_cmd_fmt[] = " %s > %sX ; rm -f %s; mv -f %sX %s";
00912 #endif
00913 tCC** ppArgs = p_fixd->patch_args;
00914
00915 argsize = sizeof( z_cmd_fmt ) + strlen( pz_temp_file )
00916 + strlen( pz_file_source );
00917 parg_size = argsize;
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927 for (;;)
00928 {
00929 tCC* p_arg = *(ppArgs++);
00930 if (p_arg == NULL)
00931 break;
00932 argsize += 24 + strlen( p_arg );
00933 }
00934
00935
00936 pz_scan = pz_cmd = xmalloc (argsize);
00937
00938
00939 parg_size = argsize - parg_size;
00940
00941 ppArgs = p_fixd->patch_args;
00942
00943
00944
00945
00946 {
00947 tCC* pArg = *(ppArgs++);
00948 for (;;)
00949 {
00950 char ch = *(pArg++);
00951 if (ch == NUL)
00952 break;
00953 *(pz_scan++) = ch;
00954 }
00955 }
00956
00957
00958
00959
00960 for (;;)
00961 {
00962 tCC* pArg = *(ppArgs++);
00963 char* pz_scan_save;
00964 if (pArg == NULL)
00965 break;
00966 *(pz_scan++) = ' ';
00967 pz_scan = make_raw_shell_str( pz_scan_save = pz_scan, pArg,
00968 parg_size - (pz_scan - pz_cmd) );
00969
00970
00971
00972
00973 while (pz_scan == (char*)NULL)
00974 {
00975 size_t already_filled = pz_scan_save - pz_cmd;
00976 pz_cmd = xrealloc (pz_cmd, argsize += 100);
00977 pz_scan_save = pz_scan = pz_cmd + already_filled;
00978 parg_size += 100;
00979 pz_scan = make_raw_shell_str( pz_scan, pArg,
00980 parg_size - (pz_scan - pz_cmd) );
00981 }
00982 }
00983
00984
00985
00986
00987 #ifdef __MSDOS__
00988 sprintf (pz_scan, z_cmd_fmt, pz_file_source, pz_temp_file );
00989 #else
00990 sprintf (pz_scan, z_cmd_fmt, pz_file_source, pz_temp_file,
00991 pz_temp_file, pz_temp_file, pz_temp_file);
00992 #endif
00993 }
00994 system( pz_cmd );
00995 free( (void*)pz_cmd );
00996 }
00997
00998
00999
01000
01001
01002
01003
01004
01005 #else
01006 static int
01007 start_fixer (int read_fd, tFixDesc* p_fixd, char* pz_fix_file)
01008 {
01009 tCC* pz_cmd_save;
01010 char* pz_cmd;
01011
01012 if ((p_fixd->fd_flags & FD_SUBROUTINE) != 0)
01013 return internal_fix (read_fd, p_fixd);
01014
01015 if ((p_fixd->fd_flags & FD_SHELL_SCRIPT) == 0)
01016 {
01017 pz_cmd = NULL;
01018 pz_cmd_save = NULL;
01019 }
01020 else
01021 {
01022 tSCC z_cmd_fmt[] = "file='%s'\n%s";
01023 pz_cmd = xmalloc (strlen (p_fixd->patch_args[2])
01024 + sizeof (z_cmd_fmt) + strlen (pz_fix_file));
01025 sprintf (pz_cmd, z_cmd_fmt, pz_fix_file, p_fixd->patch_args[2]);
01026 pz_cmd_save = p_fixd->patch_args[2];
01027 p_fixd->patch_args[2] = pz_cmd;
01028 }
01029
01030
01031
01032
01033
01034
01035
01036 for (;;)
01037 {
01038 static int failCt = 0;
01039 int fd;
01040
01041 fd = chain_open (read_fd,
01042 (tCC **) p_fixd->patch_args,
01043 (process_chain_head == -1)
01044 ? &process_chain_head : (pid_t *) NULL);
01045
01046 if (fd != -1)
01047 {
01048 read_fd = fd;
01049 break;
01050 }
01051
01052 fprintf (stderr, z_fork_err, errno, xstrerror (errno),
01053 p_fixd->fix_name);
01054
01055 if ((errno != EAGAIN) || (++failCt > 10))
01056 exit (EXIT_FAILURE);
01057 sleep (1);
01058 }
01059
01060
01061
01062 if (pz_cmd != (char*)NULL)
01063 {
01064 free ((void*)pz_cmd);
01065 p_fixd->patch_args[2] = pz_cmd_save;
01066 }
01067
01068 return read_fd;
01069 }
01070 #endif
01071
01072
01073
01074
01075
01076
01077
01078
01079 static t_bool
01080 fix_applies (tFixDesc* p_fixd)
01081 {
01082 const char *pz_fname = pz_curr_file;
01083 const char *pz_scan = p_fixd->file_list;
01084 int test_ct;
01085 tTestDesc *p_test;
01086
01087 # ifdef SEPARATE_FIX_PROC
01088
01089
01090
01091
01092
01093 if (p_fixd->fd_flags & (FD_SHELL_SCRIPT | FD_SKIP_TEST))
01094 return BOOL_FALSE;
01095 # else
01096 if (p_fixd->fd_flags & FD_SKIP_TEST)
01097 return BOOL_FALSE;
01098 # endif
01099
01100
01101
01102
01103 if (pz_scan != (char *) NULL)
01104 {
01105 size_t name_len;
01106
01107 while ((pz_fname[0] == '.') && (pz_fname[1] == '/'))
01108 pz_fname += 2;
01109 name_len = strlen (pz_fname);
01110
01111 for (;;)
01112 {
01113 pz_scan = strstr (pz_scan + 1, pz_fname);
01114
01115
01116 if (pz_scan == (char *) NULL)
01117 return BOOL_FALSE;
01118
01119
01120
01121
01122 if ((pz_scan[-1] == '|') && (pz_scan[name_len] == '|'))
01123 break;
01124 }
01125 }
01126
01127
01128
01129
01130 for (p_test = p_fixd->p_test_desc, test_ct = p_fixd->test_ct;
01131 test_ct-- > 0;
01132 p_test++)
01133 {
01134 switch (p_test->type)
01135 {
01136 case TT_TEST:
01137 if (test_test (p_test, pz_curr_file) != APPLY_FIX) {
01138 #ifdef DEBUG
01139 if (VLEVEL( VERB_EVERYTHING ))
01140 fprintf (stderr, z_failed, "TEST", p_fixd->fix_name,
01141 pz_fname, p_fixd->test_ct - test_ct);
01142 #endif
01143 return BOOL_FALSE;
01144 }
01145 break;
01146
01147 case TT_EGREP:
01148 if (egrep_test (pz_curr_data, p_test) != APPLY_FIX) {
01149 #ifdef DEBUG
01150 if (VLEVEL( VERB_EVERYTHING ))
01151 fprintf (stderr, z_failed, "EGREP", p_fixd->fix_name,
01152 pz_fname, p_fixd->test_ct - test_ct);
01153 #endif
01154 return BOOL_FALSE;
01155 }
01156 break;
01157
01158 case TT_NEGREP:
01159 if (egrep_test (pz_curr_data, p_test) == APPLY_FIX) {
01160 #ifdef DEBUG
01161 if (VLEVEL( VERB_EVERYTHING ))
01162 fprintf (stderr, z_failed, "NEGREP", p_fixd->fix_name,
01163 pz_fname, p_fixd->test_ct - test_ct);
01164 #endif
01165
01166 return BOOL_FALSE;
01167 }
01168 break;
01169
01170 case TT_FUNCTION:
01171 if (run_test (p_test->pz_test_text, pz_curr_file, pz_curr_data)
01172 != APPLY_FIX) {
01173 #ifdef DEBUG
01174 if (VLEVEL( VERB_EVERYTHING ))
01175 fprintf (stderr, z_failed, "FTEST", p_fixd->fix_name,
01176 pz_fname, p_fixd->test_ct - test_ct);
01177 #endif
01178 return BOOL_FALSE;
01179 }
01180 break;
01181 }
01182 }
01183
01184 return BOOL_TRUE;
01185 }
01186
01187
01188
01189
01190
01191
01192 static void
01193 write_replacement (tFixDesc* p_fixd)
01194 {
01195 const char* pz_text = p_fixd->patch_args[0];
01196
01197 if ((pz_text == (char*)NULL) || (*pz_text == NUL))
01198 return;
01199
01200 {
01201 FILE* out_fp = create_file ();
01202 fputs (pz_text, out_fp);
01203 fclose (out_fp);
01204 }
01205 }
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215
01216
01217 static void
01218 test_for_changes (int read_fd)
01219 {
01220 FILE *in_fp = fdopen (read_fd, "r");
01221 FILE *out_fp = (FILE *) NULL;
01222 unsigned char *pz_cmp = (unsigned char*)pz_curr_data;
01223
01224 #ifdef DO_STATS
01225 fixed_ct++;
01226 #endif
01227 for (;;)
01228 {
01229 int ch;
01230
01231 ch = getc (in_fp);
01232 if (ch == EOF)
01233 break;
01234 ch &= 0xFF;
01235
01236
01237
01238
01239 if (out_fp != (FILE *) NULL)
01240 putc (ch, out_fp);
01241
01242
01243
01244
01245 else if (ch != *pz_cmp)
01246 {
01247 out_fp = create_file ();
01248
01249 #ifdef DO_STATS
01250 altered_ct++;
01251 #endif
01252
01253 if ((char*)pz_cmp != pz_curr_data)
01254 fwrite (pz_curr_data, (size_t)((char*)pz_cmp - pz_curr_data),
01255 1, out_fp);
01256
01257
01258 putc (ch, out_fp);
01259 }
01260 else
01261
01262 pz_cmp++;
01263 }
01264
01265
01266 if (out_fp != (FILE *) NULL)
01267 {
01268 regmatch_t match;
01269
01270
01271
01272 fclose (out_fp);
01273 if (xregexec (&incl_quote_re, pz_curr_data, 1, &match, 0) == 0)
01274 extract_quoted_files (pz_curr_data, pz_curr_file, &match);
01275 }
01276
01277 fclose (in_fp);
01278 close (read_fd);
01279 }
01280
01281
01282
01283
01284
01285
01286
01287
01288 void
01289 process (void)
01290 {
01291 tFixDesc *p_fixd = fixDescList;
01292 int todo_ct = FIX_COUNT;
01293 int read_fd = -1;
01294 # ifndef SEPARATE_FIX_PROC
01295 int num_children = 0;
01296 # else
01297 char* pz_file_source = pz_curr_file;
01298 # endif
01299
01300 if (access (pz_curr_file, R_OK) != 0)
01301 {
01302 int erno = errno;
01303 fprintf (stderr, "Cannot access %s from %s\n\terror %d (%s)\n",
01304 pz_curr_file, getcwd ((char *) NULL, MAXPATHLEN),
01305 erno, xstrerror (erno));
01306 return;
01307 }
01308
01309 pz_curr_data = load_file (pz_curr_file);
01310 if (pz_curr_data == (char *) NULL)
01311 return;
01312
01313 #ifdef DO_STATS
01314 process_ct++;
01315 #endif
01316 if (VLEVEL( VERB_PROGRESS ) && have_tty)
01317 fprintf (stderr, "%6lu %-50s \r",
01318 (unsigned long) data_map_size, pz_curr_file);
01319
01320 # ifndef SEPARATE_FIX_PROC
01321 process_chain_head = NOPROCESS;
01322
01323
01324 for (; todo_ct > 0; p_fixd++, todo_ct--)
01325 {
01326 if (! fix_applies (p_fixd))
01327 continue;
01328
01329 if (VLEVEL( VERB_APPLIES ))
01330 fprintf (stderr, "Applying %-24s to %s\n",
01331 p_fixd->fix_name, pz_curr_file);
01332
01333 if (p_fixd->fd_flags & FD_REPLACEMENT)
01334 {
01335 write_replacement (p_fixd);
01336 UNLOAD_DATA();
01337 return;
01338 }
01339
01340
01341
01342
01343
01344
01345
01346 if (read_fd == -1)
01347 {
01348 read_fd = open (pz_curr_file, O_RDONLY);
01349 if (read_fd < 0)
01350 {
01351 fprintf (stderr, "Error %d (%s) opening %s\n", errno,
01352 xstrerror (errno), pz_curr_file);
01353 exit (EXIT_FAILURE);
01354 }
01355
01356
01357
01358 fflush (stdout);
01359 }
01360
01361 read_fd = start_fixer (read_fd, p_fixd, pz_curr_file);
01362 num_children++;
01363 }
01364
01365
01366
01367
01368 if (read_fd >= 0)
01369 {
01370 test_for_changes (read_fd);
01371 #ifdef DO_STATS
01372 apply_ct += num_children;
01373 #endif
01374
01375
01376 do {
01377 wait ((int *) NULL);
01378 } while (--num_children > 0);
01379 }
01380
01381 # else
01382
01383 for (; todo_ct > 0; p_fixd++, todo_ct--)
01384 {
01385 if (! fix_applies (p_fixd))
01386 continue;
01387
01388 if (VLEVEL( VERB_APPLIES ))
01389 fprintf (stderr, "Applying %-24s to %s\n",
01390 p_fixd->fix_name, pz_curr_file);
01391
01392 if (p_fixd->fd_flags & FD_REPLACEMENT)
01393 {
01394 write_replacement (p_fixd);
01395 UNLOAD_DATA();
01396 return;
01397 }
01398 fix_with_system (p_fixd, pz_curr_file, pz_file_source, pz_temp_file);
01399 pz_file_source = pz_temp_file;
01400 }
01401
01402 read_fd = open (pz_temp_file, O_RDONLY);
01403 if (read_fd < 0)
01404 {
01405 if (errno != ENOENT)
01406 fprintf (stderr, "error %d (%s) opening output (%s) for read\n",
01407 errno, xstrerror (errno), pz_temp_file);
01408 }
01409 else
01410 {
01411 test_for_changes (read_fd);
01412
01413
01414 close (read_fd);
01415 unlink (pz_temp_file);
01416 }
01417
01418 # endif
01419 UNLOAD_DATA();
01420 }