1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
29
30 /*
31 * UNIX shell
32 */
33
34 #include "defs.h"
35 #include "dup.h"
36 #include <stdio.h>
37 #include <fcntl.h>
38 #include <sys/types.h>
39 #include <sys/stat.h>
40 #include <errno.h>
41
42 short topfd;
43
44 /* ======== input output and file copying ======== */
45
46 void
initf(int fd)47 initf(int fd)
48 {
49 struct fileblk *f = standin;
50
51 f->fdes = fd;
52 f->fsiz = ((flags & oneflg) == 0 ? BUFFERSIZE : 1);
53 f->fnxt = f->fend = f->fbuf;
54 f->nxtoff = f->endoff = 0;
55 f->feval = 0;
56 f->flin = 1;
57 f->feof = FALSE;
58 }
59
60 int
estabf(unsigned char * s)61 estabf(unsigned char *s)
62 {
63 struct fileblk *f;
64
65 (f = standin)->fdes = -1;
66 f->fend = length(s) + (f->fnxt = s);
67 f->nxtoff = 0;
68 f->endoff = length(s);
69 f->flin = 1;
70 return (f->feof = (s == 0));
71 }
72
73 void
push(struct fileblk * af)74 push(struct fileblk *af)
75 {
76 struct fileblk *f;
77
78 (f = af)->fstak = standin;
79 f->feof = 0;
80 f->feval = 0;
81 standin = f;
82 }
83
84 int
pop(void)85 pop(void)
86 {
87 struct fileblk *f;
88
89 if ((f = standin)->fstak) {
90 if (f->fdes >= 0)
91 close(f->fdes);
92 standin = f->fstak;
93 return (TRUE);
94 } else
95 return (FALSE);
96 }
97
98 struct tempblk *tmpfptr;
99
100 void
pushtemp(int fd,struct tempblk * tb)101 pushtemp(int fd, struct tempblk *tb)
102 {
103 tb->fdes = fd;
104 tb->fstak = tmpfptr;
105 tmpfptr = tb;
106 }
107
108 int
poptemp(void)109 poptemp(void)
110 {
111 if (tmpfptr) {
112 close(tmpfptr->fdes);
113 tmpfptr = tmpfptr->fstak;
114 return (TRUE);
115 } else
116 return (FALSE);
117 }
118
119 void
chkpipe(int * pv)120 chkpipe(int *pv)
121 {
122 if (pipe(pv) < 0 || pv[INPIPE] < 0 || pv[OTPIPE] < 0)
123 error(piperr);
124 }
125
126 int
chkopen(unsigned char * idf,int mode)127 chkopen(unsigned char *idf, int mode)
128 {
129 int rc;
130
131 if ((rc = open((char *)idf, mode, 0666)) < 0)
132 failed(idf, badopen);
133 else
134 return (rc);
135 }
136
137 /*
138 * Make f2 be a synonym (including the close-on-exec flag) for f1, which is
139 * then closed. If f2 is descriptor 0, modify the global ioset variable
140 * accordingly.
141 */
142 void
renamef(int f1,int f2)143 renamef(int f1, int f2)
144 {
145 #ifdef RES
146 if (f1 != f2) {
147 dup(f1 | DUPFLG, f2);
148 close(f1);
149 if (f2 == 0)
150 ioset |= 1;
151 }
152 #else
153 int fs;
154
155 if (f1 != f2) {
156 fs = fcntl(f2, 1, 0);
157 close(f2);
158 fcntl(f1, 0, f2);
159 close(f1);
160 if (fs == 1)
161 fcntl(f2, 2, 1);
162 if (f2 == 0)
163 ioset |= 1;
164 }
165 #endif
166 }
167
168 int
create(unsigned char * s)169 create(unsigned char *s)
170 {
171 int rc;
172
173 if ((rc = creat((char *)s, 0666)) < 0)
174 failed(s, badcreate);
175 else
176 return (rc);
177 }
178
179
180 int
tmpfil(struct tempblk * tb)181 tmpfil(struct tempblk *tb)
182 {
183 int fd;
184 int len;
185 size_t size_left = TMPOUTSZ - tmpout_offset;
186
187 /* make sure tmp file does not already exist. */
188 do {
189 len = snprintf((char *)&tmpout[tmpout_offset], size_left,
190 "%u", serial);
191 fd = open((char *)tmpout, O_RDWR|O_CREAT|O_EXCL, 0600);
192 serial++;
193 if ((serial >= UINT_MAX) || (len >= size_left)) {
194 /*
195 * We've already cycled through all the possible
196 * numbers or the tmp file name is being
197 * truncated anyway (although TMPOUTSZ should be
198 * big enough), so start over.
199 */
200 serial = 0;
201 break;
202 }
203 } while ((fd == -1) && (errno == EEXIST));
204 if (fd != -1) {
205 pushtemp(fd, tb);
206 return (fd);
207 }
208 else
209 failed(tmpout, badcreate);
210 }
211
212 /*
213 * set by trim
214 */
215 extern BOOL nosubst;
216 #define CPYSIZ 512
217
218 void
copy(struct ionod * ioparg)219 copy(struct ionod *ioparg)
220 {
221 unsigned char *cline;
222 unsigned char *clinep;
223 struct ionod *iop;
224 unsigned int c;
225 unsigned char *ends;
226 unsigned char *start;
227 int fd;
228 int i;
229 int stripflg;
230 unsigned char *pc;
231
232
233 if (iop = ioparg) {
234 struct tempblk tb;
235 copy(iop->iolst);
236 ends = mactrim(iop->ioname);
237 stripflg = iop->iofile & IOSTRIP;
238 if (nosubst)
239 iop->iofile &= ~IODOC_SUBST;
240 fd = tmpfil(&tb);
241
242 if (fndef)
243 iop->ioname = (char *)make(tmpout);
244 else
245 iop->ioname = (char *)cpystak(tmpout);
246
247 iop->iolst = iotemp;
248 iotemp = iop;
249
250 cline = clinep = start = locstak();
251 if (stripflg) {
252 iop->iofile &= ~IOSTRIP;
253 while (*ends == '\t')
254 ends++;
255 }
256 for (;;) {
257 chkpr();
258 if (nosubst) {
259 c = readwc();
260 if (stripflg)
261 while (c == '\t')
262 c = readwc();
263
264 while (!eolchar(c)) {
265 pc = readw(c);
266 while (*pc) {
267 if (clinep >= brkend)
268 growstak(clinep);
269 *clinep++ = *pc++;
270 }
271 c = readwc();
272 }
273 } else {
274 c = nextwc();
275 if (stripflg)
276 while (c == '\t')
277 c = nextwc();
278
279 while (!eolchar(c)) {
280 pc = readw(c);
281 while (*pc) {
282 if (clinep >= brkend)
283 growstak(clinep);
284 *clinep++ = *pc++;
285 }
286 if (c == '\\') {
287 pc = readw(readwc());
288 /* *pc might be NULL */
289 /* BEGIN CSTYLED */
290 if (*pc) {
291 while (*pc) {
292 if (clinep >= brkend)
293 growstak(clinep);
294 *clinep++ = *pc++;
295 }
296 } else {
297 if (clinep >= brkend)
298 growstak(clinep);
299 *clinep++ = *pc;
300 }
301 /* END CSTYLED */
302 }
303 c = nextwc();
304 }
305 }
306
307 if (clinep >= brkend)
308 growstak(clinep);
309 *clinep = 0;
310 if (eof || eq(cline, ends)) {
311 if ((i = cline - start) > 0)
312 write(fd, start, i);
313 break;
314 } else {
315 if (clinep >= brkend)
316 growstak(clinep);
317 *clinep++ = NL;
318 }
319
320 if ((i = clinep - start) < CPYSIZ)
321 cline = clinep;
322 else
323 {
324 write(fd, start, i);
325 cline = clinep = start;
326 }
327 }
328
329 /*
330 * Pushed in tmpfil -- bug fix for problem
331 * deleting in-line script.
332 */
333 poptemp();
334 }
335 }
336
337 void
link_iodocs(struct ionod * i)338 link_iodocs(struct ionod *i)
339 {
340 int r;
341 int len;
342 size_t size_left = TMPOUTSZ - tmpout_offset;
343
344 while (i) {
345 free(i->iolink);
346
347 /* make sure tmp file does not already exist. */
348 do {
349 len = snprintf((char *)&tmpout[tmpout_offset],
350 size_left, "%u", serial);
351 serial++;
352 r = link(i->ioname, (char *)tmpout);
353 if ((serial >= UINT_MAX) || (len >= size_left)) {
354 /*
355 * We've already cycled through all the possible
356 * numbers or the tmp file name is being
357 * truncated anyway, so start over.
358 */
359 serial = 0;
360 break;
361 }
362 } while (r == -1 && errno == EEXIST);
363
364 if (r != -1) {
365 i->iolink = (char *)make(tmpout);
366 i = i->iolst;
367 } else
368 failed(tmpout, badcreate);
369
370 }
371 }
372
373 void
swap_iodoc_nm(struct ionod * i)374 swap_iodoc_nm(struct ionod *i)
375 {
376 while (i) {
377 free(i->ioname);
378 i->ioname = i->iolink;
379 i->iolink = 0;
380
381 i = i->iolst;
382 }
383 }
384
385 int
savefd(int fd)386 savefd(int fd)
387 {
388 int f;
389
390 f = fcntl(fd, F_DUPFD, 10);
391 /* this saved fd should not be found in an exec'ed cmd */
392 (void) fcntl(f, F_SETFD, FD_CLOEXEC);
393 return (f);
394 }
395
396 void
restore(int last)397 restore(int last)
398 {
399 int i;
400 int dupfd;
401
402 for (i = topfd - 1; i >= last; i--) {
403 if ((dupfd = fdmap[i].dup_fd) > 0)
404 renamef(dupfd, fdmap[i].org_fd);
405 else
406 close(fdmap[i].org_fd);
407 }
408 topfd = last;
409 }
410