| 1 | /* |
| 2 | * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. |
| 3 | * Copyright (c) 1988, 1989 by Adam de Boor |
| 4 | * Copyright (c) 1989 by Berkeley Softworks |
| 5 | * All rights reserved. |
| 6 | * |
| 7 | * This code is derived from software contributed to Berkeley by |
| 8 | * Adam de Boor. |
| 9 | * |
| 10 | * Redistribution and use in source and binary forms, with or without |
| 11 | * modification, are permitted provided that the following conditions |
| 12 | * are met: |
| 13 | * 1. Redistributions of source code must retain the above copyright |
| 14 | * notice, this list of conditions and the following disclaimer. |
| 15 | * 2. Redistributions in binary form must reproduce the above copyright |
| 16 | * notice, this list of conditions and the following disclaimer in the |
| 17 | * documentation and/or other materials provided with the distribution. |
| 18 | * 3. All advertising materials mentioning features or use of this software |
| 19 | * must display the following acknowledgement: |
| 20 | * This product includes software developed by the University of |
| 21 | * California, Berkeley and its contributors. |
| 22 | * 4. Neither the name of the University nor the names of its contributors |
| 23 | * may be used to endorse or promote products derived from this software |
| 24 | * without specific prior written permission. |
| 25 | * |
| 26 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
| 27 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 28 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| 29 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
| 30 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| 31 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
| 32 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| 33 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| 34 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
| 35 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| 36 | * SUCH DAMAGE. |
| 37 | * |
| 38 | * @(#)job.h 5.3 (Berkeley) 6/1/90 |
| 39 | */ |
| 40 | |
| 41 | /*- |
| 42 | * job.h -- |
| 43 | * Definitions pertaining to the running of jobs in parallel mode. |
| 44 | * Exported from job.c for the use of remote-execution modules. |
| 45 | */ |
| 46 | #ifndef _JOB_H_ |
| 47 | #define _JOB_H_ |
| 48 | |
| 49 | #define TMPPAT "/tmp/makeXXXXX" |
| 50 | |
| 51 | /* |
| 52 | * The SEL_ constants determine the maximum amount of time spent in select |
| 53 | * before coming out to see if a child has finished. SEL_SEC is the number of |
| 54 | * seconds and SEL_USEC is the number of micro-seconds |
| 55 | */ |
| 56 | #define SEL_SEC 0 |
| 57 | #define SEL_USEC 500000 |
| 58 | |
| 59 | \f |
| 60 | /*- |
| 61 | * Job Table definitions. |
| 62 | * |
| 63 | * Each job has several things associated with it: |
| 64 | * 1) The process id of the child shell |
| 65 | * 2) The graph node describing the target being made by this job |
| 66 | * 3) A LstNode for the first command to be saved after the job |
| 67 | * completes. This is NILLNODE if there was no "..." in the job's |
| 68 | * commands. |
| 69 | * 4) An FILE* for writing out the commands. This is only |
| 70 | * used before the job is actually started. |
| 71 | * 5) A union of things used for handling the shell's output. Different |
| 72 | * parts of the union are used based on the value of the usePipes |
| 73 | * flag. If it is true, the output is being caught via a pipe and |
| 74 | * the descriptors of our pipe, an array in which output is line |
| 75 | * buffered and the current position in that buffer are all |
| 76 | * maintained for each job. If, on the other hand, usePipes is false, |
| 77 | * the output is routed to a temporary file and all that is kept |
| 78 | * is the name of the file and the descriptor open to the file. |
| 79 | * 6) An identifier provided by and for the exclusive use of the |
| 80 | * Rmt module. |
| 81 | * 7) A word of flags which determine how the module handles errors, |
| 82 | * echoing, etc. for the job |
| 83 | * |
| 84 | * The job "table" is kept as a linked Lst in 'jobs', with the number of |
| 85 | * active jobs maintained in the 'nJobs' variable. At no time will this |
| 86 | * exceed the value of 'maxJobs', initialized by the Job_Init function. |
| 87 | * |
| 88 | * When a job is finished, the Make_Update function is called on each of the |
| 89 | * parents of the node which was just remade. This takes care of the upward |
| 90 | * traversal of the dependency graph. |
| 91 | */ |
| 92 | #define JOB_BUFSIZE 1024 |
| 93 | typedef struct Job { |
| 94 | int pid; /* The child's process ID */ |
| 95 | GNode *node; /* The target the child is making */ |
| 96 | LstNode tailCmds; /* The node of the first command to be |
| 97 | * saved when the job has been run */ |
| 98 | FILE *cmdFILE; /* When creating the shell script, this is |
| 99 | * where the commands go */ |
| 100 | char *rmtID; /* ID returned from Rmt module */ |
| 101 | short flags; /* Flags to control treatment of job */ |
| 102 | #define JOB_IGNERR 0x001 /* Ignore non-zero exits */ |
| 103 | #define JOB_SILENT 0x002 /* no output */ |
| 104 | #define JOB_SPECIAL 0x004 /* Target is a special one. i.e. run it locally |
| 105 | * if we can't export it and maxLocal is 0 */ |
| 106 | #define JOB_IGNDOTS 0x008 /* Ignore "..." lines when processing |
| 107 | * commands */ |
| 108 | #define JOB_REMOTE 0x010 /* Job is running remotely */ |
| 109 | #define JOB_FIRST 0x020 /* Job is first job for the node */ |
| 110 | #define JOB_REMIGRATE 0x040 /* Job needs to be remigrated */ |
| 111 | #define JOB_RESTART 0x080 /* Job needs to be completely restarted */ |
| 112 | #define JOB_RESUME 0x100 /* Job needs to be resumed b/c it stopped, |
| 113 | * for some reason */ |
| 114 | #define JOB_CONTINUING 0x200 /* We are in the process of resuming this job. |
| 115 | * Used to avoid infinite recursion between |
| 116 | * JobFinish and JobRestart */ |
| 117 | union { |
| 118 | struct { |
| 119 | int op_inPipe; /* Input side of pipe associated |
| 120 | * with job's output channel */ |
| 121 | int op_outPipe; /* Output side of pipe associated with |
| 122 | * job's output channel */ |
| 123 | char op_outBuf[JOB_BUFSIZE + 1]; |
| 124 | /* Buffer for storing the output of the |
| 125 | * job, line by line */ |
| 126 | int op_curPos; /* Current position in op_outBuf */ |
| 127 | } o_pipe; /* data used when catching the output via |
| 128 | * a pipe */ |
| 129 | struct { |
| 130 | char of_outFile[sizeof(TMPPAT)+2]; |
| 131 | /* Name of file to which shell output |
| 132 | * was rerouted */ |
| 133 | int of_outFd; /* Stream open to the output |
| 134 | * file. Used to funnel all |
| 135 | * from a single job to one file |
| 136 | * while still allowing |
| 137 | * multiple shell invocations */ |
| 138 | } o_file; /* Data used when catching the output in |
| 139 | * a temporary file */ |
| 140 | } output; /* Data for tracking a shell's output */ |
| 141 | } Job; |
| 142 | |
| 143 | #define outPipe output.o_pipe.op_outPipe |
| 144 | #define inPipe output.o_pipe.op_inPipe |
| 145 | #define outBuf output.o_pipe.op_outBuf |
| 146 | #define curPos output.o_pipe.op_curPos |
| 147 | #define outFile output.o_file.of_outFile |
| 148 | #define outFd output.o_file.of_outFd |
| 149 | |
| 150 | \f |
| 151 | /*- |
| 152 | * Shell Specifications: |
| 153 | * Each shell type has associated with it the following information: |
| 154 | * 1) The string which must match the last character of the shell name |
| 155 | * for the shell to be considered of this type. The longest match |
| 156 | * wins. |
| 157 | * 2) A command to issue to turn off echoing of command lines |
| 158 | * 3) A command to issue to turn echoing back on again |
| 159 | * 4) What the shell prints, and its length, when given the echo-off |
| 160 | * command. This line will not be printed when received from the shell |
| 161 | * 5) A boolean to tell if the shell has the ability to control |
| 162 | * error checking for individual commands. |
| 163 | * 6) The string to turn this checking on. |
| 164 | * 7) The string to turn it off. |
| 165 | * 8) The command-flag to give to cause the shell to start echoing |
| 166 | * commands right away. |
| 167 | * 9) The command-flag to cause the shell to Lib_Exit when an error is |
| 168 | * detected in one of the commands. |
| 169 | * |
| 170 | * Some special stuff goes on if a shell doesn't have error control. In such |
| 171 | * a case, errCheck becomes a printf template for echoing the command, |
| 172 | * should echoing be on and ignErr becomes another printf template for |
| 173 | * executing the command while ignoring the return status. If either of these |
| 174 | * strings is empty when hasErrCtl is FALSE, the command will be executed |
| 175 | * anyway as is and if it causes an error, so be it. |
| 176 | */ |
| 177 | typedef struct Shell { |
| 178 | char *name; /* the name of the shell. For Bourne and C |
| 179 | * shells, this is used only to find the |
| 180 | * shell description when used as the single |
| 181 | * source of a .SHELL target. For user-defined |
| 182 | * shells, this is the full path of the shell. |
| 183 | */ |
| 184 | Boolean hasEchoCtl; /* True if both echoOff and echoOn defined */ |
| 185 | char *echoOff; /* command to turn off echo */ |
| 186 | char *echoOn; /* command to turn it back on again */ |
| 187 | char *noPrint; /* command to skip when printing output from |
| 188 | * shell. This is usually the command which |
| 189 | * was executed to turn off echoing */ |
| 190 | int noPLen; /* length of noPrint command */ |
| 191 | Boolean hasErrCtl; /* set if can control error checking for |
| 192 | * individual commands */ |
| 193 | char *errCheck; /* string to turn error checking on */ |
| 194 | char *ignErr; /* string to turn off error checking */ |
| 195 | /* |
| 196 | * command-line flags |
| 197 | */ |
| 198 | char *echo; /* echo commands */ |
| 199 | char *exit; /* exit on error */ |
| 200 | } Shell; |
| 201 | |
| 202 | |
| 203 | extern char *targFmt; /* Format string for banner that separates |
| 204 | * output from multiple jobs. Contains a |
| 205 | * single %s where the name of the node being |
| 206 | * made should be put. */ |
| 207 | extern GNode *lastNode; /* Last node for which a banner was printed. |
| 208 | * If Rmt module finds it necessary to print |
| 209 | * a banner, it should set this to the node |
| 210 | * for which the banner was printed */ |
| 211 | extern int nJobs; /* Number of jobs running (local and remote) */ |
| 212 | extern int nLocal; /* Number of jobs running locally */ |
| 213 | extern Lst jobs; /* List of active job descriptors */ |
| 214 | extern Lst stoppedJobs; /* List of jobs that are stopped or didn't |
| 215 | * quite get started */ |
| 216 | extern Boolean jobFull; /* Non-zero if no more jobs should/will start*/ |
| 217 | |
| 218 | /* |
| 219 | * These functions should be used only by an intelligent Rmt module, hence |
| 220 | * their names do *not* include an underscore as they are not fully exported, |
| 221 | * if you see what I mean. |
| 222 | */ |
| 223 | extern void JobDoOutput(/* job, final? */); /* Funnel output from |
| 224 | * job->outPipe to the screen, |
| 225 | * filtering out echo-off |
| 226 | * strings etc. */ |
| 227 | extern void JobFinish(/* job, status */); /* Finish out a job. If |
| 228 | * status indicates job has |
| 229 | * just stopped, not finished, |
| 230 | * the descriptor is placed on |
| 231 | * the stoppedJobs list. */ |
| 232 | #endif /* _JOB_H_ */ |