Ignore:
Timestamp:
May 16, 2005, 6:54:02 PM (20 years ago)
Author:
bird
Message:

Current make snaphot, 2005-05-16.

Location:
branches/GNU/src/gmake
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • branches/GNU/src/gmake

    • Property svn:ignore
      •  

        old new  
        3434README.DOS
        3535README.W32
         36README.OS2
        3637aclocal.m4
        3738autom4te.cache
  • branches/GNU/src/gmake/job.c

    r153 r280  
    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
     
    6162
    6263# include <descrip.h>
     64char default_shell[] = "";
     65int batch_mode_shell = 0;
     66
     67#elif defined (__riscos__)
     68
    6369char default_shell[] = "";
    6470int batch_mode_shell = 0;
     
    168174#endif  /* Don't have `union wait'.  */
    169175
    170 #ifdef VMS
    171 static int vms_jobsefnmask = 0;
    172 #endif /* !VMS */
    173 
    174176#ifndef HAVE_UNISTD_H
    175177extern int dup2 ();
     
    199201static int job_next_command PARAMS ((struct child *));
    200202static int start_waiting_job PARAMS ((struct child *));
    201 #ifdef VMS
    202 static void vmsWaitForChildren PARAMS ((int *));
    203 #endif
    204203
    205204
     
    228227unsigned long job_counter = 0;
    229228
     229/* Number of jobserver tokens this instance is currently using.  */
     230
     231unsigned int jobserver_tokens = 0;
    230232
    231233
     
    237239w32_kill(int pid, int sig)
    238240{
    239   return ((process_kill(pid, sig) == TRUE) ? 0 : -1);
     241  return ((process_kill((HANDLE)pid, sig) == TRUE) ? 0 : -1);
     242}
     243
     244/* This function creates a temporary file name with the given extension
     245 * the unixy param controls both the extension and the path separator
     246 * return an xmalloc'ed string of a newly created temp file or die.  */
     247static char *
     248create_batch_filename(char const *base, int unixy)
     249{
     250  const char *const ext = unixy ? "sh" : "bat";
     251  const char *error = NULL;
     252  char temp_path[MAXPATHLEN]; /* need to know its length */
     253  unsigned path_size = GetTempPath(sizeof temp_path, temp_path);
     254  int path_is_dot = 0;
     255  unsigned uniq = 1;
     256  const unsigned sizemax = strlen (base) + strlen (ext) + 10;
     257
     258  if (path_size == 0)
     259    {
     260      path_size = GetCurrentDirectory (sizeof temp_path, temp_path);
     261      path_is_dot = 1;
     262    }
     263
     264  while (path_size > 0 &&
     265         path_size + sizemax < sizeof temp_path &&
     266         uniq < 0x10000)
     267    {
     268      unsigned size = sprintf (temp_path + path_size,
     269                               "%s%s-%x.%s",
     270                               temp_path[path_size - 1] == '\\' ? "" : "\\",
     271                               base, uniq, ext);
     272      HANDLE h = CreateFile (temp_path,  /* file name */
     273                             GENERIC_READ | GENERIC_WRITE, /* desired access */
     274                             0,                            /* no share mode */
     275                             NULL,                         /* default security attributes */
     276                             CREATE_NEW,                   /* creation disposition */
     277                             FILE_ATTRIBUTE_NORMAL |       /* flags and attributes */
     278                             FILE_ATTRIBUTE_TEMPORARY,     /* we'll delete it */
     279                             NULL);                        /* no template file */
     280
     281      if (h == INVALID_HANDLE_VALUE)
     282        {
     283          const DWORD er = GetLastError();
     284
     285          if (er == ERROR_FILE_EXISTS || er == ERROR_ALREADY_EXISTS)
     286            ++uniq;
     287
     288          /* the temporary path is not guaranteed to exist */
     289          else if (path_is_dot == 0)
     290            {
     291              path_size = GetCurrentDirectory (sizeof temp_path, temp_path);
     292              path_is_dot = 1;
     293            }
     294
     295          else
     296            {
     297              error = map_windows32_error_to_string (er);
     298              break;
     299            }
     300        }
     301      else
     302        {
     303          const unsigned final_size = path_size + size + 1;
     304          char *const path = (char *) xmalloc (final_size);
     305          memcpy (path, temp_path, final_size);
     306          CloseHandle (h);
     307          if (unixy)
     308            {
     309              char *p;
     310              int ch;
     311              for (p = path; (ch = *p) != 0; ++p)
     312                if (ch == '\\')
     313                  *p = '/';
     314            }
     315          return path; /* good return */
     316        }
     317    }
     318
     319  if (error == NULL)
     320    error = _("Cannot create a temporary file\n");
     321  fatal (NILF, error);
     322
     323  /* not reached */
     324  return NULL;
    240325}
    241326#endif /* WINDOWS32 */
     
    317402
    318403
    319 #ifdef VMS
    320 /* Wait for nchildren children to terminate */
    321 static void
    322 vmsWaitForChildren(int *status)
    323 {
    324   while (1)
    325     {
    326       if (!vms_jobsefnmask)
    327         {
    328           *status = 0;
    329           return;
    330         }
    331 
    332       *status = sys$wflor (32, vms_jobsefnmask);
    333     }
    334   return;
    335 }
    336 
    337 /* Set up IO redirection.  */
    338 
    339 char *
    340 vms_redirect (struct dsc$descriptor_s *desc, char *fname, char *ibuf)
    341 {
    342   char *fptr;
    343   extern char *vmsify ();
    344 
    345   ibuf++;
    346   while (isspace ((unsigned char)*ibuf))
    347     ibuf++;
    348   fptr = ibuf;
    349   while (*ibuf && !isspace ((unsigned char)*ibuf))
    350     ibuf++;
    351   *ibuf = 0;
    352   if (strcmp (fptr, "/dev/null") != 0)
    353     {
    354       strcpy (fname, vmsify (fptr, 0));
    355       if (strchr (fname, '.') == 0)
    356         strcat (fname, ".");
    357     }
    358   desc->dsc$w_length = strlen(fname);
    359   desc->dsc$a_pointer = fname;
    360   desc->dsc$b_dtype = DSC$K_DTYPE_T;
    361   desc->dsc$b_class = DSC$K_CLASS_S;
    362 
    363   if (*fname == 0)
    364     printf (_("Warning: Empty redirection\n"));
    365   return ibuf;
    366 }
    367 
    368 
    369 /* found apostrophe at (p-1)
    370    inc p until after closing apostrophe.
    371  */
    372 
    373 static char *
    374 vms_handle_apos (char *p)
    375 {
    376   int alast;
    377 
    378 #define SEPCHARS ",/()= "
    379 
    380   alast = 0;
    381 
    382   while (*p != 0)
    383     {
    384       if (*p == '"')
    385         {
    386           if (alast)
    387             {
    388               alast = 0;
    389               p++;
    390             }
    391           else
    392             {
    393               p++;
    394               if (strchr (SEPCHARS, *p))
    395                 break;
    396               alast = 1;
    397             }
    398         }
    399       else
    400         p++;
    401     }
    402 
    403   return p;
    404 }
    405 
    406 #endif
    407 
    408404
    409405/* Handle a dead child.  This handler may or may not ever be installed.
     
    474470    {
    475471      int remote = 0;
    476       register int pid;
     472      pid_t pid;
    477473      int exit_code, exit_sig, coredump;
    478474      register struct child *lastc, *c;
     
    543539            {
    544540#ifdef VMS
     541              static void vmsWaitForChildren PARAMS ((int *));
    545542              vmsWaitForChildren (&status);
    546543              pid = c->pid;
     
    616613            HANDLE hPID;
    617614            int err;
     615            exit_code = 0;
     616            exit_sig = 0;
     617            coredump = 0;
    618618
    619619            /* wait for anything to finish */
    620             if (hPID = process_wait_for_any()) {
    621 
    622               /* was an error found on this process? */
    623               err = process_last_err(hPID);
    624 
    625               /* get exit data */
    626               exit_code = process_exit_code(hPID);
    627 
    628               if (err)
    629                 fprintf(stderr, "make (e=%d): %s",
    630                   exit_code, map_windows32_error_to_string(exit_code));
    631 
    632               /* signal */
    633               exit_sig = process_signal(hPID);
    634 
    635               /* cleanup process */
    636               process_cleanup(hPID);
    637 
    638               coredump = 0;
    639             }
    640             pid = (int) hPID;
     620            hPID = process_wait_for_any();
     621            if (hPID)
     622              {
     623
     624                /* was an error found on this process? */
     625                err = process_last_err(hPID);
     626
     627                /* get exit data */
     628                exit_code = process_exit_code(hPID);
     629
     630                if (err)
     631                  fprintf(stderr, "make (e=%d): %s",
     632                          exit_code, map_windows32_error_to_string(exit_code));
     633
     634                /* signal */
     635                exit_sig = process_signal(hPID);
     636
     637                /* cleanup process */
     638                process_cleanup(hPID);
     639
     640                coredump = 0;
     641              }
     642            pid = (pid_t) hPID;
    641643          }
    642644#endif /* WINDOWS32 */
     
    812814free_child (struct child *child)
    813815{
    814   /* If this child is the only one it was our "free" job, so don't put a
    815      token back for it.  This child has already been removed from the list,
    816      so if there any left this wasn't the last one.  */
    817 
    818   if (job_fds[1] >= 0 && children)
     816  if (!jobserver_tokens)
     817    fatal (NILF, "INTERNAL: Freeing child 0x%08lx (%s) but no tokens left!\n",
     818           (unsigned long int) child, child->file->name);
     819
     820  /* If we're using the jobserver and this child is not the only outstanding
     821     job, put a token back into the pipe for it.  */
     822
     823  if (job_fds[1] >= 0 && jobserver_tokens > 1)
    819824    {
    820825      char token = '+';
     
    830835                    (unsigned long int) child, child->file->name));
    831836    }
     837
     838  --jobserver_tokens;
    832839
    833840  if (handling_fatal_signal) /* Don't bother free'ing if about to die.  */
     
    870877}
    871878
    872 #ifdef  POSIX
     879#ifdef POSIX
    873880void
    874881unblock_sigs (void)
     
    881888
    882889#ifdef MAKE_JOBSERVER
     890RETSIGTYPE
     891job_noop (int sig UNUSED)
     892{
     893}
    883894/* Set the child handler action flags to FLAGS.  */
    884895static void
    885 set_child_handler_action_flags (int flags)
     896set_child_handler_action_flags (int set_handler, int set_alarm)
    886897{
    887898  struct sigaction sa;
     899
     900#ifdef __EMX__
     901  /* The child handler must be turned off here.  */
     902  signal (SIGCHLD, SIG_DFL);
     903#endif
     904
    888905  bzero ((char *) &sa, sizeof sa);
    889906  sa.sa_handler = child_handler;
    890   sa.sa_flags = flags;
     907  sa.sa_flags = set_handler ? 0 : SA_RESTART;
    891908#if defined SIGCHLD
    892909  sigaction (SIGCHLD, &sa, NULL);
     
    894911#if defined SIGCLD && SIGCLD != SIGCHLD
    895912  sigaction (SIGCLD, &sa, NULL);
     913#endif
     914#if defined SIGALRM
     915  if (set_alarm)
     916    {
     917      /* If we're about to enter the read(), set an alarm to wake up in a
     918         second so we can check if the load has dropped and we can start more
     919         work.  On the way out, turn off the alarm and set SIG_DFL.  */
     920      alarm (set_handler ? 1 : 0);
     921      sa.sa_handler = set_handler ? job_noop : SIG_DFL;
     922      sa.sa_flags = 0;
     923      sigaction (SIGALRM, &sa, NULL);
     924    }
    896925#endif
    897926}
     
    11581187
    11591188#ifdef VMS
    1160 
    11611189      if (!child_execute_job (argv, child)) {
    11621190        /* Fork failed!  */
     
    15821610
    15831611        /* If we don't already have a job started, use our "free" token.  */
    1584         if (!children)
     1612        if (!jobserver_tokens)
    15851613          break;
    15861614
     
    16171645        reap_children (0, 0);
    16181646
    1619         /* If our "free" token has become available, use it.  */
     1647        /* Kick off any jobs we have waiting for an opportunity that
     1648           can run now (ie waiting for load). */
     1649        start_waiting_jobs ();
     1650
     1651        /* If our "free" slot has become available, use it; we don't need an
     1652           actual token.  */
     1653        if (!jobserver_tokens)
     1654          break;
     1655
     1656        /* There must be at least one child already, or we have no business
     1657           waiting for a token. */
    16201658        if (!children)
    1621           break;
     1659          fatal (NILF, "INTERNAL: no children as we go to sleep on read\n");
    16221660
    16231661        /* Set interruptible system calls, and read() for a job token.  */
    1624         set_child_handler_action_flags (0);
     1662        set_child_handler_action_flags (1, waiting_jobs != NULL);
    16251663        got_token = read (job_rfd, &token, 1);
    16261664        saved_errno = errno;
    1627 #ifdef __EMX__
    1628         /* The child handler must be turned off here.  */
    1629         signal (SIGCHLD, SIG_DFL);
    1630 #endif
    1631         set_child_handler_action_flags (SA_RESTART);
     1665        set_child_handler_action_flags (0, waiting_jobs != NULL);
    16321666
    16331667        /* If we got one, we're done here.  */
     
    16481682      }
    16491683#endif
     1684
     1685  ++jobserver_tokens;
    16501686
    16511687  /* The job is now primed.  Start it running.
     
    17281764load_too_high (void)
    17291765{
    1730 #if defined(__MSDOS__) || defined(VMS) || defined(_AMIGA)
     1766#if defined(__MSDOS__) || defined(VMS) || defined(_AMIGA) || defined(__riscos__)
    17311767  return 1;
    17321768#else
     
    18121848
    18131849#ifndef WINDOWS32
    1814 #ifdef VMS
    1815 #include <descrip.h>
    1816 #include <clidef.h>
    1817 
    1818 /* This is called as an AST when a child process dies (it won't get
    1819    interrupted by anything except a higher level AST).
    1820 */
    1821 int vmsHandleChildTerm(struct child *child)
    1822 {
    1823     int status;
    1824     register struct child *lastc, *c;
    1825     int child_failed;
    1826 
    1827     vms_jobsefnmask &= ~(1 << (child->efn - 32));
    1828 
    1829     lib$free_ef(&child->efn);
    1830 
    1831     (void) sigblock (fatal_signal_mask);
    1832 
    1833     child_failed = !(child->cstatus & 1 || ((child->cstatus & 7) == 0));
    1834 
    1835     /* Search for a child matching the deceased one.  */
    1836     lastc = 0;
    1837 #if defined(RECURSIVEJOBS) /* I've had problems with recursive stuff and process handling */
    1838     for (c = children; c != 0 && c != child; lastc = c, c = c->next);
    1839 #else
    1840     c = child;
    1841 #endif
    1842 
    1843     if (child_failed && !c->noerror && !ignore_errors_flag)
    1844       {
    1845         /* The commands failed.  Write an error message,
    1846            delete non-precious targets, and abort.  */
    1847         child_error (c->file->name, c->cstatus, 0, 0, 0);
    1848         c->file->update_status = 1;
    1849         delete_child_targets (c);
    1850       }
    1851     else
    1852       {
    1853         if (child_failed)
    1854           {
    1855             /* The commands failed, but we don't care.  */
    1856             child_error (c->file->name, c->cstatus, 0, 0, 1);
    1857             child_failed = 0;
    1858           }
    1859 
    1860 #if defined(RECURSIVEJOBS) /* I've had problems with recursive stuff and process handling */
    1861         /* If there are more commands to run, try to start them.  */
    1862         start_job (c);
    1863 
    1864         switch (c->file->command_state)
    1865           {
    1866           case cs_running:
    1867             /* Successfully started.  */
    1868             break;
    1869 
    1870           case cs_finished:
    1871             if (c->file->update_status != 0) {
    1872                 /* We failed to start the commands.  */
    1873                 delete_child_targets (c);
    1874             }
    1875             break;
    1876 
    1877           default:
    1878             error (NILF, _("internal error: `%s' command_state"),
    1879                    c->file->name);
    1880             abort ();
    1881             break;
    1882           }
    1883 #endif /* RECURSIVEJOBS */
    1884       }
    1885 
    1886     /* Set the state flag to say the commands have finished.  */
    1887     c->file->command_state = cs_finished;
    1888     notice_finished_file (c->file);
    1889 
    1890 #if defined(RECURSIVEJOBS) /* I've had problems with recursive stuff and process handling */
    1891     /* Remove the child from the chain and free it.  */
    1892     if (lastc == 0)
    1893       children = c->next;
    1894     else
    1895       lastc->next = c->next;
    1896     free_child (c);
    1897 #endif /* RECURSIVEJOBS */
    1898 
    1899     /* There is now another slot open.  */
    1900     if (job_slots_used > 0)
    1901       --job_slots_used;
    1902 
    1903     /* If the job failed, and the -k flag was not given, die.  */
    1904     if (child_failed && !keep_going_flag)
    1905       die (EXIT_FAILURE);
    1906 
    1907     (void) sigsetmask (sigblock (0) & ~(fatal_signal_mask));
    1908 
    1909     return 1;
    1910 }
    1911 
    1912 /* VMS:
    1913    Spawn a process executing the command in ARGV and return its pid. */
    1914 
    1915 #define MAXCMDLEN 200
    1916 
    1917 /* local helpers to make ctrl+c and ctrl+y working, see below */
    1918 #include <iodef.h>
    1919 #include <libclidef.h>
    1920 #include <ssdef.h>
    1921 
    1922 static int ctrlMask= LIB$M_CLI_CTRLY;
    1923 static int oldCtrlMask;
    1924 static int setupYAstTried= 0;
    1925 static int pidToAbort= 0;
    1926 static int chan= 0;
    1927 
    1928 static void reEnableAst(void) {
    1929         lib$enable_ctrl (&oldCtrlMask,0);
    1930 }
    1931 
    1932 static astHandler (void) {
    1933         if (pidToAbort) {
    1934                 sys$forcex (&pidToAbort, 0, SS$_ABORT);
    1935                 pidToAbort= 0;
    1936         }
    1937         kill (getpid(),SIGQUIT);
    1938 }
    1939 
    1940 static void tryToSetupYAst(void) {
    1941         $DESCRIPTOR(inputDsc,"SYS$COMMAND");
    1942         int     status;
    1943         struct {
    1944                 short int       status, count;
    1945                 int     dvi;
    1946         } iosb;
    1947 
    1948         setupYAstTried++;
    1949 
    1950         if (!chan) {
    1951                 status= sys$assign(&inputDsc,&chan,0,0);
    1952                 if (!(status&SS$_NORMAL)) {
    1953                         lib$signal(status);
    1954                         return;
    1955                 }
    1956         }
    1957         status= sys$qiow (0, chan, IO$_SETMODE|IO$M_CTRLYAST,&iosb,0,0,
    1958                 astHandler,0,0,0,0,0);
    1959         if (status==SS$_ILLIOFUNC) {
    1960                 sys$dassgn(chan);
    1961 #ifdef  CTRLY_ENABLED_ANYWAY
    1962                 fprintf (stderr,
    1963                          _("-warning, CTRL-Y will leave sub-process(es) around.\n"));
    1964 #else
    1965                 return;
    1966 #endif
    1967         }
    1968         if (status==SS$_NORMAL)
    1969                 status= iosb.status;
    1970         if (!(status&SS$_NORMAL)) {
    1971                 lib$signal(status);
    1972                 return;
    1973         }
    1974 
    1975         /* called from AST handler ? */
    1976         if (setupYAstTried>1)
    1977                 return;
    1978         if (atexit(reEnableAst))
    1979                 fprintf (stderr,
    1980                          _("-warning, you may have to re-enable CTRL-Y handling from DCL.\n"));
    1981         status= lib$disable_ctrl (&ctrlMask, &oldCtrlMask);
    1982         if (!(status&SS$_NORMAL)) {
    1983                 lib$signal(status);
    1984                 return;
    1985         }
    1986 }
    1987 int
    1988 child_execute_job (char *argv, struct child *child)
    1989 {
    1990   int i;
    1991   static struct dsc$descriptor_s cmddsc;
    1992   static struct dsc$descriptor_s pnamedsc;
    1993   static struct dsc$descriptor_s ifiledsc;
    1994   static struct dsc$descriptor_s ofiledsc;
    1995   static struct dsc$descriptor_s efiledsc;
    1996   int have_redirection = 0;
    1997   int have_newline = 0;
    1998 
    1999   int spflags = CLI$M_NOWAIT;
    2000   int status;
    2001   char *cmd = alloca (strlen (argv) + 512), *p, *q;
    2002   char ifile[256], ofile[256], efile[256];
    2003   char *comname = 0;
    2004   char procname[100];
    2005 
    2006   /* Parse IO redirection.  */
    2007 
    2008   ifile[0] = 0;
    2009   ofile[0] = 0;
    2010   efile[0] = 0;
    2011 
    2012   DB (DB_JOBS, ("child_execute_job (%s)\n", argv));
    2013 
    2014   while (isspace ((unsigned char)*argv))
    2015     argv++;
    2016 
    2017   if (*argv == 0)
    2018     return 0;
    2019 
    2020   sprintf (procname, "GMAKE_%05x", getpid () & 0xfffff);
    2021   pnamedsc.dsc$w_length = strlen(procname);
    2022   pnamedsc.dsc$a_pointer = procname;
    2023   pnamedsc.dsc$b_dtype = DSC$K_DTYPE_T;
    2024   pnamedsc.dsc$b_class = DSC$K_CLASS_S;
    2025 
    2026   /* Handle comments and redirection. */
    2027   for (p = argv, q = cmd; *p; p++, q++)
    2028     {
    2029       switch (*p)
    2030         {
    2031           case '#':
    2032             *p-- = 0;
    2033             *q-- = 0;
    2034             break;
    2035           case '\\':
    2036             p++;
    2037             if (*p == '\n')
    2038               p++;
    2039             if (isspace ((unsigned char)*p))
    2040               {
    2041                 do { p++; } while (isspace ((unsigned char)*p));
    2042                 p--;
    2043               }
    2044             *q = *p;
    2045             break;
    2046           case '<':
    2047             p = vms_redirect (&ifiledsc, ifile, p);
    2048             *q = ' ';
    2049             have_redirection = 1;
    2050             break;
    2051           case '>':
    2052             have_redirection = 1;
    2053             if (*(p-1) == '2')
    2054               {
    2055                 q--;
    2056                 if (strncmp (p, ">&1", 3) == 0)
    2057                   {
    2058                     p += 3;
    2059                     strcpy (efile, "sys$output");
    2060                     efiledsc.dsc$w_length = strlen(efile);
    2061                     efiledsc.dsc$a_pointer = efile;
    2062                     efiledsc.dsc$b_dtype = DSC$K_DTYPE_T;
    2063                     efiledsc.dsc$b_class = DSC$K_CLASS_S;
    2064                   }
    2065                 else
    2066                   {
    2067                     p = vms_redirect (&efiledsc, efile, p);
    2068                   }
    2069               }
    2070             else
    2071               {
    2072                 p = vms_redirect (&ofiledsc, ofile, p);
    2073               }
    2074             *q = ' ';
    2075             break;
    2076           case '\n':
    2077             have_newline = 1;
    2078           default:
    2079             *q = *p;
    2080             break;
    2081         }
    2082     }
    2083   *q = *p;
    2084 
    2085   if (strncmp (cmd, "builtin_", 8) == 0)
    2086     {
    2087       child->pid = 270163;
    2088       child->efn = 0;
    2089       child->cstatus = 1;
    2090 
    2091       DB (DB_JOBS, (_("BUILTIN [%s][%s]\n"), cmd, cmd+8));
    2092 
    2093       p = cmd + 8;
    2094 
    2095       if ((*(p) == 'c')
    2096           && (*(p+1) == 'd')
    2097           && ((*(p+2) == ' ') || (*(p+2) == '\t')))
    2098         {
    2099           p += 3;
    2100           while ((*p == ' ') || (*p == '\t'))
    2101             p++;
    2102           DB (DB_JOBS, (_("BUILTIN CD %s\n"), p));
    2103           if (chdir (p))
    2104             return 0;
    2105           else
    2106             return 1;
    2107         }
    2108       else if ((*(p) == 'r')
    2109           && (*(p+1) == 'm')
    2110           && ((*(p+2) == ' ') || (*(p+2) == '\t')))
    2111         {
    2112           int in_arg;
    2113 
    2114           /* rm  */
    2115           p += 3;
    2116           while ((*p == ' ') || (*p == '\t'))
    2117             p++;
    2118           in_arg = 1;
    2119 
    2120           DB (DB_JOBS, (_("BUILTIN RM %s\n"), p));
    2121           while (*p)
    2122             {
    2123               switch (*p)
    2124                 {
    2125                   case ' ':
    2126                   case '\t':
    2127                     if (in_arg)
    2128                       {
    2129                         *p++ = ';';
    2130                         in_arg = 0;
    2131                       }
    2132                     break;
    2133                   default:
    2134                     break;
    2135                 }
    2136               p++;
    2137             }
    2138         }
    2139       else
    2140         {
    2141           printf(_("Unknown builtin command '%s'\n"), cmd);
    2142           fflush(stdout);
    2143           return 0;
    2144         }
    2145     }
    2146 
    2147   /* Create a *.com file if either the command is too long for
    2148      lib$spawn, or the command contains a newline, or if redirection
    2149      is desired. Forcing commands with newlines into DCLs allows to
    2150      store search lists on user mode logicals.  */
    2151 
    2152   if (strlen (cmd) > MAXCMDLEN
    2153       || (have_redirection != 0)
    2154       || (have_newline != 0))
    2155     {
    2156       FILE *outfile;
    2157       char c;
    2158       char *sep;
    2159       int alevel = 0;   /* apostrophe level */
    2160 
    2161       if (strlen (cmd) == 0)
    2162         {
    2163           printf (_("Error, empty command\n"));
    2164           fflush (stdout);
    2165           return 0;
    2166         }
    2167 
    2168       outfile = open_tmpfile (&comname, "sys$scratch:CMDXXXXXX.COM");
    2169       if (outfile == 0)
    2170         pfatal_with_name (_("fopen (temporary file)"));
    2171 
    2172       if (ifile[0])
    2173         {
    2174           fprintf (outfile, "$ assign/user %s sys$input\n", ifile);
    2175           DB (DB_JOBS, (_("Redirected input from %s\n"), ifile));
    2176           ifiledsc.dsc$w_length = 0;
    2177         }
    2178 
    2179       if (efile[0])
    2180         {
    2181           fprintf (outfile, "$ define sys$error %s\n", efile);
    2182           DB (DB_JOBS, (_("Redirected error to %s\n"), efile));
    2183           efiledsc.dsc$w_length = 0;
    2184         }
    2185 
    2186       if (ofile[0])
    2187         {
    2188           fprintf (outfile, "$ define sys$output %s\n", ofile);
    2189           DB (DB_JOBS, (_("Redirected output to %s\n"), ofile));
    2190           ofiledsc.dsc$w_length = 0;
    2191         }
    2192 
    2193       p = sep = q = cmd;
    2194       for (c = '\n'; c; c = *q++)
    2195         {
    2196           switch (c)
    2197             {
    2198             case '\n':
    2199               /* At a newline, skip any whitespace around a leading $
    2200                  from the command and issue exactly one $ into the DCL. */
    2201               while (isspace ((unsigned char)*p))
    2202                 p++;
    2203               if (*p == '$')
    2204                 p++;
    2205               while (isspace ((unsigned char)*p))
    2206                 p++;
    2207               fwrite (p, 1, q - p, outfile);
    2208               fputc ('$', outfile);
    2209               fputc (' ', outfile);
    2210               /* Reset variables. */
    2211               p = sep = q;
    2212               break;
    2213 
    2214               /* Nice places for line breaks are after strings, after
    2215                  comma or space and before slash. */
    2216             case '"':
    2217               q = vms_handle_apos (q);
    2218               sep = q;
    2219               break;
    2220             case ',':
    2221             case ' ':
    2222               sep = q;
    2223               break;
    2224             case '/':
    2225             case '\0':
    2226               sep = q - 1;
    2227               break;
    2228             default:
    2229               break;
    2230             }
    2231           if (sep - p > 78)
    2232             {
    2233               /* Enough stuff for a line. */
    2234               fwrite (p, 1, sep - p, outfile);
    2235               p = sep;
    2236               if (*sep)
    2237                 {
    2238                   /* The command continues.  */
    2239                   fputc ('-', outfile);
    2240                 }
    2241               fputc ('\n', outfile);
    2242             }
    2243         }
    2244 
    2245       fwrite (p, 1, q - p, outfile);
    2246       fputc ('\n', outfile);
    2247 
    2248       fclose (outfile);
    2249 
    2250       sprintf (cmd, "$ @%s", comname);
    2251 
    2252       DB (DB_JOBS, (_("Executing %s instead\n"), cmd));
    2253     }
    2254 
    2255   cmddsc.dsc$w_length = strlen(cmd);
    2256   cmddsc.dsc$a_pointer = cmd;
    2257   cmddsc.dsc$b_dtype = DSC$K_DTYPE_T;
    2258   cmddsc.dsc$b_class = DSC$K_CLASS_S;
    2259 
    2260   child->efn = 0;
    2261   while (child->efn < 32 || child->efn > 63)
    2262     {
    2263       status = lib$get_ef ((unsigned long *)&child->efn);
    2264       if (!(status & 1))
    2265         return 0;
    2266     }
    2267 
    2268   sys$clref (child->efn);
    2269 
    2270   vms_jobsefnmask |= (1 << (child->efn - 32));
    2271 
    2272 /*
    2273              LIB$SPAWN  [command-string]
    2274                         [,input-file]
    2275                         [,output-file]
    2276                         [,flags]
    2277                         [,process-name]
    2278                         [,process-id] [,completion-status-address] [,byte-integer-event-flag-num]
    2279                         [,AST-address] [,varying-AST-argument]
    2280                         [,prompt-string] [,cli] [,table]
    2281 */
    2282 
    2283 #ifndef DONTWAITFORCHILD
    2284 /*
    2285  *      Code to make ctrl+c and ctrl+y working.
    2286  *      The problem starts with the synchronous case where after lib$spawn is
    2287  *      called any input will go to the child. But with input re-directed,
    2288  *      both control characters won't make it to any of the programs, neither
    2289  *      the spawning nor to the spawned one. Hence the caller needs to spawn
    2290  *      with CLI$M_NOWAIT to NOT give up the input focus. A sys$waitfr
    2291  *      has to follow to simulate the wanted synchronous behaviour.
    2292  *      The next problem is ctrl+y which isn't caught by the crtl and
    2293  *      therefore isn't converted to SIGQUIT (for a signal handler which is
    2294  *      already established). The only way to catch ctrl+y, is an AST
    2295  *      assigned to the input channel. But ctrl+y handling of DCL needs to be
    2296  *      disabled, otherwise it will handle it. Not to mention the previous
    2297  *      ctrl+y handling of DCL needs to be re-established before make exits.
    2298  *      One more: At the time of LIB$SPAWN signals are blocked. SIGQUIT will
    2299  *      make it to the signal handler after the child "normally" terminates.
    2300  *      This isn't enough. It seems reasonable for simple command lines like
    2301  *      a 'cc foobar.c' spawned in a subprocess but it is unacceptable for
    2302  *      spawning make. Therefore we need to abort the process in the AST.
    2303  *
    2304  *      Prior to the spawn it is checked if an AST is already set up for
    2305  *      ctrl+y, if not one is set up for a channel to SYS$COMMAND. In general
    2306  *      this will work except if make is run in a batch environment, but there
    2307  *      nobody can press ctrl+y. During the setup the DCL handling of ctrl+y
    2308  *      is disabled and an exit handler is established to re-enable it.
    2309  *      If the user interrupts with ctrl+y, the assigned AST will fire, force
    2310  *      an abort to the subprocess and signal SIGQUIT, which will be caught by
    2311  *      the already established handler and will bring us back to common code.
    2312  *      After the spawn (now /nowait) a sys$waitfr simulates the /wait and
    2313  *      enables the ctrl+y be delivered to this code. And the ctrl+c too,
    2314  *      which the crtl converts to SIGINT and which is caught by the common
    2315  *      signal handler. Because signals were blocked before entering this code
    2316  *      sys$waitfr will always complete and the SIGQUIT will be processed after
    2317  *      it (after termination of the current block, somewhere in common code).
    2318  *      And SIGINT too will be delayed. That is ctrl+c can only abort when the
    2319  *      current command completes. Anyway it's better than nothing :-)
    2320  */
    2321 
    2322   if (!setupYAstTried)
    2323     tryToSetupYAst();
    2324   status = lib$spawn (&cmddsc,                                  /* cmd-string  */
    2325                       (ifiledsc.dsc$w_length == 0)?0:&ifiledsc, /* input-file  */
    2326                       (ofiledsc.dsc$w_length == 0)?0:&ofiledsc, /* output-file */
    2327                       &spflags,                                 /* flags  */
    2328                       &pnamedsc,                                /* proc name  */
    2329                       &child->pid, &child->cstatus, &child->efn,
    2330                       0, 0,
    2331                       0, 0, 0);
    2332   if (status & 1)
    2333     {
    2334       pidToAbort= child->pid;
    2335       status= sys$waitfr (child->efn);
    2336       pidToAbort= 0;
    2337       vmsHandleChildTerm(child);
    2338     }
    2339 #else
    2340   status = lib$spawn (&cmddsc,
    2341                       (ifiledsc.dsc$w_length == 0)?0:&ifiledsc,
    2342                       (ofiledsc.dsc$w_length == 0)?0:&ofiledsc,
    2343                       &spflags,
    2344                       &pnamedsc,
    2345                       &child->pid, &child->cstatus, &child->efn,
    2346                       vmsHandleChildTerm, child,
    2347                       0, 0, 0);
    2348 #endif
    2349 
    2350   if (!(status & 1))
    2351     {
    2352       printf (_("Error spawning, %d\n") ,status);
    2353       fflush (stdout);
    2354       switch (status)
    2355         {
    2356         case 0x1c:
    2357           errno = EPROCLIM;
    2358           break;
    2359         default:
    2360           errno = EFAIL;
    2361         }
    2362     }
    2363 
    2364   if (comname && !ISDB (DB_JOBS))
    2365     unlink (comname);
    2366 
    2367   return (status & 1);
    2368 }
    2369 
    2370 #else /* !VMS */
    23711850
    23721851/* EMX: Start a child process. This function returns the new pid.  */
    2373 # if defined __MSDOS__ ||  defined __EMX__
     1852# if defined __MSDOS__ || defined __EMX__
    23741853int
    23751854child_execute_job (int stdin_fd, int stdout_fd, char **argv, char **envp)
     
    24091888  pid = exec_command (argv, envp);
    24101889
    2411   /* Restore stdout/stdin of the parent process.  */
    2412   if (stdin_fd != 0 && dup2 (save_stdin, 0) != 0)
    2413     fatal (NILF, _("restoring of stdin failed\n"));
    2414   if (stdout_fd != 1 && dup2 (save_stdout, 1) != 1)
    2415     fatal (NILF, _("restoring of stdout failed\n"));
     1890  /* Restore stdout/stdin of the parent and close temporary FDs.  */
     1891  if (stdin_fd != 0)
     1892    {
     1893      if (dup2 (save_stdin, 0) != 0)
     1894        fatal (NILF, _("Could not restore stdin\n"));
     1895      else
     1896        close (save_stdin);
     1897    }
     1898
     1899  if (stdout_fd != 1)
     1900    {
     1901      if (dup2 (save_stdout, 1) != 1)
     1902        fatal (NILF, _("Could not restore stdout\n"));
     1903      else
     1904        close (save_stdout);
     1905    }
    24161906
    24171907  return pid;
     
    24401930}
    24411931#endif /* !AMIGA && !__MSDOS__ */
    2442 #endif /* !VMS */
    24431932#endif /* !WINDOWS32 */
    24441933
     
    24521941int
    24531942# else
    2454  void
     1943void
    24551944# endif
    24561945exec_command (char **argv, char **envp)
     
    24921981
    24931982  /* wait and reap last child */
    2494   while (hWaitPID = process_wait_for_any())
     1983  hWaitPID = process_wait_for_any();
     1984  while (hWaitPID)
    24951985    {
    24961986      /* was an error found on this process? */
     
    25602050        char **new_argv;
    25612051        int argc;
     2052        int i=1;
    25622053
    25632054# ifdef __EMX__
     
    25782069          ++argc;
    25792070
     2071# ifdef __EMX__
     2072        if (!unixy_shell)
     2073          ++argc;
     2074# endif
     2075
    25802076        new_argv = (char **) alloca ((1 + argc + 1) * sizeof (char *));
    25812077        new_argv[0] = shell;
    2582         new_argv[1] = argv[0];
     2078
     2079# ifdef __EMX__
     2080        if (!unixy_shell)
     2081          {
     2082            new_argv[1] = "/c";
     2083            ++i;
     2084            --argc;
     2085          }
     2086# endif
     2087
     2088        new_argv[i] = argv[0];
    25832089        while (argc > 0)
    25842090          {
    2585             new_argv[1 + argc] = argv[argc];
     2091            new_argv[i + argc] = argv[argc];
    25862092            --argc;
    25872093          }
     
    27512257  char*  sh_chars;
    27522258  char** sh_cmds;
     2259#elif defined(__riscos__)
     2260  static char sh_chars[] = "";
     2261  static char *sh_cmds[] = { 0 };
    27532262#else  /* must be UNIX-ish */
    27542263  static char sh_chars[] = "#;\"*?[]&|<>(){}$`^~!";
     
    30212530                register int j;
    30222531                for (j = 0; sh_cmds[j] != 0; ++j)
    3023                   if (streq (sh_cmds[j], new_argv[0]))
    3024                     goto slow;
     2532                  {
     2533                    if (streq (sh_cmds[j], new_argv[0]))
     2534                      goto slow;
     2535# ifdef __EMX__
     2536                    /* Non-Unix shells are case insensitive.  */
     2537                    if (!unixy_shell
     2538                        && strcasecmp (sh_cmds[j], new_argv[0]) == 0)
     2539                      goto slow;
     2540# endif
     2541                  }
    30252542              }
    30262543
     
    30602577    /* Line was empty.  */
    30612578    return 0;
    3062   else
    3063     return new_argv;
     2579
     2580  return new_argv;
    30642581
    30652582 slow:;
     
    32102727      int id = GetCurrentProcessId();
    32112728      PATH_VAR(fbuf);
    3212       char* fname = NULL;
    32132729
    32142730      /* create a file name */
    32152731      sprintf(fbuf, "make%d", id);
    3216       fname = tempnam(".", fbuf);
    3217 
    3218           /* create batch file name */
    3219       *batch_filename_ptr = xmalloc(strlen(fname) + 5);
    3220       strcpy(*batch_filename_ptr, fname);
    3221 
    3222       /* make sure path name is in DOS backslash format */
    3223       if (!unixy_shell) {
    3224         fname = *batch_filename_ptr;
    3225         for (i = 0; fname[i] != '\0'; ++i)
    3226           if (fname[i] == '/')
    3227             fname[i] = '\\';
    3228         strcat(*batch_filename_ptr, ".bat");
    3229       } else {
    3230         strcat(*batch_filename_ptr, ".sh");
    3231       }
     2732      *batch_filename_ptr = create_batch_filename (fbuf, unixy_shell);
    32322733
    32332734      DB (DB_JOBS, (_("Creating temporary batch file %s\n"),
     
    32582759                                                  (char *) 0, (char *) 0,
    32592760                                                  (char **) 0);
    3260 # ifdef __EMX__
     2761#ifdef __EMX__
    32612762    else if (!unixy_shell)
    32622763      {
    3263         /* new_line is local, must not be freed therefore */
    3264         char *p, *q;
    3265         int quote;
    3266         size_t index;
    3267         size_t len;
    3268 
    3269         /* handle quotes
    3270            We have to remove all double quotes and to split the line
    3271            into distinct arguments because of the strange handling
    3272            of builtin commands by cmd: 'echo "bla"' prints "bla"
    3273            (with quotes) while 'c:\bin\echo.exe "bla"' prints bla
    3274            (without quotes). Some programs like autoconf rely
    3275            on the second behaviour. */
    3276 
    3277         len = strlen (new_line) + 1;
    3278 
    3279         /* More than 1 arg per character is impossible.  */
    3280         new_argv = (char **) xmalloc (len * sizeof (char *));
    3281 
    3282         /* All the args can fit in a buffer as big as new_line is.   */
    3283         new_argv[0] = (char *) xmalloc (len);
    3284 
    3285         index = 0;
    3286         quote = 0;
    3287         q = new_line;
    3288         p = new_argv[index];
    3289         while(*q != '\0')
    3290           {
    3291             /* searching for closing quote */
    3292             if (quote)
    3293               {
    3294                 if (*q == quote)
    3295                   {
    3296                     /* remove the quote */
    3297                     q++;
    3298                     quote = 0;
    3299                   }
    3300                 else /* normal character: copy it */
    3301                   *p++ = *q++;
    3302               }
    3303 
    3304             /* searching for opening quote */
    3305             else if (*q == '\"'
    3306 #  ifndef NO_CMD_DEFAULT
    3307                      || *q == '\''
    3308 #  endif
    3309                      )
    3310               {
    3311                 /* remove opening quote */
    3312                 quote = *q;
    3313                 q++;
    3314               }
    3315 
    3316             /* spaces outside of a quoted string: remove them
    3317                and start a new argument */
    3318             else if (*q == ' ' || *q == '\t')
    3319               {
    3320                 *p++ = '\0'; /* trailing '\0' for last argument */
    3321 
    3322                 /* remove all successive spaces */
    3323                 do
    3324                   {
    3325                     q++;
    3326                   }
    3327                 while(*q == ' ' || *q == '\t');
    3328 
    3329                 /* start new argument */
    3330                 index++;
    3331                 new_argv[index] = p;
    3332               }
    3333 
    3334             /* normal character (no space) outside a quoted string*/
    3335             else
    3336               *p++ = *q++;
    3337           } /* end while() */
    3338 
    3339         *p = '\0'; /* trailing '\0' for the last argument */
    3340         new_argv[index + 1] = NULL;
    3341 
    3342 #  ifndef NO_CMD_DEFAULT
    3343         /* special case: echo x="y"
    3344            (e.g. autoconf uses this to determine whether make works)
    3345            this is pure idioty but cmd works this way:
    3346            if 'echo' and 'x="y"' are two different arguments cmd
    3347            will print '"x="y""' but if they are only one argument
    3348            cmd will print 'bla="blurb"' as it should be
    3349            note: if we do not allow cmd to be the default shell
    3350            we do not need this kind of voodoo */
    3351         if (index == 3 && strcasecmp(new_argv[2], "echo") == 0)
    3352           {
    3353             new_argv[2][4] = ' ';
    3354             new_argv[3] = NULL;
    3355           }
    3356 #  endif
     2764        /* new_line is local, must not be freed therefore
     2765           We use line here instead of new_line because we run the shell
     2766           manually.  */
     2767        size_t line_len = strlen (line);
     2768        char *p = new_line;
     2769        char *q = new_line;
     2770        memcpy (new_line, line, line_len + 1);
     2771        /* replace all backslash-newline combination and also following tabs */
     2772        while (*q != '\0')
     2773          {
     2774            if (q[0] == '\\' && q[1] == '\n')
     2775              {
     2776                q += 2; /* remove '\\' and '\n' */
     2777                if (q[0] == '\t')
     2778                  q++; /* remove 1st tab in the next line */
     2779              }
     2780            else
     2781              *p++ = *q++;
     2782          }
     2783        *p = '\0';
     2784
     2785# ifndef NO_CMD_DEFAULT
     2786        if (strnicmp (new_line, "echo", 4) == 0
     2787            && (new_line[4] == ' ' || new_line[4] == '\t'))
     2788          {
     2789            /* the builtin echo command: handle it separately */
     2790            size_t echo_len = line_len - 5;
     2791            char *echo_line = new_line + 5;
     2792
     2793            /* special case: echo 'x="y"'
     2794               cmd works this way: a string is printed as is, i.e., no quotes
     2795               are removed. But autoconf uses a command like echo 'x="y"' to
     2796               determine whether make works. autoconf expects the output x="y"
     2797               so we will do exactly that.
     2798               Note: if we do not allow cmd to be the default shell
     2799               we do not need this kind of voodoo */
     2800            if (echo_line[0] == '\''
     2801                && echo_line[echo_len - 1] == '\''
     2802                && strncmp (echo_line + 1, "ac_maketemp=",
     2803                            strlen ("ac_maketemp=")) == 0)
     2804              {
     2805                /* remove the enclosing quotes */
     2806                memmove (echo_line, echo_line + 1, echo_len - 2);
     2807                echo_line[echo_len - 2] = '\0';
     2808              }
     2809          }
     2810# endif
     2811
     2812        {
     2813          /* Let the shell decide what to do. Put the command line into the
     2814             2nd command line argument and hope for the best ;-)  */
     2815          size_t sh_len = strlen (shell);
     2816
     2817          /* exactly 3 arguments + NULL */
     2818          new_argv = (char **) xmalloc (4 * sizeof (char *));
     2819          /* Exactly strlen(shell) + strlen("/c") + strlen(line) + 3 times
     2820             the trailing '\0' */
     2821          new_argv[0] = (char *) malloc (sh_len + line_len + 5);
     2822          memcpy (new_argv[0], shell, sh_len + 1);
     2823          new_argv[1] = new_argv[0] + sh_len + 1;
     2824          memcpy (new_argv[1], "/c", 3);
     2825          new_argv[2] = new_argv[1] + 3;
     2826          memcpy (new_argv[2], new_line, line_len + 1);
     2827          new_argv[3] = NULL;
     2828        }
    33572829      }
    33582830#elif defined(__MSDOS__)
     
    35353007}
    35363008#endif /* !HAPE_DUP2 && !_AMIGA */
     3009
     3010/* On VMS systems, include special VMS functions.  */
     3011
     3012#ifdef VMS
     3013#include "vmsjobs.c"
     3014#endif
Note: See TracChangeset for help on using the changeset viewer.