14887Schin /***********************************************************************
24887Schin * *
34887Schin * This software is part of the ast package *
4*12068SRoger.Faulkner@Oracle.COM * Copyright (c) 1982-2010 AT&T Intellectual Property *
54887Schin * and is licensed under the *
64887Schin * Common Public License, Version 1.0 *
78462SApril.Chin@Sun.COM * by AT&T Intellectual Property *
84887Schin * *
94887Schin * A copy of the License is available at *
104887Schin * http://www.opensource.org/licenses/cpl1.0.txt *
114887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
124887Schin * *
134887Schin * Information and Software Systems Research *
144887Schin * AT&T Research *
154887Schin * Florham Park NJ *
164887Schin * *
174887Schin * David Korn <dgk@research.att.com> *
184887Schin * *
194887Schin ***********************************************************************/
204887Schin #pragma prototyped
214887Schin /*
228462SApril.Chin@Sun.COM * read [-ACprs] [-d delim] [-u filenum] [-t timeout] [-n n] [-N n] [name...]
234887Schin *
244887Schin * David Korn
254887Schin * AT&T Labs
264887Schin *
274887Schin */
284887Schin
294887Schin #include <ast.h>
304887Schin #include <error.h>
314887Schin #include "defs.h"
324887Schin #include "variables.h"
334887Schin #include "lexstates.h"
344887Schin #include "io.h"
354887Schin #include "name.h"
364887Schin #include "builtins.h"
374887Schin #include "history.h"
384887Schin #include "terminal.h"
394887Schin #include "edit.h"
404887Schin
414887Schin #define R_FLAG 1 /* raw mode */
424887Schin #define S_FLAG 2 /* save in history file */
434887Schin #define A_FLAG 4 /* read into array */
444887Schin #define N_FLAG 8 /* fixed size read at most */
454887Schin #define NN_FLAG 0x10 /* fixed size read exact */
464887Schin #define V_FLAG 0x20 /* use default value */
478462SApril.Chin@Sun.COM #define C_FLAG 0x40 /* read into compound variable */
484887Schin #define D_FLAG 8 /* must be number of bits for all flags */
494887Schin
508462SApril.Chin@Sun.COM struct read_save
518462SApril.Chin@Sun.COM {
528462SApril.Chin@Sun.COM char **argv;
538462SApril.Chin@Sun.COM char *prompt;
548462SApril.Chin@Sun.COM short fd;
558462SApril.Chin@Sun.COM short plen;
568462SApril.Chin@Sun.COM int flags;
578462SApril.Chin@Sun.COM long timeout;
588462SApril.Chin@Sun.COM };
598462SApril.Chin@Sun.COM
b_read(int argc,char * argv[],void * extra)604887Schin int b_read(int argc,char *argv[], void *extra)
614887Schin {
624887Schin Sfdouble_t sec;
634887Schin register char *name;
644887Schin register int r, flags=0, fd=0;
658462SApril.Chin@Sun.COM register Shell_t *shp = ((Shbltin_t*)extra)->shp;
664887Schin long timeout = 1000*shp->st.tmout;
678462SApril.Chin@Sun.COM int save_prompt, fixargs=((Shbltin_t*)extra)->invariant;
688462SApril.Chin@Sun.COM struct read_save *rp;
694887Schin static char default_prompt[3] = {ESC,ESC};
7010898Sroland.mainz@nrubsig.org rp = (struct read_save*)(((Shbltin_t*)extra)->data);
718462SApril.Chin@Sun.COM if(argc==0)
7210898Sroland.mainz@nrubsig.org {
7310898Sroland.mainz@nrubsig.org if(rp)
7410898Sroland.mainz@nrubsig.org free((void*)rp);
758462SApril.Chin@Sun.COM return(0);
7610898Sroland.mainz@nrubsig.org }
7710898Sroland.mainz@nrubsig.org if(rp)
788462SApril.Chin@Sun.COM {
798462SApril.Chin@Sun.COM flags = rp->flags;
808462SApril.Chin@Sun.COM timeout = rp->timeout;
818462SApril.Chin@Sun.COM fd = rp->fd;
828462SApril.Chin@Sun.COM argv = rp->argv;
838462SApril.Chin@Sun.COM name = rp->prompt;
848462SApril.Chin@Sun.COM r = rp->plen;
858462SApril.Chin@Sun.COM goto bypass;
868462SApril.Chin@Sun.COM }
874887Schin while((r = optget(argv,sh_optread))) switch(r)
884887Schin {
894887Schin case 'A':
904887Schin flags |= A_FLAG;
914887Schin break;
928462SApril.Chin@Sun.COM case 'C':
938462SApril.Chin@Sun.COM flags |= C_FLAG;
948462SApril.Chin@Sun.COM break;
954887Schin case 't':
964887Schin sec = sh_strnum(opt_info.arg, (char**)0,1);
974887Schin timeout = sec ? 1000*sec : 1;
984887Schin break;
994887Schin case 'd':
1004887Schin if(opt_info.arg && *opt_info.arg!='\n')
1014887Schin {
1024887Schin char *cp = opt_info.arg;
1034887Schin flags &= ~((1<<D_FLAG)-1);
1044887Schin flags |= (mbchar(cp)<< D_FLAG);
1054887Schin }
1064887Schin break;
1074887Schin case 'p':
1084887Schin if((fd = shp->cpipe[0])<=0)
1094887Schin errormsg(SH_DICT,ERROR_exit(1),e_query);
1104887Schin break;
1114887Schin case 'n': case 'N':
1128462SApril.Chin@Sun.COM flags &= ((1<<D_FLAG)-1);
1134887Schin flags |= (r=='n'?N_FLAG:NN_FLAG);
1144887Schin r = (int)opt_info.num;
1154887Schin if((unsigned)r > (1<<((8*sizeof(int))-D_FLAG))-1)
1168462SApril.Chin@Sun.COM errormsg(SH_DICT,ERROR_exit(1),e_overlimit,opt_info.name);
1174887Schin flags |= (r<< D_FLAG);
1184887Schin break;
1194887Schin case 'r':
1204887Schin flags |= R_FLAG;
1214887Schin break;
1224887Schin case 's':
1234887Schin /* save in history file */
1244887Schin flags |= S_FLAG;
1254887Schin break;
1264887Schin case 'u':
1274887Schin fd = (int)opt_info.num;
1284887Schin if(sh_inuse(fd))
1294887Schin fd = -1;
1304887Schin break;
1314887Schin case 'v':
1324887Schin flags |= V_FLAG;
1334887Schin break;
1344887Schin case ':':
1354887Schin errormsg(SH_DICT,2, "%s", opt_info.arg);
1364887Schin break;
1374887Schin case '?':
1384887Schin errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
1394887Schin break;
1404887Schin }
1414887Schin argv += opt_info.index;
1424887Schin if(error_info.errors)
1434887Schin errormsg(SH_DICT,ERROR_usage(2), "%s", optusage((char*)0));
1444887Schin if(!((r=shp->fdstatus[fd])&IOREAD) || !(r&(IOSEEK|IONOSEEK)))
1458462SApril.Chin@Sun.COM r = sh_iocheckfd(shp,fd);
1464887Schin if(fd<0 || !(r&IOREAD))
1474887Schin errormsg(SH_DICT,ERROR_system(1),e_file+4);
1484887Schin /* look for prompt */
1494887Schin if((name = *argv) && (name=strchr(name,'?')) && (r&IOTTY))
1508462SApril.Chin@Sun.COM r = strlen(name++);
1518462SApril.Chin@Sun.COM else
1528462SApril.Chin@Sun.COM r = 0;
1538462SApril.Chin@Sun.COM if(argc==fixargs && (rp=newof(NIL(struct read_save*),struct read_save,1,0)))
1544887Schin {
1558462SApril.Chin@Sun.COM ((Shbltin_t*)extra)->data = (void*)rp;
1568462SApril.Chin@Sun.COM rp->fd = fd;
1578462SApril.Chin@Sun.COM rp->flags = flags;
1588462SApril.Chin@Sun.COM rp->timeout = timeout;
1598462SApril.Chin@Sun.COM rp->argv = argv;
1608462SApril.Chin@Sun.COM rp->prompt = name;
1618462SApril.Chin@Sun.COM rp->plen = r;
1628462SApril.Chin@Sun.COM }
1638462SApril.Chin@Sun.COM bypass:
164*12068SRoger.Faulkner@Oracle.COM shp->prompt = default_prompt;
1658462SApril.Chin@Sun.COM if(r && (shp->prompt=(char*)sfreserve(sfstderr,r,SF_LOCKR)))
1668462SApril.Chin@Sun.COM {
1678462SApril.Chin@Sun.COM memcpy(shp->prompt,name,r);
1688462SApril.Chin@Sun.COM sfwrite(sfstderr,shp->prompt,r-1);
1694887Schin }
1704887Schin shp->timeout = 0;
1714887Schin save_prompt = shp->nextprompt;
1724887Schin shp->nextprompt = 0;
1734887Schin r=sh_readline(shp,argv,fd,flags,timeout);
1744887Schin shp->nextprompt = save_prompt;
1754887Schin if(r==0 && (r=(sfeof(shp->sftable[fd])||sferror(shp->sftable[fd]))))
1764887Schin {
1774887Schin if(fd == shp->cpipe[0])
1784887Schin {
1794887Schin sh_pclose(shp->cpipe);
1804887Schin return(1);
1814887Schin }
1824887Schin }
1834887Schin sfclrerr(shp->sftable[fd]);
1844887Schin return(r);
1854887Schin }
1864887Schin
1874887Schin /*
1884887Schin * here for read timeout
1894887Schin */
timedout(void * handle)1904887Schin static void timedout(void *handle)
1914887Schin {
1924887Schin sfclrlock((Sfio_t*)handle);
1934887Schin sh_exit(1);
1944887Schin }
1954887Schin
1964887Schin /*
1974887Schin * This is the code to read a line and to split it into tokens
1984887Schin * <names> is an array of variable names
1994887Schin * <fd> is the file descriptor
2004887Schin * <flags> is union of -A, -r, -s, and contains delimiter if not '\n'
2014887Schin * <timeout> is number of milli-seconds until timeout
2024887Schin */
2034887Schin
sh_readline(register Shell_t * shp,char ** names,int fd,int flags,long timeout)2044887Schin int sh_readline(register Shell_t *shp,char **names, int fd, int flags,long timeout)
2054887Schin {
20610898Sroland.mainz@nrubsig.org register ssize_t c;
2074887Schin register unsigned char *cp;
2084887Schin register Namval_t *np;
2094887Schin register char *name, *val;
2108462SApril.Chin@Sun.COM register Sfio_t *iop;
2118462SApril.Chin@Sun.COM Namfun_t *nfp;
2124887Schin char *ifs;
2134887Schin unsigned char *cpmax;
2144887Schin unsigned char *del;
2154887Schin char was_escape = 0;
2164887Schin char use_stak = 0;
2178462SApril.Chin@Sun.COM volatile char was_write = 0;
2188462SApril.Chin@Sun.COM volatile char was_share = 1;
2194887Schin int rel, wrd;
2204887Schin long array_index = 0;
2214887Schin void *timeslot=0;
2224887Schin int delim = '\n';
2234887Schin int jmpval=0;
22410898Sroland.mainz@nrubsig.org ssize_t size = 0;
2258462SApril.Chin@Sun.COM int binary;
2264887Schin struct checkpt buff;
2278462SApril.Chin@Sun.COM if(!(iop=shp->sftable[fd]) && !(iop=sh_iostream(shp,fd)))
2284887Schin return(1);
2298462SApril.Chin@Sun.COM sh_stats(STAT_READS);
2304887Schin if(names && (name = *names))
2314887Schin {
23210898Sroland.mainz@nrubsig.org Namval_t *mp;
2334887Schin if(val= strchr(name,'?'))
2344887Schin *val = 0;
2358462SApril.Chin@Sun.COM np = nv_open(name,shp->var_tree,NV_NOASSIGN|NV_VARNAME);
23610898Sroland.mainz@nrubsig.org if(np && nv_isarray(np) && (mp=nv_opensub(np)))
23710898Sroland.mainz@nrubsig.org np = mp;
2384887Schin if((flags&V_FLAG) && shp->ed_context)
2394887Schin ((struct edit*)shp->ed_context)->e_default = np;
2404887Schin if(flags&A_FLAG)
2414887Schin {
2424887Schin flags &= ~A_FLAG;
2434887Schin array_index = 1;
2444887Schin nv_unset(np);
2454887Schin nv_putsub(np,NIL(char*),0L);
2464887Schin }
2478462SApril.Chin@Sun.COM else if(flags&C_FLAG)
2488462SApril.Chin@Sun.COM {
2498462SApril.Chin@Sun.COM delim = -1;
2508462SApril.Chin@Sun.COM nv_unset(np);
2518462SApril.Chin@Sun.COM nv_setvtree(np);
2528462SApril.Chin@Sun.COM }
2534887Schin else
2544887Schin name = *++names;
2554887Schin if(val)
2564887Schin *val = '?';
2574887Schin }
2584887Schin else
2594887Schin {
2604887Schin name = 0;
2614887Schin if(dtvnext(shp->var_tree) || shp->namespace)
2624887Schin np = nv_open(nv_name(REPLYNOD),shp->var_tree,0);
2634887Schin else
2644887Schin np = REPLYNOD;
2654887Schin }
2664887Schin if(flags>>D_FLAG) /* delimiter not new-line or fixed size read */
2674887Schin {
2684887Schin if(flags&(N_FLAG|NN_FLAG))
2694887Schin size = ((unsigned)flags)>>D_FLAG;
2704887Schin else
2714887Schin delim = ((unsigned)flags)>>D_FLAG;
2724887Schin if(shp->fdstatus[fd]&IOTTY)
2734887Schin tty_raw(fd,1);
2744887Schin }
2758462SApril.Chin@Sun.COM binary = nv_isattr(np,NV_BINARY);
2768462SApril.Chin@Sun.COM if(!binary && !(flags&(N_FLAG|NN_FLAG)))
2774887Schin {
2784887Schin Namval_t *mp;
2794887Schin /* set up state table based on IFS */
2808462SApril.Chin@Sun.COM ifs = nv_getval(mp=sh_scoped(shp,IFSNOD));
2814887Schin if((flags&R_FLAG) && shp->ifstable['\\']==S_ESC)
2824887Schin shp->ifstable['\\'] = 0;
2834887Schin else if(!(flags&R_FLAG) && shp->ifstable['\\']==0)
2844887Schin shp->ifstable['\\'] = S_ESC;
2854887Schin shp->ifstable[delim] = S_NL;
2864887Schin if(delim!='\n')
2874887Schin {
2884887Schin shp->ifstable['\n'] = 0;
2894887Schin nv_putval(mp, ifs, NV_RDONLY);
2904887Schin }
2914887Schin shp->ifstable[0] = S_EOF;
2924887Schin }
2934887Schin sfclrerr(iop);
2948462SApril.Chin@Sun.COM for(nfp=np->nvfun; nfp; nfp = nfp->next)
2958462SApril.Chin@Sun.COM {
2968462SApril.Chin@Sun.COM if(nfp->disc && nfp->disc->readf)
2978462SApril.Chin@Sun.COM {
2988462SApril.Chin@Sun.COM if((c=(*nfp->disc->readf)(np,iop,delim,nfp))>=0)
2998462SApril.Chin@Sun.COM return(c);
3008462SApril.Chin@Sun.COM }
3018462SApril.Chin@Sun.COM }
3028462SApril.Chin@Sun.COM if(binary && !(flags&(N_FLAG|NN_FLAG)))
3038462SApril.Chin@Sun.COM {
3048462SApril.Chin@Sun.COM flags |= NN_FLAG;
3058462SApril.Chin@Sun.COM size = nv_size(np);
3068462SApril.Chin@Sun.COM }
3074887Schin was_write = (sfset(iop,SF_WRITE,0)&SF_WRITE)!=0;
3084887Schin if(fd==0)
3094887Schin was_share = (sfset(iop,SF_SHARE,1)&SF_SHARE)!=0;
3104887Schin if(timeout || (shp->fdstatus[fd]&(IOTTY|IONOSEEK)))
3114887Schin {
3124887Schin sh_pushcontext(&buff,1);
3134887Schin jmpval = sigsetjmp(buff.buff,0);
3144887Schin if(jmpval)
3154887Schin goto done;
3164887Schin if(timeout)
3174887Schin timeslot = (void*)sh_timeradd(timeout,0,timedout,(void*)iop);
3184887Schin }
3194887Schin if(flags&(N_FLAG|NN_FLAG))
3204887Schin {
32110898Sroland.mainz@nrubsig.org char buf[256],*var=buf,*cur,*end,*up,*v;
3224887Schin /* reserved buffer */
3234887Schin if((c=size)>=sizeof(buf))
3244887Schin {
3254887Schin if(!(var = (char*)malloc(c+1)))
3264887Schin sh_exit(1);
3278462SApril.Chin@Sun.COM end = var + c;
3284887Schin }
3298462SApril.Chin@Sun.COM else
3308462SApril.Chin@Sun.COM end = var + sizeof(buf) - 1;
3318462SApril.Chin@Sun.COM up = cur = var;
3324887Schin if((sfset(iop,SF_SHARE,1)&SF_SHARE) && fd!=0)
3334887Schin was_share = 1;
3344887Schin if(size==0)
3354887Schin {
3364887Schin cp = sfreserve(iop,0,0);
3374887Schin c = 0;
3384887Schin }
3394887Schin else
3404887Schin {
34110898Sroland.mainz@nrubsig.org ssize_t m;
34210898Sroland.mainz@nrubsig.org int f;
3438462SApril.Chin@Sun.COM for (;;)
3444887Schin {
345*12068SRoger.Faulkner@Oracle.COM c = size;
3468462SApril.Chin@Sun.COM cp = sfreserve(iop,c,SF_LOCKR);
3478462SApril.Chin@Sun.COM f = 1;
34810898Sroland.mainz@nrubsig.org if(cp)
34910898Sroland.mainz@nrubsig.org m = sfvalue(iop);
350*12068SRoger.Faulkner@Oracle.COM else if(flags&NN_FLAG)
351*12068SRoger.Faulkner@Oracle.COM {
352*12068SRoger.Faulkner@Oracle.COM c = size;
353*12068SRoger.Faulkner@Oracle.COM m = (cp = sfreserve(iop,c,0)) ? sfvalue(iop) : 0;
354*12068SRoger.Faulkner@Oracle.COM f = 0;
355*12068SRoger.Faulkner@Oracle.COM }
35610898Sroland.mainz@nrubsig.org else
3578462SApril.Chin@Sun.COM {
358*12068SRoger.Faulkner@Oracle.COM c = sfvalue(iop);
359*12068SRoger.Faulkner@Oracle.COM m = (cp = sfreserve(iop,c,SF_LOCKR)) ? sfvalue(iop) : 0;
36010898Sroland.mainz@nrubsig.org }
36110898Sroland.mainz@nrubsig.org if(m>0 && (flags&N_FLAG) && !binary && (v=memchr(cp,'\n',m)))
36210898Sroland.mainz@nrubsig.org {
36310898Sroland.mainz@nrubsig.org *v++ = 0;
36410898Sroland.mainz@nrubsig.org m = v-(char*)cp;
3658462SApril.Chin@Sun.COM }
3668462SApril.Chin@Sun.COM if((c=m)>size)
3678462SApril.Chin@Sun.COM c = size;
3688462SApril.Chin@Sun.COM if(c>0)
3698462SApril.Chin@Sun.COM {
3708462SApril.Chin@Sun.COM if(c > (end-cur))
3718462SApril.Chin@Sun.COM {
37210898Sroland.mainz@nrubsig.org ssize_t cx = cur - var, ux = up - var;
37310898Sroland.mainz@nrubsig.org m = (end - var) + (c - (end - cur));
3748462SApril.Chin@Sun.COM if (var == buf)
3758462SApril.Chin@Sun.COM {
3768462SApril.Chin@Sun.COM v = (char*)malloc(m+1);
37710898Sroland.mainz@nrubsig.org var = memcpy(v, var, cur - var);
3788462SApril.Chin@Sun.COM }
3798462SApril.Chin@Sun.COM else
38010898Sroland.mainz@nrubsig.org var = newof(var, char, m, 1);
38110898Sroland.mainz@nrubsig.org end = var + m;
38210898Sroland.mainz@nrubsig.org cur = var + cx;
38310898Sroland.mainz@nrubsig.org up = var + ux;
3848462SApril.Chin@Sun.COM }
3858462SApril.Chin@Sun.COM memcpy((void*)cur,cp,c);
3868462SApril.Chin@Sun.COM if(f)
3878462SApril.Chin@Sun.COM sfread(iop,cp,c);
3888462SApril.Chin@Sun.COM cur += c;
3898462SApril.Chin@Sun.COM #if SHOPT_MULTIBYTE
3908462SApril.Chin@Sun.COM if(!binary && mbwide())
3918462SApril.Chin@Sun.COM {
3928462SApril.Chin@Sun.COM int x;
3938462SApril.Chin@Sun.COM int z;
3948462SApril.Chin@Sun.COM
3958462SApril.Chin@Sun.COM mbinit();
3968462SApril.Chin@Sun.COM *cur = 0;
3978462SApril.Chin@Sun.COM x = z = 0;
3988462SApril.Chin@Sun.COM while (up < cur && (z = mbsize(up)) > 0)
3998462SApril.Chin@Sun.COM {
4008462SApril.Chin@Sun.COM up += z;
4018462SApril.Chin@Sun.COM x++;
4028462SApril.Chin@Sun.COM }
4038462SApril.Chin@Sun.COM if((size -= x) > 0 && (up >= cur || z < 0) && ((flags & NN_FLAG) || z < 0 || m > c))
4048462SApril.Chin@Sun.COM continue;
4058462SApril.Chin@Sun.COM }
4068462SApril.Chin@Sun.COM #endif
4078462SApril.Chin@Sun.COM }
4088462SApril.Chin@Sun.COM #if SHOPT_MULTIBYTE
4098462SApril.Chin@Sun.COM if(!binary && mbwide() && (up == var || (flags & NN_FLAG) && size))
4108462SApril.Chin@Sun.COM cur = var;
4118462SApril.Chin@Sun.COM #endif
4128462SApril.Chin@Sun.COM *cur = 0;
413*12068SRoger.Faulkner@Oracle.COM if(c>=size || (flags&N_FLAG) || m==0)
414*12068SRoger.Faulkner@Oracle.COM {
415*12068SRoger.Faulkner@Oracle.COM if(m)
416*12068SRoger.Faulkner@Oracle.COM sfclrerr(iop);
417*12068SRoger.Faulkner@Oracle.COM break;
418*12068SRoger.Faulkner@Oracle.COM }
419*12068SRoger.Faulkner@Oracle.COM size -= c;
4204887Schin }
4214887Schin }
4224887Schin if(timeslot)
4234887Schin timerdel(timeslot);
42410898Sroland.mainz@nrubsig.org if(binary && !((size=nv_size(np)) && nv_isarray(np) && c!=size))
4254887Schin {
42610898Sroland.mainz@nrubsig.org if((c==size) && np->nvalue.cp && !nv_isarray(np))
4278462SApril.Chin@Sun.COM memcpy((char*)np->nvalue.cp,var,c);
4288462SApril.Chin@Sun.COM else
4298462SApril.Chin@Sun.COM {
43010898Sroland.mainz@nrubsig.org Namval_t *mp;
4318462SApril.Chin@Sun.COM if(var==buf)
432*12068SRoger.Faulkner@Oracle.COM var = memdup(var,c+1);
4338462SApril.Chin@Sun.COM nv_putval(np,var,NV_RAW);
4348462SApril.Chin@Sun.COM nv_setsize(np,c);
43510898Sroland.mainz@nrubsig.org if(!nv_isattr(np,NV_IMPORT|NV_EXPORT) && (mp=(Namval_t*)np->nvenv))
43610898Sroland.mainz@nrubsig.org nv_setsize(mp,c);
4378462SApril.Chin@Sun.COM }
4384887Schin }
4394887Schin else
4404887Schin {
4414887Schin nv_putval(np,var,0);
4428462SApril.Chin@Sun.COM if(var!=buf)
4434887Schin free((void*)var);
4444887Schin }
4454887Schin goto done;
4464887Schin }
4474887Schin else if(cp = (unsigned char*)sfgetr(iop,delim,0))
4484887Schin c = sfvalue(iop);
4494887Schin else if(cp = (unsigned char*)sfgetr(iop,delim,-1))
4504887Schin c = sfvalue(iop)+1;
4514887Schin if(timeslot)
4524887Schin timerdel(timeslot);
4534887Schin if((flags&S_FLAG) && !shp->hist_ptr)
4544887Schin {
4558462SApril.Chin@Sun.COM sh_histinit((void*)shp);
4564887Schin if(!shp->hist_ptr)
4574887Schin flags &= ~S_FLAG;
4584887Schin }
4594887Schin if(cp)
4604887Schin {
4614887Schin cpmax = cp + c;
4624887Schin #if SHOPT_CRNL
4634887Schin if(delim=='\n' && c>=2 && cpmax[-2]=='\r')
4644887Schin cpmax--;
4654887Schin #endif /* SHOPT_CRNL */
4664887Schin if(*(cpmax-1) != delim)
4674887Schin *(cpmax-1) = delim;
4684887Schin if(flags&S_FLAG)
4694887Schin sfwrite(shp->hist_ptr->histfp,(char*)cp,c);
4704887Schin c = shp->ifstable[*cp++];
4714887Schin #if !SHOPT_MULTIBYTE
4724887Schin if(!name && (flags&R_FLAG)) /* special case single argument */
4734887Schin {
4744887Schin /* skip over leading blanks */
4754887Schin while(c==S_SPACE)
4764887Schin c = shp->ifstable[*cp++];
4774887Schin /* strip trailing delimiters */
4784887Schin if(cpmax[-1] == '\n')
4794887Schin cpmax--;
4804887Schin if(cpmax>cp)
4814887Schin {
4824887Schin while((c=shp->ifstable[*--cpmax])==S_DELIM || c==S_SPACE);
4834887Schin cpmax[1] = 0;
4844887Schin }
4854887Schin else
4864887Schin *cpmax =0;
4874887Schin if(nv_isattr(np, NV_RDONLY))
4884887Schin {
4894887Schin errormsg(SH_DICT,ERROR_warn(0),e_readonly, nv_name(np));
4904887Schin jmpval = 1;
4914887Schin }
4924887Schin else
4934887Schin nv_putval(np,(char*)cp-1,0);
4944887Schin goto done;
4954887Schin }
4964887Schin #endif /* !SHOPT_MULTIBYTE */
4974887Schin }
4984887Schin else
4994887Schin c = S_NL;
5004887Schin shp->nextprompt = 2;
5014887Schin rel= staktell();
5024887Schin /* val==0 at the start of a field */
5034887Schin val = 0;
5044887Schin del = 0;
5054887Schin while(1)
5064887Schin {
5074887Schin switch(c)
5084887Schin {
5094887Schin #if SHOPT_MULTIBYTE
5104887Schin case S_MBYTE:
5114887Schin if(val==0)
5124887Schin val = (char*)(cp-1);
5134887Schin if(sh_strchr(ifs,(char*)cp-1)>=0)
5144887Schin {
5154887Schin c = mbsize((char*)cp-1);
5164887Schin if(name)
5174887Schin cp[-1] = 0;
5184887Schin if(c>1)
5194887Schin cp += (c-1);
5204887Schin c = S_DELIM;
5214887Schin }
5224887Schin else
5234887Schin c = 0;
5244887Schin continue;
5254887Schin #endif /*SHOPT_MULTIBYTE */
5264887Schin case S_ESC:
5274887Schin /* process escape character */
5284887Schin if((c = shp->ifstable[*cp++]) == S_NL)
5294887Schin was_escape = 1;
5304887Schin else
5314887Schin c = 0;
5324887Schin if(val)
5334887Schin {
5344887Schin stakputs(val);
5354887Schin use_stak = 1;
5364887Schin was_escape = 1;
5374887Schin *val = 0;
5384887Schin }
5394887Schin continue;
5404887Schin
5414887Schin case S_EOF:
5424887Schin /* check for end of buffer */
5434887Schin if(val && *val)
5444887Schin {
5454887Schin stakputs(val);
5464887Schin use_stak = 1;
5474887Schin }
5484887Schin val = 0;
5494887Schin if(cp>=cpmax)
5504887Schin {
5514887Schin c = S_NL;
5524887Schin break;
5534887Schin }
5544887Schin /* eliminate null bytes */
5554887Schin c = shp->ifstable[*cp++];
5564887Schin if(!name && val && (c==S_SPACE||c==S_DELIM||c==S_MBYTE))
5574887Schin c = 0;
5584887Schin continue;
5594887Schin case S_NL:
5604887Schin if(was_escape)
5614887Schin {
5624887Schin was_escape = 0;
5634887Schin if(cp = (unsigned char*)sfgetr(iop,delim,0))
5644887Schin c = sfvalue(iop);
5654887Schin else if(cp=(unsigned char*)sfgetr(iop,delim,-1))
5664887Schin c = sfvalue(iop)+1;
5674887Schin if(cp)
5684887Schin {
5694887Schin if(flags&S_FLAG)
5704887Schin sfwrite(shp->hist_ptr->histfp,(char*)cp,c);
5714887Schin cpmax = cp + c;
5724887Schin c = shp->ifstable[*cp++];
5734887Schin val=0;
5744887Schin if(!name && (c==S_SPACE || c==S_DELIM || c==S_MBYTE))
5754887Schin c = 0;
5764887Schin continue;
5774887Schin }
5784887Schin }
5794887Schin c = S_NL;
5804887Schin break;
5814887Schin
5824887Schin case S_SPACE:
5834887Schin /* skip over blanks */
5844887Schin while((c=shp->ifstable[*cp++])==S_SPACE);
5854887Schin if(!val)
5864887Schin continue;
5874887Schin #if SHOPT_MULTIBYTE
5884887Schin if(c==S_MBYTE)
5894887Schin {
5904887Schin if(sh_strchr(ifs,(char*)cp-1)>=0)
5914887Schin {
5924887Schin if((c = mbsize((char*)cp-1))>1)
5934887Schin cp += (c-1);
5944887Schin c = S_DELIM;
5954887Schin }
5964887Schin else
5974887Schin c = 0;
5984887Schin }
5994887Schin #endif /* SHOPT_MULTIBYTE */
6004887Schin if(c!=S_DELIM)
6014887Schin break;
6024887Schin /* FALL THRU */
6034887Schin
6044887Schin case S_DELIM:
6054887Schin if(!del)
6064887Schin del = cp - 1;
6074887Schin if(name)
6084887Schin {
6094887Schin /* skip over trailing blanks */
6104887Schin while((c=shp->ifstable[*cp++])==S_SPACE);
6114887Schin break;
6124887Schin }
6134887Schin /* FALL THRU */
6144887Schin
6154887Schin case 0:
6164887Schin if(val==0 || was_escape)
6174887Schin {
6184887Schin val = (char*)(cp-1);
6194887Schin was_escape = 0;
6204887Schin }
6214887Schin /* skip over word characters */
6224887Schin wrd = -1;
6234887Schin while(1)
6244887Schin {
6254887Schin while((c=shp->ifstable[*cp++])==0)
6264887Schin if(!wrd)
6274887Schin wrd = 1;
6284887Schin if(!del&&c==S_DELIM)
6294887Schin del = cp - 1;
6304887Schin if(name || c==S_NL || c==S_ESC || c==S_EOF || c==S_MBYTE)
6314887Schin break;
6324887Schin if(wrd<0)
6334887Schin wrd = 0;
6344887Schin }
6354887Schin if(wrd>0)
6364887Schin del = (unsigned char*)"";
6374887Schin if(c!=S_MBYTE)
6384887Schin cp[-1] = 0;
6394887Schin continue;
6404887Schin }
6414887Schin /* assign value and advance to next variable */
6424887Schin if(!val)
6434887Schin val = "";
6444887Schin if(use_stak)
6454887Schin {
6464887Schin stakputs(val);
6474887Schin stakputc(0);
6484887Schin val = stakptr(rel);
6494887Schin }
6504887Schin if(!name && *val)
6514887Schin {
6524887Schin /* strip off trailing space delimiters */
6534887Schin register unsigned char *vp = (unsigned char*)val + strlen(val);
6544887Schin while(shp->ifstable[*--vp]==S_SPACE);
6554887Schin if(vp==del)
6564887Schin {
6574887Schin if(vp==(unsigned char*)val)
6584887Schin vp--;
6594887Schin else
6604887Schin while(shp->ifstable[*--vp]==S_SPACE);
6614887Schin }
6624887Schin vp[1] = 0;
6634887Schin }
6644887Schin if(nv_isattr(np, NV_RDONLY))
6654887Schin {
6664887Schin errormsg(SH_DICT,ERROR_warn(0),e_readonly, nv_name(np));
6674887Schin jmpval = 1;
6684887Schin }
6694887Schin else
6704887Schin nv_putval(np,val,0);
6714887Schin val = 0;
6724887Schin del = 0;
6734887Schin if(use_stak)
6744887Schin {
6754887Schin stakseek(rel);
6764887Schin use_stak = 0;
6774887Schin }
6784887Schin if(array_index)
6794887Schin {
6804887Schin nv_putsub(np, NIL(char*), array_index++);
6814887Schin if(c!=S_NL)
6824887Schin continue;
6834887Schin name = *++names;
6844887Schin }
6854887Schin while(1)
6864887Schin {
6874887Schin if(sh_isoption(SH_ALLEXPORT)&&!strchr(nv_name(np),'.') && !nv_isattr(np,NV_EXPORT))
6884887Schin {
6894887Schin nv_onattr(np,NV_EXPORT);
6904887Schin sh_envput(sh.env,np);
6914887Schin }
6924887Schin if(name)
6934887Schin {
6944887Schin nv_close(np);
6954887Schin np = nv_open(name,shp->var_tree,NV_NOASSIGN|NV_VARNAME);
6964887Schin name = *++names;
6974887Schin }
6984887Schin else
6994887Schin np = 0;
7004887Schin if(c!=S_NL)
7014887Schin break;
7024887Schin if(!np)
7034887Schin goto done;
7044887Schin if(nv_isattr(np, NV_RDONLY))
7054887Schin {
7064887Schin errormsg(SH_DICT,ERROR_warn(0),e_readonly, nv_name(np));
7074887Schin jmpval = 1;
7084887Schin }
7094887Schin else
7104887Schin nv_putval(np, "", 0);
7114887Schin }
7124887Schin }
7134887Schin done:
7144887Schin if(timeout || (shp->fdstatus[fd]&(IOTTY|IONOSEEK)))
7154887Schin sh_popcontext(&buff);
7164887Schin if(was_write)
7174887Schin sfset(iop,SF_WRITE,1);
7184887Schin if(!was_share)
7194887Schin sfset(iop,SF_SHARE,0);
7204887Schin nv_close(np);
7214887Schin if((flags>>D_FLAG) && (shp->fdstatus[fd]&IOTTY))
7224887Schin tty_cooked(fd);
7234887Schin if(flags&S_FLAG)
7244887Schin hist_flush(shp->hist_ptr);
7254887Schin if(jmpval > 1)
7264887Schin siglongjmp(*shp->jmplist,jmpval);
7274887Schin return(jmpval);
7284887Schin }
7294887Schin
730