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