1da2e3ebdSchin /***********************************************************************
2da2e3ebdSchin *                                                                      *
3da2e3ebdSchin *               This software is part of the ast package               *
4*b30d1939SAndy Fiddaman *          Copyright (c) 1982-2012 AT&T Intellectual Property          *
5da2e3ebdSchin *                      and is licensed under the                       *
6*b30d1939SAndy Fiddaman *                 Eclipse Public License, Version 1.0                  *
77c2fbfb3SApril Chin *                    by AT&T Intellectual Property                     *
8da2e3ebdSchin *                                                                      *
9da2e3ebdSchin *                A copy of the License is available at                 *
10*b30d1939SAndy Fiddaman *          http://www.eclipse.org/org/documents/epl-v10.html           *
11*b30d1939SAndy Fiddaman *         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
12da2e3ebdSchin *                                                                      *
13da2e3ebdSchin *              Information and Software Systems Research               *
14da2e3ebdSchin *                            AT&T Research                             *
15da2e3ebdSchin *                           Florham Park NJ                            *
16da2e3ebdSchin *                                                                      *
17da2e3ebdSchin *                  David Korn <dgk@research.att.com>                   *
18da2e3ebdSchin *                                                                      *
19da2e3ebdSchin ***********************************************************************/
20da2e3ebdSchin #pragma prototyped
21da2e3ebdSchin /*
227c2fbfb3SApril Chin  * read [-ACprs] [-d delim] [-u filenum] [-t timeout] [-n n] [-N n] [name...]
23da2e3ebdSchin  *
24da2e3ebdSchin  *   David Korn
25da2e3ebdSchin  *   AT&T Labs
26da2e3ebdSchin  *
27da2e3ebdSchin  */
28da2e3ebdSchin 
29da2e3ebdSchin #include	<ast.h>
30da2e3ebdSchin #include	<error.h>
31da2e3ebdSchin #include	"defs.h"
32da2e3ebdSchin #include	"variables.h"
33da2e3ebdSchin #include	"lexstates.h"
34da2e3ebdSchin #include	"io.h"
35da2e3ebdSchin #include	"name.h"
36da2e3ebdSchin #include	"builtins.h"
37da2e3ebdSchin #include	"history.h"
38da2e3ebdSchin #include	"terminal.h"
39da2e3ebdSchin #include	"edit.h"
40da2e3ebdSchin 
41da2e3ebdSchin #define	R_FLAG	1	/* raw mode */
42da2e3ebdSchin #define	S_FLAG	2	/* save in history file */
43da2e3ebdSchin #define	A_FLAG	4	/* read into array */
44da2e3ebdSchin #define N_FLAG	8	/* fixed size read at most */
45da2e3ebdSchin #define NN_FLAG	0x10	/* fixed size read exact */
46da2e3ebdSchin #define V_FLAG	0x20	/* use default value */
477c2fbfb3SApril Chin #define	C_FLAG	0x40	/* read into compound variable */
48da2e3ebdSchin #define D_FLAG	8	/* must be number of bits for all flags */
49*b30d1939SAndy Fiddaman #define	SS_FLAG	0x80	/* read .csv format file */
50da2e3ebdSchin 
517c2fbfb3SApril Chin struct read_save
527c2fbfb3SApril Chin {
537c2fbfb3SApril Chin         char	**argv;
547c2fbfb3SApril Chin 	char	*prompt;
557c2fbfb3SApril Chin         short	fd;
567c2fbfb3SApril Chin         short	plen;
577c2fbfb3SApril Chin 	int	flags;
58*b30d1939SAndy Fiddaman 	ssize_t	len;
597c2fbfb3SApril Chin         long	timeout;
607c2fbfb3SApril Chin };
617c2fbfb3SApril Chin 
b_read(int argc,char * argv[],Shbltin_t * context)62*b30d1939SAndy Fiddaman int	b_read(int argc,char *argv[], Shbltin_t *context)
63da2e3ebdSchin {
64da2e3ebdSchin 	Sfdouble_t sec;
65da2e3ebdSchin 	register char *name;
66da2e3ebdSchin 	register int r, flags=0, fd=0;
67*b30d1939SAndy Fiddaman 	register Shell_t *shp = context->shp;
68*b30d1939SAndy Fiddaman 	ssize_t	len=0;
69da2e3ebdSchin 	long timeout = 1000*shp->st.tmout;
70*b30d1939SAndy Fiddaman 	int save_prompt, fixargs=context->invariant;
717c2fbfb3SApril Chin 	struct read_save *rp;
72da2e3ebdSchin 	static char default_prompt[3] = {ESC,ESC};
73*b30d1939SAndy Fiddaman 	rp = (struct read_save*)(context->data);
747c2fbfb3SApril Chin 	if(argc==0)
7534f9b3eeSRoland Mainz 	{
7634f9b3eeSRoland Mainz 		if(rp)
7734f9b3eeSRoland Mainz 			free((void*)rp);
787c2fbfb3SApril Chin 		return(0);
7934f9b3eeSRoland Mainz 	}
8034f9b3eeSRoland Mainz 	if(rp)
817c2fbfb3SApril Chin 	{
827c2fbfb3SApril Chin 		flags = rp->flags;
837c2fbfb3SApril Chin 		timeout = rp->timeout;
847c2fbfb3SApril Chin 		fd = rp->fd;
857c2fbfb3SApril Chin 		argv = rp->argv;
867c2fbfb3SApril Chin 		name = rp->prompt;
877c2fbfb3SApril Chin 		r = rp->plen;
887c2fbfb3SApril Chin 		goto bypass;
897c2fbfb3SApril Chin 	}
90da2e3ebdSchin 	while((r = optget(argv,sh_optread))) switch(r)
91da2e3ebdSchin 	{
92da2e3ebdSchin 	    case 'A':
93da2e3ebdSchin 		flags |= A_FLAG;
94da2e3ebdSchin 		break;
957c2fbfb3SApril Chin 	    case 'C':
967c2fbfb3SApril Chin 		flags |= C_FLAG;
977c2fbfb3SApril Chin 		break;
98da2e3ebdSchin 	    case 't':
99da2e3ebdSchin 		sec = sh_strnum(opt_info.arg, (char**)0,1);
100da2e3ebdSchin 		timeout = sec ? 1000*sec : 1;
101da2e3ebdSchin 		break;
102da2e3ebdSchin 	    case 'd':
103da2e3ebdSchin 		if(opt_info.arg && *opt_info.arg!='\n')
104da2e3ebdSchin 		{
105da2e3ebdSchin 			char *cp = opt_info.arg;
106da2e3ebdSchin 			flags &= ~((1<<D_FLAG)-1);
107da2e3ebdSchin 			flags |= (mbchar(cp)<< D_FLAG);
108da2e3ebdSchin 		}
109da2e3ebdSchin 		break;
110da2e3ebdSchin 	    case 'p':
111da2e3ebdSchin 		if((fd = shp->cpipe[0])<=0)
112da2e3ebdSchin 			errormsg(SH_DICT,ERROR_exit(1),e_query);
113da2e3ebdSchin 		break;
114da2e3ebdSchin 	    case 'n': case 'N':
1157c2fbfb3SApril Chin 		flags &= ((1<<D_FLAG)-1);
116da2e3ebdSchin 		flags |= (r=='n'?N_FLAG:NN_FLAG);
117*b30d1939SAndy Fiddaman 		len = opt_info.num;
118da2e3ebdSchin 		break;
119da2e3ebdSchin 	    case 'r':
120da2e3ebdSchin 		flags |= R_FLAG;
121da2e3ebdSchin 		break;
122da2e3ebdSchin 	    case 's':
123da2e3ebdSchin 		/* save in history file */
124da2e3ebdSchin 		flags |= S_FLAG;
125da2e3ebdSchin 		break;
126*b30d1939SAndy Fiddaman 	    case 'S':
127*b30d1939SAndy Fiddaman 		flags |= SS_FLAG;
128*b30d1939SAndy Fiddaman 		break;
129da2e3ebdSchin 	    case 'u':
130da2e3ebdSchin 		fd = (int)opt_info.num;
131*b30d1939SAndy Fiddaman 		if(sh_inuse(shp,fd))
132da2e3ebdSchin 			fd = -1;
133da2e3ebdSchin 		break;
134da2e3ebdSchin 	    case 'v':
135da2e3ebdSchin 		flags |= V_FLAG;
136da2e3ebdSchin 		break;
137da2e3ebdSchin 	    case ':':
138da2e3ebdSchin 		errormsg(SH_DICT,2, "%s", opt_info.arg);
139da2e3ebdSchin 		break;
140da2e3ebdSchin 	    case '?':
141da2e3ebdSchin 		errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
142da2e3ebdSchin 		break;
143da2e3ebdSchin 	}
144da2e3ebdSchin 	argv += opt_info.index;
145da2e3ebdSchin 	if(error_info.errors)
146da2e3ebdSchin 		errormsg(SH_DICT,ERROR_usage(2), "%s", optusage((char*)0));
147da2e3ebdSchin 	if(!((r=shp->fdstatus[fd])&IOREAD)  || !(r&(IOSEEK|IONOSEEK)))
1487c2fbfb3SApril Chin 		r = sh_iocheckfd(shp,fd);
149da2e3ebdSchin 	if(fd<0 || !(r&IOREAD))
150da2e3ebdSchin 		errormsg(SH_DICT,ERROR_system(1),e_file+4);
151da2e3ebdSchin 	/* look for prompt */
152da2e3ebdSchin 	if((name = *argv) && (name=strchr(name,'?')) && (r&IOTTY))
1537c2fbfb3SApril Chin 		r = strlen(name++);
1547c2fbfb3SApril Chin 	else
1557c2fbfb3SApril Chin 		r = 0;
1567c2fbfb3SApril Chin 	if(argc==fixargs && (rp=newof(NIL(struct read_save*),struct read_save,1,0)))
157da2e3ebdSchin 	{
158*b30d1939SAndy Fiddaman 		context->data = (void*)rp;
1597c2fbfb3SApril Chin 		rp->fd = fd;
1607c2fbfb3SApril Chin 		rp->flags = flags;
1617c2fbfb3SApril Chin 		rp->timeout = timeout;
1627c2fbfb3SApril Chin 		rp->argv = argv;
1637c2fbfb3SApril Chin 		rp->prompt = name;
1647c2fbfb3SApril Chin 		rp->plen = r;
165*b30d1939SAndy Fiddaman 		rp->len = len;
1667c2fbfb3SApril Chin 	}
1677c2fbfb3SApril Chin bypass:
1683e14f97fSRoger A. Faulkner 	shp->prompt = default_prompt;
1697c2fbfb3SApril Chin 	if(r && (shp->prompt=(char*)sfreserve(sfstderr,r,SF_LOCKR)))
1707c2fbfb3SApril Chin 	{
1717c2fbfb3SApril Chin 		memcpy(shp->prompt,name,r);
1727c2fbfb3SApril Chin 		sfwrite(sfstderr,shp->prompt,r-1);
173da2e3ebdSchin 	}
174da2e3ebdSchin 	shp->timeout = 0;
175da2e3ebdSchin 	save_prompt = shp->nextprompt;
176da2e3ebdSchin 	shp->nextprompt = 0;
177*b30d1939SAndy Fiddaman 	r=sh_readline(shp,argv,fd,flags,len,timeout);
178da2e3ebdSchin 	shp->nextprompt = save_prompt;
179da2e3ebdSchin 	if(r==0 && (r=(sfeof(shp->sftable[fd])||sferror(shp->sftable[fd]))))
180da2e3ebdSchin 	{
181*b30d1939SAndy Fiddaman 		if(fd == shp->cpipe[0] && errno!=EINTR)
182da2e3ebdSchin 			sh_pclose(shp->cpipe);
183da2e3ebdSchin 	}
184da2e3ebdSchin 	return(r);
185da2e3ebdSchin }
186da2e3ebdSchin 
187da2e3ebdSchin /*
188da2e3ebdSchin  * here for read timeout
189da2e3ebdSchin  */
timedout(void * handle)190da2e3ebdSchin static void timedout(void *handle)
191da2e3ebdSchin {
192da2e3ebdSchin 	sfclrlock((Sfio_t*)handle);
193da2e3ebdSchin 	sh_exit(1);
194da2e3ebdSchin }
195da2e3ebdSchin 
196da2e3ebdSchin /*
197da2e3ebdSchin  * This is the code to read a line and to split it into tokens
198da2e3ebdSchin  *  <names> is an array of variable names
199da2e3ebdSchin  *  <fd> is the file descriptor
200da2e3ebdSchin  *  <flags> is union of -A, -r, -s, and contains delimiter if not '\n'
201da2e3ebdSchin  *  <timeout> is number of milli-seconds until timeout
202da2e3ebdSchin  */
203da2e3ebdSchin 
sh_readline(register Shell_t * shp,char ** names,volatile int fd,int flags,ssize_t size,long timeout)204*b30d1939SAndy Fiddaman int sh_readline(register Shell_t *shp,char **names, volatile int fd, int flags,ssize_t size,long timeout)
205da2e3ebdSchin {
20634f9b3eeSRoland Mainz 	register ssize_t	c;
207da2e3ebdSchin 	register unsigned char	*cp;
208da2e3ebdSchin 	register Namval_t	*np;
209da2e3ebdSchin 	register char		*name, *val;
2107c2fbfb3SApril Chin 	register Sfio_t		*iop;
2117c2fbfb3SApril Chin 	Namfun_t		*nfp;
212da2e3ebdSchin 	char			*ifs;
213da2e3ebdSchin 	unsigned char		*cpmax;
214da2e3ebdSchin 	unsigned char		*del;
215da2e3ebdSchin 	char			was_escape = 0;
216da2e3ebdSchin 	char			use_stak = 0;
2177c2fbfb3SApril Chin 	volatile char		was_write = 0;
2187c2fbfb3SApril Chin 	volatile char		was_share = 1;
219*b30d1939SAndy Fiddaman 	volatile int		keytrap;
220da2e3ebdSchin 	int			rel, wrd;
221da2e3ebdSchin 	long			array_index = 0;
222da2e3ebdSchin 	void			*timeslot=0;
223da2e3ebdSchin 	int			delim = '\n';
224da2e3ebdSchin 	int			jmpval=0;
2257c2fbfb3SApril Chin 	int			binary;
226*b30d1939SAndy Fiddaman 	int			oflags=NV_ASSIGN|NV_VARNAME;
227*b30d1939SAndy Fiddaman 	char			inquote = 0;
228da2e3ebdSchin 	struct	checkpt		buff;
229*b30d1939SAndy Fiddaman 	Edit_t			*ep = (struct edit*)shp->gd->ed_context;
2307c2fbfb3SApril Chin 	if(!(iop=shp->sftable[fd]) && !(iop=sh_iostream(shp,fd)))
231da2e3ebdSchin 		return(1);
2327c2fbfb3SApril Chin 	sh_stats(STAT_READS);
233da2e3ebdSchin 	if(names && (name = *names))
234da2e3ebdSchin 	{
23534f9b3eeSRoland Mainz 		Namval_t *mp;
236da2e3ebdSchin 		if(val= strchr(name,'?'))
237da2e3ebdSchin 			*val = 0;
238*b30d1939SAndy Fiddaman 		if(flags&C_FLAG)
239*b30d1939SAndy Fiddaman 			oflags |= NV_ARRAY;
240*b30d1939SAndy Fiddaman 		np = nv_open(name,shp->var_tree,oflags);
24134f9b3eeSRoland Mainz 		if(np && nv_isarray(np) && (mp=nv_opensub(np)))
24234f9b3eeSRoland Mainz 			np = mp;
243*b30d1939SAndy Fiddaman 		if((flags&V_FLAG) && shp->gd->ed_context)
244*b30d1939SAndy Fiddaman 			((struct edit*)shp->gd->ed_context)->e_default = np;
245da2e3ebdSchin 		if(flags&A_FLAG)
246da2e3ebdSchin 		{
247*b30d1939SAndy Fiddaman 			Namarr_t *ap;
248da2e3ebdSchin 			flags &= ~A_FLAG;
249da2e3ebdSchin 			array_index = 1;
250*b30d1939SAndy Fiddaman 			if((ap=nv_arrayptr(np)) && !ap->fun)
251*b30d1939SAndy Fiddaman 				ap->nelem++;
252da2e3ebdSchin 			nv_unset(np);
253*b30d1939SAndy Fiddaman 			if((ap=nv_arrayptr(np)) && !ap->fun)
254*b30d1939SAndy Fiddaman 				ap->nelem--;
255da2e3ebdSchin 			nv_putsub(np,NIL(char*),0L);
256da2e3ebdSchin 		}
2577c2fbfb3SApril Chin 		else if(flags&C_FLAG)
2587c2fbfb3SApril Chin 		{
259*b30d1939SAndy Fiddaman 			char *sp =  np->nvenv;
2607c2fbfb3SApril Chin 			delim = -1;
2617c2fbfb3SApril Chin 			nv_unset(np);
262*b30d1939SAndy Fiddaman 			if(!nv_isattr(np,NV_MINIMAL))
263*b30d1939SAndy Fiddaman 				np->nvenv = sp;
2647c2fbfb3SApril Chin 			nv_setvtree(np);
2657c2fbfb3SApril Chin 		}
266da2e3ebdSchin 		else
267da2e3ebdSchin 			name = *++names;
268da2e3ebdSchin 		if(val)
269da2e3ebdSchin 			*val = '?';
270da2e3ebdSchin 	}
271da2e3ebdSchin 	else
272da2e3ebdSchin 	{
273da2e3ebdSchin 		name = 0;
274da2e3ebdSchin 		if(dtvnext(shp->var_tree) || shp->namespace)
275da2e3ebdSchin                 	np = nv_open(nv_name(REPLYNOD),shp->var_tree,0);
276da2e3ebdSchin 		else
277da2e3ebdSchin 			np = REPLYNOD;
278da2e3ebdSchin 	}
279*b30d1939SAndy Fiddaman 	keytrap =  ep?ep->e_keytrap:0;
280*b30d1939SAndy Fiddaman 	if(size || (flags>>D_FLAG))	/* delimiter not new-line or fixed size read */
281da2e3ebdSchin 	{
282*b30d1939SAndy Fiddaman 		if((shp->fdstatus[fd]&IOTTY) && !keytrap)
283da2e3ebdSchin 			tty_raw(fd,1);
284*b30d1939SAndy Fiddaman 		if(!(flags&(N_FLAG|NN_FLAG)))
285*b30d1939SAndy Fiddaman 		{
286*b30d1939SAndy Fiddaman 			delim = ((unsigned)flags)>>D_FLAG;
287*b30d1939SAndy Fiddaman 			ep->e_nttyparm.c_cc[VEOL] = delim;
288*b30d1939SAndy Fiddaman 			ep->e_nttyparm.c_lflag |= ISIG;
289*b30d1939SAndy Fiddaman 			tty_set(fd,TCSADRAIN,&ep->e_nttyparm);
290*b30d1939SAndy Fiddaman 		}
291da2e3ebdSchin 	}
2927c2fbfb3SApril Chin 	binary = nv_isattr(np,NV_BINARY);
2937c2fbfb3SApril Chin 	if(!binary && !(flags&(N_FLAG|NN_FLAG)))
294da2e3ebdSchin 	{
295da2e3ebdSchin 		Namval_t *mp;
296da2e3ebdSchin 		/* set up state table based on IFS */
2977c2fbfb3SApril Chin 		ifs = nv_getval(mp=sh_scoped(shp,IFSNOD));
298da2e3ebdSchin 		if((flags&R_FLAG) && shp->ifstable['\\']==S_ESC)
299da2e3ebdSchin 			shp->ifstable['\\'] = 0;
300da2e3ebdSchin 		else if(!(flags&R_FLAG) && shp->ifstable['\\']==0)
301da2e3ebdSchin 			shp->ifstable['\\'] = S_ESC;
302*b30d1939SAndy Fiddaman 		if(delim>0)
303*b30d1939SAndy Fiddaman 			shp->ifstable[delim] = S_NL;
304da2e3ebdSchin 		if(delim!='\n')
305da2e3ebdSchin 		{
306da2e3ebdSchin 			shp->ifstable['\n'] = 0;
307da2e3ebdSchin 			nv_putval(mp, ifs, NV_RDONLY);
308da2e3ebdSchin 		}
309da2e3ebdSchin 		shp->ifstable[0] = S_EOF;
310*b30d1939SAndy Fiddaman 		if((flags&SS_FLAG))
311*b30d1939SAndy Fiddaman 		{
312*b30d1939SAndy Fiddaman 			shp->ifstable['"'] = S_QUOTE;
313*b30d1939SAndy Fiddaman 			shp->ifstable['\r'] = S_ERR;
314*b30d1939SAndy Fiddaman 		}
315da2e3ebdSchin 	}
316da2e3ebdSchin 	sfclrerr(iop);
3177c2fbfb3SApril Chin 	for(nfp=np->nvfun; nfp; nfp = nfp->next)
3187c2fbfb3SApril Chin 	{
3197c2fbfb3SApril Chin 		if(nfp->disc && nfp->disc->readf)
3207c2fbfb3SApril Chin 		{
321*b30d1939SAndy Fiddaman 			Namval_t *mp = nv_open(name,shp->var_tree,oflags|NV_NOREF);
322*b30d1939SAndy Fiddaman 			if((c=(*nfp->disc->readf)(mp,iop,delim,nfp))>=0)
3237c2fbfb3SApril Chin 				return(c);
3247c2fbfb3SApril Chin 		}
3257c2fbfb3SApril Chin 	}
3267c2fbfb3SApril Chin 	if(binary && !(flags&(N_FLAG|NN_FLAG)))
3277c2fbfb3SApril Chin 	{
3287c2fbfb3SApril Chin 		flags |= NN_FLAG;
3297c2fbfb3SApril Chin 		size = nv_size(np);
3307c2fbfb3SApril Chin 	}
331da2e3ebdSchin 	was_write = (sfset(iop,SF_WRITE,0)&SF_WRITE)!=0;
332da2e3ebdSchin 	if(fd==0)
333*b30d1939SAndy Fiddaman 		was_share = (sfset(iop,SF_SHARE,shp->redir0!=2)&SF_SHARE)!=0;
334da2e3ebdSchin 	if(timeout || (shp->fdstatus[fd]&(IOTTY|IONOSEEK)))
335da2e3ebdSchin 	{
336*b30d1939SAndy Fiddaman 		sh_pushcontext(shp,&buff,1);
337da2e3ebdSchin 		jmpval = sigsetjmp(buff.buff,0);
338da2e3ebdSchin 		if(jmpval)
339da2e3ebdSchin 			goto done;
340da2e3ebdSchin 		if(timeout)
341da2e3ebdSchin 	                timeslot = (void*)sh_timeradd(timeout,0,timedout,(void*)iop);
342da2e3ebdSchin 	}
343da2e3ebdSchin 	if(flags&(N_FLAG|NN_FLAG))
344da2e3ebdSchin 	{
34534f9b3eeSRoland Mainz 		char buf[256],*var=buf,*cur,*end,*up,*v;
346da2e3ebdSchin 		/* reserved buffer */
347da2e3ebdSchin 		if((c=size)>=sizeof(buf))
348da2e3ebdSchin 		{
349da2e3ebdSchin 			if(!(var = (char*)malloc(c+1)))
350da2e3ebdSchin 				sh_exit(1);
3517c2fbfb3SApril Chin 			end = var + c;
352da2e3ebdSchin 		}
3537c2fbfb3SApril Chin 		else
3547c2fbfb3SApril Chin 			end = var + sizeof(buf) - 1;
3557c2fbfb3SApril Chin 		up = cur = var;
356da2e3ebdSchin 		if((sfset(iop,SF_SHARE,1)&SF_SHARE) && fd!=0)
357da2e3ebdSchin 			was_share = 1;
358da2e3ebdSchin 		if(size==0)
359da2e3ebdSchin 		{
360da2e3ebdSchin 			cp = sfreserve(iop,0,0);
361da2e3ebdSchin 			c = 0;
362da2e3ebdSchin 		}
363da2e3ebdSchin 		else
364da2e3ebdSchin 		{
36534f9b3eeSRoland Mainz 			ssize_t	m;
36634f9b3eeSRoland Mainz 			int	f;
3677c2fbfb3SApril Chin 			for (;;)
368da2e3ebdSchin 			{
3693e14f97fSRoger A. Faulkner 				c = size;
370*b30d1939SAndy Fiddaman 				if(keytrap)
3717c2fbfb3SApril Chin 				{
372*b30d1939SAndy Fiddaman 					cp = 0;
37334f9b3eeSRoland Mainz 					f = 0;
374*b30d1939SAndy Fiddaman 					m = 0;
375*b30d1939SAndy Fiddaman 					while(c-->0 && (buf[m]=ed_getchar(ep,0)))
376*b30d1939SAndy Fiddaman 						m++;
377*b30d1939SAndy Fiddaman 					if(m>0)
378*b30d1939SAndy Fiddaman 						cp = (unsigned char*)buf;
37934f9b3eeSRoland Mainz 				}
3803e14f97fSRoger A. Faulkner 				else
3813e14f97fSRoger A. Faulkner 				{
382*b30d1939SAndy Fiddaman 					f = 1;
383*b30d1939SAndy Fiddaman 					if(cp = sfreserve(iop,c,SF_LOCKR))
384*b30d1939SAndy Fiddaman 						m = sfvalue(iop);
385*b30d1939SAndy Fiddaman 					else if(flags&NN_FLAG)
386*b30d1939SAndy Fiddaman 					{
387*b30d1939SAndy Fiddaman 						c = size;
388*b30d1939SAndy Fiddaman 						m = (cp = sfreserve(iop,c,0)) ? sfvalue(iop) : 0;
389*b30d1939SAndy Fiddaman 						f = 0;
390*b30d1939SAndy Fiddaman 					}
391*b30d1939SAndy Fiddaman 					else
392*b30d1939SAndy Fiddaman 					{
393*b30d1939SAndy Fiddaman 						c = sfvalue(iop);
394*b30d1939SAndy Fiddaman 						m = (cp = sfreserve(iop,c,SF_LOCKR)) ? sfvalue(iop) : 0;
395*b30d1939SAndy Fiddaman 					}
3963e14f97fSRoger A. Faulkner 				}
39734f9b3eeSRoland Mainz 				if(m>0 && (flags&N_FLAG) && !binary && (v=memchr(cp,'\n',m)))
39834f9b3eeSRoland Mainz 				{
39934f9b3eeSRoland Mainz 					*v++ = 0;
40034f9b3eeSRoland Mainz 					m = v-(char*)cp;
4017c2fbfb3SApril Chin 				}
4027c2fbfb3SApril Chin 				if((c=m)>size)
4037c2fbfb3SApril Chin 					c = size;
4047c2fbfb3SApril Chin 				if(c>0)
4057c2fbfb3SApril Chin 				{
4067c2fbfb3SApril Chin 					if(c > (end-cur))
4077c2fbfb3SApril Chin 					{
40834f9b3eeSRoland Mainz 						ssize_t	cx = cur - var, ux = up - var;
40934f9b3eeSRoland Mainz 						m = (end - var) + (c - (end - cur));
4107c2fbfb3SApril Chin 						if (var == buf)
4117c2fbfb3SApril Chin 						{
4127c2fbfb3SApril Chin 							v = (char*)malloc(m+1);
41334f9b3eeSRoland Mainz 							var = memcpy(v, var, cur - var);
4147c2fbfb3SApril Chin 						}
4157c2fbfb3SApril Chin 						else
41634f9b3eeSRoland Mainz 							var = newof(var, char, m, 1);
41734f9b3eeSRoland Mainz 						end = var + m;
41834f9b3eeSRoland Mainz 						cur = var + cx;
41934f9b3eeSRoland Mainz 						up = var + ux;
4207c2fbfb3SApril Chin 					}
421*b30d1939SAndy Fiddaman 					if(cur!=(char*)cp)
422*b30d1939SAndy Fiddaman 						memcpy((void*)cur,cp,c);
4237c2fbfb3SApril Chin 					if(f)
4247c2fbfb3SApril Chin 						sfread(iop,cp,c);
4257c2fbfb3SApril Chin 					cur += c;
4267c2fbfb3SApril Chin #if SHOPT_MULTIBYTE
4277c2fbfb3SApril Chin 					if(!binary && mbwide())
4287c2fbfb3SApril Chin 					{
4297c2fbfb3SApril Chin 						int	x;
4307c2fbfb3SApril Chin 						int	z;
4317c2fbfb3SApril Chin 
4327c2fbfb3SApril Chin 						mbinit();
4337c2fbfb3SApril Chin 						*cur = 0;
4347c2fbfb3SApril Chin 						x = z = 0;
4357c2fbfb3SApril Chin 						while (up < cur && (z = mbsize(up)) > 0)
4367c2fbfb3SApril Chin 						{
4377c2fbfb3SApril Chin 							up += z;
4387c2fbfb3SApril Chin 							x++;
4397c2fbfb3SApril Chin 						}
4407c2fbfb3SApril Chin 						if((size -= x) > 0 && (up >= cur || z < 0) && ((flags & NN_FLAG) || z < 0 || m > c))
4417c2fbfb3SApril Chin 							continue;
4427c2fbfb3SApril Chin 					}
4437c2fbfb3SApril Chin #endif
4447c2fbfb3SApril Chin 				}
4457c2fbfb3SApril Chin #if SHOPT_MULTIBYTE
4467c2fbfb3SApril Chin 				if(!binary && mbwide() && (up == var || (flags & NN_FLAG) && size))
4477c2fbfb3SApril Chin 					cur = var;
4487c2fbfb3SApril Chin #endif
4497c2fbfb3SApril Chin 				*cur = 0;
4503e14f97fSRoger A. Faulkner 				if(c>=size || (flags&N_FLAG) || m==0)
4513e14f97fSRoger A. Faulkner 				{
4523e14f97fSRoger A. Faulkner 					if(m)
4533e14f97fSRoger A. Faulkner 						sfclrerr(iop);
4543e14f97fSRoger A. Faulkner 					break;
4553e14f97fSRoger A. Faulkner 				}
4563e14f97fSRoger A. Faulkner 				size -= c;
457da2e3ebdSchin 			}
458da2e3ebdSchin 		}
459da2e3ebdSchin 		if(timeslot)
460da2e3ebdSchin 			timerdel(timeslot);
46134f9b3eeSRoland Mainz 		if(binary && !((size=nv_size(np)) && nv_isarray(np) && c!=size))
462da2e3ebdSchin 		{
46334f9b3eeSRoland Mainz 			if((c==size) && np->nvalue.cp && !nv_isarray(np))
4647c2fbfb3SApril Chin 				memcpy((char*)np->nvalue.cp,var,c);
4657c2fbfb3SApril Chin 			else
4667c2fbfb3SApril Chin 			{
46734f9b3eeSRoland Mainz 				Namval_t *mp;
4687c2fbfb3SApril Chin 				if(var==buf)
4693e14f97fSRoger A. Faulkner 					var = memdup(var,c+1);
4707c2fbfb3SApril Chin 				nv_putval(np,var,NV_RAW);
4717c2fbfb3SApril Chin 				nv_setsize(np,c);
47234f9b3eeSRoland Mainz 				if(!nv_isattr(np,NV_IMPORT|NV_EXPORT)  && (mp=(Namval_t*)np->nvenv))
47334f9b3eeSRoland Mainz 					nv_setsize(mp,c);
4747c2fbfb3SApril Chin 			}
475da2e3ebdSchin 		}
476da2e3ebdSchin 		else
477da2e3ebdSchin 		{
478da2e3ebdSchin 			nv_putval(np,var,0);
4797c2fbfb3SApril Chin 			if(var!=buf)
480da2e3ebdSchin 				free((void*)var);
481da2e3ebdSchin 		}
482da2e3ebdSchin 		goto done;
483da2e3ebdSchin 	}
484da2e3ebdSchin 	else if(cp = (unsigned char*)sfgetr(iop,delim,0))
485da2e3ebdSchin 		c = sfvalue(iop);
486da2e3ebdSchin 	else if(cp = (unsigned char*)sfgetr(iop,delim,-1))
487*b30d1939SAndy Fiddaman 	{
488da2e3ebdSchin 		c = sfvalue(iop)+1;
489*b30d1939SAndy Fiddaman 		if(!sferror(iop) && sfgetc(iop) >=0)
490*b30d1939SAndy Fiddaman 			errormsg(SH_DICT,ERROR_exit(1),e_overlimit,"line length");
491*b30d1939SAndy Fiddaman 	}
492da2e3ebdSchin 	if(timeslot)
493da2e3ebdSchin 		timerdel(timeslot);
494*b30d1939SAndy Fiddaman 	if((flags&S_FLAG) && !shp->gd->hist_ptr)
495da2e3ebdSchin 	{
4967c2fbfb3SApril Chin 		sh_histinit((void*)shp);
497*b30d1939SAndy Fiddaman 		if(!shp->gd->hist_ptr)
498da2e3ebdSchin 			flags &= ~S_FLAG;
499da2e3ebdSchin 	}
500da2e3ebdSchin 	if(cp)
501da2e3ebdSchin 	{
502da2e3ebdSchin 		cpmax = cp + c;
503da2e3ebdSchin #if SHOPT_CRNL
504da2e3ebdSchin 		if(delim=='\n' && c>=2 && cpmax[-2]=='\r')
505da2e3ebdSchin 			cpmax--;
506da2e3ebdSchin #endif /* SHOPT_CRNL */
507da2e3ebdSchin 		if(*(cpmax-1) != delim)
508da2e3ebdSchin 			*(cpmax-1) = delim;
509da2e3ebdSchin 		if(flags&S_FLAG)
510*b30d1939SAndy Fiddaman 			sfwrite(shp->gd->hist_ptr->histfp,(char*)cp,c);
511da2e3ebdSchin 		c = shp->ifstable[*cp++];
512da2e3ebdSchin #if !SHOPT_MULTIBYTE
513da2e3ebdSchin 		if(!name && (flags&R_FLAG)) /* special case single argument */
514da2e3ebdSchin 		{
515da2e3ebdSchin 			/* skip over leading blanks */
516da2e3ebdSchin 			while(c==S_SPACE)
517da2e3ebdSchin 				c = shp->ifstable[*cp++];
518da2e3ebdSchin 			/* strip trailing delimiters */
519da2e3ebdSchin 			if(cpmax[-1] == '\n')
520da2e3ebdSchin 				cpmax--;
521da2e3ebdSchin 			if(cpmax>cp)
522da2e3ebdSchin 			{
523da2e3ebdSchin 				while((c=shp->ifstable[*--cpmax])==S_DELIM || c==S_SPACE);
524da2e3ebdSchin 				cpmax[1] = 0;
525da2e3ebdSchin 			}
526da2e3ebdSchin 			else
527da2e3ebdSchin 				*cpmax =0;
528da2e3ebdSchin 			if(nv_isattr(np, NV_RDONLY))
529da2e3ebdSchin 			{
530da2e3ebdSchin 				errormsg(SH_DICT,ERROR_warn(0),e_readonly, nv_name(np));
531da2e3ebdSchin 				jmpval = 1;
532da2e3ebdSchin 			}
533da2e3ebdSchin 			else
534da2e3ebdSchin 				nv_putval(np,(char*)cp-1,0);
535da2e3ebdSchin 			goto done;
536da2e3ebdSchin 		}
537da2e3ebdSchin #endif /* !SHOPT_MULTIBYTE */
538da2e3ebdSchin 	}
539da2e3ebdSchin 	else
540da2e3ebdSchin 		c = S_NL;
541da2e3ebdSchin 	shp->nextprompt = 2;
542da2e3ebdSchin 	rel= staktell();
543da2e3ebdSchin 	/* val==0 at the start of a field */
544da2e3ebdSchin 	val = 0;
545da2e3ebdSchin 	del = 0;
546da2e3ebdSchin 	while(1)
547da2e3ebdSchin 	{
548da2e3ebdSchin 		switch(c)
549da2e3ebdSchin 		{
550da2e3ebdSchin #if SHOPT_MULTIBYTE
551da2e3ebdSchin 		   case S_MBYTE:
552da2e3ebdSchin 			if(val==0)
553da2e3ebdSchin 				val = (char*)(cp-1);
554da2e3ebdSchin 			if(sh_strchr(ifs,(char*)cp-1)>=0)
555da2e3ebdSchin 			{
556da2e3ebdSchin 				c = mbsize((char*)cp-1);
557da2e3ebdSchin 				if(name)
558da2e3ebdSchin 					cp[-1] = 0;
559da2e3ebdSchin 				if(c>1)
560da2e3ebdSchin 					cp += (c-1);
561da2e3ebdSchin 				c = S_DELIM;
562da2e3ebdSchin 			}
563da2e3ebdSchin 			else
564da2e3ebdSchin 				c = 0;
565da2e3ebdSchin 			continue;
566da2e3ebdSchin #endif /*SHOPT_MULTIBYTE */
567*b30d1939SAndy Fiddaman 		    case S_QUOTE:
568*b30d1939SAndy Fiddaman 			c = shp->ifstable[*cp++];
569*b30d1939SAndy Fiddaman 			inquote = !inquote;
570*b30d1939SAndy Fiddaman 			if(val)
571*b30d1939SAndy Fiddaman 			{
572*b30d1939SAndy Fiddaman 				stakputs(val);
573*b30d1939SAndy Fiddaman 				use_stak = 1;
574*b30d1939SAndy Fiddaman 				*val = 0;
575*b30d1939SAndy Fiddaman 			}
576*b30d1939SAndy Fiddaman 			continue;
577da2e3ebdSchin 		    case S_ESC:
578da2e3ebdSchin 			/* process escape character */
579da2e3ebdSchin 			if((c = shp->ifstable[*cp++]) == S_NL)
580da2e3ebdSchin 				was_escape = 1;
581da2e3ebdSchin 			else
582da2e3ebdSchin 				c = 0;
583da2e3ebdSchin 			if(val)
584da2e3ebdSchin 			{
585da2e3ebdSchin 				stakputs(val);
586da2e3ebdSchin 				use_stak = 1;
587da2e3ebdSchin 				was_escape = 1;
588da2e3ebdSchin 				*val = 0;
589da2e3ebdSchin 			}
590da2e3ebdSchin 			continue;
591da2e3ebdSchin 
592*b30d1939SAndy Fiddaman 		    case S_ERR:
593*b30d1939SAndy Fiddaman 			cp++;
594*b30d1939SAndy Fiddaman 			/* FALLTHROUGH */
595da2e3ebdSchin 		    case S_EOF:
596da2e3ebdSchin 			/* check for end of buffer */
597da2e3ebdSchin 			if(val && *val)
598da2e3ebdSchin 			{
599da2e3ebdSchin 				stakputs(val);
600da2e3ebdSchin 				use_stak = 1;
601da2e3ebdSchin 			}
602da2e3ebdSchin 			val = 0;
603da2e3ebdSchin 			if(cp>=cpmax)
604da2e3ebdSchin 			{
605da2e3ebdSchin 				c = S_NL;
606da2e3ebdSchin 				break;
607da2e3ebdSchin 			}
608da2e3ebdSchin 			/* eliminate null bytes */
609da2e3ebdSchin 			c = shp->ifstable[*cp++];
610da2e3ebdSchin 			if(!name && val && (c==S_SPACE||c==S_DELIM||c==S_MBYTE))
611da2e3ebdSchin 				c = 0;
612da2e3ebdSchin 			continue;
613da2e3ebdSchin 		    case S_NL:
614da2e3ebdSchin 			if(was_escape)
615da2e3ebdSchin 			{
616da2e3ebdSchin 				was_escape = 0;
617da2e3ebdSchin 				if(cp = (unsigned char*)sfgetr(iop,delim,0))
618da2e3ebdSchin 					c = sfvalue(iop);
619da2e3ebdSchin 				else if(cp=(unsigned char*)sfgetr(iop,delim,-1))
620da2e3ebdSchin 					c = sfvalue(iop)+1;
621da2e3ebdSchin 				if(cp)
622da2e3ebdSchin 				{
623da2e3ebdSchin 					if(flags&S_FLAG)
624*b30d1939SAndy Fiddaman 						sfwrite(shp->gd->hist_ptr->histfp,(char*)cp,c);
625da2e3ebdSchin 					cpmax = cp + c;
626da2e3ebdSchin 					c = shp->ifstable[*cp++];
627da2e3ebdSchin 					val=0;
628da2e3ebdSchin 					if(!name && (c==S_SPACE || c==S_DELIM || c==S_MBYTE))
629da2e3ebdSchin 						c = 0;
630da2e3ebdSchin 					continue;
631da2e3ebdSchin 				}
632da2e3ebdSchin 			}
633da2e3ebdSchin 			c = S_NL;
634da2e3ebdSchin 			break;
635da2e3ebdSchin 
636da2e3ebdSchin 		    case S_SPACE:
637da2e3ebdSchin 			/* skip over blanks */
638da2e3ebdSchin 			while((c=shp->ifstable[*cp++])==S_SPACE);
639da2e3ebdSchin 			if(!val)
640da2e3ebdSchin 				continue;
641da2e3ebdSchin #if SHOPT_MULTIBYTE
642da2e3ebdSchin 			if(c==S_MBYTE)
643da2e3ebdSchin 			{
644da2e3ebdSchin 				if(sh_strchr(ifs,(char*)cp-1)>=0)
645da2e3ebdSchin 				{
646da2e3ebdSchin 					if((c = mbsize((char*)cp-1))>1)
647da2e3ebdSchin 						cp += (c-1);
648da2e3ebdSchin 					c = S_DELIM;
649da2e3ebdSchin 				}
650da2e3ebdSchin 				else
651da2e3ebdSchin 					c = 0;
652da2e3ebdSchin 			}
653da2e3ebdSchin #endif /* SHOPT_MULTIBYTE */
654da2e3ebdSchin 			if(c!=S_DELIM)
655da2e3ebdSchin 				break;
656da2e3ebdSchin 			/* FALL THRU */
657da2e3ebdSchin 
658da2e3ebdSchin 		    case S_DELIM:
659da2e3ebdSchin 			if(!del)
660da2e3ebdSchin 				del = cp - 1;
661da2e3ebdSchin 			if(name)
662da2e3ebdSchin 			{
663da2e3ebdSchin 				/* skip over trailing blanks */
664da2e3ebdSchin 				while((c=shp->ifstable[*cp++])==S_SPACE);
665da2e3ebdSchin 				break;
666da2e3ebdSchin 			}
667da2e3ebdSchin 			/* FALL THRU */
668da2e3ebdSchin 
669da2e3ebdSchin 		    case 0:
670da2e3ebdSchin 			if(val==0 || was_escape)
671da2e3ebdSchin 			{
672da2e3ebdSchin 				val = (char*)(cp-1);
673da2e3ebdSchin 				was_escape = 0;
674da2e3ebdSchin 			}
675da2e3ebdSchin 			/* skip over word characters */
676da2e3ebdSchin 			wrd = -1;
677da2e3ebdSchin 			while(1)
678da2e3ebdSchin 			{
679da2e3ebdSchin 				while((c=shp->ifstable[*cp++])==0)
680da2e3ebdSchin 					if(!wrd)
681da2e3ebdSchin 						wrd = 1;
682*b30d1939SAndy Fiddaman 				if(inquote)
683*b30d1939SAndy Fiddaman 				{
684*b30d1939SAndy Fiddaman 					if(c==S_QUOTE)
685*b30d1939SAndy Fiddaman 					{
686*b30d1939SAndy Fiddaman 						if(shp->ifstable[*cp]==S_QUOTE)
687*b30d1939SAndy Fiddaman 						{
688*b30d1939SAndy Fiddaman 							if(val)
689*b30d1939SAndy Fiddaman 							{
690*b30d1939SAndy Fiddaman 								stakwrite(val,cp-(unsigned char*)val);
691*b30d1939SAndy Fiddaman 								use_stak = 1;
692*b30d1939SAndy Fiddaman 							}
693*b30d1939SAndy Fiddaman 							val = (char*)++cp;
694*b30d1939SAndy Fiddaman 						}
695*b30d1939SAndy Fiddaman 						else
696*b30d1939SAndy Fiddaman 							break;
697*b30d1939SAndy Fiddaman 					}
698*b30d1939SAndy Fiddaman 					if(c && c!=S_EOF)
699*b30d1939SAndy Fiddaman 					{
700*b30d1939SAndy Fiddaman 						if(c==S_NL)
701*b30d1939SAndy Fiddaman 						{
702*b30d1939SAndy Fiddaman 							if(val)
703*b30d1939SAndy Fiddaman 							{
704*b30d1939SAndy Fiddaman 								stakwrite(val,cp-(unsigned char*)val);
705*b30d1939SAndy Fiddaman 								use_stak=1;
706*b30d1939SAndy Fiddaman 							}
707*b30d1939SAndy Fiddaman 							if(cp = (unsigned char*)sfgetr(iop,delim,0))
708*b30d1939SAndy Fiddaman 								c = sfvalue(iop);
709*b30d1939SAndy Fiddaman 							else if(cp = (unsigned char*)sfgetr(iop,delim,-1))
710*b30d1939SAndy Fiddaman 								c = sfvalue(iop)+1;
711*b30d1939SAndy Fiddaman 							val = (char*)cp;
712*b30d1939SAndy Fiddaman 						}
713*b30d1939SAndy Fiddaman 						continue;
714*b30d1939SAndy Fiddaman 					}
715*b30d1939SAndy Fiddaman 				}
716da2e3ebdSchin 				if(!del&&c==S_DELIM)
717da2e3ebdSchin 					del = cp - 1;
718da2e3ebdSchin 				if(name || c==S_NL || c==S_ESC || c==S_EOF || c==S_MBYTE)
719da2e3ebdSchin 					break;
720da2e3ebdSchin 				if(wrd<0)
721da2e3ebdSchin 					wrd = 0;
722da2e3ebdSchin 			}
723da2e3ebdSchin 			if(wrd>0)
724da2e3ebdSchin 				del = (unsigned char*)"";
725da2e3ebdSchin 			if(c!=S_MBYTE)
726da2e3ebdSchin 				cp[-1] = 0;
727da2e3ebdSchin 			continue;
728da2e3ebdSchin 		}
729da2e3ebdSchin 		/* assign value and advance to next variable */
730da2e3ebdSchin 		if(!val)
731da2e3ebdSchin 			val = "";
732da2e3ebdSchin 		if(use_stak)
733da2e3ebdSchin 		{
734da2e3ebdSchin 			stakputs(val);
735da2e3ebdSchin 			stakputc(0);
736da2e3ebdSchin 			val = stakptr(rel);
737da2e3ebdSchin 		}
738da2e3ebdSchin 		if(!name && *val)
739da2e3ebdSchin 		{
740da2e3ebdSchin 			/* strip off trailing space delimiters */
741da2e3ebdSchin 			register unsigned char	*vp = (unsigned char*)val + strlen(val);
742da2e3ebdSchin 			while(shp->ifstable[*--vp]==S_SPACE);
743da2e3ebdSchin 			if(vp==del)
744da2e3ebdSchin 			{
745da2e3ebdSchin 				if(vp==(unsigned char*)val)
746da2e3ebdSchin 					vp--;
747da2e3ebdSchin 				else
748da2e3ebdSchin 					while(shp->ifstable[*--vp]==S_SPACE);
749da2e3ebdSchin 			}
750da2e3ebdSchin 			vp[1] = 0;
751da2e3ebdSchin 		}
752da2e3ebdSchin 		if(nv_isattr(np, NV_RDONLY))
753da2e3ebdSchin 		{
754da2e3ebdSchin 			errormsg(SH_DICT,ERROR_warn(0),e_readonly, nv_name(np));
755da2e3ebdSchin 			jmpval = 1;
756da2e3ebdSchin 		}
757da2e3ebdSchin 		else
758da2e3ebdSchin 			nv_putval(np,val,0);
759da2e3ebdSchin 		val = 0;
760da2e3ebdSchin 		del = 0;
761da2e3ebdSchin 		if(use_stak)
762da2e3ebdSchin 		{
763da2e3ebdSchin 			stakseek(rel);
764da2e3ebdSchin 			use_stak = 0;
765da2e3ebdSchin 		}
766da2e3ebdSchin 		if(array_index)
767da2e3ebdSchin 		{
768da2e3ebdSchin 			nv_putsub(np, NIL(char*), array_index++);
769da2e3ebdSchin 			if(c!=S_NL)
770da2e3ebdSchin 				continue;
771da2e3ebdSchin 			name = *++names;
772da2e3ebdSchin 		}
773da2e3ebdSchin 		while(1)
774da2e3ebdSchin 		{
775da2e3ebdSchin 			if(sh_isoption(SH_ALLEXPORT)&&!strchr(nv_name(np),'.') && !nv_isattr(np,NV_EXPORT))
776da2e3ebdSchin 			{
777da2e3ebdSchin 				nv_onattr(np,NV_EXPORT);
778*b30d1939SAndy Fiddaman 				sh_envput(shp->env,np);
779da2e3ebdSchin 			}
780da2e3ebdSchin 			if(name)
781da2e3ebdSchin 			{
782da2e3ebdSchin 				nv_close(np);
783da2e3ebdSchin 				np = nv_open(name,shp->var_tree,NV_NOASSIGN|NV_VARNAME);
784da2e3ebdSchin 				name = *++names;
785da2e3ebdSchin 			}
786da2e3ebdSchin 			else
787da2e3ebdSchin 				np = 0;
788da2e3ebdSchin 			if(c!=S_NL)
789da2e3ebdSchin 				break;
790da2e3ebdSchin 			if(!np)
791da2e3ebdSchin 				goto done;
792da2e3ebdSchin 			if(nv_isattr(np, NV_RDONLY))
793da2e3ebdSchin 			{
794da2e3ebdSchin 				errormsg(SH_DICT,ERROR_warn(0),e_readonly, nv_name(np));
795da2e3ebdSchin 				jmpval = 1;
796da2e3ebdSchin 			}
797da2e3ebdSchin 			else
798da2e3ebdSchin 				nv_putval(np, "", 0);
799da2e3ebdSchin 		}
800da2e3ebdSchin 	}
801da2e3ebdSchin done:
802da2e3ebdSchin 	if(timeout || (shp->fdstatus[fd]&(IOTTY|IONOSEEK)))
803*b30d1939SAndy Fiddaman 		sh_popcontext(shp,&buff);
804da2e3ebdSchin 	if(was_write)
805da2e3ebdSchin 		sfset(iop,SF_WRITE,1);
806da2e3ebdSchin 	if(!was_share)
807da2e3ebdSchin 		sfset(iop,SF_SHARE,0);
808da2e3ebdSchin 	nv_close(np);
809*b30d1939SAndy Fiddaman 	if((shp->fdstatus[fd]&IOTTY) && !keytrap)
810da2e3ebdSchin 		tty_cooked(fd);
811da2e3ebdSchin 	if(flags&S_FLAG)
812*b30d1939SAndy Fiddaman 		hist_flush(shp->gd->hist_ptr);
813da2e3ebdSchin 	if(jmpval > 1)
814da2e3ebdSchin 		siglongjmp(*shp->jmplist,jmpval);
815da2e3ebdSchin 	return(jmpval);
816da2e3ebdSchin }
817da2e3ebdSchin 
818