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