]>
Commit | Line | Data |
---|---|---|
cf7098dd MM |
1 | diff -ur netbsd-sh/eval.c netbsd-sh-/eval.c |
2 | --- netbsd-sh/eval.c Tue May 23 12:03:18 2000 | |
3 | +++ netbsd-sh-/eval.c Mon Apr 23 23:33:34 2001 | |
4 | @@ -442,6 +442,7 @@ | |
5 | case NFROM: | |
6 | case NTO: | |
7 | case NAPPEND: | |
8 | + case NTOOV: | |
9 | expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR); | |
10 | redir->nfile.expfname = fn.list->text; | |
11 | break; | |
12 | diff -ur netbsd-sh/exec.c netbsd-sh-/exec.c | |
13 | --- netbsd-sh/exec.c Fri Jan 12 17:50:35 2001 | |
14 | +++ netbsd-sh-/exec.c Mon Apr 23 23:33:34 2001 | |
15 | @@ -125,6 +125,10 @@ | |
16 | char *cmdname; | |
17 | int e; | |
18 | ||
19 | + if (fd2 >= 0 && fd2 != 2) { | |
20 | + close(fd2); | |
21 | + } | |
22 | + | |
23 | if (strchr(argv[0], '/') != NULL) { | |
24 | tryexec(argv[0], argv, envp); | |
25 | e = errno; | |
26 | diff -ur netbsd-sh/jobs.c netbsd-sh-/jobs.c | |
27 | --- netbsd-sh/jobs.c Mon Apr 23 23:34:53 2001 | |
28 | +++ netbsd-sh-/jobs.c Mon Apr 23 23:34:30 2001 | |
29 | @@ -129,9 +129,9 @@ | |
30 | if (on) { | |
31 | do { /* while we are in the background */ | |
32 | #ifdef OLD_TTY_DRIVER | |
33 | - if (ioctl(2, TIOCGPGRP, (char *)&initialpgrp) < 0) { | |
34 | + if (ioctl(fd2, TIOCGPGRP, (char *)&initialpgrp) < 0) { | |
35 | #else | |
36 | - initialpgrp = tcgetpgrp(2); | |
37 | + initialpgrp = tcgetpgrp(fd2); | |
38 | if (initialpgrp < 0) { | |
39 | #endif | |
40 | out2str("sh: can't access tty; job control turned off\n"); | |
41 | @@ -146,7 +146,7 @@ | |
42 | } | |
43 | } while (0); | |
44 | #ifdef OLD_TTY_DRIVER | |
45 | - if (ioctl(2, TIOCGETD, (char *)&ldisc) < 0 || ldisc != NTTYDISC) { | |
46 | + if (ioctl(fd2, TIOCGETD, (char *)&ldisc) < 0 || ldisc != NTTYDISC) { | |
47 | out2str("sh: need new tty driver to run job control; job control turned off\n"); | |
48 | mflag = 0; | |
49 | return; | |
50 | @@ -157,16 +157,16 @@ | |
51 | setsignal(SIGTTIN); | |
52 | setpgid(0, rootpid); | |
53 | #ifdef OLD_TTY_DRIVER | |
54 | - ioctl(2, TIOCSPGRP, (char *)&rootpid); | |
55 | + ioctl(fd2, TIOCSPGRP, (char *)&rootpid); | |
56 | #else | |
57 | - tcsetpgrp(2, rootpid); | |
58 | + tcsetpgrp(fd2, rootpid); | |
59 | #endif | |
60 | } else { /* turning job control off */ | |
61 | setpgid(0, initialpgrp); | |
62 | #ifdef OLD_TTY_DRIVER | |
63 | - ioctl(2, TIOCSPGRP, (char *)&initialpgrp); | |
64 | + ioctl(fd2, TIOCSPGRP, (char *)&initialpgrp); | |
65 | #else | |
66 | - tcsetpgrp(2, initialpgrp); | |
67 | + tcsetpgrp(fd2, initialpgrp); | |
68 | #endif | |
69 | setsignal(SIGTSTP); | |
70 | setsignal(SIGTTOU); | |
71 | @@ -206,9 +206,9 @@ | |
72 | error("job not created under job control"); | |
73 | pgrp = jp->ps[0].pid; | |
74 | #ifdef OLD_TTY_DRIVER | |
75 | - ioctl(2, TIOCSPGRP, (char *)&pgrp); | |
76 | + ioctl(fd2, TIOCSPGRP, (char *)&pgrp); | |
77 | #else | |
78 | - tcsetpgrp(2, pgrp); | |
79 | + tcsetpgrp(fd2, pgrp); | |
80 | #endif | |
81 | restartjob(jp); | |
82 | INTOFF; | |
83 | @@ -612,10 +612,10 @@ | |
84 | if (mode == FORK_FG) { | |
85 | /*** this causes superfluous TIOCSPGRPS ***/ | |
86 | #ifdef OLD_TTY_DRIVER | |
87 | - if (ioctl(2, TIOCSPGRP, (char *)&pgrp) < 0) | |
88 | + if (ioctl(fd2, TIOCSPGRP, (char *)&pgrp) < 0) | |
89 | error("TIOCSPGRP failed, errno=%d", errno); | |
90 | #else | |
91 | - if (tcsetpgrp(2, pgrp) < 0) | |
92 | + if (tcsetpgrp(fd2, pgrp) < 0) | |
93 | error("tcsetpgrp failed, errno=%d", errno); | |
94 | #endif | |
95 | } | |
96 | @@ -734,10 +734,10 @@ | |
97 | #if JOBS | |
98 | if (jp->jobctl) { | |
99 | #ifdef OLD_TTY_DRIVER | |
100 | - if (ioctl(2, TIOCSPGRP, (char *)&mypgrp) < 0) | |
101 | + if (ioctl(fd2, TIOCSPGRP, (char *)&mypgrp) < 0) | |
102 | error("TIOCSPGRP failed, errno=%d\n", errno); | |
103 | #else | |
104 | - if (tcsetpgrp(2, mypgrp) < 0) | |
105 | + if (tcsetpgrp(fd2, mypgrp) < 0) | |
106 | error("tcsetpgrp failed, errno=%d\n", errno); | |
107 | #endif | |
108 | } | |
109 | @@ -1092,6 +1092,8 @@ | |
110 | p = ">>"; i = 1; goto redir; | |
111 | case NTOFD: | |
112 | p = ">&"; i = 1; goto redir; | |
113 | + case NTOOV: | |
114 | + p = ">|"; i = 1; goto redir; | |
115 | case NFROM: | |
116 | p = "<"; i = 0; goto redir; | |
117 | case NFROMFD: | |
118 | Only in netbsd-sh-: jobs.c.orig | |
119 | diff -ur netbsd-sh/nodetypes netbsd-sh-/nodetypes | |
120 | --- netbsd-sh/nodetypes Fri Feb 5 13:04:52 1999 | |
121 | +++ netbsd-sh-/nodetypes Mon Apr 23 23:33:34 2001 | |
122 | @@ -119,6 +119,7 @@ | |
123 | NFROM nfile # fd< fname | |
124 | NFROMTO nfile # fd<> fname | |
125 | NAPPEND nfile # fd>> fname | |
126 | +NTOOV nfile # fd>| fname | |
127 | type int | |
128 | next nodeptr # next redirection in list | |
129 | fd int # file descriptor being redirected | |
130 | diff -ur netbsd-sh/parser.c netbsd-sh-/parser.c | |
131 | --- netbsd-sh/parser.c Fri Jan 12 17:50:39 2001 | |
132 | +++ netbsd-sh-/parser.c Mon Apr 23 23:33:34 2001 | |
133 | @@ -1125,6 +1125,8 @@ | |
134 | np->type = NAPPEND; | |
135 | else if (c == '&') | |
136 | np->type = NTOFD; | |
137 | + else if (c == '|') | |
138 | + np->type = NTOOV; | |
139 | else { | |
140 | np->type = NTO; | |
141 | pungetc(); | |
142 | diff -ur netbsd-sh/redir.c netbsd-sh-/redir.c | |
143 | --- netbsd-sh/redir.c Tue May 23 12:03:19 2000 | |
144 | +++ netbsd-sh-/redir.c Mon Apr 23 23:33:34 2001 | |
145 | @@ -45,6 +45,7 @@ | |
146 | #endif | |
147 | #endif /* not lint */ | |
148 | ||
149 | +#include <sys/stat.h> | |
150 | #include <sys/types.h> | |
151 | #include <sys/param.h> /* PIPE_BUF */ | |
152 | #include <signal.h> | |
153 | @@ -66,6 +67,7 @@ | |
154 | #include "output.h" | |
155 | #include "memalloc.h" | |
156 | #include "error.h" | |
157 | +#include "options.h" | |
158 | ||
159 | ||
160 | #define EMPTY -2 /* marks an unused slot in redirtab */ | |
161 | @@ -92,8 +94,15 @@ | |
162 | */ | |
163 | int fd0_redirected = 0; | |
164 | ||
165 | -STATIC void openredirect __P((union node *, char[10 ])); | |
166 | +/* | |
167 | + * We also keep track of where fd2 goes. | |
168 | + */ | |
169 | +int fd2 = 2; | |
170 | + | |
171 | +STATIC int openredirect __P((union node *)); | |
172 | +STATIC void dupredirect __P((union node *, int, char[10 ])); | |
173 | STATIC int openhere __P((union node *)); | |
174 | +STATIC int noclobberopen __P((const char *)); | |
175 | ||
176 | ||
177 | /* | |
178 | @@ -113,6 +122,7 @@ | |
179 | struct redirtab *sv = NULL; | |
180 | int i; | |
181 | int fd; | |
182 | + int newfd; | |
183 | int try; | |
184 | char memory[10]; /* file descriptors to write to memory */ | |
185 | ||
186 | @@ -133,36 +143,47 @@ | |
187 | n->ndup.dupfd == fd) | |
188 | continue; /* redirect from/to same file descriptor */ | |
189 | ||
190 | - if ((flags & REDIR_PUSH) && sv->renamed[fd] == EMPTY) { | |
191 | - INTOFF; | |
192 | -again: | |
193 | - if ((i = fcntl(fd, F_DUPFD, 10)) == -1) { | |
194 | + INTOFF; | |
195 | + newfd = openredirect(n); | |
196 | + if (((flags & REDIR_PUSH) && sv->renamed[fd] == EMPTY) || | |
197 | + (fd == fd2)) { | |
198 | + if (newfd == fd) { | |
199 | + try++; | |
200 | + } else if ((i = fcntl(fd, F_DUPFD, 10)) == -1) { | |
201 | switch (errno) { | |
202 | case EBADF: | |
203 | if (!try) { | |
204 | - openredirect(n, memory); | |
205 | + dupredirect(n, newfd, memory); | |
206 | try++; | |
207 | - goto again; | |
208 | + break; | |
209 | } | |
210 | /* FALLTHROUGH*/ | |
211 | default: | |
212 | + if (newfd >= 0) { | |
213 | + close(newfd); | |
214 | + } | |
215 | INTON; | |
216 | error("%d: %s", fd, strerror(errno)); | |
217 | /* NOTREACHED */ | |
218 | } | |
219 | } | |
220 | if (!try) { | |
221 | - sv->renamed[fd] = i; | |
222 | close(fd); | |
223 | + if (flags & REDIR_PUSH) { | |
224 | + sv->renamed[fd] = i; | |
225 | + } | |
226 | + if (fd == fd2) { | |
227 | + fd2 = i; | |
228 | + } | |
229 | } | |
230 | - INTON; | |
231 | - } else { | |
232 | + } else if (fd != newfd) { | |
233 | close(fd); | |
234 | } | |
235 | if (fd == 0) | |
236 | fd0_redirected++; | |
237 | if (!try) | |
238 | - openredirect(n, memory); | |
239 | + dupredirect(n, newfd, memory); | |
240 | + INTON; | |
241 | } | |
242 | if (memory[1]) | |
243 | out1 = &memout; | |
244 | @@ -171,22 +192,13 @@ | |
245 | } | |
246 | ||
247 | ||
248 | -STATIC void | |
249 | -openredirect(redir, memory) | |
250 | +STATIC int | |
251 | +openredirect(redir) | |
252 | union node *redir; | |
253 | - char memory[10]; | |
254 | { | |
255 | - int fd = redir->nfile.fd; | |
256 | char *fname; | |
257 | int f; | |
258 | ||
259 | - /* | |
260 | - * We suppress interrupts so that we won't leave open file | |
261 | - * descriptors around. This may not be such a good idea because | |
262 | - * an open of a device or a fifo can block indefinitely. | |
263 | - */ | |
264 | - INTOFF; | |
265 | - memory[fd] = 0; | |
266 | switch (redir->nfile.type) { | |
267 | case NFROM: | |
268 | fname = redir->nfile.expfname; | |
269 | @@ -199,6 +211,14 @@ | |
270 | goto ecreate; | |
271 | break; | |
272 | case NTO: | |
273 | + /* Take care of noclobber mode. */ | |
274 | + if (Cflag) { | |
275 | + fname = redir->nfile.expfname; | |
276 | + if ((f = noclobberopen(fname)) < 0) | |
277 | + goto ecreate; | |
278 | + break; | |
279 | + } | |
280 | + case NTOOV: | |
281 | fname = redir->nfile.expfname; | |
282 | #ifdef O_CREAT | |
283 | if ((f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0) | |
284 | @@ -222,32 +242,48 @@ | |
285 | break; | |
286 | case NTOFD: | |
287 | case NFROMFD: | |
288 | + f = -1; | |
289 | + break; | |
290 | + case NHERE: | |
291 | + case NXHERE: | |
292 | + f = openhere(redir); | |
293 | + break; | |
294 | + default: | |
295 | + abort(); | |
296 | + } | |
297 | + | |
298 | + return f; | |
299 | +ecreate: | |
300 | + error("cannot create %s: %s", fname, errmsg(errno, E_CREAT)); | |
301 | +eopen: | |
302 | + error("cannot open %s: %s", fname, errmsg(errno, E_OPEN)); | |
303 | +} | |
304 | + | |
305 | + | |
306 | +STATIC void | |
307 | +dupredirect(redir, f, memory) | |
308 | + union node *redir; | |
309 | + int f; | |
310 | + char memory[10]; | |
311 | + { | |
312 | + int fd = redir->nfile.fd; | |
313 | + | |
314 | + memory[fd] = 0; | |
315 | + if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) { | |
316 | if (redir->ndup.dupfd >= 0) { /* if not ">&-" */ | |
317 | if (memory[redir->ndup.dupfd]) | |
318 | memory[fd] = 1; | |
319 | else | |
320 | copyfd(redir->ndup.dupfd, fd); | |
321 | } | |
322 | - INTON; | |
323 | return; | |
324 | - case NHERE: | |
325 | - case NXHERE: | |
326 | - f = openhere(redir); | |
327 | - break; | |
328 | - default: | |
329 | - abort(); | |
330 | } | |
331 | ||
332 | if (f != fd) { | |
333 | copyfd(f, fd); | |
334 | close(f); | |
335 | } | |
336 | - INTON; | |
337 | return; | |
338 | -ecreate: | |
339 | - error("cannot create %s: %s", fname, errmsg(errno, E_CREAT)); | |
340 | -eopen: | |
341 | - error("cannot open %s: %s", fname, errmsg(errno, E_OPEN)); | |
342 | } | |
343 | ||
344 | ||
345 | @@ -304,6 +340,7 @@ | |
346 | struct redirtab *rp = redirlist; | |
347 | int i; | |
348 | ||
349 | + INTOFF; | |
350 | for (i = 0 ; i < 10 ; i++) { | |
351 | if (rp->renamed[i] != EMPTY) { | |
352 | if (i == 0) | |
353 | @@ -313,9 +350,11 @@ | |
354 | copyfd(rp->renamed[i], i); | |
355 | close(rp->renamed[i]); | |
356 | } | |
357 | + if (rp->renamed[i] == fd2) { | |
358 | + fd2 = i; | |
359 | + } | |
360 | } | |
361 | } | |
362 | - INTOFF; | |
363 | redirlist = rp->next; | |
364 | ckfree(rp); | |
365 | INTON; | |
366 | @@ -359,6 +398,9 @@ | |
367 | for (i = 0 ; i < 10 ; i++) { | |
368 | if (rp->renamed[i] >= 0) { | |
369 | close(rp->renamed[i]); | |
370 | + if (rp->renamed[i] == fd2) { | |
371 | + fd2 = -1; | |
372 | + } | |
373 | } | |
374 | rp->renamed[i] = EMPTY; | |
375 | } | |
376 | @@ -388,4 +430,63 @@ | |
377 | error("%d: %s", from, strerror(errno)); | |
378 | } | |
379 | return newfd; | |
380 | +} | |
381 | + | |
382 | +/* | |
383 | + * Open a file in noclobber mode. | |
384 | + * The code was copied from bash. | |
385 | + */ | |
386 | +int | |
387 | +noclobberopen(fname) | |
388 | + const char *fname; | |
389 | +{ | |
390 | + int r, fd; | |
391 | + struct stat finfo, finfo2; | |
392 | + | |
393 | + /* | |
394 | + * If the file exists and is a regular file, return an error | |
395 | + * immediately. | |
396 | + */ | |
397 | + r = stat(fname, &finfo); | |
398 | + if (r == 0 && S_ISREG(finfo.st_mode)) { | |
399 | + errno = EEXIST; | |
400 | + return -1; | |
401 | + } | |
402 | + | |
403 | + /* | |
404 | + * If the file was not present (r != 0), make sure we open it | |
405 | + * exclusively so that if it is created before we open it, our open | |
406 | + * will fail. Make sure that we do not truncate an existing file. | |
407 | + * Note that we don't turn on O_EXCL unless the stat failed -- if the | |
408 | + * file was not a regular file, we leave O_EXCL off. | |
409 | + */ | |
410 | + if (r != 0) | |
411 | + return open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666); | |
412 | + fd = open(fname, O_WRONLY|O_CREAT, 0666); | |
413 | + | |
414 | + /* If the open failed, return the file descriptor right away. */ | |
415 | + if (fd < 0) | |
416 | + return fd; | |
417 | + | |
418 | + /* | |
419 | + * OK, the open succeeded, but the file may have been changed from a | |
420 | + * non-regular file to a regular file between the stat and the open. | |
421 | + * We are assuming that the O_EXCL open handles the case where FILENAME | |
422 | + * did not exist and is symlinked to an existing file between the stat | |
423 | + * and open. | |
424 | + */ | |
425 | + | |
426 | + /* | |
427 | + * If we can open it and fstat the file descriptor, and neither check | |
428 | + * revealed that it was a regular file, and the file has not been | |
429 | + * replaced, return the file descriptor. | |
430 | + */ | |
431 | + if (fstat(fd, &finfo2) == 0 && !S_ISREG(finfo2.st_mode) && | |
432 | + finfo.st_dev == finfo2.st_dev && finfo.st_ino == finfo2.st_ino) | |
433 | + return fd; | |
434 | + | |
435 | + /* The file has been replaced. badness. */ | |
436 | + close(fd); | |
437 | + errno = EEXIST; | |
438 | + return -1; | |
439 | } | |
440 | Only in netbsd-sh-: redir.c.orig | |
441 | diff -ur netbsd-sh/redir.h netbsd-sh-/redir.h | |
442 | --- netbsd-sh/redir.h Tue May 23 12:03:19 2000 | |
443 | +++ netbsd-sh-/redir.h Mon Apr 23 23:33:34 2001 | |
444 | @@ -42,6 +42,8 @@ | |
445 | #define REDIR_PUSH 01 /* save previous values of file descriptors */ | |
446 | #define REDIR_BACKQ 02 /* save the command output in memory */ | |
447 | ||
448 | +extern int fd2; | |
449 | + | |
450 | union node; | |
451 | void redirect __P((union node *, int)); | |
452 | void popredir __P((void)); | |
453 | diff -ur netbsd-sh/show.c netbsd-sh-/show.c | |
454 | --- netbsd-sh/show.c Sat Oct 9 13:02:09 1999 | |
455 | +++ netbsd-sh-/show.c Mon Apr 23 23:33:34 2001 | |
456 | @@ -155,6 +155,7 @@ | |
457 | case NTO: s = ">"; dftfd = 1; break; | |
458 | case NAPPEND: s = ">>"; dftfd = 1; break; | |
459 | case NTOFD: s = ">&"; dftfd = 1; break; | |
460 | + case NTOOV: s = ">|"; dftfd = 1; break; | |
461 | case NFROM: s = "<"; dftfd = 0; break; | |
462 | case NFROMFD: s = "<&"; dftfd = 0; break; | |
463 | case NFROMTO: s = "<>"; dftfd = 0; break; |