bit operations generate longword reference which may reference the
[unix-history] / usr / src / bin / sh / redir.c
CommitLineData
b87c26db
KB
1/*-
2 * Copyright (c) 1991 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Kenneth Almquist.
7 *
8 * %sccs.include.redist.c%
9 */
10
11#ifndef lint
6c604e0e 12static char sccsid[] = "@(#)redir.c 5.3 (Berkeley) %G%";
b87c26db
KB
13#endif /* not lint */
14
15/*
16 * Code for dealing with input/output redirection.
17 */
18
19#include "shell.h"
20#include "nodes.h"
21#include "jobs.h"
22#include "expand.h"
23#include "redir.h"
24#include "output.h"
25#include "memalloc.h"
26#include "error.h"
6c604e0e 27#include <sys/types.h>
b87c26db
KB
28#include <signal.h>
29#include <fcntl.h>
30#include <errno.h>
6c604e0e 31#include <unistd.h>
b87c26db
KB
32
33
34#define EMPTY -2 /* marks an unused slot in redirtab */
35#define PIPESIZE 4096 /* amount of buffering in a pipe */
36
37
38MKINIT
39struct redirtab {
40 struct redirtab *next;
41 short renamed[10];
42};
43
44
45MKINIT struct redirtab *redirlist;
46
47
48#ifdef __STDC__
49STATIC void openredirect(union node *, char *);
50STATIC int openhere(union node *);
51#else
52STATIC void openredirect();
53STATIC int openhere();
54#endif
55
56
57
58/*
59 * Process a list of redirection commands. If the REDIR_PUSH flag is set,
60 * old file descriptors are stashed away so that the redirection can be
61 * undone by calling popredir. If the REDIR_BACKQ flag is set, then the
62 * standard output, and the standard error if it becomes a duplicate of
63 * stdout, is saved in memory.
64 */
65
66void
67redirect(redir, flags)
68 union node *redir;
69 int flags;
70 {
71 union node *n;
72 struct redirtab *sv;
73 int i;
74 int fd;
75 char memory[10]; /* file descriptors to write to memory */
76
77 for (i = 10 ; --i >= 0 ; )
78 memory[i] = 0;
79 memory[1] = flags & REDIR_BACKQ;
80 if (flags & REDIR_PUSH) {
81 sv = ckmalloc(sizeof (struct redirtab));
82 for (i = 0 ; i < 10 ; i++)
83 sv->renamed[i] = EMPTY;
84 sv->next = redirlist;
85 redirlist = sv;
86 }
87 for (n = redir ; n ; n = n->nfile.next) {
88 fd = n->nfile.fd;
89 if ((flags & REDIR_PUSH) && sv->renamed[fd] == EMPTY) {
90 INTOFF;
91 if ((i = copyfd(fd, 10)) != EMPTY) {
92 sv->renamed[fd] = i;
93 close(fd);
94 }
95 INTON;
96 if (i == EMPTY)
97 error("Out of file descriptors");
98 } else {
99 close(fd);
100 }
101 openredirect(n, memory);
102 }
103 if (memory[1])
104 out1 = &memout;
105 if (memory[2])
106 out2 = &memout;
107}
108
109
110STATIC void
111openredirect(redir, memory)
112 union node *redir;
113 char memory[10];
114 {
115 int fd = redir->nfile.fd;
116 char *fname;
117 int f;
118
119 /*
120 * We suppress interrupts so that we won't leave open file
121 * descriptors around. This may not be such a good idea because
122 * an open of a device or a fifo can block indefinitely.
123 */
124 INTOFF;
125 memory[fd] = 0;
126 switch (redir->nfile.type) {
127 case NFROM:
128 fname = redir->nfile.expfname;
129 if ((f = open(fname, O_RDONLY)) < 0)
130 error("cannot open %s: %s", fname, errmsg(errno, E_OPEN));
131movefd:
132 if (f != fd) {
133 copyfd(f, fd);
134 close(f);
135 }
136 break;
137 case NTO:
138 fname = redir->nfile.expfname;
139#ifdef O_CREAT
140 if ((f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
141 error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
142#else
143 if ((f = creat(fname, 0666)) < 0)
144 error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
145#endif
146 goto movefd;
147 case NAPPEND:
148 fname = redir->nfile.expfname;
149#ifdef O_APPEND
150 if ((f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0)
151 error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
152#else
153 if ((f = open(fname, O_WRONLY)) < 0
154 && (f = creat(fname, 0666)) < 0)
155 error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
6c604e0e 156 lseek(f, (off_t)0, 2);
b87c26db
KB
157#endif
158 goto movefd;
159 case NTOFD:
160 case NFROMFD:
161 if (redir->ndup.dupfd >= 0) { /* if not ">&-" */
162 if (memory[redir->ndup.dupfd])
163 memory[fd] = 1;
164 else
165 copyfd(redir->ndup.dupfd, fd);
166 }
167 break;
168 case NHERE:
169 case NXHERE:
170 f = openhere(redir);
171 goto movefd;
172 default:
173 abort();
174 }
175 INTON;
176}
177
178
179/*
180 * Handle here documents. Normally we fork off a process to write the
181 * data to a pipe. If the document is short, we can stuff the data in
182 * the pipe without forking.
183 */
184
185STATIC int
186openhere(redir)
187 union node *redir;
188 {
189 int pip[2];
190 int len;
191
192 if (pipe(pip) < 0)
193 error("Pipe call failed");
194 if (redir->type == NHERE) {
195 len = strlen(redir->nhere.doc->narg.text);
196 if (len <= PIPESIZE) {
197 xwrite(pip[1], redir->nhere.doc->narg.text, len);
198 goto out;
199 }
200 }
201 if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
202 close(pip[0]);
203 signal(SIGINT, SIG_IGN);
204 signal(SIGQUIT, SIG_IGN);
205 signal(SIGHUP, SIG_IGN);
206#ifdef SIGTSTP
207 signal(SIGTSTP, SIG_IGN);
208#endif
209 signal(SIGPIPE, SIG_DFL);
210 if (redir->type == NHERE)
211 xwrite(pip[1], redir->nhere.doc->narg.text, len);
212 else
213 expandhere(redir->nhere.doc, pip[1]);
214 _exit(0);
215 }
216out:
217 close(pip[1]);
218 return pip[0];
219}
220
221
222
223/*
224 * Undo the effects of the last redirection.
225 */
226
227void
228popredir() {
229 register struct redirtab *rp = redirlist;
230 int i;
231
232 for (i = 0 ; i < 10 ; i++) {
233 if (rp->renamed[i] != EMPTY) {
234 close(i);
235 if (rp->renamed[i] >= 0) {
236 copyfd(rp->renamed[i], i);
237 close(rp->renamed[i]);
238 }
239 }
240 }
241 INTOFF;
242 redirlist = rp->next;
243 ckfree(rp);
244 INTON;
245}
246
247
248
249/*
250 * Undo all redirections. Called on error or interrupt.
251 */
252
253#ifdef mkinit
254
255INCLUDE "redir.h"
256
257RESET {
258 while (redirlist)
259 popredir();
260}
261
262SHELLPROC {
263 clearredir();
264}
265
266#endif
267
268
269/*
270 * Discard all saved file descriptors.
271 */
272
273void
274clearredir() {
275 register struct redirtab *rp;
276 int i;
277
278 for (rp = redirlist ; rp ; rp = rp->next) {
279 for (i = 0 ; i < 10 ; i++) {
280 if (rp->renamed[i] >= 0) {
281 close(rp->renamed[i]);
282 }
283 rp->renamed[i] = EMPTY;
284 }
285 }
286}
287
288
289
290/*
83be9114 291 * Copy a file descriptor to be >= to. Returns -1
b87c26db
KB
292 * if the source file descriptor is closed, EMPTY if there are no unused
293 * file descriptors left.
294 */
295
296int
297copyfd(from, to) {
b87c26db
KB
298 int newfd;
299
300 newfd = fcntl(from, F_DUPFD, to);
301 if (newfd < 0 && errno == EMFILE)
302 return EMPTY;
303 return newfd;
b87c26db 304}