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