1da2e3ebdSchin /***********************************************************************
2da2e3ebdSchin * *
3da2e3ebdSchin * This software is part of the ast package *
4*3e14f97fSRoger A. Faulkner * Copyright (c) 1982-2010 AT&T Intellectual Property *
5da2e3ebdSchin * and is licensed under the *
6da2e3ebdSchin * Common Public License, Version 1.0 *
77c2fbfb3SApril Chin * by AT&T Intellectual Property *
8da2e3ebdSchin * *
9da2e3ebdSchin * A copy of the License is available at *
10da2e3ebdSchin * http://www.opensource.org/licenses/cpl1.0.txt *
11da2e3ebdSchin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
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 */
49da2e3ebdSchin
507c2fbfb3SApril Chin struct read_save
517c2fbfb3SApril Chin {
527c2fbfb3SApril Chin char **argv;
537c2fbfb3SApril Chin char *prompt;
547c2fbfb3SApril Chin short fd;
557c2fbfb3SApril Chin short plen;
567c2fbfb3SApril Chin int flags;
577c2fbfb3SApril Chin long timeout;
587c2fbfb3SApril Chin };
597c2fbfb3SApril Chin
b_read(int argc,char * argv[],void * extra)60da2e3ebdSchin int b_read(int argc,char *argv[], void *extra)
61da2e3ebdSchin {
62da2e3ebdSchin Sfdouble_t sec;
63da2e3ebdSchin register char *name;
64da2e3ebdSchin register int r, flags=0, fd=0;
657c2fbfb3SApril Chin register Shell_t *shp = ((Shbltin_t*)extra)->shp;
66da2e3ebdSchin long timeout = 1000*shp->st.tmout;
677c2fbfb3SApril Chin int save_prompt, fixargs=((Shbltin_t*)extra)->invariant;
687c2fbfb3SApril Chin struct read_save *rp;
69da2e3ebdSchin static char default_prompt[3] = {ESC,ESC};
7034f9b3eeSRoland Mainz rp = (struct read_save*)(((Shbltin_t*)extra)->data);
717c2fbfb3SApril Chin if(argc==0)
7234f9b3eeSRoland Mainz {
7334f9b3eeSRoland Mainz if(rp)
7434f9b3eeSRoland Mainz free((void*)rp);
757c2fbfb3SApril Chin return(0);
7634f9b3eeSRoland Mainz }
7734f9b3eeSRoland Mainz if(rp)
787c2fbfb3SApril Chin {
797c2fbfb3SApril Chin flags = rp->flags;
807c2fbfb3SApril Chin timeout = rp->timeout;
817c2fbfb3SApril Chin fd = rp->fd;
827c2fbfb3SApril Chin argv = rp->argv;
837c2fbfb3SApril Chin name = rp->prompt;
847c2fbfb3SApril Chin r = rp->plen;
857c2fbfb3SApril Chin goto bypass;
867c2fbfb3SApril Chin }
87da2e3ebdSchin while((r = optget(argv,sh_optread))) switch(r)
88da2e3ebdSchin {
89da2e3ebdSchin case 'A':
90da2e3ebdSchin flags |= A_FLAG;
91da2e3ebdSchin break;
927c2fbfb3SApril Chin case 'C':
937c2fbfb3SApril Chin flags |= C_FLAG;
947c2fbfb3SApril Chin break;
95da2e3ebdSchin case 't':
96da2e3ebdSchin sec = sh_strnum(opt_info.arg, (char**)0,1);
97da2e3ebdSchin timeout = sec ? 1000*sec : 1;
98da2e3ebdSchin break;
99da2e3ebdSchin case 'd':
100da2e3ebdSchin if(opt_info.arg && *opt_info.arg!='\n')
101da2e3ebdSchin {
102da2e3ebdSchin char *cp = opt_info.arg;
103da2e3ebdSchin flags &= ~((1<<D_FLAG)-1);
104da2e3ebdSchin flags |= (mbchar(cp)<< D_FLAG);
105da2e3ebdSchin }
106da2e3ebdSchin break;
107da2e3ebdSchin case 'p':
108da2e3ebdSchin if((fd = shp->cpipe[0])<=0)
109da2e3ebdSchin errormsg(SH_DICT,ERROR_exit(1),e_query);
110da2e3ebdSchin break;
111da2e3ebdSchin case 'n': case 'N':
1127c2fbfb3SApril Chin flags &= ((1<<D_FLAG)-1);
113da2e3ebdSchin flags |= (r=='n'?N_FLAG:NN_FLAG);
114da2e3ebdSchin r = (int)opt_info.num;
115da2e3ebdSchin if((unsigned)r > (1<<((8*sizeof(int))-D_FLAG))-1)
1167c2fbfb3SApril Chin errormsg(SH_DICT,ERROR_exit(1),e_overlimit,opt_info.name);
117da2e3ebdSchin flags |= (r<< D_FLAG);
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;
126da2e3ebdSchin case 'u':
127da2e3ebdSchin fd = (int)opt_info.num;
128da2e3ebdSchin if(sh_inuse(fd))
129da2e3ebdSchin fd = -1;
130da2e3ebdSchin break;
131da2e3ebdSchin case 'v':
132da2e3ebdSchin flags |= V_FLAG;
133da2e3ebdSchin break;
134da2e3ebdSchin case ':':
135da2e3ebdSchin errormsg(SH_DICT,2, "%s", opt_info.arg);
136da2e3ebdSchin break;
137da2e3ebdSchin case '?':
138da2e3ebdSchin errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
139da2e3ebdSchin break;
140da2e3ebdSchin }
141da2e3ebdSchin argv += opt_info.index;
142da2e3ebdSchin if(error_info.errors)
143da2e3ebdSchin errormsg(SH_DICT,ERROR_usage(2), "%s", optusage((char*)0));
144da2e3ebdSchin if(!((r=shp->fdstatus[fd])&IOREAD) || !(r&(IOSEEK|IONOSEEK)))
1457c2fbfb3SApril Chin r = sh_iocheckfd(shp,fd);
146da2e3ebdSchin if(fd<0 || !(r&IOREAD))
147da2e3ebdSchin errormsg(SH_DICT,ERROR_system(1),e_file+4);
148da2e3ebdSchin /* look for prompt */
149da2e3ebdSchin if((name = *argv) && (name=strchr(name,'?')) && (r&IOTTY))
1507c2fbfb3SApril Chin r = strlen(name++);
1517c2fbfb3SApril Chin else
1527c2fbfb3SApril Chin r = 0;
1537c2fbfb3SApril Chin if(argc==fixargs && (rp=newof(NIL(struct read_save*),struct read_save,1,0)))
154da2e3ebdSchin {
1557c2fbfb3SApril Chin ((Shbltin_t*)extra)->data = (void*)rp;
1567c2fbfb3SApril Chin rp->fd = fd;
1577c2fbfb3SApril Chin rp->flags = flags;
1587c2fbfb3SApril Chin rp->timeout = timeout;
1597c2fbfb3SApril Chin rp->argv = argv;
1607c2fbfb3SApril Chin rp->prompt = name;
1617c2fbfb3SApril Chin rp->plen = r;
1627c2fbfb3SApril Chin }
1637c2fbfb3SApril Chin bypass:
164*3e14f97fSRoger A. Faulkner shp->prompt = default_prompt;
1657c2fbfb3SApril Chin if(r && (shp->prompt=(char*)sfreserve(sfstderr,r,SF_LOCKR)))
166da2e3ebdSchin {
167da2e3ebdSchin memcpy(shp->prompt,name,r);
168da2e3ebdSchin sfwrite(sfstderr,shp->prompt,r-1);
169da2e3ebdSchin }
170da2e3ebdSchin shp->timeout = 0;
171da2e3ebdSchin save_prompt = shp->nextprompt;
172da2e3ebdSchin shp->nextprompt = 0;
173da2e3ebdSchin r=sh_readline(shp,argv,fd,flags,timeout);
174da2e3ebdSchin shp->nextprompt = save_prompt;
175da2e3ebdSchin if(r==0 && (r=(sfeof(shp->sftable[fd])||sferror(shp->sftable[fd]))))
176da2e3ebdSchin {
177da2e3ebdSchin if(fd == shp->cpipe[0])
178da2e3ebdSchin {
179da2e3ebdSchin sh_pclose(shp->cpipe);
180da2e3ebdSchin return(1);
181da2e3ebdSchin }
182da2e3ebdSchin }
183da2e3ebdSchin sfclrerr(shp->sftable[fd]);
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,int fd,int flags,long timeout)204da2e3ebdSchin int sh_readline(register Shell_t *shp,char **names, int fd, int flags,long timeout)
205da2e3ebdSchin {
20634f9b3eeSRoland Mainz register ssize_t c;
207da2e3ebdSchin register unsigned char *cp;
208da2e3ebdSchin register Namval_t *np;
209da2e3ebdSchin register char *name, *val;
210da2e3ebdSchin 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;
219da2e3ebdSchin int rel, wrd;
220da2e3ebdSchin long array_index = 0;
221da2e3ebdSchin void *timeslot=0;
222da2e3ebdSchin int delim = '\n';
223da2e3ebdSchin int jmpval=0;
22434f9b3eeSRoland Mainz ssize_t size = 0;
2257c2fbfb3SApril Chin int binary;
226da2e3ebdSchin struct checkpt buff;
2277c2fbfb3SApril Chin if(!(iop=shp->sftable[fd]) && !(iop=sh_iostream(shp,fd)))
228da2e3ebdSchin return(1);
2297c2fbfb3SApril Chin sh_stats(STAT_READS);
230da2e3ebdSchin if(names && (name = *names))
231da2e3ebdSchin {
23234f9b3eeSRoland Mainz Namval_t *mp;
233da2e3ebdSchin if(val= strchr(name,'?'))
234da2e3ebdSchin *val = 0;
2357c2fbfb3SApril Chin np = nv_open(name,shp->var_tree,NV_NOASSIGN|NV_VARNAME);
23634f9b3eeSRoland Mainz if(np && nv_isarray(np) && (mp=nv_opensub(np)))
23734f9b3eeSRoland Mainz np = mp;
238da2e3ebdSchin if((flags&V_FLAG) && shp->ed_context)
239da2e3ebdSchin ((struct edit*)shp->ed_context)->e_default = np;
240da2e3ebdSchin if(flags&A_FLAG)
241da2e3ebdSchin {
242da2e3ebdSchin flags &= ~A_FLAG;
243da2e3ebdSchin array_index = 1;
244da2e3ebdSchin nv_unset(np);
245da2e3ebdSchin nv_putsub(np,NIL(char*),0L);
246da2e3ebdSchin }
2477c2fbfb3SApril Chin else if(flags&C_FLAG)
2487c2fbfb3SApril Chin {
2497c2fbfb3SApril Chin delim = -1;
2507c2fbfb3SApril Chin nv_unset(np);
2517c2fbfb3SApril Chin nv_setvtree(np);
2527c2fbfb3SApril Chin }
253da2e3ebdSchin else
254da2e3ebdSchin name = *++names;
255da2e3ebdSchin if(val)
256da2e3ebdSchin *val = '?';
257da2e3ebdSchin }
258da2e3ebdSchin else
259da2e3ebdSchin {
260da2e3ebdSchin name = 0;
261da2e3ebdSchin if(dtvnext(shp->var_tree) || shp->namespace)
262da2e3ebdSchin np = nv_open(nv_name(REPLYNOD),shp->var_tree,0);
263da2e3ebdSchin else
264da2e3ebdSchin np = REPLYNOD;
265da2e3ebdSchin }
266da2e3ebdSchin if(flags>>D_FLAG) /* delimiter not new-line or fixed size read */
267da2e3ebdSchin {
268da2e3ebdSchin if(flags&(N_FLAG|NN_FLAG))
269da2e3ebdSchin size = ((unsigned)flags)>>D_FLAG;
270da2e3ebdSchin else
271da2e3ebdSchin delim = ((unsigned)flags)>>D_FLAG;
272da2e3ebdSchin if(shp->fdstatus[fd]&IOTTY)
273da2e3ebdSchin tty_raw(fd,1);
274da2e3ebdSchin }
2757c2fbfb3SApril Chin binary = nv_isattr(np,NV_BINARY);
2767c2fbfb3SApril Chin if(!binary && !(flags&(N_FLAG|NN_FLAG)))
277da2e3ebdSchin {
278da2e3ebdSchin Namval_t *mp;
279da2e3ebdSchin /* set up state table based on IFS */
2807c2fbfb3SApril Chin ifs = nv_getval(mp=sh_scoped(shp,IFSNOD));
281da2e3ebdSchin if((flags&R_FLAG) && shp->ifstable['\\']==S_ESC)
282da2e3ebdSchin shp->ifstable['\\'] = 0;
283da2e3ebdSchin else if(!(flags&R_FLAG) && shp->ifstable['\\']==0)
284da2e3ebdSchin shp->ifstable['\\'] = S_ESC;
285da2e3ebdSchin shp->ifstable[delim] = S_NL;
286da2e3ebdSchin if(delim!='\n')
287da2e3ebdSchin {
288da2e3ebdSchin shp->ifstable['\n'] = 0;
289da2e3ebdSchin nv_putval(mp, ifs, NV_RDONLY);
290da2e3ebdSchin }
291da2e3ebdSchin shp->ifstable[0] = S_EOF;
292da2e3ebdSchin }
293da2e3ebdSchin sfclrerr(iop);
2947c2fbfb3SApril Chin for(nfp=np->nvfun; nfp; nfp = nfp->next)
2957c2fbfb3SApril Chin {
2967c2fbfb3SApril Chin if(nfp->disc && nfp->disc->readf)
2977c2fbfb3SApril Chin {
2987c2fbfb3SApril Chin if((c=(*nfp->disc->readf)(np,iop,delim,nfp))>=0)
2997c2fbfb3SApril Chin return(c);
3007c2fbfb3SApril Chin }
3017c2fbfb3SApril Chin }
3027c2fbfb3SApril Chin if(binary && !(flags&(N_FLAG|NN_FLAG)))
3037c2fbfb3SApril Chin {
3047c2fbfb3SApril Chin flags |= NN_FLAG;
3057c2fbfb3SApril Chin size = nv_size(np);
3067c2fbfb3SApril Chin }
307da2e3ebdSchin was_write = (sfset(iop,SF_WRITE,0)&SF_WRITE)!=0;
308da2e3ebdSchin if(fd==0)
309da2e3ebdSchin was_share = (sfset(iop,SF_SHARE,1)&SF_SHARE)!=0;
310da2e3ebdSchin if(timeout || (shp->fdstatus[fd]&(IOTTY|IONOSEEK)))
311da2e3ebdSchin {
312da2e3ebdSchin sh_pushcontext(&buff,1);
313da2e3ebdSchin jmpval = sigsetjmp(buff.buff,0);
314da2e3ebdSchin if(jmpval)
315da2e3ebdSchin goto done;
316da2e3ebdSchin if(timeout)
317da2e3ebdSchin timeslot = (void*)sh_timeradd(timeout,0,timedout,(void*)iop);
318da2e3ebdSchin }
319da2e3ebdSchin if(flags&(N_FLAG|NN_FLAG))
320da2e3ebdSchin {
32134f9b3eeSRoland Mainz char buf[256],*var=buf,*cur,*end,*up,*v;
322da2e3ebdSchin /* reserved buffer */
323da2e3ebdSchin if((c=size)>=sizeof(buf))
324da2e3ebdSchin {
325da2e3ebdSchin if(!(var = (char*)malloc(c+1)))
326da2e3ebdSchin sh_exit(1);
3277c2fbfb3SApril Chin end = var + c;
328da2e3ebdSchin }
3297c2fbfb3SApril Chin else
3307c2fbfb3SApril Chin end = var + sizeof(buf) - 1;
3317c2fbfb3SApril Chin up = cur = var;
332da2e3ebdSchin if((sfset(iop,SF_SHARE,1)&SF_SHARE) && fd!=0)
333da2e3ebdSchin was_share = 1;
334da2e3ebdSchin if(size==0)
335da2e3ebdSchin {
336da2e3ebdSchin cp = sfreserve(iop,0,0);
337da2e3ebdSchin c = 0;
338da2e3ebdSchin }
339da2e3ebdSchin else
340da2e3ebdSchin {
34134f9b3eeSRoland Mainz ssize_t m;
34234f9b3eeSRoland Mainz int f;
3437c2fbfb3SApril Chin for (;;)
3447c2fbfb3SApril Chin {
345*3e14f97fSRoger A. Faulkner c = size;
3467c2fbfb3SApril Chin cp = sfreserve(iop,c,SF_LOCKR);
3477c2fbfb3SApril Chin f = 1;
34834f9b3eeSRoland Mainz if(cp)
34934f9b3eeSRoland Mainz m = sfvalue(iop);
350*3e14f97fSRoger A. Faulkner else if(flags&NN_FLAG)
351*3e14f97fSRoger A. Faulkner {
352*3e14f97fSRoger A. Faulkner c = size;
353*3e14f97fSRoger A. Faulkner m = (cp = sfreserve(iop,c,0)) ? sfvalue(iop) : 0;
354*3e14f97fSRoger A. Faulkner f = 0;
355*3e14f97fSRoger A. Faulkner }
35634f9b3eeSRoland Mainz else
3577c2fbfb3SApril Chin {
358*3e14f97fSRoger A. Faulkner c = sfvalue(iop);
359*3e14f97fSRoger A. Faulkner m = (cp = sfreserve(iop,c,SF_LOCKR)) ? sfvalue(iop) : 0;
3607c2fbfb3SApril Chin }
3617c2fbfb3SApril Chin if(m>0 && (flags&N_FLAG) && !binary && (v=memchr(cp,'\n',m)))
36234f9b3eeSRoland Mainz {
36334f9b3eeSRoland Mainz *v++ = 0;
3647c2fbfb3SApril Chin m = v-(char*)cp;
3657c2fbfb3SApril Chin }
3667c2fbfb3SApril Chin if((c=m)>size)
367da2e3ebdSchin c = size;
368da2e3ebdSchin if(c>0)
369da2e3ebdSchin {
3707c2fbfb3SApril Chin if(c > (end-cur))
3717c2fbfb3SApril Chin {
37234f9b3eeSRoland Mainz ssize_t cx = cur - var, ux = up - var;
37334f9b3eeSRoland Mainz m = (end - var) + (c - (end - cur));
3747c2fbfb3SApril Chin if (var == buf)
3757c2fbfb3SApril Chin {
3767c2fbfb3SApril Chin v = (char*)malloc(m+1);
37734f9b3eeSRoland Mainz var = memcpy(v, var, cur - var);
378da2e3ebdSchin }
3797c2fbfb3SApril Chin else
38034f9b3eeSRoland Mainz var = newof(var, char, m, 1);
38134f9b3eeSRoland Mainz end = var + m;
38234f9b3eeSRoland Mainz cur = var + cx;
38334f9b3eeSRoland Mainz up = var + ux;
3847c2fbfb3SApril Chin }
3857c2fbfb3SApril Chin memcpy((void*)cur,cp,c);
3867c2fbfb3SApril Chin if(f)
3877c2fbfb3SApril Chin sfread(iop,cp,c);
3887c2fbfb3SApril Chin cur += c;
3897c2fbfb3SApril Chin #if SHOPT_MULTIBYTE
3907c2fbfb3SApril Chin if(!binary && mbwide())
3917c2fbfb3SApril Chin {
3927c2fbfb3SApril Chin int x;
3937c2fbfb3SApril Chin int z;
3947c2fbfb3SApril Chin
3957c2fbfb3SApril Chin mbinit();
3967c2fbfb3SApril Chin *cur = 0;
3977c2fbfb3SApril Chin x = z = 0;
3987c2fbfb3SApril Chin while (up < cur && (z = mbsize(up)) > 0)
3997c2fbfb3SApril Chin {
4007c2fbfb3SApril Chin up += z;
4017c2fbfb3SApril Chin x++;
4027c2fbfb3SApril Chin }
4037c2fbfb3SApril Chin if((size -= x) > 0 && (up >= cur || z < 0) && ((flags & NN_FLAG) || z < 0 || m > c))
4047c2fbfb3SApril Chin continue;
4057c2fbfb3SApril Chin }
4067c2fbfb3SApril Chin #endif
4077c2fbfb3SApril Chin }
4087c2fbfb3SApril Chin #if SHOPT_MULTIBYTE
4097c2fbfb3SApril Chin if(!binary && mbwide() && (up == var || (flags & NN_FLAG) && size))
4107c2fbfb3SApril Chin cur = var;
4117c2fbfb3SApril Chin #endif
4127c2fbfb3SApril Chin *cur = 0;
413*3e14f97fSRoger A. Faulkner if(c>=size || (flags&N_FLAG) || m==0)
414*3e14f97fSRoger A. Faulkner {
415*3e14f97fSRoger A. Faulkner if(m)
416da2e3ebdSchin sfclrerr(iop);
4177c2fbfb3SApril Chin break;
4187c2fbfb3SApril Chin }
419*3e14f97fSRoger A. Faulkner size -= c;
420*3e14f97fSRoger A. Faulkner }
421da2e3ebdSchin }
422da2e3ebdSchin if(timeslot)
423da2e3ebdSchin timerdel(timeslot);
42434f9b3eeSRoland Mainz if(binary && !((size=nv_size(np)) && nv_isarray(np) && c!=size))
425da2e3ebdSchin {
42634f9b3eeSRoland Mainz if((c==size) && np->nvalue.cp && !nv_isarray(np))
4277c2fbfb3SApril Chin memcpy((char*)np->nvalue.cp,var,c);
4287c2fbfb3SApril Chin else
4297c2fbfb3SApril Chin {
43034f9b3eeSRoland Mainz Namval_t *mp;
4317c2fbfb3SApril Chin if(var==buf)
432*3e14f97fSRoger A. Faulkner var = memdup(var,c+1);
433da2e3ebdSchin nv_putval(np,var,NV_RAW);
434da2e3ebdSchin nv_setsize(np,c);
43534f9b3eeSRoland Mainz if(!nv_isattr(np,NV_IMPORT|NV_EXPORT) && (mp=(Namval_t*)np->nvenv))
43634f9b3eeSRoland Mainz nv_setsize(mp,c);
437da2e3ebdSchin }
4387c2fbfb3SApril Chin }
439da2e3ebdSchin else
440da2e3ebdSchin {
441da2e3ebdSchin nv_putval(np,var,0);
4427c2fbfb3SApril Chin if(var!=buf)
443da2e3ebdSchin free((void*)var);
444da2e3ebdSchin }
445da2e3ebdSchin goto done;
446da2e3ebdSchin }
447da2e3ebdSchin else if(cp = (unsigned char*)sfgetr(iop,delim,0))
448da2e3ebdSchin c = sfvalue(iop);
449da2e3ebdSchin else if(cp = (unsigned char*)sfgetr(iop,delim,-1))
450da2e3ebdSchin c = sfvalue(iop)+1;
451da2e3ebdSchin if(timeslot)
452da2e3ebdSchin timerdel(timeslot);
453da2e3ebdSchin if((flags&S_FLAG) && !shp->hist_ptr)
454da2e3ebdSchin {
4557c2fbfb3SApril Chin sh_histinit((void*)shp);
456da2e3ebdSchin if(!shp->hist_ptr)
457da2e3ebdSchin flags &= ~S_FLAG;
458da2e3ebdSchin }
459da2e3ebdSchin if(cp)
460da2e3ebdSchin {
461da2e3ebdSchin cpmax = cp + c;
462da2e3ebdSchin #if SHOPT_CRNL
463da2e3ebdSchin if(delim=='\n' && c>=2 && cpmax[-2]=='\r')
464da2e3ebdSchin cpmax--;
465da2e3ebdSchin #endif /* SHOPT_CRNL */
466da2e3ebdSchin if(*(cpmax-1) != delim)
467da2e3ebdSchin *(cpmax-1) = delim;
468da2e3ebdSchin if(flags&S_FLAG)
469da2e3ebdSchin sfwrite(shp->hist_ptr->histfp,(char*)cp,c);
470da2e3ebdSchin c = shp->ifstable[*cp++];
471da2e3ebdSchin #if !SHOPT_MULTIBYTE
472da2e3ebdSchin if(!name && (flags&R_FLAG)) /* special case single argument */
473da2e3ebdSchin {
474da2e3ebdSchin /* skip over leading blanks */
475da2e3ebdSchin while(c==S_SPACE)
476da2e3ebdSchin c = shp->ifstable[*cp++];
477da2e3ebdSchin /* strip trailing delimiters */
478da2e3ebdSchin if(cpmax[-1] == '\n')
479da2e3ebdSchin cpmax--;
480da2e3ebdSchin if(cpmax>cp)
481da2e3ebdSchin {
482da2e3ebdSchin while((c=shp->ifstable[*--cpmax])==S_DELIM || c==S_SPACE);
483da2e3ebdSchin cpmax[1] = 0;
484da2e3ebdSchin }
485da2e3ebdSchin else
486da2e3ebdSchin *cpmax =0;
487da2e3ebdSchin if(nv_isattr(np, NV_RDONLY))
488da2e3ebdSchin {
489da2e3ebdSchin errormsg(SH_DICT,ERROR_warn(0),e_readonly, nv_name(np));
490da2e3ebdSchin jmpval = 1;
491da2e3ebdSchin }
492da2e3ebdSchin else
493da2e3ebdSchin nv_putval(np,(char*)cp-1,0);
494da2e3ebdSchin goto done;
495da2e3ebdSchin }
496da2e3ebdSchin #endif /* !SHOPT_MULTIBYTE */
497da2e3ebdSchin }
498da2e3ebdSchin else
499da2e3ebdSchin c = S_NL;
500da2e3ebdSchin shp->nextprompt = 2;
501da2e3ebdSchin rel= staktell();
502da2e3ebdSchin /* val==0 at the start of a field */
503da2e3ebdSchin val = 0;
504da2e3ebdSchin del = 0;
505da2e3ebdSchin while(1)
506da2e3ebdSchin {
507da2e3ebdSchin switch(c)
508da2e3ebdSchin {
509da2e3ebdSchin #if SHOPT_MULTIBYTE
510da2e3ebdSchin case S_MBYTE:
511da2e3ebdSchin if(val==0)
512da2e3ebdSchin val = (char*)(cp-1);
513da2e3ebdSchin if(sh_strchr(ifs,(char*)cp-1)>=0)
514da2e3ebdSchin {
515da2e3ebdSchin c = mbsize((char*)cp-1);
516da2e3ebdSchin if(name)
517da2e3ebdSchin cp[-1] = 0;
518da2e3ebdSchin if(c>1)
519da2e3ebdSchin cp += (c-1);
520da2e3ebdSchin c = S_DELIM;
521da2e3ebdSchin }
522da2e3ebdSchin else
523da2e3ebdSchin c = 0;
524da2e3ebdSchin continue;
525da2e3ebdSchin #endif /*SHOPT_MULTIBYTE */
526da2e3ebdSchin case S_ESC:
527da2e3ebdSchin /* process escape character */
528da2e3ebdSchin if((c = shp->ifstable[*cp++]) == S_NL)
529da2e3ebdSchin was_escape = 1;
530da2e3ebdSchin else
531da2e3ebdSchin c = 0;
532da2e3ebdSchin if(val)
533da2e3ebdSchin {
534da2e3ebdSchin stakputs(val);
535da2e3ebdSchin use_stak = 1;
536da2e3ebdSchin was_escape = 1;
537da2e3ebdSchin *val = 0;
538da2e3ebdSchin }
539da2e3ebdSchin continue;
540da2e3ebdSchin
541da2e3ebdSchin case S_EOF:
542da2e3ebdSchin /* check for end of buffer */
543da2e3ebdSchin if(val && *val)
544da2e3ebdSchin {
545da2e3ebdSchin stakputs(val);
546da2e3ebdSchin use_stak = 1;
547da2e3ebdSchin }
548da2e3ebdSchin val = 0;
549da2e3ebdSchin if(cp>=cpmax)
550da2e3ebdSchin {
551da2e3ebdSchin c = S_NL;
552da2e3ebdSchin break;
553da2e3ebdSchin }
554da2e3ebdSchin /* eliminate null bytes */
555da2e3ebdSchin c = shp->ifstable[*cp++];
556da2e3ebdSchin if(!name && val && (c==S_SPACE||c==S_DELIM||c==S_MBYTE))
557da2e3ebdSchin c = 0;
558da2e3ebdSchin continue;
559da2e3ebdSchin case S_NL:
560da2e3ebdSchin if(was_escape)
561da2e3ebdSchin {
562da2e3ebdSchin was_escape = 0;
563da2e3ebdSchin if(cp = (unsigned char*)sfgetr(iop,delim,0))
564da2e3ebdSchin c = sfvalue(iop);
565da2e3ebdSchin else if(cp=(unsigned char*)sfgetr(iop,delim,-1))
566da2e3ebdSchin c = sfvalue(iop)+1;
567da2e3ebdSchin if(cp)
568da2e3ebdSchin {
569da2e3ebdSchin if(flags&S_FLAG)
570da2e3ebdSchin sfwrite(shp->hist_ptr->histfp,(char*)cp,c);
571da2e3ebdSchin cpmax = cp + c;
572da2e3ebdSchin c = shp->ifstable[*cp++];
573da2e3ebdSchin val=0;
574da2e3ebdSchin if(!name && (c==S_SPACE || c==S_DELIM || c==S_MBYTE))
575da2e3ebdSchin c = 0;
576da2e3ebdSchin continue;
577da2e3ebdSchin }
578da2e3ebdSchin }
579da2e3ebdSchin c = S_NL;
580da2e3ebdSchin break;
581da2e3ebdSchin
582da2e3ebdSchin case S_SPACE:
583da2e3ebdSchin /* skip over blanks */
584da2e3ebdSchin while((c=shp->ifstable[*cp++])==S_SPACE);
585da2e3ebdSchin if(!val)
586da2e3ebdSchin continue;
587da2e3ebdSchin #if SHOPT_MULTIBYTE
588da2e3ebdSchin if(c==S_MBYTE)
589da2e3ebdSchin {
590da2e3ebdSchin if(sh_strchr(ifs,(char*)cp-1)>=0)
591da2e3ebdSchin {
592da2e3ebdSchin if((c = mbsize((char*)cp-1))>1)
593da2e3ebdSchin cp += (c-1);
594da2e3ebdSchin c = S_DELIM;
595da2e3ebdSchin }
596da2e3ebdSchin else
597da2e3ebdSchin c = 0;
598da2e3ebdSchin }
599da2e3ebdSchin #endif /* SHOPT_MULTIBYTE */
600da2e3ebdSchin if(c!=S_DELIM)
601da2e3ebdSchin break;
602da2e3ebdSchin /* FALL THRU */
603da2e3ebdSchin
604da2e3ebdSchin case S_DELIM:
605da2e3ebdSchin if(!del)
606da2e3ebdSchin del = cp - 1;
607da2e3ebdSchin if(name)
608da2e3ebdSchin {
609da2e3ebdSchin /* skip over trailing blanks */
610da2e3ebdSchin while((c=shp->ifstable[*cp++])==S_SPACE);
611da2e3ebdSchin break;
612da2e3ebdSchin }
613da2e3ebdSchin /* FALL THRU */
614da2e3ebdSchin
615da2e3ebdSchin case 0:
616da2e3ebdSchin if(val==0 || was_escape)
617da2e3ebdSchin {
618da2e3ebdSchin val = (char*)(cp-1);
619da2e3ebdSchin was_escape = 0;
620da2e3ebdSchin }
621da2e3ebdSchin /* skip over word characters */
622da2e3ebdSchin wrd = -1;
623da2e3ebdSchin while(1)
624da2e3ebdSchin {
625da2e3ebdSchin while((c=shp->ifstable[*cp++])==0)
626da2e3ebdSchin if(!wrd)
627da2e3ebdSchin wrd = 1;
628da2e3ebdSchin if(!del&&c==S_DELIM)
629da2e3ebdSchin del = cp - 1;
630da2e3ebdSchin if(name || c==S_NL || c==S_ESC || c==S_EOF || c==S_MBYTE)
631da2e3ebdSchin break;
632da2e3ebdSchin if(wrd<0)
633da2e3ebdSchin wrd = 0;
634da2e3ebdSchin }
635da2e3ebdSchin if(wrd>0)
636da2e3ebdSchin del = (unsigned char*)"";
637da2e3ebdSchin if(c!=S_MBYTE)
638da2e3ebdSchin cp[-1] = 0;
639da2e3ebdSchin continue;
640da2e3ebdSchin }
641da2e3ebdSchin /* assign value and advance to next variable */
642da2e3ebdSchin if(!val)
643da2e3ebdSchin val = "";
644da2e3ebdSchin if(use_stak)
645da2e3ebdSchin {
646da2e3ebdSchin stakputs(val);
647da2e3ebdSchin stakputc(0);
648da2e3ebdSchin val = stakptr(rel);
649da2e3ebdSchin }
650da2e3ebdSchin if(!name && *val)
651da2e3ebdSchin {
652da2e3ebdSchin /* strip off trailing space delimiters */
653da2e3ebdSchin register unsigned char *vp = (unsigned char*)val + strlen(val);
654da2e3ebdSchin while(shp->ifstable[*--vp]==S_SPACE);
655da2e3ebdSchin if(vp==del)
656da2e3ebdSchin {
657da2e3ebdSchin if(vp==(unsigned char*)val)
658da2e3ebdSchin vp--;
659da2e3ebdSchin else
660da2e3ebdSchin while(shp->ifstable[*--vp]==S_SPACE);
661da2e3ebdSchin }
662da2e3ebdSchin vp[1] = 0;
663da2e3ebdSchin }
664da2e3ebdSchin if(nv_isattr(np, NV_RDONLY))
665da2e3ebdSchin {
666da2e3ebdSchin errormsg(SH_DICT,ERROR_warn(0),e_readonly, nv_name(np));
667da2e3ebdSchin jmpval = 1;
668da2e3ebdSchin }
669da2e3ebdSchin else
670da2e3ebdSchin nv_putval(np,val,0);
671da2e3ebdSchin val = 0;
672da2e3ebdSchin del = 0;
673da2e3ebdSchin if(use_stak)
674da2e3ebdSchin {
675da2e3ebdSchin stakseek(rel);
676da2e3ebdSchin use_stak = 0;
677da2e3ebdSchin }
678da2e3ebdSchin if(array_index)
679da2e3ebdSchin {
680da2e3ebdSchin nv_putsub(np, NIL(char*), array_index++);
681da2e3ebdSchin if(c!=S_NL)
682da2e3ebdSchin continue;
683da2e3ebdSchin name = *++names;
684da2e3ebdSchin }
685da2e3ebdSchin while(1)
686da2e3ebdSchin {
687da2e3ebdSchin if(sh_isoption(SH_ALLEXPORT)&&!strchr(nv_name(np),'.') && !nv_isattr(np,NV_EXPORT))
688da2e3ebdSchin {
689da2e3ebdSchin nv_onattr(np,NV_EXPORT);
690da2e3ebdSchin sh_envput(sh.env,np);
691da2e3ebdSchin }
692da2e3ebdSchin if(name)
693da2e3ebdSchin {
694da2e3ebdSchin nv_close(np);
695da2e3ebdSchin np = nv_open(name,shp->var_tree,NV_NOASSIGN|NV_VARNAME);
696da2e3ebdSchin name = *++names;
697da2e3ebdSchin }
698da2e3ebdSchin else
699da2e3ebdSchin np = 0;
700da2e3ebdSchin if(c!=S_NL)
701da2e3ebdSchin break;
702da2e3ebdSchin if(!np)
703da2e3ebdSchin goto done;
704da2e3ebdSchin if(nv_isattr(np, NV_RDONLY))
705da2e3ebdSchin {
706da2e3ebdSchin errormsg(SH_DICT,ERROR_warn(0),e_readonly, nv_name(np));
707da2e3ebdSchin jmpval = 1;
708da2e3ebdSchin }
709da2e3ebdSchin else
710da2e3ebdSchin nv_putval(np, "", 0);
711da2e3ebdSchin }
712da2e3ebdSchin }
713da2e3ebdSchin done:
714da2e3ebdSchin if(timeout || (shp->fdstatus[fd]&(IOTTY|IONOSEEK)))
715da2e3ebdSchin sh_popcontext(&buff);
716da2e3ebdSchin if(was_write)
717da2e3ebdSchin sfset(iop,SF_WRITE,1);
718da2e3ebdSchin if(!was_share)
719da2e3ebdSchin sfset(iop,SF_SHARE,0);
720da2e3ebdSchin nv_close(np);
721da2e3ebdSchin if((flags>>D_FLAG) && (shp->fdstatus[fd]&IOTTY))
722da2e3ebdSchin tty_cooked(fd);
723da2e3ebdSchin if(flags&S_FLAG)
724da2e3ebdSchin hist_flush(shp->hist_ptr);
725da2e3ebdSchin if(jmpval > 1)
726da2e3ebdSchin siglongjmp(*shp->jmplist,jmpval);
727da2e3ebdSchin return(jmpval);
728da2e3ebdSchin }
729da2e3ebdSchin
730