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