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