1 /*
2  * $Id: shellcm.c,v 1.5 2002/07/06 08:51:42 isizaka Exp isizaka $
3  *
4  * This file is part of "Ngraph for X11".
5  *
6  * Copyright (C) 2002, Satoshi ISHIZAKA. isizaka@msa.biglobe.ne.jp
7  *
8  * "Ngraph for X11" is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * "Ngraph for X11" is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21  *
22  */
23 
24 /**
25  *
26  * $Log: shellcm.c,v $
27  * Revision 1.5  2002/07/06 08:51:42  isizaka
28  * change to GPL.
29  *
30  * Revision 1.4  2001/03/23 12:15:31  isizaka
31  * for 6.3.13
32  *
33  * Revision 1.3  1999/04/15 12:15:27  isizaka
34  * for release 6.03.01
35  *
36  * Revision 1.2  1999/04/11 06:08:10  isizaka
37  * *** empty log message ***
38  *
39  * Revision 1.1  1999/03/17 13:46:09  isizaka
40  * Initial revision
41  *
42  *
43  **/
44 
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <string.h>
48 #include <ctype.h>
49 #include <errno.h>
50 #ifndef WINDOWS
51 #include <unistd.h>
52 #else
53 #include <dir.h>
54 #endif
55 #include "ngraph.h"
56 #include "object.h"
57 #include "nstring.h"
58 #include "ioutil.h"
59 #include "mathcode.h"
60 #include "mathfn.h"
61 #include "shell.h"
62 #include "shellcm.h"
63 
64 #define TRUE  1
65 #define FALSE 0
66 
67 #define ERR 128
68 
cmcd(struct nshell * nshell,int argc,char ** argv)69 int cmcd(struct nshell *nshell,int argc,char **argv)
70 {
71   char *home;
72 
73   if (argv[1]!=NULL) {
74     if (chdir(argv[1])!=0) {
75       sherror3(argv[0],ERRNODIR,argv[1]);
76       return ERR;
77     }
78   } else {
79     if ((home=getval(nshell,"HOME"))!=NULL) {
80       if (chdir(home)!=0) {
81         sherror3(argv[0],ERRNODIR,home);
82         return ERR;
83       }
84     }
85   }
86   return 0;
87 }
88 
cmecho(struct nshell * nshell,int argc,char ** argv)89 int cmecho(struct nshell *nshell,int argc,char **argv)
90 {
91   int i;
92 
93   for (i=1;i<argc;i++) {
94     printfstdout("%.256s",argv[i]);
95     if (i!=(argc-1)) printfstdout(" ");
96   }
97   putstdout("");
98   return 0;
99 }
100 
cmeval(struct nshell * nshell,int argc,char ** argv)101 int cmeval(struct nshell *nshell,int argc,char **argv)
102 {
103   char *s;
104   int i,rcode;
105 
106   if ((s=nstrnew())==NULL) return ERR;
107   for (i=1;i<argc;i++) {
108     if ((s=nstrcat(s,argv[i]))==NULL) return ERR;
109     if ((s=nstrccat(s,' '))==NULL) return ERR;
110   }
111   rcode=cmdexecute(nshell,s);
112   memfree(s);
113   if ((rcode!=0) && (rcode!=1)) return ERR;
114   return 0;
115 }
116 
cmexit(struct nshell * nshell,int argc,char ** argv)117 int cmexit(struct nshell *nshell,int argc,char **argv)
118 {
119   int a;
120   char *endptr;
121 
122   if (argc>2) {
123     sherror4(argv[0],ERREXTARG);
124     return ERREXTARG;
125   } else if (argc==2) {
126     a=strtol(argv[1],&endptr,10);
127     if (endptr[0]!='\0') {
128       sherror3(argv[0],ERRNUMERIC,argv[1]);
129       return ERRNUMERIC;
130     } else {
131       nshell->quit=TRUE;
132       return a;
133     }
134   } else {
135     nshell->quit=TRUE;
136     return nshell->status;
137   }
138 }
139 
cmexport(struct nshell * nshell,int argc,char ** argv)140 int cmexport(struct nshell *nshell,int argc,char **argv)
141 {
142   int i;
143   struct explist *valcur;
144 
145   if (argv[1]==NULL) {
146     valcur=nshell->exproot;
147     while (valcur!=NULL) {
148       printfstdout("%.256s\n",valcur->val);
149       valcur=valcur->next;
150     }
151     return 0;
152   } else {
153     for (i=1;i<argc;i++)
154       if (addexp(nshell,argv[1])==NULL) return ERR;
155     return 0;
156   }
157 }
158 
cmpwd(struct nshell * nshell,int argc,char ** argv)159 int cmpwd(struct nshell *nshell,int argc,char **argv)
160 {
161   char *s;
162 
163   if ((s=ngetcwd())==NULL) return ERR;
164   putstdout(s);
165   memfree(s);
166   return 0;
167 }
168 
cmset(struct nshell * nshell,int argc,char ** argv)169 int cmset(struct nshell *nshell,int argc,char **argv)
170 {
171   struct vallist *valcur;
172   struct cmdlist *cmdcur;
173   struct prmlist *prmcur;
174   char *s;
175   int i,j,ops;
176   char **argv2;
177   int argc2;
178 
179   if (argc<2) {
180     valcur=nshell->valroot;
181     while (valcur!=NULL) {
182       if (!valcur->func)
183         printfstdout("%.256s=%.256s\n",valcur->name,(char *)(valcur->val));
184       valcur=valcur->next;
185     }
186     valcur=nshell->valroot;
187     while (valcur!=NULL) {
188       if (valcur->func) {
189         printfstdout("%.256s=()\n",valcur->name);
190         putstdout("{");
191         cmdcur=valcur->val;
192         while (cmdcur!=NULL) {
193           prmcur=cmdcur->prm;
194           printfstdout("    ");
195           while (prmcur!=NULL) {
196             if (prmcur->str!=NULL) printfstdout("%.256s ",prmcur->str);
197             prmcur=prmcur->next;
198           }
199           printfstdout("\n");
200           cmdcur=cmdcur->next;
201         }
202         putstdout("}");
203       }
204       valcur=valcur->next;
205     }
206   } else {
207     for (j=1;j<argc;j++) {
208       s=argv[j];
209       if ((s[0]=='-') && (s[1]=='-')) {
210         for (i=1;i<=strlen(argv[j]);i++) argv[j][i-1]=argv[j][i];
211         break;
212       } else if ((s[0]=='-') || (s[0]=='+')) {
213         if ((s[1]=='\0') || (strchr("efvx",s[1])==NULL)) {
214           sherror3(argv[0],ERRILOPS,s);
215           return ERRILOPS;
216         }
217       } else break;
218     }
219     if (j!=argc) {
220       argv2=NULL;
221       if ((s=memalloc(strlen((nshell->argv)[0])+1))==NULL) return ERR;
222       strcpy(s,(nshell->argv)[0]);
223       if (arg_add(&argv2,s)==NULL) {
224         memfree(s);
225         arg_del(argv2);
226         return ERR;
227       }
228       for (;j<argc;j++) {
229         if ((s=memalloc(strlen(argv[j])+1))==NULL) return ERR;
230         strcpy(s,argv[j]);
231         if (arg_add(&argv2,s)==NULL) {
232           memfree(s);
233           arg_del(argv2);
234           return ERR;
235         }
236       }
237       argc2=getargc(argv2);
238       arg_del(nshell->argv);
239       nshell->argv=argv2;
240       nshell->argc=argc2;
241     }
242     for (j=1;j<argc;j++) {
243       s=argv[j];
244       if (s[0]=='-') ops=TRUE;
245       else if (s[0]=='+') ops=FALSE;
246       else break;
247       switch (s[1]) {
248       case 'e':
249         nshell->optione=ops;
250         break;
251       case 'f':
252         nshell->optionf=ops;
253         break;
254       case 'v':
255         nshell->optionv=ops;
256         break;
257       case 'x':
258         nshell->optionx=ops;
259         break;
260       }
261     }
262   }
263   return 0;
264 }
265 
cmshift(struct nshell * nshell,int argc,char ** argv)266 int cmshift(struct nshell *nshell,int argc,char **argv)
267 {
268   int i,a;
269   char *arg,*endptr;
270 
271   if (argc>2) {
272     sherror4(argv[0],ERREXTARG);
273     return ERREXTARG;
274   } else if (argc==2) {
275     arg=argv[1];
276     a=strtol(arg,&endptr,10);
277     if (endptr[0]!='\0') {
278       sherror3(argv[0],ERRNUMERIC,arg);
279       return ERRNUMERIC;
280     }
281   } else a=1;
282 
283   if (a<0) a=0;
284   if ((a+1)>=nshell->argc) a=nshell->argc-1;
285   for (i=a+1;i<nshell->argc;i++) {
286     memfree(nshell->argv[i-a]);
287     nshell->argv[i-a]=nshell->argv[i];
288     nshell->argv[i]=NULL;
289   }
290   nshell->argc-=a;
291   return 0;
292 }
293 
cmtype(struct nshell * nshell,int argc,char ** argv)294 int cmtype(struct nshell *nshell,int argc,char **argv)
295 {
296   struct prmlist *prm2;
297   struct cmdlist *cmdcur;
298   int i,j;
299   char *cmdname;
300 
301   for (j=1;j<argc;j++) {
302     for (i=1;i<CPCMDNUM;i++)
303       if (strcmp0(cpcmdtable[i],argv[j])==0) break;
304     if (i!=CPCMDNUM) {
305       printfstdout("%.256s is a shell keyword.\n",argv[j]);
306     } else if ((cmdcur=getfunc(nshell,argv[j]))!=NULL) {
307       printfstdout("%.256s is a function.\n",argv[j]);
308       printfstdout("%.256s=()\n",argv[j]);
309       putstdout("{");
310       while (cmdcur!=NULL) {
311         prm2=cmdcur->prm;
312         printfstdout("    ");
313         while (prm2!=NULL) {
314           if (prm2->str!=NULL) printfstdout("%.256s ",prm2->str);
315           prm2=prm2->next;
316         }
317         printfstdout("\n");
318         cmdcur=cmdcur->next;
319       }
320       putstdout("}");
321     } else if ((strcmp0(".",argv[j])==0)
322     || (strcmp0("break",argv[j])==0)
323     || (strcmp0("continue",argv[j])==0)
324     || (strcmp0("return",argv[j])==0)) {
325       printfstdout("%.256s is a shell builtin.\n",argv[j]);
326     } else {
327       for (i=0;i<CMDNUM;i++)
328         if (strcmp0(argv[j],cmdtable[i].name)==0) break;
329       if (i!=CMDNUM) {
330         printfstdout("%.256s is a shell builtin.\n",argv[j]);
331       } else {
332         cmdname=nsearchpath(getval(nshell,"PATH"),argv[j],FALSE);
333         if (cmdname==NULL) {
334           sherror3(argv[0],ERRCFOUND,argv[j]);
335         } else {
336           printfstdout("%.256s is %.256s.\n",argv[j],cmdname);
337 	}
338         memfree(cmdname);
339       }
340     }
341   }
342   return 0;
343 }
344 
cmunset(struct nshell * nshell,int argc,char ** argv)345 int cmunset(struct nshell *nshell,int argc,char **argv)
346 {
347   int i;
348 
349   for (i=1;i<argc;i++) {
350     if ((strcmp0(argv[i],"PATH")!=0) && (strcmp0(argv[i],"PS1")!=0)
351     && (strcmp0(argv[i],"PS2")!=0) && (strcmp0(argv[i],"IFS")!=0)) {
352       if (!delval(nshell,argv[i])) return ERR;
353    } else {
354       sherror3(argv[0],ERRUNSET,argv[i]);
355       return ERR;
356     }
357   }
358   return 0;
359 }
360 
objdisp(struct objlist * root,struct objlist * parent,int * tab)361 void objdisp(struct objlist *root,struct objlist *parent,int *tab)
362 {
363   int i;
364   struct objlist *objcur;
365 
366   (*tab)++;
367   objcur=root;
368   while (objcur!=NULL) {
369     if (objcur->parent==parent) {
370       for (i=1;i<*tab;i++) printfstdout("\t");
371       printfstdout("%.256s\n",objcur->name);
372       objdisp(objcur,objcur,tab);
373     }
374     objcur=objcur->next;
375   }
376   (*tab)--;
377 }
378 
dispfield(struct objlist * obj,char * name)379 void dispfield(struct objlist *obj,char *name)
380 {
381   int j,ftype;
382   char perm[4],type[10];
383   char *alist;
384   char **enumlist;
385 
386   ftype=chkobjfieldtype(obj,name);
387   switch (ftype) {
388   case NVOID:    strcpy(type,"void"); break;
389   case NBOOL:    strcpy(type,"bool"); break;
390   case NCHAR:    strcpy(type,"char"); break;
391   case NINT:     strcpy(type,"int"); break;
392   case NDOUBLE:  strcpy(type,"double"); break;
393   case NSTR:     strcpy(type,"char*"); break;
394   case NPOINTER: strcpy(type,"void*"); break;
395   case NIARRAY:  strcpy(type,"int[]"); break;
396   case NDARRAY:  strcpy(type,"double[]"); break;
397   case NSARRAY:  strcpy(type,"*char[]"); break;
398   case NENUM:    strcpy(type,"enum("); break;
399   case NOBJ:     strcpy(type,"obj"); break;
400   case NLABEL:   strcpy(type,"label"); break;
401   case NVFUNC:   strcpy(type,"void("); break;
402   case NBFUNC:   strcpy(type,"bool("); break;
403   case NCFUNC:   strcpy(type,"char("); break;
404   case NIFUNC:   strcpy(type,"int("); break;
405   case NDFUNC:   strcpy(type,"double("); break;
406   case NSFUNC:   strcpy(type,"*char("); break;
407   case NIAFUNC:  strcpy(type,"int[]("); break;
408   case NDAFUNC:  strcpy(type,"double[]("); break;
409   case NSAFUNC:  strcpy(type,"*char[]("); break;
410   default:      strcpy(type,"unknown"); break;
411   }
412   if (chkobjperm(obj,name) & NREAD) perm[0]='r';
413   else perm[0]='-';
414   if (chkobjperm(obj,name) & NWRITE) perm[1]='w';
415   else perm[1]='-';
416   if (chkobjperm(obj,name) & NEXEC) perm[2]='x';
417   else perm[2]='-';
418   perm[3]='\0';
419   printfstdout("%3s %15.256s    %.256s",
420                    (char *)perm,(char *)name,(char *)type);
421   if (ftype>=NVFUNC) {
422     if ((alist=chkobjarglist(obj,name))!=NULL) {
423       if (alist[0]=='\0') printfstdout(" void");
424       else
425         for (j=0;alist[j]!='\0';j++) {
426           switch (alist[j]) {
427           case 'b': printfstdout(" bool"); break;
428           case 'c': printfstdout(" char"); break;
429           case 'i': printfstdout(" int"); break;
430           case 'd': printfstdout(" double"); break;
431           case 's': printfstdout(" char *"); break;
432           case 'p': printfstdout(" void *"); break;
433           case 'o': printfstdout(" obj"); break;
434           }
435           if (alist[j+1]=='a') {
436             printfstdout("[]");
437             j++;
438           }
439         }
440     }
441     printfstdout(" )");
442   } else if (ftype==NENUM) {
443     if ((enumlist=(char **)chkobjarglist(obj,name))!=NULL) {
444       for (j=0;enumlist[j]!=NULL;j++) printfstdout(" %s",enumlist[j]);
445       printfstdout(" )");
446     }
447   }
448   printfstdout("\n");
449 }
450 
cmobject(struct nshell * nshell,int argc,char ** argv)451 int cmobject(struct nshell *nshell,int argc,char **argv)
452 {
453   struct objlist *obj;
454   int i,j,tab;
455   char *name;
456 
457   if (argc<2) {
458     tab=0;
459     objdisp(chkobjroot(),NULL,&tab);
460     return 0;
461   } else {
462     if ((obj=getobject(argv[1]))==NULL) return ERR;
463   }
464   if (argc==2) {
465     printfstdout("object: %.256s\n",chkobjectname(obj));
466     if (chkobjectalias(obj)!=NULL)
467       printfstdout("alias: %.256s\n",chkobjectalias(obj));
468     else
469       printfstdout("alias:\n");
470     printfstdout("version: %.256s\n",chkobjver(obj));
471     if (chkobjparent(obj)!=NULL)
472       printfstdout("parent: %.256s\n",chkobjectname(chkobjparent(obj)));
473     else
474       printfstdout("parent: (null)\n");
475     printfstdout("object id: %d\n",chkobjectid(obj));
476     printfstdout("number of fields: %d\n",chkobjfieldnum(obj));
477     printfstdout("size of instance: %d\n",chkobjsize(obj));
478     printfstdout("current instance: %d\n",chkobjcurinst(obj));
479     printfstdout("last instance id: %d\n",chkobjlastinst(obj));
480     for (i=0;i<chkobjfieldnum(obj);i++) {
481       name=chkobjfieldname(obj,i);
482       dispfield(obj,name);
483     }
484   }
485   for (i=2;i<argc;i++) {
486     if (argv[i][0]=='-') {
487       if (strcmp0(argv[i]+1,"name")==0) printfstdout("%.256s\n",chkobjectname(obj));
488       else if (strcmp0(argv[i]+1,"version")==0) printfstdout("%.256s\n",chkobjver(obj));
489       else if (strcmp0(argv[i]+1,"parent")==0) {
490         if (chkobjparent(obj)!=NULL)
491           printfstdout("%.256s\n",chkobjectname(chkobjparent(obj)));
492         else
493           printfstdout("(null)\n");
494       } else if (strcmp0(argv[i]+1,"id")==0) printfstdout("%d\n",chkobjectid(obj));
495       else if (strcmp0(argv[i]+1,"filed")==0) printfstdout("%d\n",chkobjfieldnum(obj));
496       else if (strcmp0(argv[i]+1,"size")==0) printfstdout("%d\n",chkobjsize(obj));
497       else if (strcmp0(argv[i]+1,"current")==0) printfstdout("%d\n",chkobjcurinst(obj));
498       else if (strcmp0(argv[i]+1,"last")==0) printfstdout("%d\n",chkobjlastinst(obj));
499       else if (strcmp0(argv[i]+1,"instance")==0) printfstdout("%d\n",chkobjlastinst(obj)+1);
500       else if (strcmp0(argv[i]+1,"instances")==0) {
501         for (j=0;j<=chkobjlastinst(obj);j++) {
502           printfstdout("%d",j);
503           if (j!=chkobjlastinst(obj)) printfstdout(" ");
504           else printfstdout("\n");
505         }
506       } else {
507         sherror3(argv[0],ERROPTION,argv[i]);
508         return ERROPTION;
509       }
510     } else break;
511   }
512   for (;i<argc;i++) {
513     if (getobjfield(obj,argv[i])==-1) return ERR;
514     dispfield(obj,argv[i]);
515   }
516   return 0;
517 }
518 
dispparent(struct objlist * parent,int noinst)519 void dispparent(struct objlist *parent,int noinst)
520 {
521   struct objlist *ocur;
522 
523   ocur=chkobjroot();
524   while (ocur!=NULL) {
525     if (chkobjparent(ocur)==parent) {
526       if ((chkobjlastinst(ocur)!=-1) || (!noinst))
527         putstdout(chkobjectname(ocur));
528       dispparent(ocur,noinst);
529     }
530     ocur=ocur->next;
531   }
532 }
533 
cmderive(struct nshell * nshell,int argc,char ** argv)534 int cmderive(struct nshell *nshell,int argc,char **argv)
535 {
536   struct objlist *obj;
537   int i,noinst;
538 
539   noinst=FALSE;
540   for (i=1;i<argc;i++) {
541     if (argv[i][0]=='-') {
542       if (strcmp0(argv[i]+1,"instance")==0) noinst=TRUE;
543       else {
544         sherror3(argv[0],ERROPTION,argv[i]);
545         return ERROPTION;
546       }
547     } else break;
548   }
549   if (i==argc) {
550     if ((obj=getobject("object"))==NULL) return ERR;
551     if ((chkobjlastinst(obj)!=-1) || (!noinst))
552       putstdout(chkobjectname(obj));
553     dispparent(obj,noinst);
554   } else {
555     for (;i<argc;i++) {
556       if ((obj=getobject(argv[i]))==NULL) return ERR;
557       if ((chkobjlastinst(obj)!=-1) || (!noinst))
558         putstdout(chkobjectname(obj));
559       dispparent(obj,noinst);
560     }
561   }
562   return 0;
563 }
564 
cmnew(struct nshell * nshell,int argc,char ** argv)565 int cmnew(struct nshell *nshell,int argc,char **argv)
566 {
567   struct objlist *obj;
568   struct narray iarray;
569   int i,anum,id;
570 
571   if (argc<2) {
572     sherror4(argv[0],ERROBJARG);
573     return ERROBJARG;
574   }
575   arrayinit(&iarray,sizeof(int));
576   if (getobjilist(argv[1],&obj,&iarray,FALSE,NULL)) return ERR;
577   anum=arraynum(&iarray);
578   arraydel(&iarray);
579   if (anum!=0) {
580     sherror3(argv[0],ERRNEWINST,argv[1]);
581     arraydel(&iarray);
582     return ERRNEWINST;
583   }
584   if ((id=newobj(obj))==-1) return ERR;
585   for (i=2;i<argc;i++) {
586     if (sputfield(obj,id,argv[i])!=0) {
587       delobj(obj,id);
588       return ERR;
589     }
590   }
591   return 0;
592 }
593 
cmdel(struct nshell * nshell,int argc,char ** argv)594 int cmdel(struct nshell*nshell,int argc,char **argv)
595 {
596   struct objlist *obj;
597   struct narray iarray;
598   int i,j,id,anum,*adata;
599 
600   if (argc<2) {
601     sherror4(argv[0],ERROBJARG);
602     return ERROBJARG;
603   } else if (argc>2) {
604     sherror4(argv[0],ERRMANYARG);
605     return ERRMANYARG;
606   }
607   arrayinit(&iarray,sizeof(int));
608   if (getobjilist(argv[1],&obj,&iarray,TRUE,NULL)) return ERR;
609   anum=arraynum(&iarray);
610   if (anum==0) {
611     sherror4(argv[0],ERRNONEINST);
612     arraydel(&iarray);
613     return ERRNONEINST;
614   }
615   adata=arraydata(&iarray);
616   for (i=0;i<anum;i++)
617     for (j=1;j<anum;j++)
618       if (adata[j-1]<adata[j]) {
619         id=adata[j-1];
620         adata[j-1]=adata[j];
621         adata[j]=id;
622       }
623   j=0;
624   for (i=1;i<anum;i++)
625     if (adata[i]!=adata[j]) {
626       j++;
627       adata[j]=adata[i];
628     }
629   for (i=0;i<=j;i++)
630     if (delobj(obj,adata[i])==-1) {
631       arraydel(&iarray);
632       return ERR;
633     }
634   arraydel(&iarray);
635   return 0;
636 }
637 
cmexist(struct nshell * nshell,int argc,char ** argv)638 int cmexist(struct nshell*nshell,int argc,char **argv)
639 {
640   struct objlist *obj;
641   struct narray iarray;
642   int anum;
643 
644   if (argc<2) {
645     sherror4(argv[0],ERROBJARG);
646     return ERROBJARG;
647   } else if (argc>2) {
648     sherror4(argv[0],ERRMANYARG);
649     return ERRMANYARG;
650   }
651   arrayinit(&iarray,sizeof(int));
652   if (chkobjilist(argv[1],&obj,&iarray,TRUE,NULL)) anum=0;
653   else {
654     anum=arraynum(&iarray);
655     arraydel(&iarray);
656   }
657   printfstdout("%d\n",anum);
658   if (anum==0) return ERRNONEINST;
659   return 0;
660 }
661 
cmget(struct nshell * nshell,int argc,char ** argv)662 int cmget(struct nshell*nshell,int argc,char **argv)
663 {
664   struct objlist *obj;
665   struct narray iarray;
666   char *field,*valstr;
667   int i,j,k,l,id,anum,len,*adata;
668   int nowrite,nofield,noid,quote,perm,multi;
669 
670   if (argc<2) {
671     sherror4(argv[0],ERROBJARG);
672     return ERROBJARG;
673   }
674   arrayinit(&iarray,sizeof(int));
675   if (getobjilist(argv[1],&obj,&iarray,TRUE,NULL)) return ERR;
676   anum=arraynum(&iarray);
677   adata=arraydata(&iarray);
678   if (anum==0) {
679     sherror4(argv[0],ERRNONEINST);
680     arraydel(&iarray);
681     return ERRNONEINST;
682   }
683   nowrite=FALSE;
684   nofield=FALSE;
685   noid=FALSE;
686   quote=FALSE;
687   for (j=2;j<argc;j++) {
688     if (argv[j][0]=='-') {
689       if (strcmp0(argv[j]+1,"write")==0) nowrite=TRUE;
690       else if (strcmp0(argv[j]+1,"field")==0) nofield=TRUE;
691       else if (strcmp0(argv[j]+1,"id")==0) noid=TRUE;
692       else if (strcmp0(argv[j]+1,"quote")==0) quote=TRUE;
693       else {
694         sherror3(argv[0],ERROPTION,argv[j]);
695         arraydel(&iarray);
696         return ERROPTION;
697       }
698     } else break;
699   }
700   if (anum==1) multi=FALSE;
701   else multi=TRUE;
702   for (l=0;l<anum;l++) {
703     id=adata[l];
704     if (j==argc) {
705       for (i=0;i<chkobjfieldnum(obj);i++) {
706         field=chkobjfieldname(obj,i);
707         perm=chkobjperm(obj,field);
708         if (((perm&NREAD)==1) && ((perm&NEXEC)==0)
709         && (!nowrite || ((perm&NWRITE)==1))) {
710           if (sgetfield(obj,id,field,&valstr,FALSE,FALSE,quote)!=0) {
711             arraydel(&iarray);
712             return ERR;
713           }
714           if (multi && !noid) printfstdout("%d: ",id);
715           if (!nofield) printfstdout("%.256s:",field);
716           putstdout(valstr);
717           memfree(valstr);
718         }
719       }
720     } else {
721       for (k=j;k<argc;k++) {
722         field=argv[k];
723         if (!nowrite || ((chkobjperm(obj,field)&NWRITE)==1)) {
724           if (sgetfield(obj,id,field,&valstr,FALSE,FALSE,quote)!=0) {
725             arraydel(&iarray);
726             return ERR;
727           }
728           if (multi && !noid) printfstdout("%d: ",id);
729           if (!nofield) {
730             field=getitok2(&field,&len,":=");
731             printfstdout("%.256s:",field);
732             memfree(field);
733           }
734           putstdout(valstr);
735           memfree(valstr);
736         }
737       }
738     }
739   }
740   arraydel(&iarray);
741   return 0;
742 }
743 
cmput(struct nshell * nshell,int argc,char ** argv)744 int cmput(struct nshell*nshell,int argc,char **argv)
745 {
746   struct objlist *obj;
747   char *image;
748   int i,j,id,anum,*adata;
749   struct narray iarray;
750 
751   if (argc<2) {
752     sherror4(argv[0],ERROBJARG);
753     return ERROBJARG;
754   }
755   arrayinit(&iarray,sizeof(int));
756   if (getobjilist(argv[1],&obj,&iarray,TRUE,NULL)) return ERR;
757   anum=arraynum(&iarray);
758   adata=arraydata(&iarray);
759   if (anum==0) {
760     sherror4(argv[0],ERRNONEINST);
761     arraydel(&iarray);
762     return ERRNONEINST;
763   }
764   if (argc==2) {
765     sherror4(argv[0],ERRNOFIELD);
766     arraydel(&iarray);
767     return ERRNOFIELD;
768   }
769   for (i=0;i<anum;i++) {
770     id=adata[i];
771     if ((image=saveobj(obj,id))==NULL) {
772       arraydel(&iarray);
773       return ERR;
774     }
775     for (j=2;j<argc;j++) {
776       if (sputfield(obj,id,argv[j])!=0) {
777         restoreobj(obj,id,image);
778         arraydel(&iarray);
779         return ERR;
780       }
781     }
782     memfree(image);
783   }
784   arraydel(&iarray);
785   return 0;
786 }
787 
cmcpy(struct nshell * nshell,int argc,char ** argv)788 int cmcpy(struct nshell*nshell,int argc,char **argv)
789 {
790   struct objlist *obj;
791   struct narray iarray;
792   int i,j,anum,sid,did,*adata;
793   char *field;
794   int perm,type;
795 
796   if (argc<2) {
797     sherror4(argv[0],ERROBJARG);
798     return ERROBJARG;
799   }
800   arrayinit(&iarray,sizeof(int));
801   if (getobjilist(argv[1],&obj,&iarray,TRUE,NULL)) return ERR;
802   anum=arraynum(&iarray);
803   adata=arraydata(&iarray);
804   if (anum<2) {
805     sherror4(argv[0],ERRTWOINST);
806     arraydel(&iarray);
807     return ERRTWOINST;
808   }
809   for (i=1;i<anum;i++) {
810     sid=adata[0];
811     did=adata[i];
812     if (argc==2) {
813       for (j=0;j<chkobjfieldnum(obj);j++) {
814         field=chkobjfieldname(obj,j);
815         perm=chkobjperm(obj,field);
816         type=chkobjfieldtype(obj,field);
817         if (((perm&NREAD)!=0) && ((perm&NWRITE)!=0) && (type<NVFUNC)) {
818           if (copyobj(obj,field,did,sid)==-1) {
819             arraydel(&iarray);
820             return ERR;
821           }
822         }
823       }
824     } else {
825       for (j=2;j<argc;j++)
826         if (copyobj(obj,argv[j],did,sid)==-1) {
827           arraydel(&iarray);
828           return ERR;
829         }
830     }
831   }
832   arraydel(&iarray);
833   return 0;
834 }
835 
cmmove(struct nshell * nshell,int argc,char ** argv)836 int cmmove(struct nshell*nshell,int argc,char **argv)
837 {
838   struct objlist *obj;
839   struct narray iarray;
840   int anum,id1,id2,*adata;
841 
842   if (argc<2) {
843     sherror4(argv[0],ERROBJARG);
844     return ERROBJARG;
845   } else if (argc>2) {
846     sherror4(argv[0],ERRMANYARG);
847     return ERRMANYARG;
848   }
849   arrayinit(&iarray,sizeof(int));
850   if (getobjilist(argv[1],&obj,&iarray,TRUE,NULL)) return ERR;
851   anum=arraynum(&iarray);
852   adata=arraydata(&iarray);
853   if (anum!=2) {
854     sherror4(argv[0],ERRTWOINST);
855     arraydel(&iarray);
856     return ERRTWOINST;
857   }
858   id1=adata[0];
859   id2=adata[1];
860   arraydel(&iarray);
861   if (strcmp0(argv[0],"move")==0) {
862     if (moveobj(obj,id2,id1)==-1) return ERR;
863   } else if (strcmp0(argv[0],"exch")==0) {
864     if (exchobj(obj,id2,id1)==-1) return ERR;
865   }
866   return 0;
867 }
868 
cmmovetop(struct nshell * nshell,int argc,char ** argv)869 int cmmovetop(struct nshell*nshell,int argc,char **argv)
870 {
871   struct objlist *obj;
872   struct narray iarray;
873   int i,anum,top,rcode,*adata;
874 
875   if (argc<2) {
876     sherror4(argv[0],ERROBJARG);
877     return ERROBJARG;
878   } else if (argc>2) {
879     sherror4(argv[0],ERRMANYARG);
880     return ERRMANYARG;
881   }
882   arrayinit(&iarray,sizeof(int));
883   if (getobjilist(argv[1],&obj,&iarray,TRUE,NULL)) return ERR;
884   anum=arraynum(&iarray);
885   adata=arraydata(&iarray);
886   if (strcmp0(argv[0],"movetop")==0) top=0;
887   else if (strcmp0(argv[0],"moveup")==0) top=1;
888   else if (strcmp0(argv[0],"movedown")==0) top=2;
889   else top=3;
890   for (i=0;i<anum;i++) {
891     if (top==0) rcode=movetopobj(obj,adata[i]);
892     else if (top==1) rcode=moveupobj(obj,adata[i]);
893     else if (top==2) rcode=movedownobj(obj,adata[i]);
894     else rcode=movelastobj(obj,adata[i]);
895     if (rcode==-1) {
896       arraydel(&iarray);
897       return ERR;
898     }
899   }
900   arraydel(&iarray);
901   return 0;
902 }
903 
cmexe(struct nshell * nshell,int argc,char ** argv)904 int cmexe(struct nshell*nshell,int argc,char **argv)
905 {
906   struct objlist *obj;
907   struct narray iarray;
908   int i,j,id,anum,*adata;
909 
910   if (argc<2) {
911     sherror4(argv[0],ERROBJARG);
912     return ERROBJARG;
913   }
914   arrayinit(&iarray,sizeof(int));
915   if (getobjilist(argv[1],&obj,&iarray,TRUE,NULL)) return ERR;
916   anum=arraynum(&iarray);
917   adata=arraydata(&iarray);
918   if (anum==0) {
919     sherror4(argv[0],ERRNONEINST);
920     arraydel(&iarray);
921     return ERRNONEINST;
922   }
923   if (argc==2) {
924     sherror4(argv[0],ERRNOFIELD);
925     arraydel(&iarray);
926     return ERRNOFIELD;
927   }
928   for (j=0;j<anum;j++) {
929     id=adata[j];
930     for (i=2;i<argc;i++) {
931       if (sexefield(obj,id,argv[i])!=0) {
932         arraydel(&iarray);
933         return ERR;
934       }
935     }
936   }
937   arraydel(&iarray);
938   return 0;
939 }
940 
cmdexpr(struct nshell * nshell,int argc,char ** argv)941 int cmdexpr(struct nshell*nshell,int argc,char **argv)
942 {
943   int rcode,ecode;
944   char *code;
945   double vd;
946   int i;
947   double memory[MEMORYNUM];
948   char memorystat[MEMORYNUM];
949   char *s;
950 
951   if (argc<1) {
952     sherror4(argv[0],ERRSMLARG);
953     return ERRSMLARG;
954   }
955   if ((s=nstrnew())==NULL) return ERR;
956   for (i=1;i<argc;i++)
957     if ((s=nstrcat(s,argv[i]))==NULL) return ERR;
958   rcode=mathcode(s,&code,NULL,NULL,NULL,NULL,
959                  FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE);
960   memfree(s);
961   if (rcode!=MCNOERR) {
962     if (rcode==MCSYNTAX) ecode=ERRMSYNTAX;
963     else if (rcode==MCILLEGAL) ecode=ERRMILLEGAL;
964     else if (rcode==MCNEST) ecode=ERRMNEST;
965     sherror4(argv[0],ERRVALUE);
966     return ecode;
967   }
968   for (i=0;i<MEMORYNUM;i++) {memory[i]=0;memorystat[i]=MNOERR;}
969   rcode=calculate(code,1,
970                   0,MNOERR,0,MNOERR,0,MNOERR,
971                   0,0,0,0,0,0,0,0,0,0,0,0,0,0,
972                   NULL,NULL,
973                   memory,memorystat,
974                   NULL,NULL,
975                   NULL,NULL,
976                   NULL,NULL,NULL,
977                   NULL,NULL,NULL,0,NULL,NULL,NULL,0,&vd);
978   memfree(code);
979   ecode=0;
980   if (rcode==MSERR) ecode=ERRMSYNTAX;
981   else if (rcode==MERR) ecode=ERRMFAT;
982   if (ecode!=0) {
983     sherror4(argv[0],ecode);
984     return ecode;
985   }
986   if (rcode==MNAN) {
987     putstdout("nan");
988     return ERR;
989   } else if (rcode==MUNDEF) {
990     putstdout("undifined");
991     return ERR;
992   }
993   if (argv[0][0]=='d') printfstdout("%.15e\n",vd);
994   else printfstdout("%d\n",nround(vd));
995   return 0;
996 }
997 
cmread(struct nshell * nshell,int argc,char ** argv)998 int cmread(struct nshell *nshell,int argc,char **argv)
999 {
1000   int c,i,len;
1001   char *s,*po,*s2,*ifs;
1002 
1003   if ((s=nstrnew())==NULL) return ERR;
1004   while (TRUE) {
1005     c=getstdin();
1006     if ((c=='\n') || (c==EOF)) break;
1007     if ((s=nstrccat(s,c))==NULL) return ERR;
1008   }
1009   if (argc==1) {
1010     addval(nshell,"REPLY",s);
1011   } else {
1012     po=s;
1013     ifs=getval(nshell,"IFS");
1014     for (i=1;i<argc;i++) {
1015       if ((s2=getitok2(&po,&len,ifs))!=NULL) {
1016         addval(nshell,argv[i],s2);
1017         memfree(s2);
1018       } else {
1019         addval(nshell,argv[i],"");
1020       }
1021     }
1022   }
1023   memfree(s);
1024   if (c==EOF) return ERR;
1025   else return 0;
1026 }
1027