/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
/*
* UNIX shell
*/
#include "defs.h"
#include "dup.h"
#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
short topfd;
/* ======== input output and file copying ======== */
void
initf(int fd)
{
struct fileblk *f = standin;
f->fdes = fd;
f->fsiz = ((flags & oneflg) == 0 ? BUFFERSIZE : 1);
f->fnxt = f->fend = f->fbuf;
f->nxtoff = f->endoff = 0;
f->feval = 0;
f->flin = 1;
f->feof = FALSE;
}
int
estabf(unsigned char *s)
{
struct fileblk *f;
(f = standin)->fdes = -1;
f->fend = length(s) + (f->fnxt = s);
f->nxtoff = 0;
f->endoff = length(s);
f->flin = 1;
return (f->feof = (s == 0));
}
void
push(struct fileblk *af)
{
struct fileblk *f;
(f = af)->fstak = standin;
f->feof = 0;
f->feval = 0;
standin = f;
}
int
pop(void)
{
struct fileblk *f;
if ((f = standin)->fstak) {
if (f->fdes >= 0)
close(f->fdes);
standin = f->fstak;
return (TRUE);
} else
return (FALSE);
}
struct tempblk *tmpfptr;
void
pushtemp(int fd, struct tempblk *tb)
{
tb->fdes = fd;
tb->fstak = tmpfptr;
tmpfptr = tb;
}
int
poptemp(void)
{
if (tmpfptr) {
close(tmpfptr->fdes);
tmpfptr = tmpfptr->fstak;
return (TRUE);
} else
return (FALSE);
}
void
chkpipe(int *pv)
{
if (pipe(pv) < 0 || pv[INPIPE] < 0 || pv[OTPIPE] < 0)
error(piperr);
}
int
chkopen(unsigned char *idf, int mode)
{
int rc;
if ((rc = open((char *)idf, mode, 0666)) < 0)
failed(idf, badopen);
else
return (rc);
}
/*
* Make f2 be a synonym (including the close-on-exec flag) for f1, which is
* then closed. If f2 is descriptor 0, modify the global ioset variable
* accordingly.
*/
void
renamef(int f1, int f2)
{
#ifdef RES
if (f1 != f2) {
dup(f1 | DUPFLG, f2);
close(f1);
if (f2 == 0)
ioset |= 1;
}
#else
int fs;
if (f1 != f2) {
fs = fcntl(f2, 1, 0);
close(f2);
fcntl(f1, 0, f2);
close(f1);
if (fs == 1)
fcntl(f2, 2, 1);
if (f2 == 0)
ioset |= 1;
}
#endif
}
int
create(unsigned char *s)
{
int rc;
if ((rc = creat((char *)s, 0666)) < 0)
failed(s, badcreate);
else
return (rc);
}
int
tmpfil(struct tempblk *tb)
{
int fd;
int len;
size_t size_left = TMPOUTSZ - tmpout_offset;
/* make sure tmp file does not already exist. */
do {
len = snprintf((char *)&tmpout[tmpout_offset], size_left,
"%u", serial);
fd = open((char *)tmpout, O_RDWR|O_CREAT|O_EXCL, 0600);
serial++;
if ((serial >= UINT_MAX) || (len >= size_left)) {
/*
* We've already cycled through all the possible
* numbers or the tmp file name is being
* truncated anyway (although TMPOUTSZ should be
* big enough), so start over.
*/
serial = 0;
break;
}
} while ((fd == -1) && (errno == EEXIST));
if (fd != -1) {
pushtemp(fd, tb);
return (fd);
}
else
failed(tmpout, badcreate);
}
/*
* set by trim
*/
extern BOOL nosubst;
#define CPYSIZ 512
void
copy(struct ionod *ioparg)
{
unsigned char *cline;
unsigned char *clinep;
struct ionod *iop;
unsigned int c;
unsigned char *ends;
unsigned char *start;
int fd;
int i;
int stripflg;
unsigned char *pc;
if (iop = ioparg) {
struct tempblk tb;
copy(iop->iolst);
ends = mactrim(iop->ioname);
stripflg = iop->iofile & IOSTRIP;
if (nosubst)
iop->iofile &= ~IODOC_SUBST;
fd = tmpfil(&tb);
if (fndef)
iop->ioname = (char *)make(tmpout);
else
iop->ioname = (char *)cpystak(tmpout);
iop->iolst = iotemp;
iotemp = iop;
cline = clinep = start = locstak();
if (stripflg) {
iop->iofile &= ~IOSTRIP;
while (*ends == '\t')
ends++;
}
for (;;) {
chkpr();
if (nosubst) {
c = readwc();
if (stripflg)
while (c == '\t')
c = readwc();
while (!eolchar(c)) {
pc = readw(c);
while (*pc) {
if (clinep >= brkend)
growstak(clinep);
*clinep++ = *pc++;
}
c = readwc();
}
} else {
c = nextwc();
if (stripflg)
while (c == '\t')
c = nextwc();
while (!eolchar(c)) {
pc = readw(c);
while (*pc) {
if (clinep >= brkend)
growstak(clinep);
*clinep++ = *pc++;
}
if (c == '\\') {
pc = readw(readwc());
/* *pc might be NULL */
/* BEGIN CSTYLED */
if (*pc) {
while (*pc) {
if (clinep >= brkend)
growstak(clinep);
*clinep++ = *pc++;
}
} else {
if (clinep >= brkend)
growstak(clinep);
*clinep++ = *pc;
}
/* END CSTYLED */
}
c = nextwc();
}
}
if (clinep >= brkend)
growstak(clinep);
*clinep = 0;
if (eof || eq(cline, ends)) {
if ((i = cline - start) > 0)
write(fd, start, i);
break;
} else {
if (clinep >= brkend)
growstak(clinep);
*clinep++ = NL;
}
if ((i = clinep - start) < CPYSIZ)
cline = clinep;
else
{
write(fd, start, i);
cline = clinep = start;
}
}
/*
* Pushed in tmpfil -- bug fix for problem
* deleting in-line script.
*/
poptemp();
}
}
void
link_iodocs(struct ionod *i)
{
int r;
int len;
size_t size_left = TMPOUTSZ - tmpout_offset;
while (i) {
free(i->iolink);
/* make sure tmp file does not already exist. */
do {
len = snprintf((char *)&tmpout[tmpout_offset],
size_left, "%u", serial);
serial++;
r = link(i->ioname, (char *)tmpout);
if ((serial >= UINT_MAX) || (len >= size_left)) {
/*
* We've already cycled through all the possible
* numbers or the tmp file name is being
* truncated anyway, so start over.
*/
serial = 0;
break;
}
} while (r == -1 && errno == EEXIST);
if (r != -1) {
i->iolink = (char *)make(tmpout);
i = i->iolst;
} else
failed(tmpout, badcreate);
}
}
void
swap_iodoc_nm(struct ionod *i)
{
while (i) {
free(i->ioname);
i->ioname = i->iolink;
i->iolink = 0;
i = i->iolst;
}
}
int
savefd(int fd)
{
int f;
f = fcntl(fd, F_DUPFD, 10);
/* this saved fd should not be found in an exec'ed cmd */
(void) fcntl(f, F_SETFD, FD_CLOEXEC);
return (f);
}
void
restore(int last)
{
int i;
int dupfd;
for (i = topfd - 1; i >= last; i--) {
if ((dupfd = fdmap[i].dup_fd) > 0)
renamef(dupfd, fdmap[i].org_fd);
else
close(fdmap[i].org_fd);
}
topfd = last;
}