1 /*
2  * ***************************************************************************
3  * MALOC = < Minimal Abstraction Layer for Object-oriented C >
4  * Copyright (C) 1994-- Michael Holst
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  *
20  * rcsid="$Id: vsh.c,v 1.27 2010/08/12 05:40:27 fetk Exp $"
21  * ***************************************************************************
22  */
23 
24 /*
25  * ***************************************************************************
26  * File:     vsh.c
27  *
28  * Purpose:  Class Vsh: methods.
29  *
30  * Author:   Michael Holst
31  * ***************************************************************************
32  */
33 
34 #include "vsh_p.h"
35 #include "vpup.h"
36 
37 VEMBED(rcsid="$Id: vsh.c,v 1.27 2010/08/12 05:40:27 fetk Exp $")
38 
39 /* use lex/yacc or not */
40 #define VSH_LEX_YACC_NOT 1
41 
42 /* lex/yacc support */
43 VPUBLIC int cmdKey = 0;
44 VPUBLIC Vsh *Vsh_thee = VNULL;
45 VPUBLIC COMMAND *global_command = VNULL;
46 
47 /* command structure */
48 typedef enum VSH_command {
49     vshcom_none,
50     vshcom_clear,
51     vshcom_help,
52     vshcom_pause,
53     vshcom_delay,
54     vshcom_set,
55     vshcom_penv,
56     vshcom_pinfo,
57     vshcom_cd,
58     vshcom_cdw,
59     vshcom_io,
60     vshcom_noio,
61     vshcom_exit,
62     vshcom_dot,
63     vshcom_sockg,
64     vshcom_sockm,
65     vshcom_sockk,
66     vshcom_sorry
67 } VSH_command;
68 
69 VPRIVATE void Vsh_publishVars(Vsh *thee, int argc, char **argv);
70 VPRIVATE void Vsh_readlineReset(void);
71 
72 /*
73  * ***************************************************************************
74  * Class Vsh: Inlineable methods
75  * ***************************************************************************
76  */
77 #if !defined(VINLINE_MALOC)
78 #endif /* if !defined(VINLINE_MALOC) */
79 
80 /*
81  * ***************************************************************************
82  * Class Vsh: Non-inlineable methods
83  * ***************************************************************************
84  */
85 
86 /*
87  * ***************************************************************************
88  * Routine:  Vsh_ctor
89  *
90  * Purpose:  Create the shell.
91  *
92  * Author:   Michael Holst
93  * ***************************************************************************
94  */
Vsh_ctor(Vmem * vmem,int argc,char ** argv)95 VPUBLIC Vsh* Vsh_ctor(Vmem *vmem, int argc, char **argv)
96 {
97     Vsh *thee = VNULL;
98 
99     VDEBUGIO("Vsh_ctor: CREATING object..");
100 
101     thee = Vmem_malloc( VNULL, 1, sizeof(Vsh) );
102     if (vmem == VNULL) {
103         thee->vmem = Vmem_ctor( "Vsh" );
104         thee->iMadeVmem = 1;
105     } else {
106         thee->vmem = vmem;
107         thee->iMadeVmem = 0;
108     }
109 
110     VDEBUGIO("..done.\n");
111 
112     /* start i/o layer */
113     Vio_start();
114 
115     /* initialization */
116     thee->processArgs = 1;
117     thee->inUnit      = VNULL;
118     thee->scUnit      = VNULL;
119     thee->clUnit      = VNULL;
120     thee->cinUnit     = VNULL;
121     thee->cinName[0]  = '\0';
122     thee->PR[0]       = '\0';
123     thee->PR_PATH[0]  = '\0';
124     strcpy(thee->PR_EXIT,"exit");
125     thee->envValuLen = 0;
126     thee->envInfoLen = 0;
127     thee->envValu = Vmem_malloc(thee->vmem,1,sizeof(char*));
128     thee->envInfo = Vmem_malloc(thee->vmem,1,sizeof(char*));
129     thee->envValu[0] = VNULL;
130     thee->envInfo[0] = VNULL;
131     thee->buf        = VNULL;
132     thee->bufsize    = 0;
133 
134     /* set the builtin/thee pointers */
135     thee->Ext_thee    = VNULL;
136     thee->Ext_builtin = VNULL;
137     Vsh_thee = thee;
138 
139     /* publish other variables */
140     Vsh_publishVars(thee, argc, argv);
141 
142     /* return the object */
143     return thee;
144 }
145 
146 /*
147  * ***************************************************************************
148  * Routine:  Vsh_dtor
149  *
150  * Purpose:  Destroy the shell.
151  *
152  * Author:   Michael Holst
153  * ***************************************************************************
154  */
Vsh_dtor(Vsh ** thee)155 VPUBLIC void Vsh_dtor(Vsh **thee)
156 {
157     VASSERT( (*thee) != VNULL );
158     if ((*thee) != VNULL) {
159 
160         /* wipe the environment */
161         Vsh_wipe( (*thee) );
162 
163         /* stop i/o layer */
164         Vio_stop();
165 
166         VDEBUGIO("Vsh_dtor: DESTROYING object..");
167         if ((*thee)->iMadeVmem) Vmem_dtor( &((*thee)->vmem) );
168         Vmem_free( VNULL, 1, sizeof(Vsh), (void**)thee );
169         VDEBUGIO("..done.\n");
170 
171         (*thee) = VNULL;
172     }
173 }
174 
175 /*
176  * ***************************************************************************
177  * Routine:  Vsh_publishVars
178  *
179  * Purpose:  Publish environment variables.
180  *
181  * Author:   Michael Holst
182  * ***************************************************************************
183  */
Vsh_publishVars(Vsh * thee,int argc,char ** argv)184 VPRIVATE void Vsh_publishVars(Vsh *thee, int argc, char **argv)
185 {
186     char homeDirectory[VMAX_ARGLEN];
187     char workDirectory[VMAX_ARGLEN];
188     char userName[VMAX_ARGLEN];
189     char hostName[VMAX_ARGLEN];
190     char osName[VMAX_ARGLEN];
191     char configFile[VMAX_ARGLEN];
192     char buf1[VMAX_ARGLEN], buf2[VMAX_ARGLEN];
193     char *term, *cterm;
194     int i, numVars = 11;
195     typedef struct vshVars {
196         char envi[VMAX_ARGLEN];
197         char valu[VMAX_ARGLEN];
198         char info[VMAX_ARGLEN];
199     } vshVars;
200     vshVars envVars[] = {
201         /* --------   -----       ----------- */
202         /* VARIABLE   VALUE       EXPLANATION */
203         /* --------   -----       ----------- */
204         /* ===[ SOCKET=1 ]=== */
205         { "GVLO",     "2x1",
206             "socket layout (1x1,...,4x1,1x1s,...,4x1s)" },
207 
208         /* ===[ INPUTDEV=5 ]=== */
209         { "ISKEY",    "file",
210             "VIO INPUT DEV type (sdio,file,buff,unix,inet)" },
211         { "ISFMT",    "asc",
212             "VIO INPUT DEV format (asc,xdr)" },
213         { "IFNAM",    "mcin.m",
214             "VIO INPUT DEV file (filename for file I/O)" },
215         { "ISNAM",    "0",
216             "VIO INPUT DEV name ([ buff | unix | inet ] number)" },
217         { "IHVAL",    "localhost",
218             "VIO INPUT DEV host (INET hostname or IP address)" },
219 
220         /* ===[ OUTPUTDEV=5 ]=== */
221         { "OSKEY",    "inet",
222             "VIO OUTPUT DEV type (sdio,file,buff,unix,inet)" },
223         { "OSFMT",    "asc",
224             "VIO OUTPUT DEV format (asc,xdr)" },
225         { "OFNAM",    "mcout.m",
226             "VIO OUTPUT DEV file (filename for file I/O)" },
227         { "OSNAM",    "1",
228             "VIO OUTPUT DEV name ([ buff | unix | inet ] number)" },
229         { "OHVAL",    "localhost",
230             "VIO OUTPUT DEV host (INET hostname or IP address)" },
231     };
232 
233     /* get username, hostname, and osname */
234     VASSERT( Vnm_getuser(userName,sizeof(userName)) );
235     VASSERT( Vnm_gethost(hostName,sizeof(hostName)) );
236     VASSERT( Vnm_getos(osName,sizeof(osName)) );
237 
238     /* get the home directory */
239     /*
240      * NOTES: the first call to Vnm_gethome fixes the home directory
241      *        for all time, regardless of who makes the call.
242      */
243     VASSERT( Vnm_gethome(homeDirectory,sizeof(homeDirectory)) );
244 
245     /* get the working directory */
246     /*
247      * NOTES: each call to Vnm_getcwd may return a different value;
248      *        it returns the current working directory, which may be
249      *        modified by calls to Vnm_chdir.
250      */
251     VASSERT( Vnm_getcwd(workDirectory,sizeof(workDirectory)) );
252 
253     /* get some other stuff (may be null) */
254     term  = getenv("TERM");
255     cterm = getenv("COLORTERM");
256 
257     /* config file */
258     sprintf(configFile,"%s/%s",homeDirectory,"rc.mcsh");
259 
260     /* export to the variables */
261     VASSERT( Vsh_putenv(     thee, "USER",      userName               )
262           && Vsh_putenvInfo( thee, "USER",      "user name"            ) );
263     VASSERT( Vsh_putenv(     thee, "HOSTNAME",  hostName               )
264           && Vsh_putenvInfo( thee, "HOSTNAME",  "host name"            ) );
265     VASSERT( Vsh_putenv(     thee, "OSTYPE",    osName                 )
266           && Vsh_putenvInfo( thee, "OSTYPE",    "operating system"     ) );
267     VASSERT( Vsh_putenv(     thee, "HOME",      homeDirectory          )
268           && Vsh_putenvInfo( thee, "HOME",      "home directory"       ) );
269     VASSERT( Vsh_putenv(     thee, "CWD",       workDirectory          )
270           && Vsh_putenvInfo( thee, "CWD",       "working directory"    ) );
271     VASSERT( Vsh_putenv(     thee, "TERM",      term                   )
272           && Vsh_putenvInfo( thee, "TERM",      "terminal type"        ) );
273     VASSERT( Vsh_putenv(     thee, "COLORTERM", cterm                  )
274           && Vsh_putenvInfo( thee, "COLORTERM", "color terminal type"  ) );
275 
276     /* init file name, shell name, prompt */
277     VASSERT( Vsh_putenv(     thee, "ENV",       configFile             )
278           && Vsh_putenvInfo( thee, "ENV",       "environ file"         ) );
279     VASSERT( Vsh_putenv(     thee, "SHELL",     thee->PR               )
280           && Vsh_putenvInfo( thee, "SHELL",     "command shell"        ) );
281     VASSERT( Vsh_putenv(     thee, "PROMPT",    thee->PR_PATH          )
282           && Vsh_putenvInfo( thee, "PROMPT",    "command shell prompt" ) );
283 
284     /* publish remaining variables */
285     for (i=0; i<numVars; i++) {
286         VASSERT( Vsh_putenv(     thee, envVars[i].envi, envVars[i].valu )
287               && Vsh_putenvInfo( thee, envVars[i].envi, envVars[i].info ) );
288     }
289 
290     /* publish argc/argv variables */
291     VASSERT( Vsh_putenvInt(thee,"ARGC",argc)
292           && Vsh_putenvInfo(thee,"ARGC","Number of command line parameters") );
293     for (i=0; i<argc; i++) {
294         sprintf(buf1,"ARG%d",i);
295         sprintf(buf2,"Command line parameter <%d>",i);
296         VASSERT( Vsh_putenv(     thee, buf1, argv[i] )
297               && Vsh_putenvInfo( thee, buf1, buf2    ) );
298     }
299 }
300 
301 /*
302  * ***************************************************************************
303  * Routine:  Vsh_trace
304  *
305  * Purpose:  Trace of token stream.
306  *
307  * Author:   Michael Holst
308  * ***************************************************************************
309  */
Vsh_trace(char * from,char * arg)310 VPUBLIC void Vsh_trace(char *from, char *arg) {
311 #if defined(VSH_TRACE)
312 #   if defined(VSH_LEX_YACC)
313         fprintf(stderr, "%s token=<%s>, yytext=<%s>\n", from, arg, yytext);
314 #   else
315         fprintf(stderr, "%s token=<%s>\n", from, arg);
316 #   endif
317 #endif
318 }
319 
320 /*
321  * ***************************************************************************
322  * Routine:  Vsh_isInteractive
323  *
324  * Purpose:  Is this an interactive shell.
325  *
326  * Author:   Michael Holst
327  * ***************************************************************************
328  */
Vsh_isInteractive(Vsh * thee)329 VPUBLIC int Vsh_isInteractive(Vsh *thee) {
330     return ((thee->cinUnit == stdin) && isatty(fileno(stdin)));
331 }
332 
333 /*
334  * ***************************************************************************
335  * Routine:  Vsh_findVar
336  *
337  * Purpose:  Find a variable in the environment.
338  *
339  * Notes:    The parameters are:
340  *
341  *               env    --> the environment variable array
342  *               envLen --> the environment variable array length
343  *               var    --> the variable we are looking for
344  *               term   --> the character terminator (usually "=" or ":")
345  *
346  * Author:   Michael Holst
347  * ***************************************************************************
348  */
Vsh_findVar(char ** env,int envLen,const char * var,const char term)349 VPUBLIC int Vsh_findVar(char **env, int envLen,
350     const char *var, const char term)
351 {
352     int i, j, len, ifnd, foundEq;
353     char varBuf[VMAX_BUFSIZE];
354 
355     /* look for variable in the environment */
356     ifnd = -1;
357     i = 0;
358     while ((ifnd < 0) && (i<envLen)) {
359 
360         /* grab the complete string */
361         strcpy(varBuf,env[i]);
362 
363         /* strip out the variable and the value */
364         len = strlen(varBuf);
365         foundEq = 0;
366         for (j=0; j<len; j++) {
367             if (!foundEq) {
368                 if (varBuf[j] == term) {
369                     varBuf[j] = '\0';
370                     foundEq = 1;
371                 }
372             } else {
373                varBuf[j] = '\0';
374             }
375         }
376 
377         /* now check for match */
378         if (!strcmp(varBuf,var)) {
379             ifnd = i;
380         }
381 
382         /* next iteration */
383         i++;
384     }
385 
386     return ifnd;
387 }
388 
389 /*
390  * ***************************************************************************
391  * Routine:  Vsh_putenv
392  *
393  * Purpose:  Place a variable with a value in the environment.
394  *
395  * Author:   Michael Holst
396  * ***************************************************************************
397  */
Vsh_putenv(Vsh * thee,const char * envi,const char * valu)398 VPUBLIC int Vsh_putenv(Vsh *thee, const char *envi, const char *valu)
399 {
400     int i, len, ifnd;
401     char *newValu, **newValuList, valuLoc[VMAX_BUFSIZE];
402 
403     VASSERT( envi != VNULL );
404     if (valu == VNULL ) {
405         valuLoc[0] = '\0';
406     } else {
407         strcpy(valuLoc,valu);
408     }
409 
410     /* make the variable=value string */
411     len = strlen(envi) + 1 + strlen(valuLoc) + 1;
412     newValu = Vmem_malloc(thee->vmem,len,sizeof(char));
413     sprintf(newValu,"%s=%s",envi,valuLoc);
414 
415     /* look for variable in the environment */
416     ifnd = Vsh_findVar(thee->envValu,thee->envValuLen,envi,'=');
417 
418     /* if variable exists, just change it */
419     if (ifnd >= 0) {
420 
421         if (valuLoc[0] != '\0') {
422 
423             /* free old VALU */
424             len = strlen(thee->envValu[ifnd]) + 1;
425             Vmem_free(thee->vmem,len,sizeof(char),
426                 (void**)&(thee->envValu[ifnd]) );
427 
428             /* point to new VALU */
429             thee->envValu[ifnd] = newValu;
430         }
431 
432     /* variable doesn't exist; must create it */
433     } else {
434 
435         /* expand the environment */
436         thee->envValuLen++;
437 
438         /* make a new VALU list with one more slot */
439         len = thee->envValuLen + 1;
440         newValuList = Vmem_malloc(thee->vmem,len,sizeof(char*));
441 
442         /* copy the old VALU list into the new VALU list */
443         for (i=0; i<thee->envValuLen-1; i++) {
444             newValuList[i] = thee->envValu[i];
445         }
446         newValuList[thee->envValuLen-1] = newValu;
447         newValuList[thee->envValuLen] = VNULL;
448 
449         /* free old VALU list */
450         len = thee->envValuLen;
451         Vmem_free(thee->vmem,len,sizeof(char*), (void**)&(thee->envValu) );
452 
453         /* setup the new VALU list */
454         thee->envValu = newValuList;
455     }
456 
457     return 1;
458 }
459 
460 /*
461  * ***************************************************************************
462  * Routine:  Vsh_putenvInfo
463  *
464  * Purpose:  Place a variable with an info string in the environment.
465  *
466  * Author:   Michael Holst
467  * ***************************************************************************
468  */
Vsh_putenvInfo(Vsh * thee,const char * envi,const char * info)469 VPUBLIC int Vsh_putenvInfo(Vsh *thee, const char *envi, const char *info)
470 {
471     int i, len, ifnd;
472     char *newInfo, **newInfoList, infoLoc[VMAX_BUFSIZE];
473 
474     VASSERT( envi != VNULL );
475     if (info == VNULL ) {
476         infoLoc[0] = '\0';
477     } else {
478         strcpy(infoLoc,info);
479     }
480 
481     /* make the variable=info string */
482     len = strlen(envi) + 2 + strlen(infoLoc) + 1;
483     newInfo = Vmem_malloc(thee->vmem,len,sizeof(char));
484     sprintf(newInfo,"%s: %s",envi,infoLoc);
485 
486     /* look for variable in the environment */
487     ifnd = Vsh_findVar(thee->envInfo,thee->envInfoLen,envi,':');
488 
489     /* if variable exists, just change it */
490     if (ifnd >= 0) {
491 
492         if (infoLoc[0] != '\0') {
493 
494             /* free old INFO */
495             len = strlen(thee->envInfo[ifnd]) + 1;
496             Vmem_free(thee->vmem,len,sizeof(char),
497                 (void**)&(thee->envInfo[ifnd]) );
498 
499             /* point to new INFO */
500             thee->envInfo[ifnd] = newInfo;
501         }
502 
503     /* variable doesn't exist; must create it */
504     } else {
505 
506         /* expand the environment */
507         thee->envInfoLen++;
508 
509         /* make a new INFO list with one more slot */
510         len = thee->envInfoLen + 1;
511         newInfoList = Vmem_malloc(thee->vmem,len,sizeof(char*));
512 
513         /* copy the old INFO list into the new INFO list */
514         for (i=0; i<thee->envInfoLen-1; i++) {
515             newInfoList[i] = thee->envInfo[i];
516         }
517         newInfoList[thee->envInfoLen-1] = newInfo;
518         newInfoList[thee->envInfoLen] = VNULL;
519 
520         /* free old INFO list */
521         len = thee->envInfoLen;
522         Vmem_free(thee->vmem,len,sizeof(char*), (void**)&(thee->envInfo) );
523 
524         /* setup the new INFO list */
525         thee->envInfo = newInfoList;
526     }
527 
528     return 1;
529 }
530 
531 /*
532  * ***************************************************************************
533  * Routine:  Vsh_putenvInt
534  *
535  * Purpose:  Place a variable with a value (integer) in the environment.
536  *
537  * Author:   Michael Holst
538  * ***************************************************************************
539  */
Vsh_putenvInt(Vsh * thee,const char * envi,const int valu)540 VPUBLIC int Vsh_putenvInt(Vsh *thee, const char *envi, const int valu)
541 {
542     char buf[VMAX_BUFSIZE];
543 
544     sprintf(buf,"%d",valu);
545     Vsh_putenv(thee,envi,buf);
546 
547     return 1;
548 }
549 
550 /*
551  * ***************************************************************************
552  * Routine:  Vsh_putenvReal
553  *
554  * Purpose:  Place a variable with a value (real) in the environment.
555  *
556  * Author:   Michael Holst
557  * ***************************************************************************
558  */
Vsh_putenvReal(Vsh * thee,const char * envi,const double valu)559 VPUBLIC int Vsh_putenvReal(Vsh *thee, const char *envi, const double valu)
560 {
561     char buf[VMAX_BUFSIZE];
562 
563     sprintf(buf,"%e",valu);
564     Vsh_putenv(thee,envi,buf);
565 
566     return 1;
567 }
568 
569 
570 /*
571  * ***************************************************************************
572  * Routine:  Vsh_getenv
573  *
574  * Purpose:  Get a value of variable in the environment.
575  *
576  * Author:   Michael Holst
577  * ***************************************************************************
578  */
Vsh_getenv(Vsh * thee,const char * envi)579 VPUBLIC char* Vsh_getenv(Vsh *thee, const char *envi)
580 {
581     int ifnd;
582 
583     ifnd = Vsh_findVar(thee->envValu,thee->envValuLen,envi,'=');
584     if (ifnd >= 0) {
585         return (thee->envValu[ifnd]+strlen(envi)+1);
586     } else {
587         return VNULL;
588     }
589 }
590 
591 /*
592  * ***************************************************************************
593  * Routine:  Vsh_getenvInfo
594  *
595  * Purpose:  Get info associated with a variable in the environment.
596  *
597  * Author:   Michael Holst
598  * ***************************************************************************
599  */
Vsh_getenvInfo(Vsh * thee,const char * envi)600 VPUBLIC char* Vsh_getenvInfo(Vsh *thee, const char *envi)
601 {
602     int ifnd;
603 
604     ifnd = Vsh_findVar(thee->envInfo,thee->envInfoLen,envi,':');
605     if (ifnd >= 0) {
606         return (thee->envInfo[ifnd]+strlen(envi)+2);
607     } else {
608         return VNULL;
609     }
610 }
611 
612 /*
613  * ***************************************************************************
614  * Routine:  Vsh_getenvInt
615  *
616  * Purpose:  Get a value of variable in the environment as an integer.
617  *
618  * Author:   Michael Holst
619  * ***************************************************************************
620  */
Vsh_getenvInt(Vsh * thee,const char * envi)621 VPUBLIC int Vsh_getenvInt(Vsh *thee, const char *envi)
622 {
623     int ifnd;
624 
625     ifnd = Vsh_findVar(thee->envValu,thee->envValuLen,envi,'=');
626     if (ifnd >= 0) {
627         return atoi(thee->envValu[ifnd]+strlen(envi)+1);
628     } else {
629         return 0;
630     }
631 }
632 
633 /*
634  * ***************************************************************************
635  * Routine:  Vsh_getenvReal
636  *
637  * Purpose:  Get a value of variable in the environment as a real.
638  *
639  * Author:   Michael Holst
640  * ***************************************************************************
641  */
Vsh_getenvReal(Vsh * thee,const char * envi)642 VPUBLIC double Vsh_getenvReal(Vsh *thee, const char *envi)
643 {
644     int ifnd;
645 
646     ifnd = Vsh_findVar(thee->envValu,thee->envValuLen,envi,'=');
647     if (ifnd >= 0) {
648         return atof(thee->envValu[ifnd]+strlen(envi)+1);
649     } else {
650         return 0.0;
651     }
652 }
653 
654 /*
655  * ***************************************************************************
656  * Routine:  Vsh_remove
657  *
658  * Purpose:  Remove a variable from the environment.
659  *
660  * Author:   Michael Holst
661  * ***************************************************************************
662  */
Vsh_remove(Vsh * thee,const char * envi)663 VPUBLIC void Vsh_remove(Vsh *thee, const char *envi)
664 {
665     /* unsetenv(envi); */
666 }
667 
668 /*
669  * ***************************************************************************
670  * Routine:  Vsh_wipe
671  *
672  * Purpose:  Wipe the environment.
673  *
674  * Author:   Michael Holst
675  * ***************************************************************************
676  */
Vsh_wipe(Vsh * thee)677 VPUBLIC void Vsh_wipe(Vsh *thee)
678 {
679     int i, len;
680 
681     VASSERT( thee->envValu != VNULL );
682 
683     /* wipe the entire environment */
684     for (i=0; i<thee->envValuLen; i++) {
685         len = strlen(thee->envValu[i]) + 1;
686         Vmem_free(thee->vmem,len,sizeof(char), (void**)&(thee->envValu[i]) );
687     }
688     len = thee->envValuLen + 1;
689     Vmem_free(thee->vmem,len,sizeof(char*), (void**)&(thee->envValu) );
690     for (i=0; i<thee->envInfoLen; i++) {
691         len = strlen(thee->envInfo[i]) + 1;
692         Vmem_free(thee->vmem,len,sizeof(char), (void**)&(thee->envInfo[i]) );
693     }
694     len = thee->envInfoLen + 1;
695     Vmem_free(thee->vmem,len,sizeof(char*), (void**)&(thee->envInfo) );
696 }
697 
698 /*
699  * ***************************************************************************
700  * Routine:  Vsh_printenv
701  *
702  * Purpose:  Print the environment.
703  *
704  * Author:   Michael Holst
705  * ***************************************************************************
706  */
Vsh_printenv(Vsh * thee)707 VPUBLIC void Vsh_printenv(Vsh *thee)
708 {
709     int i;
710 
711     for (i=0; i<thee->envValuLen; i++) {
712         Vnm_print(1,"%s\n",thee->envValu[i]);
713     }
714 }
715 
716 /*
717  * ***************************************************************************
718  * Routine:  Vsh_printenvInfo
719  *
720  * Purpose:  Print the environment info.
721  *
722  * Author:   Michael Holst
723  * ***************************************************************************
724  */
Vsh_printenvInfo(Vsh * thee)725 VPUBLIC void Vsh_printenvInfo(Vsh *thee)
726 {
727     int i;
728 
729     for (i=0; i<thee->envInfoLen; i++) {
730         Vnm_print(1,"%s\n",thee->envInfo[i]);
731     }
732 }
733 
734 /*
735  * ***************************************************************************
736  * Routine:  Vsh_completion
737  *
738  * Purpose:  Command completion action.
739  *
740  * Notes:    The return type and argument list is mandated by readline:
741  *
742  *               int func(int count, int key)
743  *
744  *           Useful tips: the readline library uses the following conventions
745  *           for simplifying the notation for function pointers:
746  *
747  *               typedef int IFunction ();
748  *               typedef void VFunction ();
749  *               typedef char *CPFunction ();
750  *               typedef char **CPPFunction ();
751  *
752  *           This allows one to replace something like:
753  *
754  *               int (*)()func;
755  *
756  *           with simply:
757  *
758  *               IFunction *func;
759  *
760  * Author:   Michael Holst
761  * ***************************************************************************
762  */
763 #if defined(HAVE_READLINE_READLINE_H)
Vsh_completion(int count,int key)764 VPRIVATE int Vsh_completion(int count, int key)
765 {
766     int cargc = 1;
767     char *cargv[2] = { "help", VNULL };
768 
769     Vnm_print(1,"\n");
770     Vsh_builtIn(Vsh_thee, cargc, cargv);
771     Vnm_print(1,"%s",Vsh_thee->PR_PATH);
772 
773     Vsh_readlineReset();
774 
775     return 0;
776 }
777 #endif
778 
779 /*
780  * ***************************************************************************
781  * Routine:  Vsh_readlineInit
782  *
783  * Purpose:  Initialize the readline library.
784  *
785  * Author:   Michael Holst
786  * ***************************************************************************
787  */
Vsh_readlineInit(void)788 VPRIVATE void Vsh_readlineInit(void)
789 {
790     static int init=0;
791 
792     if (!init) {
793         init = 1;
794 
795 #if defined(HAVE_READLINE_READLINE_H)
796 #if 0
797         rl_catch_signals = 0;
798         rl_catch_sigwinch = 0;
799 #endif
800         rl_bind_key(9, &Vsh_completion);
801 #endif
802     }
803 }
804 
805 /*
806  * ***************************************************************************
807  * Routine:  Vsh_readlineReset
808  *
809  * Purpose:  Reset the readline library (e.g. free partial input string).
810  *
811  * Author:   Michael Holst
812  * ***************************************************************************
813  */
Vsh_readlineReset(void)814 VPRIVATE void Vsh_readlineReset(void)
815 {
816     Vsh_readlineInit();
817 
818 #if defined(HAVE_READLINE_READLINE_H)
819 #if 0
820     rl_free_line_state();
821     rl_resize_terminal();
822 #endif
823 #endif
824 }
825 
826 /*
827  * ***************************************************************************
828  * Routine:  Vsh_addhist
829  *
830  * Purpose:  Put an input line into the history list.
831  *
832  * Author:   Michael Holst
833  * ***************************************************************************
834  */
Vsh_addhist(char * buf,int buflen)835 VPUBLIC void Vsh_addhist(char *buf, int buflen)
836 {
837     Vsh_readlineInit();
838 
839 #if defined(HAVE_READLINE_HISTORY_H)
840     add_history(buf);
841 #endif
842 }
843 
844 /*
845  * ***************************************************************************
846  * Routine:  Vsh_readline
847  *
848  * Purpose:  Get an input line.
849  *
850  * Author:   Michael Holst
851  * ***************************************************************************
852  */
Vsh_readline(char * prompt,char * buf,int buflen,FILE * stream)853 VPUBLIC char *Vsh_readline(char *prompt, char *buf, int buflen, FILE *stream)
854 {
855     char *key;
856 
857     if (stream != stdin) {
858         key = fgets(buf, buflen, stream);
859     } else {
860 
861 #if defined(HAVE_READLINE_READLINE_H)
862         Vsh_readlineInit();
863         key = readline(prompt);
864         if (key == VNULL) {
865             buf[0] = '\n';
866             buf[1] = '\0';
867         } else if (key[0] == '\0') {
868             buf[0] = '\n';
869             buf[1] = '\0';
870             free(key);
871         } else {
872             strncpy(buf,key,buflen);
873             free(key);
874         }
875 #else
876         Vnm_print(1,"%s",prompt);
877         key = fgets(buf, buflen, stream);
878 #endif
879 
880     }
881 
882     return key;
883 }
884 
885 /*
886  * ***************************************************************************
887  * Routine:  Vsh_shell
888  *
889  * Purpose:  A bash-like shell with user-definable extensions.
890  *
891  * Author:   Michael Holst
892  * ***************************************************************************
893  */
Vsh_shell(Vsh * thee,char * pPR,void * pthee,int (* builtin)(void * thee,int argc,char ** argv))894 VPUBLIC int Vsh_shell(Vsh *thee, char *pPR, void *pthee,
895     int (*builtin)(void *thee, int argc, char **argv))
896 {
897     int i, argc, offset;
898     char **argvPtr, buf[VMAX_ARGLEN];
899     char *argvNULL = "\0";
900     struct stat fInfo;
901 
902     /* we will need argc and argv[] */
903     argc = Vsh_getenvInt(thee, "ARGC");
904     argvPtr = Vmem_malloc(thee->vmem, VMAX_ARGLEN, sizeof(char*));
905     for (i=0; i<argc; i++) {
906         sprintf(buf,"ARG%d",i);
907         argvPtr[i] = Vsh_getenv(thee, buf);
908     }
909     argvPtr[argc] = argvNULL;
910 
911     /* paranoia: check type sizes on the machine */
912     Vnm_typeChk();
913 
914     /* the externally supplied builtin object pointer and function */
915     thee->Ext_thee    = pthee;
916     thee->Ext_builtin = builtin;
917 
918     /* construct a reasonable shell command prompt if not given as argument */
919     if (pPR != VNULL) {
920         if (pPR[0] != '\0') {
921             sprintf(thee->PR,"%s",pPR);
922         }
923     }
924     if (thee->PR[0] == '\0') {
925         VASSERT( argc > 0 );
926         strncpy(buf,argvPtr[0],VMAX_ARGLEN);
927         offset = 0;
928         if (strlen(buf) >= 2) {
929             /* remove the "./" if it is there */
930             if ((buf[0] == '.') && (buf[1] == '/')) {
931                 offset = 2;
932             /* remove "-" if there; happens when vsh is a login shell */
933             } else if (buf[0] == '-') {
934                 offset = 1;
935             }
936         }
937         sprintf(thee->PR,"%s",buf+offset);
938     }
939     Vsh_putenv(thee,"SHELL",thee->PR);
940 
941     /*
942      * if filename given on command line, try to take input from there.
943      */
944     thee->inUnit = stdin;
945     if (thee->processArgs) {
946         for (i=1; i<argc; i++) {
947 
948             /* is the argument the "-h" option */
949             if (!strcmp(argvPtr[i],"-h")) {
950                 VJMPERR1(1);
951 
952             /* is the argument the "-io" option */
953             } else if (!strcmp(argvPtr[i],"-io")) {
954                 Vnm_redirect(0);
955 
956             /* is the argument the "-noio" option */
957             } else if (!strcmp(argvPtr[i],"-noio")) {
958                 Vnm_redirect(1);
959 
960             /* try to open the argument as a script file */
961             } else {
962                 thee->clUnit = fopen(argvPtr[i], "r");
963                 if (thee->clUnit == VNULL) {
964                     Vnm_print(2,"%s: Problem opening file <%s>\n",
965                         thee->PR, argvPtr[i]);
966                     thee->inUnit = stdin;
967                     VJMPERR1(1);
968                 } else thee->inUnit = thee->clUnit;
969             }
970         }
971     }
972 
973     /* the current input unit starts out as stdin or a script */
974     thee->cinUnit = thee->inUnit;
975 
976     /* we first execute the user's configuration file */
977     if ( !stat(Vsh_getenv(thee,"ENV"), &fInfo) ) {
978         if (VS_ISREG(fInfo.st_mode)) {
979             thee->scUnit = fopen(Vsh_getenv(thee,"ENV"), "r");
980             if (thee->scUnit != VNULL) {
981                 thee->cinUnit = thee->scUnit;
982                 strncpy(thee->cinName,Vsh_getenv(thee,"ENV"),VMAX_ARGLEN);
983                 Vnm_print(0,"Starting <%s> script named <%s>\n",
984                     thee->PR,thee->cinName);
985             }
986         }
987     }
988 
989     /* start the command shell parsing loop */
990     cmdKey = 0;
991     while (cmdKey != 2) {
992 
993         /*
994          * Parse a single input unit.
995          * An input unit is a complete shell statement
996          * (e.g. one-line command, if-then-else, while, case, etc)
997          * which may span multiple lines of input.
998          */
999 #if defined(VSH_LEX_YACC)
1000         yyparse();  /* for complex Bourne-shell compatible input units */
1001         Vsh_yyexecute(global_command);
1002 #else
1003         Vsh_parse();  /* for simple one-line commands only */
1004         Vsh_execute();
1005 #endif
1006 
1007     }
1008 
1009     /* close the input unit for a command-line file if we had one */
1010     if (thee->clUnit != VNULL) VASSERT( !fclose(thee->clUnit) );
1011 
1012     /* free the argv storage */
1013     Vmem_free( thee->vmem, VMAX_ARGLEN, sizeof(char*), (void**)&argvPtr );
1014 
1015     /* no error */
1016     return 1;
1017 
1018   VERROR1:
1019     /* close the input unit for a command-line file if we had one */
1020     if (thee->clUnit != VNULL) VASSERT( !fclose(thee->clUnit) );
1021 
1022     /* free the argv storage */
1023     Vmem_free( thee->vmem, VMAX_ARGLEN, sizeof(char*), (void**)argvPtr );
1024 
1025     /* print a usage menu */
1026     Vnm_print(2,"usage: ./%s [ -h | -io | -noio ]"
1027                 " [ shellScriptFile ]\n",thee->PR);
1028 
1029     /* error, but not fatal */
1030     return 1;
1031 }
1032 
1033 /*
1034  * ***************************************************************************
1035  * Routine:  Vsh_input
1036  *
1037  * Purpose:  Read a single newline-terminated line of input.
1038  *
1039  * Notes:    We output a prompt if appropriate to do so.
1040  *           We catch any SIGINTs generated during input just like
1041  *           any normal command shell.  If one is caught, we jump
1042  *           back to the input prompt via setjmp/longjmp.
1043  *           We also handle killing of scripts via SIGINT, and
1044  *           correctly handle prompt output on redirection.
1045  *
1046  *           This routine is used with the following macro:
1047  *
1048  *               define VSH_INPUT(buf,result,max_size) { \
1049  *                   result = Vsh_input(buf,max_size); \
1050  *               }
1051  *
1052  *           which has exactly the same functionality as the YY_INPUT
1053  *           macro used by LEX.  Forcing LEX to use VSH_INPUT in place
1054  *           of YY_INPUT allows all of the above to work for a
1055  *           LEX/YACC-generated command shell parser.
1056  *
1057  * Input:    buf[0..buflen-1] = character buffer to read in to
1058  *           buflen           = length of buf
1059  *
1060  * Output:   returned = number of characters actually read in.
1061  *
1062  * Author:   Michael Holst
1063  * ***************************************************************************
1064  */
Vsh_input(char * buf,int buflen)1065 VPUBLIC int Vsh_input(char *buf, int buflen)
1066 {
1067     int numRead;
1068     char *key, currDirectory[VMAX_ARGLEN];
1069     jmp_buf *jbuf;
1070 
1071     /* setup for the jump */
1072     jbuf = Vnm_signalInit();
1073     if (setjmp(*jbuf)) {
1074 
1075         /* FIRST: kill any script that may have been executing */
1076         Vsh_thee->cinUnit = Vsh_thee->inUnit;
1077 
1078         /* SECOND: reset the readline input buffer */
1079         Vsh_readlineReset();
1080 
1081         /* THIRD: restart lex on the (possibly) new input unit */
1082 #if defined(VSH_LEX_YACC)
1083             yyrestart(Vsh_thee->cinUnit);
1084 #endif
1085 
1086         /* FOURTH: print a newline if we are in interactive mode */
1087         if (Vsh_isInteractive(Vsh_thee)) {
1088             Vnm_print(1,"%s",VNEWLINE_STRING);
1089         }
1090     }
1091 
1092     /* close script unit if open -- must have killed it */
1093     if ( ((Vsh_thee->cinUnit != Vsh_thee->scUnit)
1094          || feof(Vsh_thee->scUnit)) && (Vsh_thee->scUnit != VNULL) ) {
1095         VASSERT( !fclose(Vsh_thee->scUnit) );
1096         Vsh_thee->scUnit = VNULL;
1097         Vnm_print(0,"Stopping <%s> script named <%s>\n",
1098             Vsh_thee->PR,Vsh_thee->cinName);
1099         strncpy(Vsh_thee->cinName," ",VMAX_ARGLEN);
1100     }
1101 
1102     /* OKAY-TO-JUMP back to the input prompt now */
1103     Vnm_jmpOkSet();
1104 
1105     /* deal with different I/O units */
1106     if (Vsh_isInteractive(Vsh_thee)) {
1107         VASSERT( Vnm_getcwd(currDirectory,sizeof(currDirectory)) );
1108         sprintf(Vsh_thee->PR_PATH,"%s@%s<%s+%s>%% ",
1109             Vsh_getenv(Vsh_thee,"USER"),
1110             Vsh_getenv(Vsh_thee,"HOSTNAME"),
1111             Vsh_getenv(Vsh_thee,"OSTYPE"),
1112             Vsh_thee->PR);
1113         Vsh_putenv(Vsh_thee,"PROMPT",Vsh_thee->PR_PATH);
1114     }
1115 
1116     /* get the input line */
1117     memset(buf, VNULL_SYMBOL, buflen);
1118     key = Vsh_readline(Vsh_thee->PR_PATH, buf, buflen, Vsh_thee->cinUnit);
1119     if ((key == VNULL) && (Vsh_thee->cinUnit==Vsh_thee->scUnit)) {
1120 
1121         /* shut down the script handling */
1122         VASSERT( Vsh_thee->scUnit != VNULL );
1123         VASSERT( feof(Vsh_thee->scUnit) );
1124         VASSERT( !fclose(Vsh_thee->scUnit) );
1125         Vsh_thee->scUnit = VNULL;
1126         Vnm_print(0,"Stopping <%s> script named <%s>\n",
1127             Vsh_thee->PR,Vsh_thee->cinName);
1128         strncpy(Vsh_thee->cinName," ",VMAX_ARGLEN);
1129 
1130         /* deal with different I/O units */
1131         Vsh_thee->cinUnit = Vsh_thee->inUnit;
1132         if (Vsh_isInteractive(Vsh_thee)) {
1133             VASSERT( Vnm_getcwd(currDirectory,sizeof(currDirectory)) );
1134             sprintf(Vsh_thee->PR_PATH,"%s@%s<%s+%s>%% ",
1135                 Vsh_getenv(Vsh_thee,"USER"),
1136                 Vsh_getenv(Vsh_thee,"HOSTNAME"),
1137                 Vsh_getenv(Vsh_thee,"OSTYPE"),
1138                 Vsh_thee->PR);
1139             Vsh_putenv(Vsh_thee,"PROMPT",Vsh_thee->PR_PATH);
1140         }
1141 
1142         /* get the input line */
1143         memset(buf, VNULL_SYMBOL, buflen);
1144         key = Vsh_readline(Vsh_thee->PR_PATH,
1145             buf, buflen, Vsh_thee->cinUnit);
1146     }
1147 
1148     /* calculate the number of characters actually read */
1149     if (key == VNULL) {
1150         numRead = 0;
1151     } else {
1152         numRead = strlen(buf);
1153     }
1154     VASSERT( numRead <= buflen );
1155 
1156     /* NOT-OKAY-TO-JUMP back to the input prompt now */
1157     Vnm_jmpOkClear();
1158 
1159     /* clear the numerical loop signal before executing the command */
1160     Vnm_sigIntClear();
1161 
1162     /* return num chars read */
1163     return numRead;
1164 }
1165 
1166 /*
1167  * ***************************************************************************
1168  * Routine:  Vsh_getCmd
1169  *
1170  * Purpose:  Decode the input string into a legal command.
1171  *
1172  * Author:   Michael Holst
1173  * ***************************************************************************
1174  */
Vsh_getCmd(int argc,char ** argv)1175 VPRIVATE VSH_command Vsh_getCmd(int argc, char **argv)
1176 {
1177     VSH_command theCmd = vshcom_none;
1178     if (!strcmp(argv[0],"")) {
1179         theCmd = vshcom_none;
1180     } else if ( (!strcmp(argv[0],"c")) || (!strcmp(argv[0],"clear")) ) {
1181         theCmd = vshcom_clear;
1182     } else if (!strcmp(argv[0],"help")) {
1183         theCmd = vshcom_help;
1184     } else if (!strcmp(argv[0],"pause")) {
1185         theCmd = vshcom_pause;
1186     } else if (!strcmp(argv[0],"delay")) {
1187         theCmd = vshcom_delay;
1188     } else if (!strcmp(argv[0],"set")) {
1189         theCmd = vshcom_set;
1190     } else if (!strcmp(argv[0],"penv")) {
1191         theCmd = vshcom_penv;
1192     } else if (!strcmp(argv[0],"pinfo")) {
1193         theCmd = vshcom_pinfo;
1194     } else if (!strcmp(argv[0],"cd")) {
1195         theCmd = vshcom_cd;
1196     } else if (!strcmp(argv[0],"cdw")) {
1197         theCmd = vshcom_cdw;
1198     } else if (!strcmp(argv[0],"io")) {
1199         theCmd = vshcom_io;
1200     } else if (!strcmp(argv[0],"noio")) {
1201         theCmd = vshcom_noio;
1202     } else if (!strcmp(argv[0],"exit")) {
1203         theCmd = vshcom_exit;
1204     } else if (!strcmp(argv[0],".")) {
1205         theCmd = vshcom_dot;
1206     } else if (!strcmp(argv[0],"sockg")) {
1207         theCmd = vshcom_sockg;
1208     } else if (!strcmp(argv[0],"sockm")) {
1209         theCmd = vshcom_sockm;
1210     } else if (!strcmp(argv[0],"sockk")) {
1211         theCmd = vshcom_sockk;
1212     } else {
1213         theCmd = vshcom_none;
1214     }
1215     return theCmd;
1216 }
1217 
1218 /*
1219  * ***************************************************************************
1220  * Routine:  Vsh_execCmd
1221  *
1222  * Purpose:  Fork a child to exec a command, wait for child to finish.
1223  *
1224  * Author:   Michael Holst
1225  * ***************************************************************************
1226  */
Vsh_execCmd(const char * PR,int argc,char ** argv,char * inbuf)1227 VPUBLIC void Vsh_execCmd(const char *PR, int argc, char **argv, char *inbuf)
1228 {
1229     /* fork a child to do the work (real shell behavior) */
1230 #if !defined(HAVE_WINSOCK_H)
1231 
1232     static pid_t child_pid;
1233     char PR_TMP[VMAX_ARGLEN];
1234 
1235     VASSERT( argc > 0 );
1236     sprintf(PR_TMP,"%s: %s",PR,argv[0]);
1237 
1238     if ((child_pid=fork()) == 0) {
1239         /* NOTE: child should NOT return except on error */
1240         Vpup_execCmd(PR_TMP,argc,argv,inbuf);
1241         perror(PR_TMP);
1242         exit(1);
1243     } else if (child_pid > 0) {
1244         wait(VNULL);
1245     } else {
1246         perror(PR_TMP);
1247     }
1248 
1249     /* fork() does not exist on Win32 */
1250     /* (also fork() is BROKEN in Linux 2.1.85 believe it or not...) */
1251     /* SO, we fake it by passing command to underlying shell -- bummer! */
1252 #else
1253 
1254     Vnm_system(inbuf);
1255 
1256 #endif
1257 }
1258 
1259 /*
1260  * ***************************************************************************
1261  * Routine:  Vsh_memChk
1262  *
1263  * Purpose:  Print the exact current malloc usage.
1264  *
1265  * Author:   Michael Holst
1266  * ***************************************************************************
1267  */
Vsh_memChk(Vsh * thee)1268 VPUBLIC void Vsh_memChk(Vsh *thee)
1269 {
1270     if (thee->iMadeVmem) Vmem_print(thee->vmem);
1271 }
1272 
1273 /*
1274  * ***************************************************************************
1275  * Routine:  Vsh_killSockets
1276  *
1277  * Purpose:  Kill any socket graphics.
1278  *
1279  * Author:   Michael Holst
1280  * ***************************************************************************
1281  */
Vsh_killSockets(Vsh * thee)1282 VPRIVATE void Vsh_killSockets(Vsh *thee)
1283 {
1284     Vnm_systemKill("gvx");
1285     Vnm_systemKill("mcsg");
1286     Vnm_systemKill("mcbridge");
1287     Vnm_system("sleep 1");
1288 }
1289 
1290 /*
1291  * ***************************************************************************
1292  * Routine:  Vsh_builtIn
1293  *
1294  * Purpose:  Vsh_shell built-in commands.
1295  *
1296  * Author:   Michael Holst
1297  * ***************************************************************************
1298  */
Vsh_builtIn(Vsh * thee,int argc,char ** argv)1299 VPUBLIC int Vsh_builtIn(Vsh *thee, int argc, char **argv)
1300 {
1301     int i, rc;
1302     VSH_command theCmd;
1303     struct stat fInfo;
1304     jmp_buf *jbuf;
1305 
1306     char sysc[VMAX_BUFSIZE];
1307     char sofmt[VMAX_ARGLEN], sokey[VMAX_ARGLEN];
1308 
1309     static int  init=0;
1310     static char buf[VMAX_BUFSIZE], workDirectory[VMAX_ARGLEN];
1311     static char PR_TMP[VMAX_ARGLEN];
1312     static char env[VMAX_BUFSIZE], com[VMAX_BUFSIZE];
1313     static char sock[VMAX_BUFSIZE];
1314     const char *stmp;
1315 
1316     /* one-time intialization */
1317     if (!init) {
1318         init=1;
1319 
1320         /* make the env message (%s slots = 12) */
1321         stmp =
1322           "%s: Execution environment, directories, and files:\n"
1323           "    Shell                --> <%s>\n"
1324           "    User name            --> <%s>\n"
1325           "    Host name            --> <%s>\n"
1326           "    Operating system     --> <%s>\n"
1327           "    Home directory       --> <%s>\n"
1328           "    Work directory       --> <%s>\n"
1329           "    Startup script       --> <%s/%s>\n"
1330           "    Command history file --> <%s/%s>\n"
1331           "    I/O capture file     --> <%s/%s>\n";
1332         sprintf(env,stmp,thee->PR,
1333             thee->PR,
1334             Vsh_getenv(thee,"USER"),
1335             Vsh_getenv(thee,"HOSTNAME"),
1336             Vsh_getenv(thee,"OSTYPE"),
1337             Vsh_getenv(thee,"HOME"),
1338             Vsh_getenv(thee,"CWD"),
1339             Vsh_getenv(thee,"HOME"),"rc.mcsh",
1340             Vsh_getenv(thee,"HOME"),"hist.mcsh",
1341             Vsh_getenv(thee,"HOME"),"io.mc");
1342 
1343         /* make the com message (%s slots = 2) */
1344         stmp =
1345           "%s: Shell interaction commands: \n"
1346           "    help [ env|com|sock ] --> print help messages\n"
1347           "    c | clear                 --> clear the screen\n"
1348           "    pause                     --> pause until carriage return\n"
1349           "    delay                     --> delay for three seconds\n"
1350           "    cd | cdw                  --> cd to home or work directory\n";
1351         sprintf(com,stmp,thee->PR);
1352         stmp =
1353           "    io | noio                 --> display extra io or not\n"
1354           "    set [var [val]]           --> set or print variables\n"
1355           "    penv [var]                --> print variable\n"
1356           "    pinfo [var]               --> print variable information\n"
1357           "    . scriptfile              --> execute an vsh scriptfile\n"
1358           "    exit | CTRL-D             --> exit the <%s> shell\n";
1359         sprintf(buf,stmp,thee->PR);
1360         strcat(com,buf);
1361 
1362         /* make the socket message (%s slots = 1) */
1363         stmp = "%s: Socket Graphics manipulation commands: \n"
1364             "    sockk --> kill all socket graphics processes\n"
1365             "    sockg --> start geomview socket displays\n"
1366             "    sockm --> start mcsg socket displays\n";
1367         sprintf(sock,stmp,thee->PR);
1368     }
1369 
1370     /* the user-defined shell gets first shot at the command */
1371     if (thee->Ext_builtin != VNULL) {
1372         rc = (*(thee->Ext_builtin))(thee->Ext_thee,argc,argv);
1373         if (rc != 0) return rc;
1374     }
1375 
1376     /* now it is our turn; set default return code (success) */
1377     rc = 1;
1378 
1379     /* get the command */
1380     theCmd = Vsh_getCmd(argc, argv);
1381 
1382     /* decode and execute the command */
1383     switch (theCmd) {
1384 
1385       case vshcom_pause:
1386         sprintf(PR_TMP,"%s: Press <return> to continue..", thee->PR);
1387         memset(buf, VNULL_SYMBOL, sizeof(buf));
1388 
1389         /* setup for the jump */
1390         jbuf = Vnm_signalInit();
1391         if (setjmp(*jbuf)) {
1392 
1393             /* FIRST: kill any script that may have been executing */
1394             thee->cinUnit = thee->inUnit;
1395 
1396             /* SECOND: reset the readline input buffer */
1397             Vsh_readlineReset();
1398 
1399             /* THIRD: restart lex on the (possibly) new input unit */
1400 #if defined(VSH_LEX_YACC)
1401                 yyrestart(thee->cinUnit);
1402 #endif
1403 
1404             /* FOURTH: print a newline if we are in interactive mode */
1405             if (Vsh_isInteractive(thee)) {
1406                 Vnm_print(1,"%s",VNEWLINE_STRING);
1407             }
1408 
1409             Vnm_jmpOkClear();
1410             Vnm_sigIntClear();
1411         } else {
1412             Vnm_jmpOkSet();
1413             Vsh_readline(PR_TMP, buf, sizeof(buf), stdin);
1414             Vnm_jmpOkClear();
1415             Vnm_sigIntClear();
1416         }
1417         rc = 1;
1418         break;
1419 
1420       case vshcom_delay:
1421         Vnm_sleep(3000000);
1422         break;
1423 
1424       case vshcom_clear:
1425         memset(buf, VNULL_SYMBOL, sizeof(buf));
1426 #if !defined(HAVE_WINSOCK_H)
1427         strcpy(buf,"clear");
1428 #else
1429         strcpy(buf,"cls");
1430 #endif
1431         Vnm_system(buf);
1432         break;
1433 
1434       case vshcom_help:
1435         if (argc==1) {
1436             Vnm_print(1,"%s: Vsh-layer Help Menu:\n",thee->PR);
1437             Vnm_print(1,"    help env  --> Help on %s environment\n",
1438                 thee->PR);
1439             Vnm_print(1,"    help com  --> Help on %s shell commands\n",
1440                 thee->PR);
1441             Vnm_print(1,"    help sock --> Help on %s socket graphics\n",
1442                 thee->PR);
1443         } else {
1444             if (!strcmp(argv[1],"env")) {
1445                 Vnm_print(1, "%s", env);
1446             } else if (!strcmp(argv[1],"com")) {
1447                 Vnm_print(1, "%s", com);
1448             } else if (!strcmp(argv[1],"sock")) {
1449                 Vnm_print(1, "%s", sock);
1450             } else {
1451                 /* we are the last shell layer; nothing to defer to */
1452             }
1453         }
1454         break;
1455 
1456       case vshcom_set:
1457         if (argc <= 1) {
1458             Vsh_printenv(thee);
1459         } else if (argc == 2) {
1460             Vnm_print(2,"%s: %s=%s\n",
1461                 thee->PR,argv[1],Vsh_getenv(thee,argv[1]));
1462         } else if (argc == 3) {
1463             Vsh_putenv(thee,argv[1],argv[2]);
1464         } else if (argc > 3) {
1465             Vsh_putenv(thee,argv[1],argv[2]);
1466             buf[0] = '\0';
1467             for (i=3; i<argc; i++) {
1468                 if (i>3) strcat(buf," ");
1469                 strcat(buf,argv[i]);
1470             }
1471             Vsh_putenvInfo(thee,argv[1],buf);
1472         } else VASSERT(0);
1473         break;
1474 
1475       case vshcom_penv:
1476         if (argc <= 1) {
1477             Vsh_printenv(thee);
1478         } else if (argc == 2) {
1479             Vnm_print(2,"%s: %s=%s\n",
1480                 thee->PR,argv[1],Vsh_getenv(thee,argv[1]));
1481         } else Vnm_print(2,"%s: %s: Too many arguments\n",thee->PR,argv[0]);
1482         break;
1483 
1484       case vshcom_pinfo:
1485         if (argc <= 1) {
1486             Vsh_printenvInfo(thee);
1487         } else if (argc == 2) {
1488             Vnm_print(2,"%s: %s: %s\n",
1489                 thee->PR,argv[1],Vsh_getenvInfo(thee,argv[1]));
1490         } else Vnm_print(2,"%s: %s: Too many arguments\n",thee->PR,argv[0]);
1491         break;
1492 
1493       case vshcom_cd:
1494         if (argc==1) {
1495             if (Vnm_chdir(Vsh_getenv(thee,"HOME")) == -1) {
1496                 Vnm_print(2,"%s: %s: %s: No such directory\n",
1497                     thee->PR, argv[0], Vsh_getenv(thee,"HOME"));
1498             }
1499             VASSERT( Vnm_getcwd(workDirectory,sizeof(workDirectory)) );
1500             Vsh_putenv(thee,"CWD", workDirectory);
1501         } else {
1502             if (Vnm_chdir(argv[1]) == -1) {
1503                 Vnm_print(2,"%s: %s: %s: No such directory\n",
1504                     thee->PR, argv[0], argv[1]);
1505             }
1506             VASSERT( Vnm_getcwd(workDirectory,sizeof(workDirectory)) );
1507             Vsh_putenv(thee,"CWD", workDirectory);
1508         }
1509         break;
1510 
1511       case vshcom_cdw:
1512         if (argc==1) {
1513             if (Vnm_chdir(Vsh_getenv(thee,"MCSH_HOME")) == -1) {
1514                 Vnm_print(2,"%s: %s: %s: No such directory\n",
1515                     thee->PR, argv[0], Vsh_getenv(thee,"MCSH_HOME"));
1516             }
1517             VASSERT( Vnm_getcwd(workDirectory,sizeof(workDirectory)) );
1518             Vsh_putenv(thee,"CWD", workDirectory);
1519         } else {
1520             if (Vnm_chdir(argv[1]) == -1) {
1521                 Vnm_print(2,"%s: %s: %s: No such directory\n",
1522                     thee->PR, argv[0], argv[1]);
1523             }
1524             VASSERT( Vnm_getcwd(workDirectory,sizeof(workDirectory)) );
1525             Vsh_putenv(thee,"CWD", workDirectory);
1526         }
1527         break;
1528 
1529       case vshcom_io:
1530         Vnm_redirect(0);
1531         break;
1532 
1533       case vshcom_noio:
1534         Vnm_redirect(1);
1535         break;
1536 
1537       case vshcom_exit:
1538         if (Vnm_chdir(Vsh_getenv(thee,"HOME")) == -1)
1539             Vnm_print(2,"%s: %s: %s: No such directory\n",
1540                 thee->PR, "cd", Vsh_getenv(thee,"HOME"));
1541         rc = 2;
1542         break;
1543 
1544       case vshcom_dot:
1545         if (argc <= 1) {
1546             Vnm_print(2,"%s: Filename argument required\n", thee->PR);
1547         } else if ( !stat(argv[1], &fInfo) ) {
1548             if (VS_ISREG(fInfo.st_mode)) {
1549                 thee->scUnit = fopen(argv[1], "r");
1550                 if (thee->scUnit != VNULL) {
1551                     thee->cinUnit = thee->scUnit;
1552                     strncpy(thee->cinName,argv[1],VMAX_ARGLEN);
1553                     Vnm_print(0,"Starting <%s> script named <%s>\n",
1554                         thee->PR,thee->cinName);
1555                 } else {
1556                     Vnm_print(2,"%s: Problem opening <%s>\n",
1557                         thee->PR,argv[1]);
1558                 }
1559             } else {
1560                 Vnm_print(2,"%s: File <%s> not normal\n",
1561                     thee->PR,argv[1]);
1562             }
1563         } else {
1564             Vnm_print(2,"%s: File <%s> not found\n",thee->PR,argv[1]);
1565         }
1566         break;
1567 
1568       case vshcom_sockg:
1569         Vsh_killSockets(thee);
1570         strncpy(sofmt,Vsh_getenv(thee,"OSFMT"),VMAX_ARGLEN);
1571         if (!strcmp("unix",Vsh_getenv(thee,"OSKEY"))) {
1572             strncpy(sokey,"Mcs",VMAX_ARGLEN);
1573         } else if (!strcmp("inet",Vsh_getenv(thee,"OSKEY"))) {
1574             strncpy(sokey,"Mcs",VMAX_ARGLEN);
1575         } else {
1576             strncpy(sokey,"Mcs",VMAX_ARGLEN);
1577         }
1578         if (!strcmp("1x1",Vsh_getenv(thee,"GVLO"))) {
1579             sprintf(sysc,"geomview -nopanels -wpos 436,445@55,520 -%s 0",sokey);
1580             Vnm_systemBack(sysc);
1581             if (!strcmp("inet",Vsh_getenv(thee,"OSKEY"))) {
1582                 Vnm_systemBack("mcbridge -i2u 0 0");
1583             }
1584         } else if (!strcmp("2x1",Vsh_getenv(thee,"GVLO"))) {
1585             sprintf(sysc,"geomview -nopanels -wpos 436,445@55,520 -%s 0",sokey);
1586             Vnm_systemBack(sysc);
1587             sprintf(sysc,"geomview -nopanels -wpos 436,445@55,50  -%s 1",sokey);
1588             Vnm_systemBack(sysc);
1589             if (!strcmp("inet",Vsh_getenv(thee,"OSKEY"))) {
1590                 Vnm_systemBack("mcbridge -i2u 0 0");
1591                 Vnm_systemBack("mcbridge -i2u 1 1");
1592             }
1593         } else if (!strcmp("3x1",Vsh_getenv(thee,"GVLO"))) {
1594             sprintf(sysc,"geomview -nopanels -wpos 436,287@55,684 -%s 0",sokey);
1595             Vnm_systemBack(sysc);
1596             sprintf(sysc,"geomview -nopanels -wpos 436,287@55,367 -%s 1",sokey);
1597             Vnm_systemBack(sysc);
1598             sprintf(sysc,"geomview -nopanels -wpos 436,287@55,50  -%s 2",sokey);
1599             Vnm_systemBack(sysc);
1600             if (!strcmp("inet",Vsh_getenv(thee,"OSKEY"))) {
1601                 Vnm_systemBack("mcbridge -i2u 0 0");
1602                 Vnm_systemBack("mcbridge -i2u 1 1");
1603                 Vnm_systemBack("mcbridge -i2u 2 2");
1604             }
1605         } else if (!strcmp("4x1",Vsh_getenv(thee,"GVLO"))) {
1606             sprintf(sysc,"geomview -nopanels -wpos 255,255 -%s 0",sokey);
1607             Vnm_systemBack(sysc);
1608             sprintf(sysc,"geomview -nopanels -wpos 255,255 -%s 1",sokey);
1609             Vnm_systemBack(sysc);
1610             sprintf(sysc,"geomview -nopanels -wpos 255,255 -%s 2",sokey);
1611             Vnm_systemBack(sysc);
1612             sprintf(sysc,"geomview -nopanels -wpos 255,255 -%s 3",sokey);
1613             Vnm_systemBack(sysc);
1614             if (!strcmp("inet",Vsh_getenv(thee,"OSKEY"))) {
1615                 Vnm_systemBack("mcbridge -i2u 0 0");
1616                 Vnm_systemBack("mcbridge -i2u 1 1");
1617                 Vnm_systemBack("mcbridge -i2u 2 2");
1618                 Vnm_systemBack("mcbridge -i2u 3 3");
1619             }
1620         } else if (!strcmp("1x1s",Vsh_getenv(thee,"GVLO"))) {
1621             sprintf(sysc,"geomview -nopanels -wpos 282,245 -%s 0",sokey);
1622             Vnm_systemBack(sysc);
1623             if (!strcmp("inet",Vsh_getenv(thee,"OSKEY"))) {
1624                 Vnm_systemBack("mcbridge -i2u 0 0");
1625             }
1626         } else if (!strcmp("2x1s",Vsh_getenv(thee,"GVLO"))) {
1627             sprintf(sysc,"geomview -nopanels -wpos 282,245 -%s 0",sokey);
1628             Vnm_systemBack(sysc);
1629             sprintf(sysc,"geomview -nopanels -wpos 282,245 -%s 1",sokey);
1630             Vnm_systemBack(sysc);
1631             if (!strcmp("inet",Vsh_getenv(thee,"OSKEY"))) {
1632                 Vnm_systemBack("mcbridge -i2u 0 0");
1633                 Vnm_systemBack("mcbridge -i2u 1 1");
1634             }
1635         } else if (!strcmp("3x1s",Vsh_getenv(thee,"GVLO"))) {
1636             sprintf(sysc,"geomview -nopanels -wpos 282,152 -%s 0",sokey);
1637             Vnm_systemBack(sysc);
1638             sprintf(sysc,"geomview -nopanels -wpos 282,152 -%s 1",sokey);
1639             Vnm_systemBack(sysc);
1640             sprintf(sysc,"geomview -nopanels -wpos 282,152 -%s 2",sokey);
1641             Vnm_systemBack(sysc);
1642             if (!strcmp("inet",Vsh_getenv(thee,"OSKEY"))) {
1643                 Vnm_systemBack("mcbridge -i2u 0 0");
1644                 Vnm_systemBack("mcbridge -i2u 1 1");
1645                 Vnm_systemBack("mcbridge -i2u 2 2");
1646             }
1647         } else if (!strcmp("4x1s",Vsh_getenv(thee,"GVLO"))) {
1648             sprintf(sysc,"geomview -nopanels -wpos 255,255 -%s 0",sokey);
1649             Vnm_systemBack(sysc);
1650             sprintf(sysc,"geomview -nopanels -wpos 255,255 -%s 1",sokey);
1651             Vnm_systemBack(sysc);
1652             sprintf(sysc,"geomview -nopanels -wpos 255,255 -%s 2",sokey);
1653             Vnm_systemBack(sysc);
1654             sprintf(sysc,"geomview -nopanels -wpos 255,255 -%s 3",sokey);
1655             Vnm_systemBack(sysc);
1656             if (!strcmp("inet",Vsh_getenv(thee,"OSKEY"))) {
1657                 Vnm_systemBack("mcbridge -i2u 0 0");
1658                 Vnm_systemBack("mcbridge -i2u 1 1");
1659                 Vnm_systemBack("mcbridge -i2u 2 2");
1660                 Vnm_systemBack("mcbridge -i2u 3 3");
1661             }
1662         } else {
1663             Vnm_print(2,"%s: %s: Incorrect argument <%s>\n",
1664                 thee->PR,"GVLO",Vsh_getenv(thee,"GVLO"));
1665         }
1666         Vnm_system("sleep 3");
1667         break;
1668 
1669       case vshcom_sockm:
1670         Vsh_killSockets(thee);
1671         strncpy(sofmt,Vsh_getenv(thee,"OSFMT"),VMAX_ARGLEN);
1672         if (!strcmp("unix",Vsh_getenv(thee,"OSKEY"))) {
1673             strncpy(sokey,"Mcs",VMAX_ARGLEN);
1674         } else if (!strcmp("inet",Vsh_getenv(thee,"OSKEY"))) {
1675             strncpy(sokey,"Mci",VMAX_ARGLEN);
1676         } else {
1677             strncpy(sokey,"Mci",VMAX_ARGLEN);
1678         }
1679         if (!strcmp("1x1",Vsh_getenv(thee,"GVLO"))) {
1680             sprintf(sysc,"mcsg -%s -wpos 436,445@55,520 -%s 0",sofmt,sokey);
1681             Vnm_systemBack(sysc);
1682         } else if (!strcmp("2x1",Vsh_getenv(thee,"GVLO"))) {
1683             sprintf(sysc,"mcsg -%s -wpos 436,445@55,520 -%s 0",sofmt,sokey);
1684             Vnm_systemBack(sysc);
1685             sprintf(sysc,"mcsg -%s -wpos 436,445@55,50  -%s 1",sofmt,sokey);
1686             Vnm_systemBack(sysc);
1687         } else if (!strcmp("3x1",Vsh_getenv(thee,"GVLO"))) {
1688             sprintf(sysc,"mcsg -%s -wpos 436,287@55,684 -%s 0",sofmt,sokey);
1689             Vnm_systemBack(sysc);
1690             sprintf(sysc,"mcsg -%s -wpos 436,287@55,367 -%s 1",sofmt,sokey);
1691             Vnm_systemBack(sysc);
1692             sprintf(sysc,"mcsg -%s -wpos 436,287@55,50  -%s 2",sofmt,sokey);
1693             Vnm_systemBack(sysc);
1694         } else if (!strcmp("4x1",Vsh_getenv(thee,"GVLO"))) {
1695             sprintf(sysc,"mcsg -%s -wpos 255,255 -%s 0",sofmt,sokey);
1696             Vnm_systemBack(sysc);
1697             sprintf(sysc,"mcsg -%s -wpos 255,255 -%s 1",sofmt,sokey);
1698             Vnm_systemBack(sysc);
1699             sprintf(sysc,"mcsg -%s -wpos 255,255 -%s 2",sofmt,sokey);
1700             Vnm_systemBack(sysc);
1701             sprintf(sysc,"mcsg -%s -wpos 255,255 -%s 3",sofmt,sokey);
1702             Vnm_systemBack(sysc);
1703         } else if (!strcmp("1x1s",Vsh_getenv(thee,"GVLO"))) {
1704             sprintf(sysc,"mcsg -%s -wpos 282,245 -%s 0",sofmt,sokey);
1705             Vnm_systemBack(sysc);
1706         } else if (!strcmp("2x1s",Vsh_getenv(thee,"GVLO"))) {
1707             sprintf(sysc,"mcsg -%s -wpos 282,245 -%s 0",sofmt,sokey);
1708             Vnm_systemBack(sysc);
1709             sprintf(sysc,"mcsg -%s -wpos 282,245 -%s 1",sofmt,sokey);
1710             Vnm_systemBack(sysc);
1711         } else if (!strcmp("3x1s",Vsh_getenv(thee,"GVLO"))) {
1712             sprintf(sysc,"mcsg -%s -wpos 282,152 -%s 0",sofmt,sokey);
1713             Vnm_systemBack(sysc);
1714             sprintf(sysc,"mcsg -%s -wpos 282,152 -%s 1",sofmt,sokey);
1715             Vnm_systemBack(sysc);
1716             sprintf(sysc,"mcsg -%s -wpos 282,152 -%s 2",sofmt,sokey);
1717             Vnm_systemBack(sysc);
1718         } else if (!strcmp("4x1s",Vsh_getenv(thee,"GVLO"))) {
1719             sprintf(sysc,"mcsg -%s -wpos 500,300 -%s 0",sofmt,sokey);
1720             Vnm_systemBack(sysc);
1721             sprintf(sysc,"mcsg -%s -wpos 500,300 -%s 1",sofmt,sokey);
1722             Vnm_systemBack(sysc);
1723             sprintf(sysc,"mcsg -%s -wpos 500,300 -%s 2",sofmt,sokey);
1724             Vnm_systemBack(sysc);
1725             sprintf(sysc,"mcsg -%s -wpos 500,300 -%s 3",sofmt,sokey);
1726             Vnm_systemBack(sysc);
1727         } else if (!strcmp("2x1r",Vsh_getenv(thee,"GVLO"))) {
1728             sprintf(sysc,"mcsg -%s -wpos 425,345@55,0 -%s 0",sofmt,sokey);
1729             Vnm_systemBack(sysc);
1730             sprintf(sysc,"mcsg -%s -wpos 425,345@55,369 -%s 1",sofmt,sokey);
1731             Vnm_systemBack(sysc);
1732         } else {
1733             Vnm_print(2,"%s: %s: Incorrect argument <%s>\n",
1734                 thee->PR,"GVLO",Vsh_getenv(thee,"GVLO"));
1735         }
1736         Vnm_system("sleep 3");
1737         break;
1738 
1739       case vshcom_sockk:
1740         Vsh_killSockets(thee);
1741         break;
1742 
1743       case vshcom_sorry:
1744         Vnm_system("play sorry.au");
1745         break;
1746 
1747       default:
1748         rc = 0;
1749         break;
1750     }
1751     return rc;
1752 }
1753 
1754 /*
1755  * ***************************************************************************
1756  * Routine:  Vsh_ioSetup
1757  *
1758  * Purpose:  Setup for an I/O command.
1759  *
1760  * Author:   Michael Holst
1761  * ***************************************************************************
1762  */
Vsh_ioSetup(Vsh * thee,char * key)1763 VPUBLIC Vio *Vsh_ioSetup(Vsh *thee, char *key)
1764 {
1765     char iodev[VMAX_BUFSIZE], iofmt[VMAX_BUFSIZE];
1766     char iohost[VMAX_BUFSIZE], iofile[VMAX_BUFSIZE];
1767     Vio *sock;
1768 
1769     /* setup for a read */
1770     if (!strcmp("r",key)) {
1771 
1772         strncpy(iohost,Vsh_getenv(thee,"IHVAL"),VMAX_BUFSIZE);
1773 
1774         if (!strcmp("sdio",Vsh_getenv(thee,"ISKEY"))) {
1775             strncpy(iodev,"SDIO",VMAX_BUFSIZE);
1776             strncpy(iofile,"console",VMAX_BUFSIZE);
1777         } else if (!strcmp("file",Vsh_getenv(thee,"ISKEY"))) {
1778             strncpy(iodev,"FILE",VMAX_BUFSIZE);
1779             strncpy(iofile,Vsh_getenv(thee,"IFNAM"),VMAX_BUFSIZE);
1780         } else if (!strcmp("buff",Vsh_getenv(thee,"ISKEY"))) {
1781             strncpy(iodev,"BUFF",VMAX_BUFSIZE);
1782             strncpy(iofile,Vsh_getenv(thee,"ISNAM"),VMAX_BUFSIZE);
1783         } else if (!strcmp("unix",Vsh_getenv(thee,"ISKEY"))) {
1784             strncpy(iodev,"UNIX",VMAX_BUFSIZE);
1785             strncpy(iofile,Vsh_getenv(thee,"ISNAM"),VMAX_BUFSIZE);
1786         } else if (!strcmp("inet",Vsh_getenv(thee,"ISKEY"))) {
1787             strncpy(iodev,"INET",VMAX_BUFSIZE);
1788             strncpy(iofile,Vsh_getenv(thee,"ISNAM"),VMAX_BUFSIZE);
1789         } else {
1790             Vnm_print(2,"Vsh_ioSetup: Internal logic error.\n");
1791             VJMPERR1( 0 );
1792         }
1793 
1794         if (!strcmp("asc",Vsh_getenv(thee,"ISFMT"))) {
1795             strncpy(iofmt,"ASC", VMAX_BUFSIZE);
1796         } else if (!strcmp("xdr",Vsh_getenv(thee,"ISFMT"))) {
1797             strncpy(iofmt,"XDR", VMAX_BUFSIZE);
1798         } else {
1799             Vnm_print(2,"Vsh_ioSetup: Internal logic error.\n");
1800             VJMPERR1( 0 );
1801         }
1802 
1803     /* setup for a write */
1804     } else if (!strcmp("w",key)) {
1805 
1806         strncpy(iohost,Vsh_getenv(thee,"OHVAL"),VMAX_BUFSIZE);
1807 
1808         if (!strcmp("sdio",Vsh_getenv(thee,"OSKEY"))) {
1809             strncpy(iodev,"SDIO",VMAX_BUFSIZE);
1810             strncpy(iofile,"console",VMAX_BUFSIZE);
1811         } else if (!strcmp("file",Vsh_getenv(thee,"OSKEY"))) {
1812             strncpy(iodev,"FILE",VMAX_BUFSIZE);
1813             strncpy(iofile,Vsh_getenv(thee,"OFNAM"),VMAX_BUFSIZE);
1814         } else if (!strcmp("buff",Vsh_getenv(thee,"OSKEY"))) {
1815             strncpy(iodev,"BUFF",VMAX_BUFSIZE);
1816             strncpy(iofile,Vsh_getenv(thee,"OSNAM"),VMAX_BUFSIZE);
1817         } else if (!strcmp("unix",Vsh_getenv(thee,"OSKEY"))) {
1818             strncpy(iodev,"UNIX",VMAX_BUFSIZE);
1819             strncpy(iofile,Vsh_getenv(thee,"OSNAM"),VMAX_BUFSIZE);
1820         } else if (!strcmp("inet",Vsh_getenv(thee,"OSKEY"))) {
1821             strncpy(iodev,"INET",VMAX_BUFSIZE);
1822             strncpy(iofile,Vsh_getenv(thee,"OSNAM"),VMAX_BUFSIZE);
1823         } else {
1824             Vnm_print(2,"Vsh_ioSetup: Internal logic error.\n");
1825             VJMPERR1( 0 );
1826         }
1827 
1828         if (!strcmp("asc",Vsh_getenv(thee,"OSFMT"))) {
1829             strncpy(iofmt,"ASC", VMAX_BUFSIZE);
1830         } else if (!strcmp("xdr",Vsh_getenv(thee,"OSFMT"))) {
1831             strncpy(iofmt,"XDR", VMAX_BUFSIZE);
1832         } else {
1833             Vnm_print(2,"Vsh_ioSetup: Internal logic error.\n");
1834             VJMPERR1( 0 );
1835         }
1836 
1837     } else {
1838         Vnm_print(2,"Vsh_ioSetup: Internal logic error.\n");
1839         VJMPERR1( 0 );
1840     }
1841 
1842     /* create socket and associate the buffer */
1843     VJMPERR1( VNULL != (sock=Vio_socketOpen(key,iodev,iofmt,iohost,iofile)) );
1844     Vio_bufTake(sock, thee->buf, thee->bufsize);
1845     thee->bufsize = 0;
1846     thee->buf     = VNULL;
1847 
1848     /* return without error */
1849     return sock;
1850 
1851   VERROR1:
1852     Vnm_print(2,"Vsh_ioSetup: bailing out.\n");
1853     return VNULL;
1854 }
1855 
1856 /*
1857  * ***************************************************************************
1858  * Routine:  Vsh_ioCleanup
1859  *
1860  * Purpose:  Cleanup an I/O command.
1861  *
1862  * Author:   Michael Holst
1863  * ***************************************************************************
1864  */
Vsh_ioCleanup(Vsh * thee,Vio ** sock)1865 VPUBLIC void Vsh_ioCleanup(Vsh *thee, Vio **sock)
1866 {
1867     VJMPERR1( VNULL != thee );
1868     VJMPERR1( VNULL != *sock );
1869 
1870     /* snag the buffer before destroying the socket */
1871     thee->bufsize = Vio_bufSize(*sock);
1872     thee->buf     = Vio_bufGive(*sock);
1873 
1874     /* return without error */
1875     Vio_socketClose( sock );
1876     return;
1877 
1878   VERROR1:
1879     Vnm_print(2,"Vsh_ioCleanup: bailing out.\n");
1880     return;
1881 }
1882 
1883