1*7dd7cddfSDavid du Colombier /*
2*7dd7cddfSDavid du Colombier * shell buffered IO and formatted output
3*7dd7cddfSDavid du Colombier */
4*7dd7cddfSDavid du Colombier
5*7dd7cddfSDavid du Colombier #include <ctype.h>
6*7dd7cddfSDavid du Colombier #include "sh.h"
7*7dd7cddfSDavid du Colombier #include "ksh_stat.h"
8*7dd7cddfSDavid du Colombier
9*7dd7cddfSDavid du Colombier static int initio_done;
10*7dd7cddfSDavid du Colombier
11*7dd7cddfSDavid du Colombier /*
12*7dd7cddfSDavid du Colombier * formatted output functions
13*7dd7cddfSDavid du Colombier */
14*7dd7cddfSDavid du Colombier
15*7dd7cddfSDavid du Colombier
16*7dd7cddfSDavid du Colombier /* A shell error occured (eg, syntax error, etc.) */
17*7dd7cddfSDavid du Colombier void
18*7dd7cddfSDavid du Colombier #ifdef HAVE_PROTOTYPES
errorf(const char * fmt,...)19*7dd7cddfSDavid du Colombier errorf(const char *fmt, ...)
20*7dd7cddfSDavid du Colombier #else
21*7dd7cddfSDavid du Colombier errorf(fmt, va_alist)
22*7dd7cddfSDavid du Colombier const char *fmt;
23*7dd7cddfSDavid du Colombier va_dcl
24*7dd7cddfSDavid du Colombier #endif
25*7dd7cddfSDavid du Colombier {
26*7dd7cddfSDavid du Colombier va_list va;
27*7dd7cddfSDavid du Colombier
28*7dd7cddfSDavid du Colombier shl_stdout_ok = 0; /* debugging: note that stdout not valid */
29*7dd7cddfSDavid du Colombier exstat = 1;
30*7dd7cddfSDavid du Colombier if (*fmt) {
31*7dd7cddfSDavid du Colombier error_prefix(TRUE);
32*7dd7cddfSDavid du Colombier SH_VA_START(va, fmt);
33*7dd7cddfSDavid du Colombier shf_vfprintf(shl_out, fmt, va);
34*7dd7cddfSDavid du Colombier va_end(va);
35*7dd7cddfSDavid du Colombier shf_putchar('\n', shl_out);
36*7dd7cddfSDavid du Colombier }
37*7dd7cddfSDavid du Colombier shf_flush(shl_out);
38*7dd7cddfSDavid du Colombier unwind(LERROR);
39*7dd7cddfSDavid du Colombier }
40*7dd7cddfSDavid du Colombier
41*7dd7cddfSDavid du Colombier /* like errorf(), but no unwind is done */
42*7dd7cddfSDavid du Colombier void
43*7dd7cddfSDavid du Colombier #ifdef HAVE_PROTOTYPES
warningf(int fileline,const char * fmt,...)44*7dd7cddfSDavid du Colombier warningf(int fileline, const char *fmt, ...)
45*7dd7cddfSDavid du Colombier #else
46*7dd7cddfSDavid du Colombier warningf(fileline, fmt, va_alist)
47*7dd7cddfSDavid du Colombier int fileline;
48*7dd7cddfSDavid du Colombier const char *fmt;
49*7dd7cddfSDavid du Colombier va_dcl
50*7dd7cddfSDavid du Colombier #endif
51*7dd7cddfSDavid du Colombier {
52*7dd7cddfSDavid du Colombier va_list va;
53*7dd7cddfSDavid du Colombier
54*7dd7cddfSDavid du Colombier error_prefix(fileline);
55*7dd7cddfSDavid du Colombier SH_VA_START(va, fmt);
56*7dd7cddfSDavid du Colombier shf_vfprintf(shl_out, fmt, va);
57*7dd7cddfSDavid du Colombier va_end(va);
58*7dd7cddfSDavid du Colombier shf_putchar('\n', shl_out);
59*7dd7cddfSDavid du Colombier shf_flush(shl_out);
60*7dd7cddfSDavid du Colombier }
61*7dd7cddfSDavid du Colombier
62*7dd7cddfSDavid du Colombier /* Used by built-in utilities to prefix shell and utility name to message
63*7dd7cddfSDavid du Colombier * (also unwinds environments for special builtins).
64*7dd7cddfSDavid du Colombier */
65*7dd7cddfSDavid du Colombier void
66*7dd7cddfSDavid du Colombier #ifdef HAVE_PROTOTYPES
bi_errorf(const char * fmt,...)67*7dd7cddfSDavid du Colombier bi_errorf(const char *fmt, ...)
68*7dd7cddfSDavid du Colombier #else
69*7dd7cddfSDavid du Colombier bi_errorf(fmt, va_alist)
70*7dd7cddfSDavid du Colombier const char *fmt;
71*7dd7cddfSDavid du Colombier va_dcl
72*7dd7cddfSDavid du Colombier #endif
73*7dd7cddfSDavid du Colombier {
74*7dd7cddfSDavid du Colombier va_list va;
75*7dd7cddfSDavid du Colombier
76*7dd7cddfSDavid du Colombier shl_stdout_ok = 0; /* debugging: note that stdout not valid */
77*7dd7cddfSDavid du Colombier exstat = 1;
78*7dd7cddfSDavid du Colombier if (*fmt) {
79*7dd7cddfSDavid du Colombier error_prefix(TRUE);
80*7dd7cddfSDavid du Colombier /* not set when main() calls parse_args() */
81*7dd7cddfSDavid du Colombier if (builtin_argv0)
82*7dd7cddfSDavid du Colombier shf_fprintf(shl_out, "%s: ", builtin_argv0);
83*7dd7cddfSDavid du Colombier SH_VA_START(va, fmt);
84*7dd7cddfSDavid du Colombier shf_vfprintf(shl_out, fmt, va);
85*7dd7cddfSDavid du Colombier va_end(va);
86*7dd7cddfSDavid du Colombier shf_putchar('\n', shl_out);
87*7dd7cddfSDavid du Colombier }
88*7dd7cddfSDavid du Colombier shf_flush(shl_out);
89*7dd7cddfSDavid du Colombier /* POSIX special builtins and ksh special builtins cause
90*7dd7cddfSDavid du Colombier * non-interactive shells to exit.
91*7dd7cddfSDavid du Colombier * XXX odd use of KEEPASN; also may not want LERROR here
92*7dd7cddfSDavid du Colombier */
93*7dd7cddfSDavid du Colombier if ((builtin_flag & SPEC_BI)
94*7dd7cddfSDavid du Colombier || (Flag(FPOSIX) && (builtin_flag & KEEPASN)))
95*7dd7cddfSDavid du Colombier {
96*7dd7cddfSDavid du Colombier builtin_argv0 = (char *) 0;
97*7dd7cddfSDavid du Colombier unwind(LERROR);
98*7dd7cddfSDavid du Colombier }
99*7dd7cddfSDavid du Colombier }
100*7dd7cddfSDavid du Colombier
101*7dd7cddfSDavid du Colombier /* Called when something that shouldn't happen does */
102*7dd7cddfSDavid du Colombier void
103*7dd7cddfSDavid du Colombier #ifdef HAVE_PROTOTYPES
internal_errorf(int jump,const char * fmt,...)104*7dd7cddfSDavid du Colombier internal_errorf(int jump, const char *fmt, ...)
105*7dd7cddfSDavid du Colombier #else
106*7dd7cddfSDavid du Colombier internal_errorf(jump, fmt, va_alist)
107*7dd7cddfSDavid du Colombier int jump;
108*7dd7cddfSDavid du Colombier const char *fmt;
109*7dd7cddfSDavid du Colombier va_dcl
110*7dd7cddfSDavid du Colombier #endif
111*7dd7cddfSDavid du Colombier {
112*7dd7cddfSDavid du Colombier va_list va;
113*7dd7cddfSDavid du Colombier
114*7dd7cddfSDavid du Colombier error_prefix(TRUE);
115*7dd7cddfSDavid du Colombier shf_fprintf(shl_out, "internal error: ");
116*7dd7cddfSDavid du Colombier SH_VA_START(va, fmt);
117*7dd7cddfSDavid du Colombier shf_vfprintf(shl_out, fmt, va);
118*7dd7cddfSDavid du Colombier va_end(va);
119*7dd7cddfSDavid du Colombier shf_putchar('\n', shl_out);
120*7dd7cddfSDavid du Colombier shf_flush(shl_out);
121*7dd7cddfSDavid du Colombier if (jump)
122*7dd7cddfSDavid du Colombier unwind(LERROR);
123*7dd7cddfSDavid du Colombier }
124*7dd7cddfSDavid du Colombier
125*7dd7cddfSDavid du Colombier /* used by error reporting functions to print "ksh: .kshrc[25]: " */
126*7dd7cddfSDavid du Colombier void
error_prefix(fileline)127*7dd7cddfSDavid du Colombier error_prefix(fileline)
128*7dd7cddfSDavid du Colombier int fileline;
129*7dd7cddfSDavid du Colombier {
130*7dd7cddfSDavid du Colombier /* Avoid foo: foo[2]: ... */
131*7dd7cddfSDavid du Colombier if (!fileline || !source || !source->file
132*7dd7cddfSDavid du Colombier || strcmp(source->file, kshname) != 0)
133*7dd7cddfSDavid du Colombier shf_fprintf(shl_out, "%s: ", kshname + (*kshname == '-'));
134*7dd7cddfSDavid du Colombier if (fileline && source && source->file != NULL) {
135*7dd7cddfSDavid du Colombier shf_fprintf(shl_out, "%s[%d]: ", source->file,
136*7dd7cddfSDavid du Colombier source->errline > 0 ? source->errline : source->line);
137*7dd7cddfSDavid du Colombier source->errline = 0;
138*7dd7cddfSDavid du Colombier }
139*7dd7cddfSDavid du Colombier }
140*7dd7cddfSDavid du Colombier
141*7dd7cddfSDavid du Colombier /* printf to shl_out (stderr) with flush */
142*7dd7cddfSDavid du Colombier void
143*7dd7cddfSDavid du Colombier #ifdef HAVE_PROTOTYPES
shellf(const char * fmt,...)144*7dd7cddfSDavid du Colombier shellf(const char *fmt, ...)
145*7dd7cddfSDavid du Colombier #else
146*7dd7cddfSDavid du Colombier shellf(fmt, va_alist)
147*7dd7cddfSDavid du Colombier const char *fmt;
148*7dd7cddfSDavid du Colombier va_dcl
149*7dd7cddfSDavid du Colombier #endif
150*7dd7cddfSDavid du Colombier {
151*7dd7cddfSDavid du Colombier va_list va;
152*7dd7cddfSDavid du Colombier
153*7dd7cddfSDavid du Colombier if (!initio_done) /* shl_out may not be set up yet... */
154*7dd7cddfSDavid du Colombier return;
155*7dd7cddfSDavid du Colombier SH_VA_START(va, fmt);
156*7dd7cddfSDavid du Colombier shf_vfprintf(shl_out, fmt, va);
157*7dd7cddfSDavid du Colombier va_end(va);
158*7dd7cddfSDavid du Colombier shf_flush(shl_out);
159*7dd7cddfSDavid du Colombier }
160*7dd7cddfSDavid du Colombier
161*7dd7cddfSDavid du Colombier /* printf to shl_stdout (stdout) */
162*7dd7cddfSDavid du Colombier void
163*7dd7cddfSDavid du Colombier #ifdef HAVE_PROTOTYPES
shprintf(const char * fmt,...)164*7dd7cddfSDavid du Colombier shprintf(const char *fmt, ...)
165*7dd7cddfSDavid du Colombier #else
166*7dd7cddfSDavid du Colombier shprintf(fmt, va_alist)
167*7dd7cddfSDavid du Colombier const char *fmt;
168*7dd7cddfSDavid du Colombier va_dcl
169*7dd7cddfSDavid du Colombier #endif
170*7dd7cddfSDavid du Colombier {
171*7dd7cddfSDavid du Colombier va_list va;
172*7dd7cddfSDavid du Colombier
173*7dd7cddfSDavid du Colombier if (!shl_stdout_ok)
174*7dd7cddfSDavid du Colombier internal_errorf(1, "shl_stdout not valid");
175*7dd7cddfSDavid du Colombier SH_VA_START(va, fmt);
176*7dd7cddfSDavid du Colombier shf_vfprintf(shl_stdout, fmt, va);
177*7dd7cddfSDavid du Colombier va_end(va);
178*7dd7cddfSDavid du Colombier }
179*7dd7cddfSDavid du Colombier
180*7dd7cddfSDavid du Colombier #ifdef KSH_DEBUG
181*7dd7cddfSDavid du Colombier static struct shf *kshdebug_shf;
182*7dd7cddfSDavid du Colombier
183*7dd7cddfSDavid du Colombier void
kshdebug_init_()184*7dd7cddfSDavid du Colombier kshdebug_init_()
185*7dd7cddfSDavid du Colombier {
186*7dd7cddfSDavid du Colombier if (kshdebug_shf)
187*7dd7cddfSDavid du Colombier shf_close(kshdebug_shf);
188*7dd7cddfSDavid du Colombier kshdebug_shf = shf_open("/tmp/ksh-debug.log",
189*7dd7cddfSDavid du Colombier O_WRONLY|O_APPEND|O_CREAT, 0600,
190*7dd7cddfSDavid du Colombier SHF_WR|SHF_MAPHI);
191*7dd7cddfSDavid du Colombier if (kshdebug_shf) {
192*7dd7cddfSDavid du Colombier shf_fprintf(kshdebug_shf, "\nNew shell[pid %d]\n", getpid());
193*7dd7cddfSDavid du Colombier shf_flush(kshdebug_shf);
194*7dd7cddfSDavid du Colombier }
195*7dd7cddfSDavid du Colombier }
196*7dd7cddfSDavid du Colombier
197*7dd7cddfSDavid du Colombier /* print to debugging log */
198*7dd7cddfSDavid du Colombier void
199*7dd7cddfSDavid du Colombier # ifdef HAVE_PROTOTYPES
kshdebug_printf_(const char * fmt,...)200*7dd7cddfSDavid du Colombier kshdebug_printf_(const char *fmt, ...)
201*7dd7cddfSDavid du Colombier # else
202*7dd7cddfSDavid du Colombier kshdebug_printf_(fmt, va_alist)
203*7dd7cddfSDavid du Colombier const char *fmt;
204*7dd7cddfSDavid du Colombier va_dcl
205*7dd7cddfSDavid du Colombier # endif
206*7dd7cddfSDavid du Colombier {
207*7dd7cddfSDavid du Colombier va_list va;
208*7dd7cddfSDavid du Colombier
209*7dd7cddfSDavid du Colombier if (!kshdebug_shf)
210*7dd7cddfSDavid du Colombier return;
211*7dd7cddfSDavid du Colombier SH_VA_START(va, fmt);
212*7dd7cddfSDavid du Colombier shf_fprintf(kshdebug_shf, "[%d] ", getpid());
213*7dd7cddfSDavid du Colombier shf_vfprintf(kshdebug_shf, fmt, va);
214*7dd7cddfSDavid du Colombier va_end(va);
215*7dd7cddfSDavid du Colombier shf_flush(kshdebug_shf);
216*7dd7cddfSDavid du Colombier }
217*7dd7cddfSDavid du Colombier
218*7dd7cddfSDavid du Colombier void
kshdebug_dump_(str,mem,nbytes)219*7dd7cddfSDavid du Colombier kshdebug_dump_(str, mem, nbytes)
220*7dd7cddfSDavid du Colombier const char *str;
221*7dd7cddfSDavid du Colombier const void *mem;
222*7dd7cddfSDavid du Colombier int nbytes;
223*7dd7cddfSDavid du Colombier {
224*7dd7cddfSDavid du Colombier int i, j;
225*7dd7cddfSDavid du Colombier int nprow = 16;
226*7dd7cddfSDavid du Colombier
227*7dd7cddfSDavid du Colombier if (!kshdebug_shf)
228*7dd7cddfSDavid du Colombier return;
229*7dd7cddfSDavid du Colombier shf_fprintf(kshdebug_shf, "[%d] %s:\n", getpid(), str);
230*7dd7cddfSDavid du Colombier for (i = 0; i < nbytes; i += nprow) {
231*7dd7cddfSDavid du Colombier char c = '\t';
232*7dd7cddfSDavid du Colombier for (j = 0; j < nprow && i + j < nbytes; j++) {
233*7dd7cddfSDavid du Colombier shf_fprintf(kshdebug_shf, "%c%02x",
234*7dd7cddfSDavid du Colombier c, ((const unsigned char *) mem)[i + j]);
235*7dd7cddfSDavid du Colombier c = ' ';
236*7dd7cddfSDavid du Colombier }
237*7dd7cddfSDavid du Colombier shf_fprintf(kshdebug_shf, "\n");
238*7dd7cddfSDavid du Colombier }
239*7dd7cddfSDavid du Colombier shf_flush(kshdebug_shf);
240*7dd7cddfSDavid du Colombier }
241*7dd7cddfSDavid du Colombier #endif /* KSH_DEBUG */
242*7dd7cddfSDavid du Colombier
243*7dd7cddfSDavid du Colombier /* test if we can seek backwards fd (returns 0 or SHF_UNBUF) */
244*7dd7cddfSDavid du Colombier int
can_seek(fd)245*7dd7cddfSDavid du Colombier can_seek(fd)
246*7dd7cddfSDavid du Colombier int fd;
247*7dd7cddfSDavid du Colombier {
248*7dd7cddfSDavid du Colombier struct stat statb;
249*7dd7cddfSDavid du Colombier
250*7dd7cddfSDavid du Colombier return fstat(fd, &statb) == 0 && !S_ISREG(statb.st_mode) ?
251*7dd7cddfSDavid du Colombier SHF_UNBUF : 0;
252*7dd7cddfSDavid du Colombier }
253*7dd7cddfSDavid du Colombier
254*7dd7cddfSDavid du Colombier struct shf shf_iob[3];
255*7dd7cddfSDavid du Colombier
256*7dd7cddfSDavid du Colombier void
initio()257*7dd7cddfSDavid du Colombier initio()
258*7dd7cddfSDavid du Colombier {
259*7dd7cddfSDavid du Colombier shf_fdopen(1, SHF_WR, shl_stdout); /* force buffer allocation */
260*7dd7cddfSDavid du Colombier shf_fdopen(2, SHF_WR, shl_out);
261*7dd7cddfSDavid du Colombier shf_fdopen(2, SHF_WR, shl_spare); /* force buffer allocation */
262*7dd7cddfSDavid du Colombier initio_done = 1;
263*7dd7cddfSDavid du Colombier kshdebug_init();
264*7dd7cddfSDavid du Colombier }
265*7dd7cddfSDavid du Colombier
266*7dd7cddfSDavid du Colombier /* A dup2() with error checking */
267*7dd7cddfSDavid du Colombier int
ksh_dup2(ofd,nfd,errok)268*7dd7cddfSDavid du Colombier ksh_dup2(ofd, nfd, errok)
269*7dd7cddfSDavid du Colombier int ofd;
270*7dd7cddfSDavid du Colombier int nfd;
271*7dd7cddfSDavid du Colombier int errok;
272*7dd7cddfSDavid du Colombier {
273*7dd7cddfSDavid du Colombier int ret = dup2(ofd, nfd);
274*7dd7cddfSDavid du Colombier
275*7dd7cddfSDavid du Colombier if (ret < 0 && errno != EBADF && !errok)
276*7dd7cddfSDavid du Colombier errorf("too many files open in shell");
277*7dd7cddfSDavid du Colombier
278*7dd7cddfSDavid du Colombier #ifdef DUP2_BROKEN
279*7dd7cddfSDavid du Colombier /* Ultrix systems like to preserve the close-on-exec flag */
280*7dd7cddfSDavid du Colombier if (ret >= 0)
281*7dd7cddfSDavid du Colombier (void) fcntl(nfd, F_SETFD, 0);
282*7dd7cddfSDavid du Colombier #endif /* DUP2_BROKEN */
283*7dd7cddfSDavid du Colombier
284*7dd7cddfSDavid du Colombier return ret;
285*7dd7cddfSDavid du Colombier }
286*7dd7cddfSDavid du Colombier
287*7dd7cddfSDavid du Colombier /*
288*7dd7cddfSDavid du Colombier * move fd from user space (0<=fd<10) to shell space (fd>=10),
289*7dd7cddfSDavid du Colombier * set close-on-exec flag.
290*7dd7cddfSDavid du Colombier */
291*7dd7cddfSDavid du Colombier int
savefd(fd,noclose)292*7dd7cddfSDavid du Colombier savefd(fd, noclose)
293*7dd7cddfSDavid du Colombier int fd;
294*7dd7cddfSDavid du Colombier int noclose;
295*7dd7cddfSDavid du Colombier {
296*7dd7cddfSDavid du Colombier int nfd;
297*7dd7cddfSDavid du Colombier
298*7dd7cddfSDavid du Colombier if (fd < FDBASE) {
299*7dd7cddfSDavid du Colombier nfd = ksh_dupbase(fd, FDBASE);
300*7dd7cddfSDavid du Colombier if (nfd < 0)
301*7dd7cddfSDavid du Colombier if (errno == EBADF)
302*7dd7cddfSDavid du Colombier return -1;
303*7dd7cddfSDavid du Colombier else
304*7dd7cddfSDavid du Colombier errorf("too many files open in shell");
305*7dd7cddfSDavid du Colombier if (!noclose)
306*7dd7cddfSDavid du Colombier close(fd);
307*7dd7cddfSDavid du Colombier } else
308*7dd7cddfSDavid du Colombier nfd = fd;
309*7dd7cddfSDavid du Colombier fd_clexec(nfd);
310*7dd7cddfSDavid du Colombier return nfd;
311*7dd7cddfSDavid du Colombier }
312*7dd7cddfSDavid du Colombier
313*7dd7cddfSDavid du Colombier void
restfd(fd,ofd)314*7dd7cddfSDavid du Colombier restfd(fd, ofd)
315*7dd7cddfSDavid du Colombier int fd, ofd;
316*7dd7cddfSDavid du Colombier {
317*7dd7cddfSDavid du Colombier if (fd == 2)
318*7dd7cddfSDavid du Colombier shf_flush(&shf_iob[fd]);
319*7dd7cddfSDavid du Colombier if (ofd < 0) /* original fd closed */
320*7dd7cddfSDavid du Colombier close(fd);
321*7dd7cddfSDavid du Colombier else {
322*7dd7cddfSDavid du Colombier ksh_dup2(ofd, fd, TRUE); /* XXX: what to do if this fails? */
323*7dd7cddfSDavid du Colombier close(ofd);
324*7dd7cddfSDavid du Colombier }
325*7dd7cddfSDavid du Colombier }
326*7dd7cddfSDavid du Colombier
327*7dd7cddfSDavid du Colombier void
openpipe(pv)328*7dd7cddfSDavid du Colombier openpipe(pv)
329*7dd7cddfSDavid du Colombier register int *pv;
330*7dd7cddfSDavid du Colombier {
331*7dd7cddfSDavid du Colombier if (pipe(pv) < 0)
332*7dd7cddfSDavid du Colombier errorf("can't create pipe - try again");
333*7dd7cddfSDavid du Colombier pv[0] = savefd(pv[0], 0);
334*7dd7cddfSDavid du Colombier pv[1] = savefd(pv[1], 0);
335*7dd7cddfSDavid du Colombier }
336*7dd7cddfSDavid du Colombier
337*7dd7cddfSDavid du Colombier void
closepipe(pv)338*7dd7cddfSDavid du Colombier closepipe(pv)
339*7dd7cddfSDavid du Colombier register int *pv;
340*7dd7cddfSDavid du Colombier {
341*7dd7cddfSDavid du Colombier close(pv[0]);
342*7dd7cddfSDavid du Colombier close(pv[1]);
343*7dd7cddfSDavid du Colombier }
344*7dd7cddfSDavid du Colombier
345*7dd7cddfSDavid du Colombier /* Called by iosetup() (deals with 2>&4, etc.), c_read, c_print to turn
346*7dd7cddfSDavid du Colombier * a string (the X in 2>&X, read -uX, print -uX) into a file descriptor.
347*7dd7cddfSDavid du Colombier */
348*7dd7cddfSDavid du Colombier int
check_fd(name,mode,emsgp)349*7dd7cddfSDavid du Colombier check_fd(name, mode, emsgp)
350*7dd7cddfSDavid du Colombier char *name;
351*7dd7cddfSDavid du Colombier int mode;
352*7dd7cddfSDavid du Colombier const char **emsgp;
353*7dd7cddfSDavid du Colombier {
354*7dd7cddfSDavid du Colombier int fd, fl;
355*7dd7cddfSDavid du Colombier
356*7dd7cddfSDavid du Colombier if (isdigit(name[0]) && !name[1]) {
357*7dd7cddfSDavid du Colombier fd = name[0] - '0';
358*7dd7cddfSDavid du Colombier if ((fl = fcntl(fd = name[0] - '0', F_GETFL, 0)) < 0) {
359*7dd7cddfSDavid du Colombier if (emsgp)
360*7dd7cddfSDavid du Colombier *emsgp = "bad file descriptor";
361*7dd7cddfSDavid du Colombier return -1;
362*7dd7cddfSDavid du Colombier }
363*7dd7cddfSDavid du Colombier fl &= O_ACCMODE;
364*7dd7cddfSDavid du Colombier #ifdef OS2
365*7dd7cddfSDavid du Colombier if (mode == W_OK ) {
366*7dd7cddfSDavid du Colombier if (setmode(fd, O_TEXT) == -1) {
367*7dd7cddfSDavid du Colombier if (emsgp)
368*7dd7cddfSDavid du Colombier *emsgp = "couldn't set write mode";
369*7dd7cddfSDavid du Colombier return -1;
370*7dd7cddfSDavid du Colombier }
371*7dd7cddfSDavid du Colombier } else if (mode == R_OK)
372*7dd7cddfSDavid du Colombier if (setmode(fd, O_BINARY) == -1) {
373*7dd7cddfSDavid du Colombier if (emsgp)
374*7dd7cddfSDavid du Colombier *emsgp = "couldn't set read mode";
375*7dd7cddfSDavid du Colombier return -1;
376*7dd7cddfSDavid du Colombier }
377*7dd7cddfSDavid du Colombier #else /* OS2 */
378*7dd7cddfSDavid du Colombier /* X_OK is a kludge to disable this check for dups (x<&1):
379*7dd7cddfSDavid du Colombier * historical shells never did this check (XXX don't know what
380*7dd7cddfSDavid du Colombier * posix has to say).
381*7dd7cddfSDavid du Colombier */
382*7dd7cddfSDavid du Colombier if (!(mode & X_OK) && fl != O_RDWR
383*7dd7cddfSDavid du Colombier && (((mode & R_OK) && fl != O_RDONLY)
384*7dd7cddfSDavid du Colombier || ((mode & W_OK) && fl != O_WRONLY)))
385*7dd7cddfSDavid du Colombier {
386*7dd7cddfSDavid du Colombier if (emsgp)
387*7dd7cddfSDavid du Colombier *emsgp = (fl == O_WRONLY) ?
388*7dd7cddfSDavid du Colombier "fd not open for reading"
389*7dd7cddfSDavid du Colombier : "fd not open for writing";
390*7dd7cddfSDavid du Colombier return -1;
391*7dd7cddfSDavid du Colombier }
392*7dd7cddfSDavid du Colombier #endif /* OS2 */
393*7dd7cddfSDavid du Colombier return fd;
394*7dd7cddfSDavid du Colombier }
395*7dd7cddfSDavid du Colombier #ifdef KSH
396*7dd7cddfSDavid du Colombier else if (name[0] == 'p' && !name[1])
397*7dd7cddfSDavid du Colombier return coproc_getfd(mode, emsgp);
398*7dd7cddfSDavid du Colombier #endif /* KSH */
399*7dd7cddfSDavid du Colombier if (emsgp)
400*7dd7cddfSDavid du Colombier *emsgp = "illegal file descriptor name";
401*7dd7cddfSDavid du Colombier return -1;
402*7dd7cddfSDavid du Colombier }
403*7dd7cddfSDavid du Colombier
404*7dd7cddfSDavid du Colombier #ifdef KSH
405*7dd7cddfSDavid du Colombier /* Called once from main */
406*7dd7cddfSDavid du Colombier void
coproc_init()407*7dd7cddfSDavid du Colombier coproc_init()
408*7dd7cddfSDavid du Colombier {
409*7dd7cddfSDavid du Colombier coproc.read = coproc.readw = coproc.write = -1;
410*7dd7cddfSDavid du Colombier coproc.njobs = 0;
411*7dd7cddfSDavid du Colombier coproc.id = 0;
412*7dd7cddfSDavid du Colombier }
413*7dd7cddfSDavid du Colombier
414*7dd7cddfSDavid du Colombier /* Called by c_read() when eof is read - close fd if it is the co-process fd */
415*7dd7cddfSDavid du Colombier void
coproc_read_close(fd)416*7dd7cddfSDavid du Colombier coproc_read_close(fd)
417*7dd7cddfSDavid du Colombier int fd;
418*7dd7cddfSDavid du Colombier {
419*7dd7cddfSDavid du Colombier if (coproc.read >= 0 && fd == coproc.read) {
420*7dd7cddfSDavid du Colombier coproc_readw_close(fd);
421*7dd7cddfSDavid du Colombier close(coproc.read);
422*7dd7cddfSDavid du Colombier coproc.read = -1;
423*7dd7cddfSDavid du Colombier }
424*7dd7cddfSDavid du Colombier }
425*7dd7cddfSDavid du Colombier
426*7dd7cddfSDavid du Colombier /* Called by c_read() and by iosetup() to close the other side of the
427*7dd7cddfSDavid du Colombier * read pipe, so reads will actually terminate.
428*7dd7cddfSDavid du Colombier */
429*7dd7cddfSDavid du Colombier void
coproc_readw_close(fd)430*7dd7cddfSDavid du Colombier coproc_readw_close(fd)
431*7dd7cddfSDavid du Colombier int fd;
432*7dd7cddfSDavid du Colombier {
433*7dd7cddfSDavid du Colombier if (coproc.readw >= 0 && coproc.read >= 0 && fd == coproc.read) {
434*7dd7cddfSDavid du Colombier close(coproc.readw);
435*7dd7cddfSDavid du Colombier coproc.readw = -1;
436*7dd7cddfSDavid du Colombier }
437*7dd7cddfSDavid du Colombier }
438*7dd7cddfSDavid du Colombier
439*7dd7cddfSDavid du Colombier /* Called by c_print when a write to a fd fails with EPIPE and by iosetup
440*7dd7cddfSDavid du Colombier * when co-process input is dup'd
441*7dd7cddfSDavid du Colombier */
442*7dd7cddfSDavid du Colombier void
coproc_write_close(fd)443*7dd7cddfSDavid du Colombier coproc_write_close(fd)
444*7dd7cddfSDavid du Colombier int fd;
445*7dd7cddfSDavid du Colombier {
446*7dd7cddfSDavid du Colombier if (coproc.write >= 0 && fd == coproc.write) {
447*7dd7cddfSDavid du Colombier close(coproc.write);
448*7dd7cddfSDavid du Colombier coproc.write = -1;
449*7dd7cddfSDavid du Colombier }
450*7dd7cddfSDavid du Colombier }
451*7dd7cddfSDavid du Colombier
452*7dd7cddfSDavid du Colombier /* Called to check for existance of/value of the co-process file descriptor.
453*7dd7cddfSDavid du Colombier * (Used by check_fd() and by c_read/c_print to deal with -p option).
454*7dd7cddfSDavid du Colombier */
455*7dd7cddfSDavid du Colombier int
coproc_getfd(mode,emsgp)456*7dd7cddfSDavid du Colombier coproc_getfd(mode, emsgp)
457*7dd7cddfSDavid du Colombier int mode;
458*7dd7cddfSDavid du Colombier const char **emsgp;
459*7dd7cddfSDavid du Colombier {
460*7dd7cddfSDavid du Colombier int fd = (mode & R_OK) ? coproc.read : coproc.write;
461*7dd7cddfSDavid du Colombier
462*7dd7cddfSDavid du Colombier if (fd >= 0)
463*7dd7cddfSDavid du Colombier return fd;
464*7dd7cddfSDavid du Colombier if (emsgp)
465*7dd7cddfSDavid du Colombier *emsgp = "no coprocess";
466*7dd7cddfSDavid du Colombier return -1;
467*7dd7cddfSDavid du Colombier }
468*7dd7cddfSDavid du Colombier
469*7dd7cddfSDavid du Colombier /* called to close file descriptors related to the coprocess (if any)
470*7dd7cddfSDavid du Colombier * Should be called with SIGCHLD blocked.
471*7dd7cddfSDavid du Colombier */
472*7dd7cddfSDavid du Colombier void
coproc_cleanup(reuse)473*7dd7cddfSDavid du Colombier coproc_cleanup(reuse)
474*7dd7cddfSDavid du Colombier int reuse;
475*7dd7cddfSDavid du Colombier {
476*7dd7cddfSDavid du Colombier /* This to allow co-processes to share output pipe */
477*7dd7cddfSDavid du Colombier if (!reuse || coproc.readw < 0 || coproc.read < 0) {
478*7dd7cddfSDavid du Colombier if (coproc.read >= 0) {
479*7dd7cddfSDavid du Colombier close(coproc.read);
480*7dd7cddfSDavid du Colombier coproc.read = -1;
481*7dd7cddfSDavid du Colombier }
482*7dd7cddfSDavid du Colombier if (coproc.readw >= 0) {
483*7dd7cddfSDavid du Colombier close(coproc.readw);
484*7dd7cddfSDavid du Colombier coproc.readw = -1;
485*7dd7cddfSDavid du Colombier }
486*7dd7cddfSDavid du Colombier }
487*7dd7cddfSDavid du Colombier if (coproc.write >= 0) {
488*7dd7cddfSDavid du Colombier close(coproc.write);
489*7dd7cddfSDavid du Colombier coproc.write = -1;
490*7dd7cddfSDavid du Colombier }
491*7dd7cddfSDavid du Colombier }
492*7dd7cddfSDavid du Colombier #endif /* KSH */
493*7dd7cddfSDavid du Colombier
494*7dd7cddfSDavid du Colombier
495*7dd7cddfSDavid du Colombier /*
496*7dd7cddfSDavid du Colombier * temporary files
497*7dd7cddfSDavid du Colombier */
498*7dd7cddfSDavid du Colombier
499*7dd7cddfSDavid du Colombier struct temp *
maketemp(ap,type,tlist)500*7dd7cddfSDavid du Colombier maketemp(ap, type, tlist)
501*7dd7cddfSDavid du Colombier Area *ap;
502*7dd7cddfSDavid du Colombier Temp_type type;
503*7dd7cddfSDavid du Colombier struct temp **tlist;
504*7dd7cddfSDavid du Colombier {
505*7dd7cddfSDavid du Colombier static unsigned int inc;
506*7dd7cddfSDavid du Colombier struct temp *tp;
507*7dd7cddfSDavid du Colombier int len;
508*7dd7cddfSDavid du Colombier int fd;
509*7dd7cddfSDavid du Colombier char *path;
510*7dd7cddfSDavid du Colombier const char *dir;
511*7dd7cddfSDavid du Colombier
512*7dd7cddfSDavid du Colombier dir = tmpdir ? tmpdir : "/tmp";
513*7dd7cddfSDavid du Colombier /* The 20 + 20 is a paranoid worst case for pid/inc */
514*7dd7cddfSDavid du Colombier len = strlen(dir) + 3 + 20 + 20 + 1;
515*7dd7cddfSDavid du Colombier tp = (struct temp *) alloc(sizeof(struct temp) + len, ap);
516*7dd7cddfSDavid du Colombier tp->name = path = (char *) &tp[1];
517*7dd7cddfSDavid du Colombier tp->shf = (struct shf *) 0;
518*7dd7cddfSDavid du Colombier tp->type = type;
519*7dd7cddfSDavid du Colombier while (1) {
520*7dd7cddfSDavid du Colombier /* Note that temp files need to fit 8.3 DOS limits */
521*7dd7cddfSDavid du Colombier shf_snprintf(path, len, "%s/sh%05u.%03x",
522*7dd7cddfSDavid du Colombier dir, (unsigned) procpid, inc++);
523*7dd7cddfSDavid du Colombier /* Mode 0600 to be paranoid, O_TRUNC in case O_EXCL isn't
524*7dd7cddfSDavid du Colombier * really there.
525*7dd7cddfSDavid du Colombier */
526*7dd7cddfSDavid du Colombier fd = open(path, O_RDWR|O_CREAT|O_EXCL|O_TRUNC, 0600);
527*7dd7cddfSDavid du Colombier if (fd >= 0) {
528*7dd7cddfSDavid du Colombier tp->shf = shf_fdopen(fd, SHF_WR, (struct shf *) 0);
529*7dd7cddfSDavid du Colombier break;
530*7dd7cddfSDavid du Colombier }
531*7dd7cddfSDavid du Colombier if (errno != EINTR
532*7dd7cddfSDavid du Colombier #ifdef EEXIST
533*7dd7cddfSDavid du Colombier && errno != EEXIST
534*7dd7cddfSDavid du Colombier #endif /* EEXIST */
535*7dd7cddfSDavid du Colombier #ifdef EISDIR
536*7dd7cddfSDavid du Colombier && errno != EISDIR
537*7dd7cddfSDavid du Colombier #endif /* EISDIR */
538*7dd7cddfSDavid du Colombier )
539*7dd7cddfSDavid du Colombier /* Error must be printed by caller: don't know here if
540*7dd7cddfSDavid du Colombier * errorf() or bi_errorf() should be used.
541*7dd7cddfSDavid du Colombier */
542*7dd7cddfSDavid du Colombier break;
543*7dd7cddfSDavid du Colombier }
544*7dd7cddfSDavid du Colombier tp->next = NULL;
545*7dd7cddfSDavid du Colombier tp->pid = procpid;
546*7dd7cddfSDavid du Colombier
547*7dd7cddfSDavid du Colombier tp->next = *tlist;
548*7dd7cddfSDavid du Colombier *tlist = tp;
549*7dd7cddfSDavid du Colombier
550*7dd7cddfSDavid du Colombier return tp;
551*7dd7cddfSDavid du Colombier }
552