Changeset 287 for trunk/src/gmake/job.c


Ignore:
Timestamp:
May 17, 2005, 1:34:55 AM (20 years ago)
Author:
bird
Message:

join + optimizations.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/gmake/job.c

    r232 r287  
    11/* Job execution and handling for GNU Make.
    2 Copyright (C) 1988,89,90,91,92,93,94,95,96,97,99 Free Software Foundation, Inc.
     2Copyright (C) 1988,1989,1990,1991,1992,1993,1994,1995,1996,1997,1999,
     32000,2001,2002,2003,2004,2005 Free Software Foundation, Inc.
    34This file is part of GNU Make.
    45
     
    6970
    7071# include <descrip.h>
     72char default_shell[] = "";
     73int batch_mode_shell = 0;
     74
     75#elif defined (__riscos__)
     76
    7177char default_shell[] = "";
    7278int batch_mode_shell = 0;
     
    176182#endif  /* Don't have `union wait'.  */
    177183
    178 #ifdef VMS
    179 static int vms_jobsefnmask = 0;
    180 #endif /* !VMS */
    181 
    182184#ifndef HAVE_UNISTD_H
    183185extern int dup2 ();
     
    207209static int job_next_command PARAMS ((struct child *));
    208210static int start_waiting_job PARAMS ((struct child *));
    209 #ifdef VMS
    210 static void vmsWaitForChildren PARAMS ((int *));
    211 #endif
    212211#ifdef MAKE_DLLSHELL
    213212static int spawn_command PARAMS ((char **argv, char **envp, struct child *child));
     
    239238unsigned long job_counter = 0;
    240239
     240/* Number of jobserver tokens this instance is currently using.  */
     241
     242unsigned int jobserver_tokens = 0;
    241243
    242244
     
    248250w32_kill(int pid, int sig)
    249251{
    250   return ((process_kill(pid, sig) == TRUE) ? 0 : -1);
     252  return ((process_kill((HANDLE)pid, sig) == TRUE) ? 0 : -1);
     253}
     254
     255/* This function creates a temporary file name with the given extension
     256 * the unixy param controls both the extension and the path separator
     257 * return an xmalloc'ed string of a newly created temp file or die.  */
     258static char *
     259create_batch_filename(char const *base, int unixy)
     260{
     261  const char *const ext = unixy ? "sh" : "bat";
     262  const char *error = NULL;
     263  char temp_path[MAXPATHLEN]; /* need to know its length */
     264  unsigned path_size = GetTempPath(sizeof temp_path, temp_path);
     265  int path_is_dot = 0;
     266  unsigned uniq = 1;
     267  const unsigned sizemax = strlen (base) + strlen (ext) + 10;
     268
     269  if (path_size == 0)
     270    {
     271      path_size = GetCurrentDirectory (sizeof temp_path, temp_path);
     272      path_is_dot = 1;
     273    }
     274
     275  while (path_size > 0 &&
     276         path_size + sizemax < sizeof temp_path &&
     277         uniq < 0x10000)
     278    {
     279      unsigned size = sprintf (temp_path + path_size,
     280                               "%s%s-%x.%s",
     281                               temp_path[path_size - 1] == '\\' ? "" : "\\",
     282                               base, uniq, ext);
     283      HANDLE h = CreateFile (temp_path,  /* file name */
     284                             GENERIC_READ | GENERIC_WRITE, /* desired access */
     285                             0,                            /* no share mode */
     286                             NULL,                         /* default security attributes */
     287                             CREATE_NEW,                   /* creation disposition */
     288                             FILE_ATTRIBUTE_NORMAL |       /* flags and attributes */
     289                             FILE_ATTRIBUTE_TEMPORARY,     /* we'll delete it */
     290                             NULL);                        /* no template file */
     291
     292      if (h == INVALID_HANDLE_VALUE)
     293        {
     294          const DWORD er = GetLastError();
     295
     296          if (er == ERROR_FILE_EXISTS || er == ERROR_ALREADY_EXISTS)
     297            ++uniq;
     298
     299          /* the temporary path is not guaranteed to exist */
     300          else if (path_is_dot == 0)
     301            {
     302              path_size = GetCurrentDirectory (sizeof temp_path, temp_path);
     303              path_is_dot = 1;
     304            }
     305
     306          else
     307            {
     308              error = map_windows32_error_to_string (er);
     309              break;
     310            }
     311        }
     312      else
     313        {
     314          const unsigned final_size = path_size + size + 1;
     315          char *const path = (char *) xmalloc (final_size);
     316          memcpy (path, temp_path, final_size);
     317          CloseHandle (h);
     318          if (unixy)
     319            {
     320              char *p;
     321              int ch;
     322              for (p = path; (ch = *p) != 0; ++p)
     323                if (ch == '\\')
     324                  *p = '/';
     325            }
     326          return path; /* good return */
     327        }
     328    }
     329
     330  if (error == NULL)
     331    error = _("Cannot create a temporary file\n");
     332  fatal (NILF, error);
     333
     334  /* not reached */
     335  return NULL;
    251336}
    252337#endif /* WINDOWS32 */
     
    328413
    329414
    330 #ifdef VMS
    331 /* Wait for nchildren children to terminate */
    332 static void
    333 vmsWaitForChildren(int *status)
    334 {
    335   while (1)
    336     {
    337       if (!vms_jobsefnmask)
    338         {
    339           *status = 0;
    340           return;
    341         }
    342 
    343       *status = sys$wflor (32, vms_jobsefnmask);
    344     }
    345   return;
    346 }
    347 
    348 /* Set up IO redirection.  */
    349 
    350 char *
    351 vms_redirect (struct dsc$descriptor_s *desc, char *fname, char *ibuf)
    352 {
    353   char *fptr;
    354   extern char *vmsify ();
    355 
    356   ibuf++;
    357   while (isspace ((unsigned char)*ibuf))
    358     ibuf++;
    359   fptr = ibuf;
    360   while (*ibuf && !isspace ((unsigned char)*ibuf))
    361     ibuf++;
    362   *ibuf = 0;
    363   if (strcmp (fptr, "/dev/null") != 0)
    364     {
    365       strcpy (fname, vmsify (fptr, 0));
    366       if (strchr (fname, '.') == 0)
    367         strcat (fname, ".");
    368     }
    369   desc->dsc$w_length = strlen(fname);
    370   desc->dsc$a_pointer = fname;
    371   desc->dsc$b_dtype = DSC$K_DTYPE_T;
    372   desc->dsc$b_class = DSC$K_CLASS_S;
    373 
    374   if (*fname == 0)
    375     printf (_("Warning: Empty redirection\n"));
    376   return ibuf;
    377 }
    378 
    379 
    380 /* found apostrophe at (p-1)
    381    inc p until after closing apostrophe.
    382  */
    383 
    384 static char *
    385 vms_handle_apos (char *p)
    386 {
    387   int alast;
    388 
    389 #define SEPCHARS ",/()= "
    390 
    391   alast = 0;
    392 
    393   while (*p != 0)
    394     {
    395       if (*p == '"')
    396         {
    397           if (alast)
    398             {
    399               alast = 0;
    400               p++;
    401             }
    402           else
    403             {
    404               p++;
    405               if (strchr (SEPCHARS, *p))
    406                 break;
    407               alast = 1;
    408             }
    409         }
    410       else
    411         p++;
    412     }
    413 
    414   return p;
    415 }
    416 
    417 #endif
    418 
    419415
    420416/* Handle a dead child.  This handler may or may not ever be installed.
     
    485481    {
    486482      int remote = 0;
    487       register int pid;
     483      pid_t pid;
    488484      int exit_code, exit_sig, coredump;
    489485      register struct child *lastc, *c;
     
    569565            {
    570566#ifdef VMS
     567              static void vmsWaitForChildren PARAMS ((int *));
    571568              vmsWaitForChildren (&status);
    572569              pid = c->pid;
     
    644641            HANDLE hPID;
    645642            int err;
     643            exit_code = 0;
     644            exit_sig = 0;
     645            coredump = 0;
    646646
    647647            /* wait for anything to finish */
    648             if (hPID = process_wait_for_any()) {
    649 
    650               /* was an error found on this process? */
    651               err = process_last_err(hPID);
    652 
    653               /* get exit data */
    654               exit_code = process_exit_code(hPID);
    655 
    656               if (err)
    657                 fprintf(stderr, "make (e=%d): %s",
    658                   exit_code, map_windows32_error_to_string(exit_code));
    659 
    660               /* signal */
    661               exit_sig = process_signal(hPID);
    662 
    663               /* cleanup process */
    664               process_cleanup(hPID);
    665 
    666               coredump = 0;
    667             }
    668             pid = (int) hPID;
     648            hPID = process_wait_for_any();
     649            if (hPID)
     650              {
     651
     652                /* was an error found on this process? */
     653                err = process_last_err(hPID);
     654
     655                /* get exit data */
     656                exit_code = process_exit_code(hPID);
     657
     658                if (err)
     659                  fprintf(stderr, "make (e=%d): %s",
     660                          exit_code, map_windows32_error_to_string(exit_code));
     661
     662                /* signal */
     663                exit_sig = process_signal(hPID);
     664
     665                /* cleanup process */
     666                process_cleanup(hPID);
     667
     668                coredump = 0;
     669              }
     670            pid = (pid_t) hPID;
    669671          }
    670672#endif /* WINDOWS32 */
     
    840842free_child (struct child *child)
    841843{
    842   /* If this child is the only one it was our "free" job, so don't put a
    843      token back for it.  This child has already been removed from the list,
    844      so if there any left this wasn't the last one.  */
    845 
    846   if (job_fds[1] >= 0 && children)
     844  if (!jobserver_tokens)
     845    fatal (NILF, "INTERNAL: Freeing child 0x%08lx (%s) but no tokens left!\n",
     846           (unsigned long int) child, child->file->name);
     847
     848  /* If we're using the jobserver and this child is not the only outstanding
     849     job, put a token back into the pipe for it.  */
     850
     851  if (job_fds[1] >= 0 && jobserver_tokens > 1)
    847852    {
    848853      char token = '+';
     
    858863                    (unsigned long int) child, child->file->name));
    859864    }
     865
     866  --jobserver_tokens;
    860867
    861868  if (handling_fatal_signal) /* Don't bother free'ing if about to die.  */
     
    898905}
    899906
    900 #ifdef  POSIX
     907#ifdef POSIX
    901908void
    902909unblock_sigs (void)
     
    909916
    910917#ifdef MAKE_JOBSERVER
     918RETSIGTYPE
     919job_noop (int sig UNUSED)
     920{
     921}
    911922/* Set the child handler action flags to FLAGS.  */
    912923static void
    913 set_child_handler_action_flags (int flags)
     924set_child_handler_action_flags (int set_handler, int set_alarm)
    914925{
    915926  struct sigaction sa;
     927
     928#ifdef __EMX__
     929  /* The child handler must be turned off here.  */
     930  signal (SIGCHLD, SIG_DFL);
     931#endif
     932
    916933  bzero ((char *) &sa, sizeof sa);
    917934  sa.sa_handler = child_handler;
    918   sa.sa_flags = flags;
     935  sa.sa_flags = set_handler ? 0 : SA_RESTART;
    919936#if defined SIGCHLD
    920937  sigaction (SIGCHLD, &sa, NULL);
     
    922939#if defined SIGCLD && SIGCLD != SIGCHLD
    923940  sigaction (SIGCLD, &sa, NULL);
     941#endif
     942#if defined SIGALRM
     943  if (set_alarm)
     944    {
     945      /* If we're about to enter the read(), set an alarm to wake up in a
     946         second so we can check if the load has dropped and we can start more
     947         work.  On the way out, turn off the alarm and set SIG_DFL.  */
     948      alarm (set_handler ? 1 : 0);
     949      sa.sa_handler = set_handler ? job_noop : SIG_DFL;
     950      sa.sa_flags = 0;
     951      sigaction (SIGALRM, &sa, NULL);
     952    }
    924953#endif
    925954}
     
    12261255
    12271256#ifdef VMS
    1228 
    12291257      if (!child_execute_job (argv, child)) {
    12301258        /* Fork failed!  */
     
    16701698
    16711699        /* If we don't already have a job started, use our "free" token.  */
    1672         if (!children)
     1700        if (!jobserver_tokens)
    16731701          break;
    16741702
     
    17051733        reap_children (0, 0);
    17061734
    1707         /* If our "free" token has become available, use it.  */
     1735        /* Kick off any jobs we have waiting for an opportunity that
     1736           can run now (ie waiting for load). */
     1737        start_waiting_jobs ();
     1738
     1739        /* If our "free" slot has become available, use it; we don't need an
     1740           actual token.  */
     1741        if (!jobserver_tokens)
     1742          break;
     1743
     1744        /* There must be at least one child already, or we have no business
     1745           waiting for a token. */
    17081746        if (!children)
    1709           break;
     1747          fatal (NILF, "INTERNAL: no children as we go to sleep on read\n");
    17101748
    17111749        /* Set interruptible system calls, and read() for a job token.  */
    1712         set_child_handler_action_flags (0);
     1750        set_child_handler_action_flags (1, waiting_jobs != NULL);
    17131751        got_token = read (job_rfd, &token, 1);
    17141752        saved_errno = errno;
    1715 #if defined(__EMX__) && !defined(__INNOTEK_LIBC__)
    1716         /* The child handler must be turned off here.  */
    1717         signal (SIGCHLD, SIG_DFL);
    1718 #endif
    1719         set_child_handler_action_flags (SA_RESTART);
     1753        set_child_handler_action_flags (0, waiting_jobs != NULL);
    17201754
    17211755        /* If we got one, we're done here.  */
     
    17361770      }
    17371771#endif
     1772
     1773  ++jobserver_tokens;
    17381774
    17391775  /* The job is now primed.  Start it running.
     
    18161852load_too_high (void)
    18171853{
    1818 #if defined(__MSDOS__) || defined(VMS) || defined(_AMIGA)
     1854#if defined(__MSDOS__) || defined(VMS) || defined(_AMIGA) || defined(__riscos__)
    18191855  return 1;
    18201856#else
     
    19001936
    19011937#ifndef WINDOWS32
    1902 #ifdef VMS
    1903 #include <descrip.h>
    1904 #include <clidef.h>
    1905 
    1906 /* This is called as an AST when a child process dies (it won't get
    1907    interrupted by anything except a higher level AST).
    1908 */
    1909 int vmsHandleChildTerm(struct child *child)
    1910 {
    1911     int status;
    1912     register struct child *lastc, *c;
    1913     int child_failed;
    1914 
    1915     vms_jobsefnmask &= ~(1 << (child->efn - 32));
    1916 
    1917     lib$free_ef(&child->efn);
    1918 
    1919     (void) sigblock (fatal_signal_mask);
    1920 
    1921     child_failed = !(child->cstatus & 1 || ((child->cstatus & 7) == 0));
    1922 
    1923     /* Search for a child matching the deceased one.  */
    1924     lastc = 0;
    1925 #if defined(RECURSIVEJOBS) /* I've had problems with recursive stuff and process handling */
    1926     for (c = children; c != 0 && c != child; lastc = c, c = c->next);
    1927 #else
    1928     c = child;
    1929 #endif
    1930 
    1931     if (child_failed && !c->noerror && !ignore_errors_flag)
    1932       {
    1933         /* The commands failed.  Write an error message,
    1934            delete non-precious targets, and abort.  */
    1935         child_error (c->file->name, c->cstatus, 0, 0, 0);
    1936         c->file->update_status = 1;
    1937         delete_child_targets (c);
    1938       }
    1939     else
    1940       {
    1941         if (child_failed)
    1942           {
    1943             /* The commands failed, but we don't care.  */
    1944             child_error (c->file->name, c->cstatus, 0, 0, 1);
    1945             child_failed = 0;
    1946           }
    1947 
    1948 #if defined(RECURSIVEJOBS) /* I've had problems with recursive stuff and process handling */
    1949         /* If there are more commands to run, try to start them.  */
    1950         start_job (c);
    1951 
    1952         switch (c->file->command_state)
    1953           {
    1954           case cs_running:
    1955             /* Successfully started.  */
    1956             break;
    1957 
    1958           case cs_finished:
    1959             if (c->file->update_status != 0) {
    1960                 /* We failed to start the commands.  */
    1961                 delete_child_targets (c);
    1962             }
    1963             break;
    1964 
    1965           default:
    1966             error (NILF, _("internal error: `%s' command_state"),
    1967                    c->file->name);
    1968             abort ();
    1969             break;
    1970           }
    1971 #endif /* RECURSIVEJOBS */
    1972       }
    1973 
    1974     /* Set the state flag to say the commands have finished.  */
    1975     c->file->command_state = cs_finished;
    1976     notice_finished_file (c->file);
    1977 
    1978 #if defined(RECURSIVEJOBS) /* I've had problems with recursive stuff and process handling */
    1979     /* Remove the child from the chain and free it.  */
    1980     if (lastc == 0)
    1981       children = c->next;
    1982     else
    1983       lastc->next = c->next;
    1984     free_child (c);
    1985 #endif /* RECURSIVEJOBS */
    1986 
    1987     /* There is now another slot open.  */
    1988     if (job_slots_used > 0)
    1989       --job_slots_used;
    1990 
    1991     /* If the job failed, and the -k flag was not given, die.  */
    1992     if (child_failed && !keep_going_flag)
    1993       die (EXIT_FAILURE);
    1994 
    1995     (void) sigsetmask (sigblock (0) & ~(fatal_signal_mask));
    1996 
    1997     return 1;
    1998 }
    1999 
    2000 /* VMS:
    2001    Spawn a process executing the command in ARGV and return its pid. */
    2002 
    2003 #define MAXCMDLEN 200
    2004 
    2005 /* local helpers to make ctrl+c and ctrl+y working, see below */
    2006 #include <iodef.h>
    2007 #include <libclidef.h>
    2008 #include <ssdef.h>
    2009 
    2010 static int ctrlMask= LIB$M_CLI_CTRLY;
    2011 static int oldCtrlMask;
    2012 static int setupYAstTried= 0;
    2013 static int pidToAbort= 0;
    2014 static int chan= 0;
    2015 
    2016 static void reEnableAst(void) {
    2017         lib$enable_ctrl (&oldCtrlMask,0);
    2018 }
    2019 
    2020 static astHandler (void) {
    2021         if (pidToAbort) {
    2022                 sys$forcex (&pidToAbort, 0, SS$_ABORT);
    2023                 pidToAbort= 0;
    2024         }
    2025         kill (getpid(),SIGQUIT);
    2026 }
    2027 
    2028 static void tryToSetupYAst(void) {
    2029         $DESCRIPTOR(inputDsc,"SYS$COMMAND");
    2030         int     status;
    2031         struct {
    2032                 short int       status, count;
    2033                 int     dvi;
    2034         } iosb;
    2035 
    2036         setupYAstTried++;
    2037 
    2038         if (!chan) {
    2039                 status= sys$assign(&inputDsc,&chan,0,0);
    2040                 if (!(status&SS$_NORMAL)) {
    2041                         lib$signal(status);
    2042                         return;
    2043                 }
    2044         }
    2045         status= sys$qiow (0, chan, IO$_SETMODE|IO$M_CTRLYAST,&iosb,0,0,
    2046                 astHandler,0,0,0,0,0);
    2047         if (status==SS$_ILLIOFUNC) {
    2048                 sys$dassgn(chan);
    2049 #ifdef  CTRLY_ENABLED_ANYWAY
    2050                 fprintf (stderr,
    2051                          _("-warning, CTRL-Y will leave sub-process(es) around.\n"));
    2052 #else
    2053                 return;
    2054 #endif
    2055         }
    2056         if (status==SS$_NORMAL)
    2057                 status= iosb.status;
    2058         if (!(status&SS$_NORMAL)) {
    2059                 lib$signal(status);
    2060                 return;
    2061         }
    2062 
    2063         /* called from AST handler ? */
    2064         if (setupYAstTried>1)
    2065                 return;
    2066         if (atexit(reEnableAst))
    2067                 fprintf (stderr,
    2068                          _("-warning, you may have to re-enable CTRL-Y handling from DCL.\n"));
    2069         status= lib$disable_ctrl (&ctrlMask, &oldCtrlMask);
    2070         if (!(status&SS$_NORMAL)) {
    2071                 lib$signal(status);
    2072                 return;
    2073         }
    2074 }
    2075 int
    2076 child_execute_job (char *argv, struct child *child)
    2077 {
    2078   int i;
    2079   static struct dsc$descriptor_s cmddsc;
    2080   static struct dsc$descriptor_s pnamedsc;
    2081   static struct dsc$descriptor_s ifiledsc;
    2082   static struct dsc$descriptor_s ofiledsc;
    2083   static struct dsc$descriptor_s efiledsc;
    2084   int have_redirection = 0;
    2085   int have_newline = 0;
    2086 
    2087   int spflags = CLI$M_NOWAIT;
    2088   int status;
    2089   char *cmd = alloca (strlen (argv) + 512), *p, *q;
    2090   char ifile[256], ofile[256], efile[256];
    2091   char *comname = 0;
    2092   char procname[100];
    2093 
    2094   /* Parse IO redirection.  */
    2095 
    2096   ifile[0] = 0;
    2097   ofile[0] = 0;
    2098   efile[0] = 0;
    2099 
    2100   DB (DB_JOBS, ("child_execute_job (%s)\n", argv));
    2101 
    2102   while (isspace ((unsigned char)*argv))
    2103     argv++;
    2104 
    2105   if (*argv == 0)
    2106     return 0;
    2107 
    2108   sprintf (procname, "GMAKE_%05x", getpid () & 0xfffff);
    2109   pnamedsc.dsc$w_length = strlen(procname);
    2110   pnamedsc.dsc$a_pointer = procname;
    2111   pnamedsc.dsc$b_dtype = DSC$K_DTYPE_T;
    2112   pnamedsc.dsc$b_class = DSC$K_CLASS_S;
    2113 
    2114   /* Handle comments and redirection. */
    2115   for (p = argv, q = cmd; *p; p++, q++)
    2116     {
    2117       switch (*p)
    2118         {
    2119           case '#':
    2120             *p-- = 0;
    2121             *q-- = 0;
    2122             break;
    2123           case '\\':
    2124             p++;
    2125             if (*p == '\n')
    2126               p++;
    2127             if (isspace ((unsigned char)*p))
    2128               {
    2129                 do { p++; } while (isspace ((unsigned char)*p));
    2130                 p--;
    2131               }
    2132             *q = *p;
    2133             break;
    2134           case '<':
    2135             p = vms_redirect (&ifiledsc, ifile, p);
    2136             *q = ' ';
    2137             have_redirection = 1;
    2138             break;
    2139           case '>':
    2140             have_redirection = 1;
    2141             if (*(p-1) == '2')
    2142               {
    2143                 q--;
    2144                 if (strncmp (p, ">&1", 3) == 0)
    2145                   {
    2146                     p += 3;
    2147                     strcpy (efile, "sys$output");
    2148                     efiledsc.dsc$w_length = strlen(efile);
    2149                     efiledsc.dsc$a_pointer = efile;
    2150                     efiledsc.dsc$b_dtype = DSC$K_DTYPE_T;
    2151                     efiledsc.dsc$b_class = DSC$K_CLASS_S;
    2152                   }
    2153                 else
    2154                   {
    2155                     p = vms_redirect (&efiledsc, efile, p);
    2156                   }
    2157               }
    2158             else
    2159               {
    2160                 p = vms_redirect (&ofiledsc, ofile, p);
    2161               }
    2162             *q = ' ';
    2163             break;
    2164           case '\n':
    2165             have_newline = 1;
    2166           default:
    2167             *q = *p;
    2168             break;
    2169         }
    2170     }
    2171   *q = *p;
    2172 
    2173   if (strncmp (cmd, "builtin_", 8) == 0)
    2174     {
    2175       child->pid = 270163;
    2176       child->efn = 0;
    2177       child->cstatus = 1;
    2178 
    2179       DB (DB_JOBS, (_("BUILTIN [%s][%s]\n"), cmd, cmd+8));
    2180 
    2181       p = cmd + 8;
    2182 
    2183       if ((*(p) == 'c')
    2184           && (*(p+1) == 'd')
    2185           && ((*(p+2) == ' ') || (*(p+2) == '\t')))
    2186         {
    2187           p += 3;
    2188           while ((*p == ' ') || (*p == '\t'))
    2189             p++;
    2190           DB (DB_JOBS, (_("BUILTIN CD %s\n"), p));
    2191           if (chdir (p))
    2192             return 0;
    2193           else
    2194             return 1;
    2195         }
    2196       else if ((*(p) == 'r')
    2197           && (*(p+1) == 'm')
    2198           && ((*(p+2) == ' ') || (*(p+2) == '\t')))
    2199         {
    2200           int in_arg;
    2201 
    2202           /* rm  */
    2203           p += 3;
    2204           while ((*p == ' ') || (*p == '\t'))
    2205             p++;
    2206           in_arg = 1;
    2207 
    2208           DB (DB_JOBS, (_("BUILTIN RM %s\n"), p));
    2209           while (*p)
    2210             {
    2211               switch (*p)
    2212                 {
    2213                   case ' ':
    2214                   case '\t':
    2215                     if (in_arg)
    2216                       {
    2217                         *p++ = ';';
    2218                         in_arg = 0;
    2219                       }
    2220                     break;
    2221                   default:
    2222                     break;
    2223                 }
    2224               p++;
    2225             }
    2226         }
    2227       else
    2228         {
    2229           printf(_("Unknown builtin command '%s'\n"), cmd);
    2230           fflush(stdout);
    2231           return 0;
    2232         }
    2233     }
    2234 
    2235   /* Create a *.com file if either the command is too long for
    2236      lib$spawn, or the command contains a newline, or if redirection
    2237      is desired. Forcing commands with newlines into DCLs allows to
    2238      store search lists on user mode logicals.  */
    2239 
    2240   if (strlen (cmd) > MAXCMDLEN
    2241       || (have_redirection != 0)
    2242       || (have_newline != 0))
    2243     {
    2244       FILE *outfile;
    2245       char c;
    2246       char *sep;
    2247       int alevel = 0;   /* apostrophe level */
    2248 
    2249       if (strlen (cmd) == 0)
    2250         {
    2251           printf (_("Error, empty command\n"));
    2252           fflush (stdout);
    2253           return 0;
    2254         }
    2255 
    2256       outfile = open_tmpfile (&comname, "sys$scratch:CMDXXXXXX.COM");
    2257       if (outfile == 0)
    2258         pfatal_with_name (_("fopen (temporary file)"));
    2259 
    2260       if (ifile[0])
    2261         {
    2262           fprintf (outfile, "$ assign/user %s sys$input\n", ifile);
    2263           DB (DB_JOBS, (_("Redirected input from %s\n"), ifile));
    2264           ifiledsc.dsc$w_length = 0;
    2265         }
    2266 
    2267       if (efile[0])
    2268         {
    2269           fprintf (outfile, "$ define sys$error %s\n", efile);
    2270           DB (DB_JOBS, (_("Redirected error to %s\n"), efile));
    2271           efiledsc.dsc$w_length = 0;
    2272         }
    2273 
    2274       if (ofile[0])
    2275         {
    2276           fprintf (outfile, "$ define sys$output %s\n", ofile);
    2277           DB (DB_JOBS, (_("Redirected output to %s\n"), ofile));
    2278           ofiledsc.dsc$w_length = 0;
    2279         }
    2280 
    2281       p = sep = q = cmd;
    2282       for (c = '\n'; c; c = *q++)
    2283         {
    2284           switch (c)
    2285             {
    2286             case '\n':
    2287               /* At a newline, skip any whitespace around a leading $
    2288                  from the command and issue exactly one $ into the DCL. */
    2289               while (isspace ((unsigned char)*p))
    2290                 p++;
    2291               if (*p == '$')
    2292                 p++;
    2293               while (isspace ((unsigned char)*p))
    2294                 p++;
    2295               fwrite (p, 1, q - p, outfile);
    2296               fputc ('$', outfile);
    2297               fputc (' ', outfile);
    2298               /* Reset variables. */
    2299               p = sep = q;
    2300               break;
    2301 
    2302               /* Nice places for line breaks are after strings, after
    2303                  comma or space and before slash. */
    2304             case '"':
    2305               q = vms_handle_apos (q);
    2306               sep = q;
    2307               break;
    2308             case ',':
    2309             case ' ':
    2310               sep = q;
    2311               break;
    2312             case '/':
    2313             case '\0':
    2314               sep = q - 1;
    2315               break;
    2316             default:
    2317               break;
    2318             }
    2319           if (sep - p > 78)
    2320             {
    2321               /* Enough stuff for a line. */
    2322               fwrite (p, 1, sep - p, outfile);
    2323               p = sep;
    2324               if (*sep)
    2325                 {
    2326                   /* The command continues.  */
    2327                   fputc ('-', outfile);
    2328                 }
    2329               fputc ('\n', outfile);
    2330             }
    2331         }
    2332 
    2333       fwrite (p, 1, q - p, outfile);
    2334       fputc ('\n', outfile);
    2335 
    2336       fclose (outfile);
    2337 
    2338       sprintf (cmd, "$ @%s", comname);
    2339 
    2340       DB (DB_JOBS, (_("Executing %s instead\n"), cmd));
    2341     }
    2342 
    2343   cmddsc.dsc$w_length = strlen(cmd);
    2344   cmddsc.dsc$a_pointer = cmd;
    2345   cmddsc.dsc$b_dtype = DSC$K_DTYPE_T;
    2346   cmddsc.dsc$b_class = DSC$K_CLASS_S;
    2347 
    2348   child->efn = 0;
    2349   while (child->efn < 32 || child->efn > 63)
    2350     {
    2351       status = lib$get_ef ((unsigned long *)&child->efn);
    2352       if (!(status & 1))
    2353         return 0;
    2354     }
    2355 
    2356   sys$clref (child->efn);
    2357 
    2358   vms_jobsefnmask |= (1 << (child->efn - 32));
    2359 
    2360 /*
    2361              LIB$SPAWN  [command-string]
    2362                         [,input-file]
    2363                         [,output-file]
    2364                         [,flags]
    2365                         [,process-name]
    2366                         [,process-id] [,completion-status-address] [,byte-integer-event-flag-num]
    2367                         [,AST-address] [,varying-AST-argument]
    2368                         [,prompt-string] [,cli] [,table]
    2369 */
    2370 
    2371 #ifndef DONTWAITFORCHILD
    2372 /*
    2373  *      Code to make ctrl+c and ctrl+y working.
    2374  *      The problem starts with the synchronous case where after lib$spawn is
    2375  *      called any input will go to the child. But with input re-directed,
    2376  *      both control characters won't make it to any of the programs, neither
    2377  *      the spawning nor to the spawned one. Hence the caller needs to spawn
    2378  *      with CLI$M_NOWAIT to NOT give up the input focus. A sys$waitfr
    2379  *      has to follow to simulate the wanted synchronous behaviour.
    2380  *      The next problem is ctrl+y which isn't caught by the crtl and
    2381  *      therefore isn't converted to SIGQUIT (for a signal handler which is
    2382  *      already established). The only way to catch ctrl+y, is an AST
    2383  *      assigned to the input channel. But ctrl+y handling of DCL needs to be
    2384  *      disabled, otherwise it will handle it. Not to mention the previous
    2385  *      ctrl+y handling of DCL needs to be re-established before make exits.
    2386  *      One more: At the time of LIB$SPAWN signals are blocked. SIGQUIT will
    2387  *      make it to the signal handler after the child "normally" terminates.
    2388  *      This isn't enough. It seems reasonable for simple command lines like
    2389  *      a 'cc foobar.c' spawned in a subprocess but it is unacceptable for
    2390  *      spawning make. Therefore we need to abort the process in the AST.
    2391  *
    2392  *      Prior to the spawn it is checked if an AST is already set up for
    2393  *      ctrl+y, if not one is set up for a channel to SYS$COMMAND. In general
    2394  *      this will work except if make is run in a batch environment, but there
    2395  *      nobody can press ctrl+y. During the setup the DCL handling of ctrl+y
    2396  *      is disabled and an exit handler is established to re-enable it.
    2397  *      If the user interrupts with ctrl+y, the assigned AST will fire, force
    2398  *      an abort to the subprocess and signal SIGQUIT, which will be caught by
    2399  *      the already established handler and will bring us back to common code.
    2400  *      After the spawn (now /nowait) a sys$waitfr simulates the /wait and
    2401  *      enables the ctrl+y be delivered to this code. And the ctrl+c too,
    2402  *      which the crtl converts to SIGINT and which is caught by the common
    2403  *      signal handler. Because signals were blocked before entering this code
    2404  *      sys$waitfr will always complete and the SIGQUIT will be processed after
    2405  *      it (after termination of the current block, somewhere in common code).
    2406  *      And SIGINT too will be delayed. That is ctrl+c can only abort when the
    2407  *      current command completes. Anyway it's better than nothing :-)
    2408  */
    2409 
    2410   if (!setupYAstTried)
    2411     tryToSetupYAst();
    2412   status = lib$spawn (&cmddsc,                                  /* cmd-string  */
    2413                       (ifiledsc.dsc$w_length == 0)?0:&ifiledsc, /* input-file  */
    2414                       (ofiledsc.dsc$w_length == 0)?0:&ofiledsc, /* output-file */
    2415                       &spflags,                                 /* flags  */
    2416                       &pnamedsc,                                /* proc name  */
    2417                       &child->pid, &child->cstatus, &child->efn,
    2418                       0, 0,
    2419                       0, 0, 0);
    2420   if (status & 1)
    2421     {
    2422       pidToAbort= child->pid;
    2423       status= sys$waitfr (child->efn);
    2424       pidToAbort= 0;
    2425       vmsHandleChildTerm(child);
    2426     }
    2427 #else
    2428   status = lib$spawn (&cmddsc,
    2429                       (ifiledsc.dsc$w_length == 0)?0:&ifiledsc,
    2430                       (ofiledsc.dsc$w_length == 0)?0:&ofiledsc,
    2431                       &spflags,
    2432                       &pnamedsc,
    2433                       &child->pid, &child->cstatus, &child->efn,
    2434                       vmsHandleChildTerm, child,
    2435                       0, 0, 0);
    2436 #endif
    2437 
    2438   if (!(status & 1))
    2439     {
    2440       printf (_("Error spawning, %d\n") ,status);
    2441       fflush (stdout);
    2442       switch (status)
    2443         {
    2444         case 0x1c:
    2445           errno = EPROCLIM;
    2446           break;
    2447         default:
    2448           errno = EFAIL;
    2449         }
    2450     }
    2451 
    2452   if (comname && !ISDB (DB_JOBS))
    2453     unlink (comname);
    2454 
    2455   return (status & 1);
    2456 }
    2457 
    2458 #else /* !VMS */
    24591938
    24601939/* EMX: Start a child process. This function returns the new pid.  */
    2461 # if defined __MSDOS__ ||  defined __EMX__
    24621940/* The child argument can be NULL (that's why we return the pid), if it is
    24631941   and the shell is a dllshell:// a child structure is created and inserted
     
    24661944   BTW. the name of this function in this port is very misleading, spawn_job
    24671945   would perhaps be more appropriate. */
    2468 
     1946# if defined __MSDOS__ || defined __EMX__
    24691947int
    24701948child_execute_job (int stdin_fd, int stdout_fd, char **argv, char **envp,
     
    25091987#endif
    25101988
    2511   /* Restore stdout/stdin of the parent process.  */
    2512   if (stdin_fd != 0 && dup2 (save_stdin, 0) != 0)
    2513     fatal (NILF, _("restoring of stdin failed\n"));
    2514   if (stdout_fd != 1 && dup2 (save_stdout, 1) != 1)
    2515     fatal (NILF, _("restoring of stdout failed\n"));
    2516 
    2517   /* Cleanup handles */
     1989  /* Restore stdout/stdin of the parent and close temporary FDs.  */
    25181990  if (stdin_fd != 0)
    2519     close (save_stdin);
     1991    {
     1992      if (dup2 (save_stdin, 0) != 0)
     1993        fatal (NILF, _("Could not restore stdin\n"));
     1994      else
     1995        close (save_stdin);
     1996    }
     1997
    25201998  if (stdout_fd != 1)
    2521     close (save_stdout);
     1999    {
     2000      if (dup2 (save_stdout, 1) != 1)
     2001        fatal (NILF, _("Could not restore stdout\n"));
     2002      else
     2003        close (save_stdout);
     2004    }
    25222005
    25232006  return pid;
     
    25462029}
    25472030#endif /* !AMIGA && !__MSDOS__ */
    2548 #endif /* !VMS */
    25492031#endif /* !WINDOWS32 */
    25502032
     
    26782160int
    26792161# else
    2680  void
     2162void
    26812163# endif
    26822164exec_command (char **argv, char **envp)
     
    27182200
    27192201  /* wait and reap last child */
    2720   while (hWaitPID = process_wait_for_any())
     2202  hWaitPID = process_wait_for_any();
     2203  while (hWaitPID)
    27212204    {
    27222205      /* was an error found on this process? */
     
    27862269        char **new_argv;
    27872270        int argc;
     2271        int i=1;
    27882272
    27892273# ifdef __EMX__
     
    28042288          ++argc;
    28052289
     2290# ifdef __EMX__
     2291        if (!unixy_shell)
     2292          ++argc;
     2293# endif
     2294
    28062295        new_argv = (char **) alloca ((1 + argc + 1) * sizeof (char *));
    28072296        new_argv[0] = shell;
    2808         new_argv[1] = argv[0];
     2297
     2298# ifdef __EMX__
     2299        if (!unixy_shell)
     2300          {
     2301            new_argv[1] = "/c";
     2302            ++i;
     2303            --argc;
     2304          }
     2305# endif
     2306
     2307        new_argv[i] = argv[0];
    28092308        while (argc > 0)
    28102309          {
    2811             new_argv[1 + argc] = argv[argc];
     2310            new_argv[i + argc] = argv[argc];
    28122311            --argc;
    28132312          }
     
    29772476  char*  sh_chars;
    29782477  char** sh_cmds;
     2478#elif defined(__riscos__)
     2479  static char sh_chars[] = "";
     2480  static char *sh_cmds[] = { 0 };
    29792481#else  /* must be UNIX-ish */
    29802482  static char sh_chars[] = "#;\"*?[]&|<>(){}$`^~!";
     
    32542756                register int j;
    32552757                for (j = 0; sh_cmds[j] != 0; ++j)
    3256                   if (streq (sh_cmds[j], new_argv[0]))
    3257                     goto slow;
     2758                  {
     2759                    if (streq (sh_cmds[j], new_argv[0]))
     2760                      goto slow;
     2761# ifdef __EMX__
     2762                    /* Non-Unix shells are case insensitive.  */
     2763                    if (!unixy_shell
     2764                        && strcasecmp (sh_cmds[j], new_argv[0]) == 0)
     2765                      goto slow;
     2766# endif
     2767                  }
    32582768              }
    32592769
     
    32932803    /* Line was empty.  */
    32942804    return 0;
    3295   else
    3296     return new_argv;
     2805
     2806  return new_argv;
    32972807
    32982808 slow:;
     
    34432953      int id = GetCurrentProcessId();
    34442954      PATH_VAR(fbuf);
    3445       char* fname = NULL;
    34462955
    34472956      /* create a file name */
    34482957      sprintf(fbuf, "make%d", id);
    3449       fname = tempnam(".", fbuf);
    3450 
    3451           /* create batch file name */
    3452       *batch_filename_ptr = xmalloc(strlen(fname) + 5);
    3453       strcpy(*batch_filename_ptr, fname);
    3454 
    3455       /* make sure path name is in DOS backslash format */
    3456       if (!unixy_shell) {
    3457         fname = *batch_filename_ptr;
    3458         for (i = 0; fname[i] != '\0'; ++i)
    3459           if (fname[i] == '/')
    3460             fname[i] = '\\';
    3461         strcat(*batch_filename_ptr, ".bat");
    3462       } else {
    3463         strcat(*batch_filename_ptr, ".sh");
    3464       }
     2958      *batch_filename_ptr = create_batch_filename (fbuf, unixy_shell);
    34652959
    34662960      DB (DB_JOBS, (_("Creating temporary batch file %s\n"),
     
    34912985                                                  (char *) 0, (char *) 0,
    34922986                                                  (char **) 0);
    3493 # ifdef __EMX__
     2987#ifdef __EMX__
    34942988    else if (!unixy_shell)
    34952989      {
    3496         /* new_line is local, must not be freed therefore */
    3497         char *p, *q;
    3498         int quote;
    3499         size_t index;
    3500         size_t len;
    3501 
    3502         /* handle quotes
    3503            We have to remove all double quotes and to split the line
    3504            into distinct arguments because of the strange handling
    3505            of builtin commands by cmd: 'echo "bla"' prints "bla"
    3506            (with quotes) while 'c:\bin\echo.exe "bla"' prints bla
    3507            (without quotes). Some programs like autoconf rely
    3508            on the second behaviour. */
    3509 
    3510         len = strlen (new_line) + 1;
    3511 
    3512         /* More than 1 arg per character is impossible.  */
    3513         new_argv = (char **) xmalloc (len * sizeof (char *));
    3514 
    3515         /* All the args can fit in a buffer as big as new_line is.   */
    3516         new_argv[0] = (char *) xmalloc (len);
    3517 
    3518         index = 0;
    3519         quote = 0;
    3520         q = new_line;
    3521         p = new_argv[index];
    3522         while(*q != '\0')
    3523           {
    3524             /* searching for closing quote */
    3525             if (quote)
    3526               {
    3527                 if (*q == quote)
    3528                   {
    3529                     /* remove the quote */
    3530                     q++;
    3531                     quote = 0;
    3532                   }
    3533                 else /* normal character: copy it */
    3534                   *p++ = *q++;
    3535               }
    3536 
    3537             /* searching for opening quote */
    3538             else if (*q == '\"'
    3539 #  ifndef NO_CMD_DEFAULT
    3540                      || *q == '\''
    3541 #  endif
    3542                      )
    3543               {
    3544                 /* remove opening quote */
    3545                 quote = *q;
    3546                 q++;
    3547               }
    3548 
    3549             /* spaces outside of a quoted string: remove them
    3550                and start a new argument */
    3551             else if (*q == ' ' || *q == '\t')
    3552               {
    3553                 *p++ = '\0'; /* trailing '\0' for last argument */
    3554 
    3555                 /* remove all successive spaces */
    3556                 do
    3557                   {
    3558                     q++;
    3559                   }
    3560                 while(*q == ' ' || *q == '\t');
    3561 
    3562                 /* start new argument */
    3563                 index++;
    3564                 new_argv[index] = p;
    3565               }
    3566 
    3567             /* normal character (no space) outside a quoted string*/
    3568             else
    3569               *p++ = *q++;
    3570           } /* end while() */
    3571 
    3572         *p = '\0'; /* trailing '\0' for the last argument */
    3573         new_argv[index + 1] = NULL;
    3574 
    3575 #  ifndef NO_CMD_DEFAULT
    3576         /* special case: echo x="y"
    3577            (e.g. autoconf uses this to determine whether make works)
    3578            this is pure idioty but cmd works this way:
    3579            if 'echo' and 'x="y"' are two different arguments cmd
    3580            will print '"x="y""' but if they are only one argument
    3581            cmd will print 'bla="blurb"' as it should be
    3582            note: if we do not allow cmd to be the default shell
    3583            we do not need this kind of voodoo */
    3584         if (index == 3 && strcasecmp(new_argv[2], "echo") == 0)
    3585           {
    3586             new_argv[2][4] = ' ';
    3587             new_argv[3] = NULL;
    3588           }
    3589 #  endif
     2990        /* new_line is local, must not be freed therefore
     2991           We use line here instead of new_line because we run the shell
     2992           manually.  */
     2993        size_t line_len = strlen (line);
     2994        char *p = new_line;
     2995        char *q = new_line;
     2996        memcpy (new_line, line, line_len + 1);
     2997        /* replace all backslash-newline combination and also following tabs */
     2998        while (*q != '\0')
     2999          {
     3000            if (q[0] == '\\' && q[1] == '\n')
     3001              {
     3002                q += 2; /* remove '\\' and '\n' */
     3003                if (q[0] == '\t')
     3004                  q++; /* remove 1st tab in the next line */
     3005              }
     3006            else
     3007              *p++ = *q++;
     3008          }
     3009        *p = '\0';
     3010
     3011# ifndef NO_CMD_DEFAULT
     3012        if (strnicmp (new_line, "echo", 4) == 0
     3013            && (new_line[4] == ' ' || new_line[4] == '\t'))
     3014          {
     3015            /* the builtin echo command: handle it separately */
     3016            size_t echo_len = line_len - 5;
     3017            char *echo_line = new_line + 5;
     3018
     3019            /* special case: echo 'x="y"'
     3020               cmd works this way: a string is printed as is, i.e., no quotes
     3021               are removed. But autoconf uses a command like echo 'x="y"' to
     3022               determine whether make works. autoconf expects the output x="y"
     3023               so we will do exactly that.
     3024               Note: if we do not allow cmd to be the default shell
     3025               we do not need this kind of voodoo */
     3026            if (echo_line[0] == '\''
     3027                && echo_line[echo_len - 1] == '\''
     3028                && strncmp (echo_line + 1, "ac_maketemp=",
     3029                            strlen ("ac_maketemp=")) == 0)
     3030              {
     3031                /* remove the enclosing quotes */
     3032                memmove (echo_line, echo_line + 1, echo_len - 2);
     3033                echo_line[echo_len - 2] = '\0';
     3034              }
     3035          }
     3036# endif
     3037
     3038        {
     3039          /* Let the shell decide what to do. Put the command line into the
     3040             2nd command line argument and hope for the best ;-)  */
     3041          size_t sh_len = strlen (shell);
     3042
     3043          /* exactly 3 arguments + NULL */
     3044          new_argv = (char **) xmalloc (4 * sizeof (char *));
     3045          /* Exactly strlen(shell) + strlen("/c") + strlen(line) + 3 times
     3046             the trailing '\0' */
     3047          new_argv[0] = (char *) malloc (sh_len + line_len + 5);
     3048          memcpy (new_argv[0], shell, sh_len + 1);
     3049          new_argv[1] = new_argv[0] + sh_len + 1;
     3050          memcpy (new_argv[1], "/c", 3);
     3051          new_argv[2] = new_argv[1] + 3;
     3052          memcpy (new_argv[2], new_line, line_len + 1);
     3053          new_argv[3] = NULL;
     3054        }
    35903055      }
    35913056#elif defined(__MSDOS__)
     
    37683233}
    37693234#endif /* !HAPE_DUP2 && !_AMIGA */
     3235
     3236/* On VMS systems, include special VMS functions.  */
     3237
     3238#ifdef VMS
     3239#include "vmsjobs.c"
     3240#endif
Note: See TracChangeset for help on using the changeset viewer.