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 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 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 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 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 101 pushtemp(int fd, struct tempblk *tb) 102 { 103 tb->fdes = fd; 104 tb->fstak = tmpfptr; 105 tmpfptr = tb; 106 } 107 108 int 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 120 chkpipe(int *pv) 121 { 122 if (pipe(pv) < 0 || pv[INPIPE] < 0 || pv[OTPIPE] < 0) 123 error(piperr); 124 } 125 126 int 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 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 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 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 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 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 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 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 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