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