📄 fixincl.c
字号:
/* Install modified versions of certain ANSI-incompatible system header files which are fixed to work correctly with ANSI C and placed in a directory that GNU C will search. Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc.This file is part of GNU CC.GNU CC is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2, or (at your option)any later version.GNU CC is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with GNU CC; see the file COPYING. If not, write tothe Free Software Foundation, 59 Temple Place - Suite 330,Boston, MA 02111-1307, USA. */#include "auto-host.h"#include "gansidecl.h"#include "system.h"#include <signal.h>#include "gnu-regex.h"#include "server.h"static const char program_id[] = "fixincl version 1.0";#define MINIMUM_MAXIMUM_LINES 128/* If this particular system's header files define the macro `MAXPATHLEN', we happily take advantage of it; otherwise we use a value which ought to be large enough. */#ifndef MAXPATHLEN# define MAXPATHLEN 4096#endif#define NAME_TABLE_SIZE (MINIMUM_MAXIMUM_LINES * MAXPATHLEN)#ifndef EXIT_SUCCESS# define EXIT_SUCCESS 0#endif#ifndef EXIT_FAILURE# define EXIT_FAILURE 1#endifchar *file_name_buf;#define tSCC static const char#define tCC const char#define tSC static chartypedef int t_success;#define FAILURE (-1)#define SUCCESS 0#define PROBLEM 1#define SUCCEEDED(p) ((p) == SUCCESS)#define SUCCESSFUL(p) SUCCEEDED (p)#define FAILED(p) ((p) < SUCCESS)#define HADGLITCH(p) ((p) > SUCCESS)#define NUL '\0'/* Test Descriptor Each fix may have associated tests that determine whether the fix needs to be applied or not. Each test has a type (from the te_test_type enumeration); associated test text; and, if the test is TT_EGREP or the negated form TT_NEGREP, a pointer to the compiled version of the text string. */typedef enum{ TT_TEST, TT_EGREP, TT_NEGREP} te_test_type;typedef struct test_desc tTestDesc;struct test_desc{ te_test_type type; const char *pz_test_text; regex_t *p_test_regex;};typedef struct patch_desc tPatchDesc;/* Fix Descriptor Everything you ever wanted to know about how to apply a particular fix (which files, how to qualify them, how to actually make the fix, etc...) */#define FD_MACH_ONLY 0x0000#define FD_MACH_IFNOT 0x0001#define FD_SHELL_SCRIPT 0x0002#define FD_SKIP_TEST 0x8000typedef struct fix_desc tFixDesc;struct fix_desc{ const char* fix_name; /* Name of the fix */ const char* file_list; /* List of files it applies to */ const char** papz_machs; /* List of machine/os-es it applies to */ regex_t* unused; int test_ct; int fd_flags; tTestDesc* p_test_desc; const char** patch_args;};/* Working environment strings. Essentially, invocation 'options'. */char *pz_dest_dir = NULL;char *pz_src_dir = NULL;char *pz_machine = NULL;char *pz_find_base = NULL;int find_base_len = 0;pid_t process_chain_head = (pid_t) -1;const char incl_quote_pat[] = "^[ \t]*#[ \t]*include[ \t]*\"[^/]";regex_t incl_quote_re;char *load_file _P_((const char *));void process _P_((char *, const char *));void run_compiles ();void wait_for_pid _P_(( pid_t ));void initialize ();#include "fixincl.x"/* * * * * * * * * * * * * * * * * * * * * MAIN ROUTINE */intmain (argc, argv) int argc; char **argv;{ static const char gnu_lib_mark[] = "This file is part of the GNU C Library";#ifndef NO_BOGOSITY_LIMITS# define BOGUS_LIMIT MINIMUM_MAXIMUM_LINES size_t loop_ct;#endif char *apz_names[BOGUS_LIMIT]; size_t file_name_ct; /* Before anything else, ensure we can allocate our file name buffer. */ file_name_buf = (char *) malloc (NAME_TABLE_SIZE); if (file_name_buf == (char *) NULL) { fprintf (stderr, "fixincl cannot allocate 0x%08X bytes\n", NAME_TABLE_SIZE); exit (EXIT_FAILURE); } switch (argc) { case 1: break; case 2: if (strcmp (argv[1], "-v") == 0) { static const char zFmt[] = "echo '%s'"; /* The 'version' option is really used to test that: 1. The program loads correctly (no missing libraries) 2. we can correctly run our server shell process 3. that we can compile all the regular expressions. */ run_compiles (); sprintf (file_name_buf, zFmt, program_id); fputs (file_name_buf + 5, stdout); exit (strcmp (run_shell (file_name_buf), program_id)); } freopen (argv[1], "r", stdin); break; default: fputs ("fixincl ERROR: too many command line arguments\n", stderr); exit (EXIT_FAILURE); } initialize ();#ifndef NO_BOGOSITY_LIMITS /* Some systems only allow so many calls to fork(2). This is inadequate for this program. Consequently, we must let a grandfather process spawn children that then spawn all the processes that do the real work. */ for (;;) { file_name_ct = 0; { char *pz_buf = file_name_buf; /* Only the parent process can read from stdin without confusing the world. (How does the child tell the parent to skip forward? Pipes and files behave differently.) */ while ( (file_name_ct < BOGUS_LIMIT) && (pz_buf < (file_name_buf + NAME_TABLE_SIZE - MAXPATHLEN))) { if (fgets (pz_buf, MAXPATHLEN, stdin) == (char *) NULL) break; while (isspace (*pz_buf)) pz_buf++; if ((*pz_buf == '\0') || (*pz_buf == '#')) continue; apz_names[file_name_ct++] = pz_buf; pz_buf += strlen (pz_buf); while (isspace (pz_buf[-1])) pz_buf--; *pz_buf++ = '\0'; } } /* IF we did not get any files this time thru THEN we must be done. */ if (file_name_ct == 0) return EXIT_SUCCESS; fflush (stdout); fflush (stderr); { pid_t child = fork (); if (child == NULLPROCESS) break; if (child == NOPROCESS) { fprintf (stderr, "Error %d (%s) forking in main\n", errno, strerror (errno)); exit (EXIT_FAILURE); }#ifdef DEBUG fprintf (stderr, "Waiting for %d to complete %d files\n", child, file_name_ct);#endif wait_for_pid( child, file_name_ct ); } }#else /*#*/ error "NON-BOGUS LIMITS NOT SUPPORTED?!?!"#endif /* For every file specified in stdandard in (except as throttled for bogus reasons)... */ for (loop_ct = 0; loop_ct < file_name_ct; loop_ct++) { char *pz_data; char *pz_file_name = apz_names[loop_ct]; if (access (pz_file_name, R_OK) != 0) { int erno = errno; fprintf (stderr, "Cannot access %s from %s\n\terror %d (%s)\n", pz_file_name, getcwd ((char *) NULL, MAXPATHLEN), erno, strerror (erno)); } else if (pz_data = load_file (pz_file_name), (pz_data != (char *) NULL)) { if (strstr (pz_data, gnu_lib_mark) == (char *) NULL) process (pz_data, pz_file_name); free ((void *) pz_data); } } return EXIT_SUCCESS;}/* * * * * * * * * * * * */voidinitialize(){ static const char var_not_found[] = "fixincl ERROR: %s environment variable not defined\n"; { static const char var[] = "TARGET_MACHINE"; pz_machine = getenv (var); if (pz_machine == (char *) NULL) { fprintf (stderr, var_not_found, var); exit (EXIT_FAILURE); } } { static const char var[] = "DESTDIR"; pz_dest_dir = getenv (var); if (pz_dest_dir == (char *) NULL) { fprintf (stderr, var_not_found, var); exit (EXIT_FAILURE); } } { static const char var[] = "SRCDIR"; pz_src_dir = getenv (var); if (pz_src_dir == (char *) NULL) { fprintf (stderr, var_not_found, var); exit (EXIT_FAILURE); } } { static const char var[] = "FIND_BASE"; pz_find_base = getenv (var); if (pz_find_base == (char *) NULL) { fprintf (stderr, var_not_found, var); exit (EXIT_FAILURE); } find_base_len = strlen( pz_find_base ); } /* Compile all the regular expressions now. That way, it is done only once for the whole run. */ run_compiles (); signal (SIGQUIT, SIG_IGN); signal (SIGIOT, SIG_IGN); signal (SIGPIPE, SIG_IGN); signal (SIGALRM, SIG_IGN); signal (SIGTERM, SIG_IGN); /* Make sure that if we opened a server process, we close it now. This is the grandparent process. We don't need the server anymore and our children should make their own. */ close_server (); (void)wait ( (int*)NULL );}/* * * * * * * * * * * * * wait_for_pid - Keep calling `wait(2)' until it returns the process id we are looking for. Not every system has `waitpid(2)'. We also ensure that the children exit with success. */voidwait_for_pid(child, file_name_ct) pid_t child; int file_name_ct;{ for (;;) { int status; pid_t dead_kid = wait (&status); if (dead_kid == child) { if (! WIFEXITED( status )) { fprintf (stderr, "child process %d is hung on signal %d\n", child, WSTOPSIG( status )); exit (EXIT_FAILURE); } if (WEXITSTATUS( status ) != 0) { fprintf (stderr, "child process %d exited with status %d\n", child, WEXITSTATUS( status )); exit (EXIT_FAILURE); } break; /* normal child completion */ } /* IF there is an error, THEN see if it is retryable.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -