1a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner/* --------------- Moved here from job.c ---------------
2a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner   This file must be #included in job.c, as it accesses static functions.
3a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
4a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' TurnerCopyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
5a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner2006 Free Software Foundation, Inc.
6a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' TurnerThis file is part of GNU Make.
7a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
8a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' TurnerGNU Make is free software; you can redistribute it and/or modify it under the
9a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turnerterms of the GNU General Public License as published by the Free Software
10a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' TurnerFoundation; either version 2, or (at your option) any later version.
11a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
12a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' TurnerGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
13a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' TurnerWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' TurnerA PARTICULAR PURPOSE.  See the GNU General Public License for more details.
15a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
16a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' TurnerYou should have received a copy of the GNU General Public License along with
17a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' TurnerGNU Make; see the file COPYING.  If not, write to the Free Software
18a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' TurnerFoundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
19a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
20a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner#include <string.h>
21a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner#include <descrip.h>
22a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner#include <clidef.h>
23a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
24a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turnerextern char *vmsify PARAMS ((char *name, int type));
25a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
26a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turnerstatic int vms_jobsefnmask = 0;
27a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
28a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner/* Wait for nchildren children to terminate */
29a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turnerstatic void
30a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' TurnervmsWaitForChildren(int *status)
31a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner{
32a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  while (1)
33a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner    {
34a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner      if (!vms_jobsefnmask)
35a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	{
36a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	  *status = 0;
37a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	  return;
38a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	}
39a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
40a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner      *status = sys$wflor (32, vms_jobsefnmask);
41a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner    }
42a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  return;
43a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner}
44a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
45a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner/* Set up IO redirection.  */
46a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
47a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turnerchar *
48a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turnervms_redirect (struct dsc$descriptor_s *desc, char *fname, char *ibuf)
49a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner{
50a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  char *fptr;
51a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
52a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  ibuf++;
53a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  while (isspace ((unsigned char)*ibuf))
54a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner    ibuf++;
55a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  fptr = ibuf;
56a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  while (*ibuf && !isspace ((unsigned char)*ibuf))
57a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner    ibuf++;
58a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  *ibuf = 0;
59a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  if (strcmp (fptr, "/dev/null") != 0)
60a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner    {
61a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner      strcpy (fname, vmsify (fptr, 0));
62a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner      if (strchr (fname, '.') == 0)
63a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	strcat (fname, ".");
64a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner    }
65a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  desc->dsc$w_length = strlen(fname);
66a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  desc->dsc$a_pointer = fname;
67a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  desc->dsc$b_dtype = DSC$K_DTYPE_T;
68a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  desc->dsc$b_class = DSC$K_CLASS_S;
69a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
70a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  if (*fname == 0)
71a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner    printf (_("Warning: Empty redirection\n"));
72a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  return ibuf;
73a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner}
74a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
75a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
76a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner/* found apostrophe at (p-1)
77a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner   inc p until after closing apostrophe.
78a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner */
79a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
80a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turnerchar *
81a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turnervms_handle_apos (char *p)
82a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner{
83a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  int alast;
84a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
85a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner#define SEPCHARS ",/()= "
86a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
87a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  alast = 0;
88a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
89a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  while (*p != 0)
90a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner    {
91a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner      if (*p == '"')
92a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	{
93a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner          if (alast)
94a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner            {
95a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner              alast = 0;
96a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner              p++;
97a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	    }
98a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	  else
99a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	    {
100a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	      p++;
101a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	      if (strchr (SEPCHARS, *p))
102a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner		break;
103a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	      alast = 1;
104a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	    }
105a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	}
106a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner      else
107a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	p++;
108a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner    }
109a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
110a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  return p;
111a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner}
112a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
113a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner/* This is called as an AST when a child process dies (it won't get
114a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner   interrupted by anything except a higher level AST).
115a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner*/
116a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turnerint
117a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' TurnervmsHandleChildTerm(struct child *child)
118a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner{
119a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner    int status;
120a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner    register struct child *lastc, *c;
121a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner    int child_failed;
122a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
123a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner    vms_jobsefnmask &= ~(1 << (child->efn - 32));
124a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
125a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner    lib$free_ef(&child->efn);
126a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
127a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner    (void) sigblock (fatal_signal_mask);
128a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
129a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner    child_failed = !(child->cstatus & 1 || ((child->cstatus & 7) == 0));
130a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
131a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner    /* Search for a child matching the deceased one.  */
132a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner    lastc = 0;
133a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner#if defined(RECURSIVEJOBS) /* I've had problems with recursive stuff and process handling */
134a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner    for (c = children; c != 0 && c != child; lastc = c, c = c->next)
135a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner      ;
136a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner#else
137a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner    c = child;
138a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner#endif
139a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
140a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner    if (child_failed && !c->noerror && !ignore_errors_flag)
141a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner      {
142a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	/* The commands failed.  Write an error message,
143a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	   delete non-precious targets, and abort.  */
144a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	child_error (c->file->name, c->cstatus, 0, 0, 0);
145a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	c->file->update_status = 1;
146a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	delete_child_targets (c);
147a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner      }
148a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner    else
149a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner      {
150a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	if (child_failed)
151a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	  {
152a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	    /* The commands failed, but we don't care.  */
153a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	    child_error (c->file->name, c->cstatus, 0, 0, 1);
154a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	    child_failed = 0;
155a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	  }
156a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
157a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner#if defined(RECURSIVEJOBS) /* I've had problems with recursive stuff and process handling */
158a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	/* If there are more commands to run, try to start them.  */
159a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	start_job (c);
160a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
161a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	switch (c->file->command_state)
162a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	  {
163a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	  case cs_running:
164a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	    /* Successfully started.  */
165a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	    break;
166a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
167a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	  case cs_finished:
168a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	    if (c->file->update_status != 0) {
169a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner		/* We failed to start the commands.  */
170a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner		delete_child_targets (c);
171a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	    }
172a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	    break;
173a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
174a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	  default:
175a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	    error (NILF, _("internal error: `%s' command_state"),
176a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner                   c->file->name);
177a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	    abort ();
178a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	    break;
179a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	  }
180a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner#endif /* RECURSIVEJOBS */
181a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner      }
182a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
183a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner    /* Set the state flag to say the commands have finished.  */
184a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner    c->file->command_state = cs_finished;
185a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner    notice_finished_file (c->file);
186a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
187a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner#if defined(RECURSIVEJOBS) /* I've had problems with recursive stuff and process handling */
188a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner    /* Remove the child from the chain and free it.  */
189a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner    if (lastc == 0)
190a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner      children = c->next;
191a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner    else
192a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner      lastc->next = c->next;
193a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner    free_child (c);
194a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner#endif /* RECURSIVEJOBS */
195a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
196a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner    /* There is now another slot open.  */
197a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner    if (job_slots_used > 0)
198a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner      --job_slots_used;
199a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
200a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner    /* If the job failed, and the -k flag was not given, die.  */
201a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner    if (child_failed && !keep_going_flag)
202a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner      die (EXIT_FAILURE);
203a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
204a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner    (void) sigsetmask (sigblock (0) & ~(fatal_signal_mask));
205a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
206a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner    return 1;
207a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner}
208a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
209a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner/* VMS:
210a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner   Spawn a process executing the command in ARGV and return its pid. */
211a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
212a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner#define MAXCMDLEN 200
213a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
214a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner/* local helpers to make ctrl+c and ctrl+y working, see below */
215a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner#include <iodef.h>
216a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner#include <libclidef.h>
217a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner#include <ssdef.h>
218a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
219a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turnerstatic int ctrlMask= LIB$M_CLI_CTRLY;
220a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turnerstatic int oldCtrlMask;
221a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turnerstatic int setupYAstTried= 0;
222a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turnerstatic int pidToAbort= 0;
223a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turnerstatic int chan= 0;
224a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
225a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turnerstatic void
226a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' TurnerreEnableAst(void)
227a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner{
228a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	lib$enable_ctrl (&oldCtrlMask,0);
229a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner}
230a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
231a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turnerstatic void
232a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' TurnerastHandler (void)
233a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner{
234a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	if (pidToAbort) {
235a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner		sys$forcex (&pidToAbort, 0, SS$_ABORT);
236a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner		pidToAbort= 0;
237a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	}
238a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	kill (getpid(),SIGQUIT);
239a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner}
240a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
241a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turnerstatic void
242a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' TurnertryToSetupYAst(void)
243a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner{
244a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	$DESCRIPTOR(inputDsc,"SYS$COMMAND");
245a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	int	status;
246a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	struct {
247a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner		short int	status, count;
248a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner		int	dvi;
249a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	} iosb;
250a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
251a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	setupYAstTried++;
252a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
253a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	if (!chan) {
254a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner		status= sys$assign(&inputDsc,&chan,0,0);
255a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner		if (!(status&SS$_NORMAL)) {
256a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner			lib$signal(status);
257a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner			return;
258a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner		}
259a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	}
260a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	status= sys$qiow (0, chan, IO$_SETMODE|IO$M_CTRLYAST,&iosb,0,0,
261a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner		astHandler,0,0,0,0,0);
262a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	if (status==SS$_NORMAL)
263a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner		status= iosb.status;
264a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner        if (status==SS$_ILLIOFUNC || status==SS$_NOPRIV) {
265a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner		sys$dassgn(chan);
266a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner#ifdef	CTRLY_ENABLED_ANYWAY
267a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner		fprintf (stderr,
268a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner                         _("-warning, CTRL-Y will leave sub-process(es) around.\n"));
269a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner#else
270a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner		return;
271a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner#endif
272a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	}
273a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	else if (!(status&SS$_NORMAL)) {
274a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner		sys$dassgn(chan);
275a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner		lib$signal(status);
276a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner		return;
277a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	}
278a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
279a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	/* called from AST handler ? */
280a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	if (setupYAstTried>1)
281a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner		return;
282a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	if (atexit(reEnableAst))
283a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner		fprintf (stderr,
284a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner                         _("-warning, you may have to re-enable CTRL-Y handling from DCL.\n"));
285a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	status= lib$disable_ctrl (&ctrlMask, &oldCtrlMask);
286a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	if (!(status&SS$_NORMAL)) {
287a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner		lib$signal(status);
288a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner		return;
289a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	}
290a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner}
291a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
292a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turnerint
293a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turnerchild_execute_job (char *argv, struct child *child)
294a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner{
295a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  int i;
296a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  static struct dsc$descriptor_s cmddsc;
297a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  static struct dsc$descriptor_s pnamedsc;
298a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  static struct dsc$descriptor_s ifiledsc;
299a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  static struct dsc$descriptor_s ofiledsc;
300a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  static struct dsc$descriptor_s efiledsc;
301a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  int have_redirection = 0;
302a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  int have_newline = 0;
303a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
304a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  int spflags = CLI$M_NOWAIT;
305a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  int status;
306a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  char *cmd = alloca (strlen (argv) + 512), *p, *q;
307a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  char ifile[256], ofile[256], efile[256];
308a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  char *comname = 0;
309a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  char procname[100];
310a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  int in_string;
311a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
312a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  /* Parse IO redirection.  */
313a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
314a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  ifile[0] = 0;
315a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  ofile[0] = 0;
316a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  efile[0] = 0;
317a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
318a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  DB (DB_JOBS, ("child_execute_job (%s)\n", argv));
319a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
320a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  while (isspace ((unsigned char)*argv))
321a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner    argv++;
322a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
323a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  if (*argv == 0)
324a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner    return 0;
325a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
326a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  sprintf (procname, "GMAKE_%05x", getpid () & 0xfffff);
327a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  pnamedsc.dsc$w_length = strlen(procname);
328a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  pnamedsc.dsc$a_pointer = procname;
329a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  pnamedsc.dsc$b_dtype = DSC$K_DTYPE_T;
330a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  pnamedsc.dsc$b_class = DSC$K_CLASS_S;
331a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
332a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  in_string = 0;
333a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  /* Handle comments and redirection. */
334a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  for (p = argv, q = cmd; *p; p++, q++)
335a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner    {
336a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner      if (*p == '"')
337a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner        in_string = !in_string;
338a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner      if (in_string)
339a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner        {
340a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner          *q = *p;
341a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner          continue;
342a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner        }
343a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner      switch (*p)
344a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	{
345a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	  case '#':
346a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	    *p-- = 0;
347a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	    *q-- = 0;
348a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	    break;
349a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	  case '\\':
350a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	    p++;
351a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	    if (*p == '\n')
352a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	      p++;
353a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	    if (isspace ((unsigned char)*p))
354a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	      {
355a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner		do { p++; } while (isspace ((unsigned char)*p));
356a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner		p--;
357a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	      }
358a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	    *q = *p;
359a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	    break;
360a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	  case '<':
361a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	    p = vms_redirect (&ifiledsc, ifile, p);
362a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	    *q = ' ';
363a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	    have_redirection = 1;
364a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	    break;
365a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	  case '>':
366a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	    have_redirection = 1;
367a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	    if (*(p-1) == '2')
368a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	      {
369a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner		q--;
370a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner		if (strncmp (p, ">&1", 3) == 0)
371a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner		  {
372a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner		    p += 3;
373a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner		    strcpy (efile, "sys$output");
374a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner		    efiledsc.dsc$w_length = strlen(efile);
375a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner		    efiledsc.dsc$a_pointer = efile;
376a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner		    efiledsc.dsc$b_dtype = DSC$K_DTYPE_T;
377a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner		    efiledsc.dsc$b_class = DSC$K_CLASS_S;
378a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner		  }
379a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner		else
380a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner		  {
381a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner		    p = vms_redirect (&efiledsc, efile, p);
382a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner		  }
383a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	      }
384a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	    else
385a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	      {
386a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner		p = vms_redirect (&ofiledsc, ofile, p);
387a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	      }
388a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	    *q = ' ';
389a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	    break;
390a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	  case '\n':
391a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	    have_newline = 1;
392a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	  default:
393a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	    *q = *p;
394a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	    break;
395a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	}
396a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner    }
397a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  *q = *p;
398a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  while (isspace ((unsigned char)*--q))
399a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner    *q = '\0';
400a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
401a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  if (strncmp (cmd, "builtin_", 8) == 0)
402a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner    {
403a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner      child->pid = 270163;
404a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner      child->efn = 0;
405a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner      child->cstatus = 1;
406a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
407a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner      DB (DB_JOBS, (_("BUILTIN [%s][%s]\n"), cmd, cmd+8));
408a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
409a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner      p = cmd + 8;
410a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
411a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner      if ((*(p) == 'c')
412a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	  && (*(p+1) == 'd')
413a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	  && ((*(p+2) == ' ') || (*(p+2) == '\t')))
414a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	{
415a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	  p += 3;
416a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	  while ((*p == ' ') || (*p == '\t'))
417a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	    p++;
418a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	  DB (DB_JOBS, (_("BUILTIN CD %s\n"), p));
419a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	  if (chdir (p))
420a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	    return 0;
421a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	  else
422a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	    return 1;
423a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	}
424a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner      else if ((*(p) == 'r')
425a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	  && (*(p+1) == 'm')
426a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	  && ((*(p+2) == ' ') || (*(p+2) == '\t')))
427a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	{
428a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	  int in_arg;
429a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
430a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	  /* rm  */
431a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	  p += 3;
432a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	  while ((*p == ' ') || (*p == '\t'))
433a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	    p++;
434a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	  in_arg = 1;
435a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
436a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	  DB (DB_JOBS, (_("BUILTIN RM %s\n"), p));
437a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	  while (*p)
438a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	    {
439a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	      switch (*p)
440a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner		{
441a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner		  case ' ':
442a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner		  case '\t':
443a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner		    if (in_arg)
444a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner		      {
445a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner			*p++ = ';';
446a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner			in_arg = 0;
447a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner		      }
448a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner		    break;
449a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner		  default:
450a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner		    break;
451a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner		}
452a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	      p++;
453a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	    }
454a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	}
455a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner      else
456a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	{
457a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	  printf(_("Unknown builtin command '%s'\n"), cmd);
458a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	  fflush(stdout);
459a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	  return 0;
460a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	}
461a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner    }
462a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
463a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  /* Create a *.com file if either the command is too long for
464a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner     lib$spawn, or the command contains a newline, or if redirection
465a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner     is desired. Forcing commands with newlines into DCLs allows to
466a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner     store search lists on user mode logicals.  */
467a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
468a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  if (strlen (cmd) > MAXCMDLEN
469a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner      || (have_redirection != 0)
470a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner      || (have_newline != 0))
471a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner    {
472a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner      FILE *outfile;
473a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner      char c;
474a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner      char *sep;
475a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner      int alevel = 0;	/* apostrophe level */
476a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
477a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner      if (strlen (cmd) == 0)
478a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	{
479a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	  printf (_("Error, empty command\n"));
480a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	  fflush (stdout);
481a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	  return 0;
482a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	}
483a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
484a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner      outfile = open_tmpfile (&comname, "sys$scratch:CMDXXXXXX.COM");
485a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner      if (outfile == 0)
486a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	pfatal_with_name (_("fopen (temporary file)"));
487a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
488a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner      if (ifile[0])
489a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	{
490a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	  fprintf (outfile, "$ assign/user %s sys$input\n", ifile);
491a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner          DB (DB_JOBS, (_("Redirected input from %s\n"), ifile));
492a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	  ifiledsc.dsc$w_length = 0;
493a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	}
494a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
495a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner      if (efile[0])
496a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	{
497a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	  fprintf (outfile, "$ define sys$error %s\n", efile);
498a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner          DB (DB_JOBS, (_("Redirected error to %s\n"), efile));
499a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	  efiledsc.dsc$w_length = 0;
500a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	}
501a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
502a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner      if (ofile[0])
503a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	{
504a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	  fprintf (outfile, "$ define sys$output %s\n", ofile);
505a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	  DB (DB_JOBS, (_("Redirected output to %s\n"), ofile));
506a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	  ofiledsc.dsc$w_length = 0;
507a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	}
508a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
509a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner      p = sep = q = cmd;
510a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner      for (c = '\n'; c; c = *q++)
511a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	{
512a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	  switch (c)
513a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	    {
514a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner            case '\n':
515a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner              /* At a newline, skip any whitespace around a leading $
516a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner                 from the command and issue exactly one $ into the DCL. */
517a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner              while (isspace ((unsigned char)*p))
518a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner                p++;
519a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner              if (*p == '$')
520a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner                p++;
521a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner              while (isspace ((unsigned char)*p))
522a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner                p++;
523a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner              fwrite (p, 1, q - p, outfile);
524a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner              fputc ('$', outfile);
525a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner              fputc (' ', outfile);
526a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner              /* Reset variables. */
527a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner              p = sep = q;
528a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner              break;
529a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
530a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	      /* Nice places for line breaks are after strings, after
531a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner		 comma or space and before slash. */
532a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner            case '"':
533a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner              q = vms_handle_apos (q);
534a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner              sep = q;
535a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner              break;
536a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner            case ',':
537a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner            case ' ':
538a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner              sep = q;
539a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner              break;
540a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner            case '/':
541a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner            case '\0':
542a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner              sep = q - 1;
543a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner              break;
544a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner            default:
545a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner              break;
546a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	    }
547a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	  if (sep - p > 78)
548a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	    {
549a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	      /* Enough stuff for a line. */
550a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	      fwrite (p, 1, sep - p, outfile);
551a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	      p = sep;
552a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	      if (*sep)
553a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner		{
554a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner		  /* The command continues.  */
555a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner		  fputc ('-', outfile);
556a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner		}
557a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	      fputc ('\n', outfile);
558a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	    }
559a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  	}
560a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
561a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner      fwrite (p, 1, q - p, outfile);
562a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner      fputc ('\n', outfile);
563a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
564a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner      fclose (outfile);
565a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
566a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner      sprintf (cmd, "$ @%s", comname);
567a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
568a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner      DB (DB_JOBS, (_("Executing %s instead\n"), cmd));
569a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner    }
570a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
571a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  cmddsc.dsc$w_length = strlen(cmd);
572a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  cmddsc.dsc$a_pointer = cmd;
573a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  cmddsc.dsc$b_dtype = DSC$K_DTYPE_T;
574a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  cmddsc.dsc$b_class = DSC$K_CLASS_S;
575a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
576a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  child->efn = 0;
577a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  while (child->efn < 32 || child->efn > 63)
578a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner    {
579a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner      status = lib$get_ef ((unsigned long *)&child->efn);
580a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner      if (!(status & 1))
581a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner	return 0;
582a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner    }
583a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
584a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  sys$clref (child->efn);
585a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
586a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  vms_jobsefnmask |= (1 << (child->efn - 32));
587a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
588a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner/*
589a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner             LIB$SPAWN  [command-string]
590a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner			[,input-file]
591a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner			[,output-file]
592a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner			[,flags]
593a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner			[,process-name]
594a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner			[,process-id] [,completion-status-address] [,byte-integer-event-flag-num]
595a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner			[,AST-address] [,varying-AST-argument]
596a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner			[,prompt-string] [,cli] [,table]
597a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner*/
598a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
599a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner#ifndef DONTWAITFORCHILD
600a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner/*
601a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner *	Code to make ctrl+c and ctrl+y working.
602a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner *	The problem starts with the synchronous case where after lib$spawn is
603a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner *	called any input will go to the child. But with input re-directed,
604a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner *	both control characters won't make it to any of the programs, neither
605a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner *	the spawning nor to the spawned one. Hence the caller needs to spawn
606a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner *	with CLI$M_NOWAIT to NOT give up the input focus. A sys$waitfr
607a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner *	has to follow to simulate the wanted synchronous behaviour.
608a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner *	The next problem is ctrl+y which isn't caught by the crtl and
609a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner *	therefore isn't converted to SIGQUIT (for a signal handler which is
610a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner *	already established). The only way to catch ctrl+y, is an AST
611a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner *	assigned to the input channel. But ctrl+y handling of DCL needs to be
612a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner *	disabled, otherwise it will handle it. Not to mention the previous
613a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner *	ctrl+y handling of DCL needs to be re-established before make exits.
614a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner *	One more: At the time of LIB$SPAWN signals are blocked. SIGQUIT will
615a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner *	make it to the signal handler after the child "normally" terminates.
616a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner *	This isn't enough. It seems reasonable for simple command lines like
617a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner *	a 'cc foobar.c' spawned in a subprocess but it is unacceptable for
618a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner *	spawning make. Therefore we need to abort the process in the AST.
619a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner *
620a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner *	Prior to the spawn it is checked if an AST is already set up for
621a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner *	ctrl+y, if not one is set up for a channel to SYS$COMMAND. In general
622a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner *	this will work except if make is run in a batch environment, but there
623a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner *	nobody can press ctrl+y. During the setup the DCL handling of ctrl+y
624a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner *	is disabled and an exit handler is established to re-enable it.
625a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner *	If the user interrupts with ctrl+y, the assigned AST will fire, force
626a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner *	an abort to the subprocess and signal SIGQUIT, which will be caught by
627a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner *	the already established handler and will bring us back to common code.
628a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner *	After the spawn (now /nowait) a sys$waitfr simulates the /wait and
629a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner *	enables the ctrl+y be delivered to this code. And the ctrl+c too,
630a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner *	which the crtl converts to SIGINT and which is caught by the common
631a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner *	signal handler. Because signals were blocked before entering this code
632a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner *	sys$waitfr will always complete and the SIGQUIT will be processed after
633a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner *	it (after termination of the current block, somewhere in common code).
634a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner *	And SIGINT too will be delayed. That is ctrl+c can only abort when the
635a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner *	current command completes. Anyway it's better than nothing :-)
636a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner */
637a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
638a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  if (!setupYAstTried)
639a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner    tryToSetupYAst();
640a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  status = lib$spawn (&cmddsc,					/* cmd-string  */
641a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner		      (ifiledsc.dsc$w_length == 0)?0:&ifiledsc, /* input-file  */
642a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner		      (ofiledsc.dsc$w_length == 0)?0:&ofiledsc, /* output-file */
643a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner		      &spflags,					/* flags  */
644a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner		      &pnamedsc,				/* proc name  */
645a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner		      &child->pid, &child->cstatus, &child->efn,
646a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner		      0, 0,
647a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner		      0, 0, 0);
648a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  if (status & 1)
649a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner    {
650a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner      pidToAbort= child->pid;
651a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner      status= sys$waitfr (child->efn);
652a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner      pidToAbort= 0;
653a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner      vmsHandleChildTerm(child);
654a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner    }
655a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner#else
656a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  status = lib$spawn (&cmddsc,
657a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner		      (ifiledsc.dsc$w_length == 0)?0:&ifiledsc,
658a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner		      (ofiledsc.dsc$w_length == 0)?0:&ofiledsc,
659a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner		      &spflags,
660a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner		      &pnamedsc,
661a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner		      &child->pid, &child->cstatus, &child->efn,
662a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner		      vmsHandleChildTerm, child,
663a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner		      0, 0, 0);
664a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner#endif
665a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
666a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  if (!(status & 1))
667a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner    {
668a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner      printf (_("Error spawning, %d\n") ,status);
669a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner      fflush (stdout);
670a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner      switch (status)
671a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner        {
672a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner        case 0x1c:
673a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner          errno = EPROCLIM;
674a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner          break;
675a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner        default:
676a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner          errno = EFAIL;
677a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner        }
678a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner    }
679a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
680a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  if (comname && !ISDB (DB_JOBS))
681a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner    unlink (comname);
682a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner
683a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner  return (status & 1);
684a86d4c1bde70365cbbe874ad9ddb3f06916d2085David 'Digit' Turner}
685