summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/fixinc/fixincl.c273
-rw-r--r--gcc/fixinc/server.c15
-rw-r--r--gcc/fixinc/server.h2
3 files changed, 185 insertions, 105 deletions
diff --git a/gcc/fixinc/fixincl.c b/gcc/fixinc/fixincl.c
index 36a86a70c6d..c8c54366aa3 100644
--- a/gcc/fixinc/fixincl.c
+++ b/gcc/fixinc/fixincl.c
@@ -147,9 +147,11 @@ 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 (const char *pzFile);
-void process (char *data, const char *file);
-void run_compiles (void);
+char *load_file (const char *);
+void process (char *, const char *);
+void run_compiles ();
+void wait_for_pid( pid_t, int );
+void initialize ();
#include "fixincl.x"
@@ -164,8 +166,6 @@ main (argc, argv)
{
static const char gnu_lib_mark[] =
"This file is part of the GNU C Library";
- static const char var_not_found[] =
- "fixincl ERROR: %s environment variable not defined\n";
#ifndef NO_BOGOSITY_LIMITS
# define BOGUS_LIMIT MINIMUM_MAXIMUM_LINES
@@ -212,6 +212,113 @@ main (argc, argv)
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;
+
+ {
+ 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);
+ }
+
+ wait_for_pid( child, file_name_ct );
+ }
+ }
+#else
+#error "NON-BOGUS LIMITS NOT SUPPORTED?!?!"
+#endif
+
+ /*
+ Here we are the child of the grandparent process. The parent
+ of all the little fixup processes. We ignore the deaths of
+ our children. */
+
+ signal (SIGCLD, SIG_IGN);
+
+#ifdef DEBUG
+ fprintf (stderr, "Child start -- processing %d files\n",
+ file_name_ct);
+#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;
+}
+
+
+/* * * * * * * * * * * * */
+
+void
+initialize()
+{
+ static const char var_not_found[] =
+ "fixincl ERROR: %s environment variable not defined\n";
+
{
static const char var[] = "TARGET_MACHINE";
pz_machine = getenv (var);
@@ -264,110 +371,74 @@ main (argc, argv)
signal (SIGALRM, SIG_IGN);
signal (SIGTERM, SIG_IGN);
-#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 (;;)
- {
- char *pz_buf;
- pid_t child;
-
- /* 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.) */
- file_name_ct = 0;
- pz_buf = file_name_buf;
- 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;
-
- child = fork ();
- if (child == NULLPROCESS)
- break;
+ /*
+ 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. */
- if (child == NOPROCESS)
- {
- fprintf (stderr, "Error %d (%s) forking in main\n",
- errno, strerror (errno));
- exit (EXIT_FAILURE);
- }
-#ifndef DEBUG
- {
- int status;
- (void)wait (&status);
- }
-#else
- fprintf (stderr, "Waiting for %d to complete %d files\n",
- child, file_name_ct);
+ close_server ();
+ (void)wait ( (int*)NULL );
+}
- {
- int status;
- pid_t dead_kid = wait (&status);
+/* * * * * * * * * * * * *
+
+ 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. */
- if (dead_kid != child)
- fprintf (stderr, "fixincl woke up from a strange child %d (not %d)\n",
- dead_kid, child);
- else
- fprintf (stderr, "child finished %d files %s\n", file_name_ct,
- status ? strerror (status & 0xFF) : "ok");
- }
-#endif
- }
-#else
-#error "NON-BOGUS LIMITS NOT SUPPORTED?!?!"
+void
+wait_for_pid( pid_t child, int file_name_ct )
+{
+#ifdef DEBUG
+ fprintf (stderr, "Waiting for %d to complete %d files\n",
+ child, file_name_ct);
#endif
- signal (SIGCLD, SIG_IGN);
+ 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);
+ }
#ifdef DEBUG
- fprintf (stderr, "Child start -- processing %d files\n",
- file_name_ct);
+ fprintf (stderr, "child finished %d files %s\n", file_name_ct,
+ status ? strerror (status & 0xFF) : "ok");
#endif
+ break; /* normal child completion */
+ }
- /* 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 there is an error, THEN see if it is retryable.
+ If it is not retryable, then break out of this loop. */
+ if (dead_kid == NOPROCESS)
+ {
+ switch (errno) {
+ case EINTR:
+ case EAGAIN:
+ break;
- 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);
- }
- }
+ default:
+ fprintf (stderr, "Error %d (%s) waiting for %d to finish\n",
+ errno, strerror( errno ), child );
+ /* FALLTHROUGH */
- return EXIT_SUCCESS;
+ case ECHILD: /* no children to wait for?? */
+ return;
+ }
+ }
+ } done_waiting:;
}
@@ -476,6 +547,12 @@ run_compiles ()
exit (EXIT_FAILURE);
}
+ /* Make sure re_compile_pattern does not stumble across invalid
+ data */
+
+ memset ( (void*)p_re, '\0', REGEX_COUNT * sizeof (regex_t) );
+ memset ( (void*)&incl_quote_re, '\0', sizeof (regex_t) );
+
/* The patterns we search for are all egrep patterns.
In the shell version of this program, we invoke egrep
with the supplied pattern. Here, we will run
diff --git a/gcc/fixinc/server.c b/gcc/fixinc/server.c
index 2a195a61eb4..51f86b50e19 100644
--- a/gcc/fixinc/server.c
+++ b/gcc/fixinc/server.c
@@ -178,14 +178,17 @@ load_data (fp)
* Make certain the server process is dead, close the
* pipes to it and from it, finally NULL out the file pointers
*/
-static void
+void
close_server ()
{
- kill ((pid_t) server_id, SIGKILL);
- server_id = NULLPROCESS;
- fclose (server_pair.pf_read);
- fclose (server_pair.pf_write);
- server_pair.pf_read = server_pair.pf_write = (FILE *) NULL;
+ if (server_id != NULLPROCESS)
+ {
+ kill ((pid_t) server_id, SIGKILL);
+ server_id = NULLPROCESS;
+ fclose (server_pair.pf_read);
+ fclose (server_pair.pf_write);
+ server_pair.pf_read = server_pair.pf_write = (FILE *) NULL;
+ }
}
/*
diff --git a/gcc/fixinc/server.h b/gcc/fixinc/server.h
index 0c2a0bf6093..f270f36df36 100644
--- a/gcc/fixinc/server.h
+++ b/gcc/fixinc/server.h
@@ -90,5 +90,5 @@ pid_t proc2_open _P_ (( t_fd_pair * p_pair, t_pchar * pp_args));
int chain_open _P_ (( int in_fd,
t_pchar * pp_args,
pid_t * p_child));
-
+void close_server _P_ (( void ));
#endif /* FIXINC_SERVER_H */