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