shellLib.c
上传用户:nvosite88
上传日期:2007-01-17
资源大小:4983k
文件大小:29k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* shellLib.c - shell execution routines */
  2. /* Copyright 1987-2002 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 04a,30apr02,elr  Isolate logRtn from shell's stdin, stdout for security
  8.            +fmk  SPR 74345 - fix exit to work properly during telnet/rlogin
  9.                  session. Added shellIsRemoteConnectedSet() and 
  10.                  shellIsRemoteConnectedGet() so that shell can be notified of
  11.                  remote connection and give connection status.
  12. 03z,16oct01,jn   use symFindSymbol for symbol lookup (SPR #7453)
  13. 03y,08oct01,fmk  increase size of errnoString in get1Redir() SPR 27859 and get
  14.                  rid of compiler warnings
  15. 03x,07jul99,cno  Correct "syntax error" message (SPR24924)
  16. 03w,14mar99,jdi  doc: removed refs to config.h and/or configAll.h (SPR 25663).
  17. 03v,16jun98,fle  Remove trailing white space from command (^M), merged from
  18.                  jimmyb's fix : SPR # 21507
  19. 03u,10oct95,jdi  doc: added .tG Shell to shellHistory() and shellPromptSet().
  20. 03t,05may93,caf  tweaked for ansi.
  21. 03s,05sep93,jcf  made calls to remCurId[SG]et indirect so network is decoupled.
  22. 03r,12jul93,jmm  removed VX_STDIO option from shellTaskOptions (spr 2041)
  23. 03q,20jan93,jdi  documentation cleanup for 5.1.
  24. 03p,02aug92,jcf  changed shellSigHandler to use sc_pregs for trcStack basis.
  25. 03o,29jul92,jwt  restored SPARC stack trace - added code to trcStack().
  26. 03n,28jul92,jwt  restored 02y modification removed in 03i; 
  27.                  fixed version numbers.
  28. 03m,20jul92,smb  fixed shell hanging due to errno macro.
  29. 03l,09jul92,rrr  changed xsignal.h to private/sigLibP.h
  30. 03k,26may92,rrr  the tree shuffle
  31. 03j,30apr92,rrr  some preparation for posix signals.
  32. 03i,30mar92,yao  removed if condtionals to calls to trcStack() .
  33. 03h,12mar92,yao  correctly casted paramaters for excJobAdd().  changed
  34.  copyright notice.
  35. 03g,06jan92,yao  removed if conditional to call excInfoShow() for I960.
  36. 03f,17dec91,rrr  Removed decl for trcLib so it would compile.
  37. 03e,13dec91,gae  ANSI cleanup.
  38. 03d,14nov91,jpb  fixed problem with logout trashing user name.
  39.  save initial username and password and restore these
  40.  upon logout.  see spr 916 and 1100.
  41. 03c,15oct91,yao  fixed bug introduced in 03a for shell script.
  42. 03b,04oct91,rrr  passed through the ansification filter
  43.                   -changed functions to ansi style
  44.   -changed includes to have absolute path from h/
  45.   -fixed #else and #endif
  46.   -changed READ, WRITE and UPDATE to O_RDONLY O_WRONLY and ...
  47.   -changed VOID to void
  48.   -changed copyright notice
  49. 03a,29aug91,yao  made the shell work with stdin directed to "/null"
  50.  or uninitialized.
  51. 02z,01aug91,yao  fixed to pass 6 args to excJobAdd() call.
  52. 02y,18feb91,jwt  removed SPARC signal handler attempt to trace own stack.
  53. 02x,29apr91,hdn  added defines and macros for TRON architecture.
  54. 02w,05apr91,jdi  documentation -- removed header parens and x-ref numbers;
  55.  made shellLogout NOMANUAL; doc review by gae.
  56. 02v,25mar91,del  added I960 functionality to signal handler.
  57. 02u,13mar91,jaa  documentation cleanup.
  58. 02t,05oct90,dnw  made shellRestart() and shellLoginInstall() be NOMANUAL.
  59. 02s,10aug90,dnw  added include of shellLib.h.
  60. 02r,01aug90,jcf  added include of sigLib.h.
  61. 02q,13jul90,dnw  added print of errno when redirection open/creat fails
  62.  added errnoStringGet()
  63. 02p,24may90,jcf  made execute externally visible.
  64.  fixed ledId sign comparison in execShell.
  65. 02o,18apr90,shl  added shell security.
  66. 02n,14apr90,jcf  remove tcb extension dependencies.
  67.     changed shell name to tShell.
  68. 02m,10nov89,dab  made ledId global.
  69. 02l,01sep88,ecs  mangled for SPARC; bumped shellTaskStackSize from 5k.
  70. 02k,23may89,dnw  added VX_FP_TASK to shell task options.
  71. 02j,16nov88,gae  made shell be locked when not interactive, i.e. doing scripts.
  72.  made shell history size be a global variable.
  73. 02i,27oct88,jcf  added taskSuspend (0) to shellSigHandler so sigHandlerCleanup
  74.    is never run on a deleted task.
  75. 02h,23sep88,gae  documentation.
  76. 02g,06jun88,dnw  changed taskSpawn/taskCreate args.
  77. 02f,30may88,dnw  changed to v4 names.
  78. 02e,29may88,dnw  added VX_UNBREAKABLE to shell task options.
  79. 02d,28may88,dnw  renamed h to shellHistory and logout to shellLogout
  80.    (h and logout moved to usrLib).
  81.  removed call to dbgSetTaskBreakable() since shell is spawned
  82.    unbreakable.
  83.  replace shellSetOrig...() with shellOrigStdSet().
  84.  changed call to create() to creat().
  85. 02c,26may88,gae  added signal handling to shell task.
  86. 02b,02apr88,gae  made it work with I/O system changes.
  87.  added VX_STDIO option to shell.
  88.  made shell complain when output can't be closed properly.
  89. 02a,27jan88,jcf  made kernel independent.
  90.    removed unnecessary include of a_out.h
  91. 01e,21nov87,gae  fixed double prompt bug with scripts.
  92. 01d,02nov87,dnw  moved logout() and shellLogoutInstall() here from usrLib.
  93.    +gae  changed "korn" references to "led".
  94. 01c,24oct87,gae  changed name from shellExec.c.
  95.  changed setOrig{In,Out,Err}Fd() to shellSetOrig{In,Out,Err}(),
  96.    setShellPrompt() to shellSetPrompt(), and abortScript() to
  97.    shellAbortScript().  Added h() and shellLock().
  98. 01b,21oct87,gae  added shellInit().
  99. 01a,06sep87,gae  split from shell.yacc.
  100.  made shell restart itself on end of file.
  101. */
  102. /*
  103. DESCRIPTION
  104. This library contains the execution support routines for the VxWorks shell.
  105. It provides the basic programmer's interface to VxWorks.
  106. It is a C-expression interpreter, containing no built-in commands.
  107. The nature, use, and syntax of the shell are more fully described in
  108. the "Target Shell" chapter of the
  109. .I "VxWorks Programmer's Guide."
  110. INCLUDE FILES: shellLib.h
  111. SEE ALSO: ledLib,
  112. .pG "Target Shell"
  113. */
  114. #include "vxWorks.h"
  115. #include "shellLib.h"
  116. #include "ctype.h"
  117. #include "ioLib.h"
  118. #include "memLib.h"
  119. #include "string.h"
  120. #include "symLib.h"
  121. #include "sysSymTbl.h"
  122. #include "private/sigLibP.h"
  123. #include "taskLib.h"
  124. #include "remLib.h"
  125. #include "unistd.h"
  126. #include "fcntl.h"
  127. #include "stdio.h"
  128. #include "ledLib.h"
  129. #include "fioLib.h"
  130. #include "trcLib.h"
  131. #include "errno.h"
  132. #include "private/funcBindP.h"
  133. IMPORT void yystart ();
  134. IMPORT int yyparse ();
  135. #define MAX_PROMPT_LEN 80
  136. #define MAX_SHELL_LINE 128 /* max chars on line typed to shell */
  137. /* global variables */
  138. int ledId; /* Line EDitor descriptor (-1 = don't use) */
  139. /* shell task parameters */
  140. int shellTaskId;
  141. char *shellTaskName = "tShell";
  142. int shellTaskPriority = 1;
  143. int shellTaskOptions = VX_FP_TASK | VX_UNBREAKABLE;
  144. int shellTaskStackSize = 20000; /* default/previous stack size */
  145. int shellHistSize = 20; /* default shell history size */
  146. int redirInFd; /* fd of input redirection stream */
  147. int redirOutFd; /* fd of output redirection stream */
  148. /* local variables */
  149. LOCAL char promptString [MAX_PROMPT_LEN] = "-> ";
  150. LOCAL BOOL shellAbort;    /* TRUE = someone requested shell to abort */
  151. LOCAL BOOL shellLocked;    /* TRUE = shell is in exclusive use */
  152. LOCAL BOOL shellExecuting;    /* TRUE = shell was already executing */
  153. LOCAL int origFd [3];    /* fd of original interactive streams */
  154. LOCAL FUNCPTR loginRtn;            /* network login routine */
  155. LOCAL int loginRtnVar;             /* network login routine variable */
  156. LOCAL FUNCPTR logoutRtn;    /* network logout routine */
  157. LOCAL int logoutVar;    /* network logout variable */
  158. LOCAL BOOL startRemoteSession;     /* TRUE = non-console, run security check */
  159. LOCAL BOOL shellIsRemoteConnected; /* TRUE = connected to remote session */
  160. LOCAL char *redirErrMsgWithString = "  errno = %#x (%s)n";
  161. LOCAL char *redirErrMsg = "  errno = %#xn";
  162. LOCAL char originalUser [MAX_IDENTITY_LEN];     /* original current user and */
  163. LOCAL char originalPasswd [MAX_IDENTITY_LEN];   /* password before any rlogin */
  164. /* forward declarations */
  165. void shell ();
  166. /* forward static functions */
  167. static void shellSigHandler
  168.     (
  169.     int signal,
  170.     int code,
  171.     struct sigcontext * pContext
  172.     );
  173. static STATUS execShell
  174.     (
  175.     BOOL interactive
  176.     );
  177. static STATUS getRedir
  178.     (
  179.     char * line,
  180.     int * pInFd,
  181.     int * pOutFd
  182.     );
  183. static STATUS get1Redir
  184.     (
  185.     char * line,
  186.     int * pInFd,
  187.     int * pOutFd
  188.     );
  189. static STATUS errnoStringGet
  190.     (
  191.     int errnum,
  192.     char * errnoString
  193.     );
  194. static void stringTrimRight /* string a string right */
  195.     (
  196.     char * strToTrim /* string to trim right  */
  197.     );
  198. /*******************************************************************************
  199. *
  200. * shellInit - start the shell
  201. *
  202. * This routine starts the shell task.  If the configuration macro INCLUDE_SHELL
  203. * is defined, shellInit() is called by the root task, usrRoot(), in usrConfig.c.
  204. *
  205. * RETURNS: OK or ERROR.
  206. *
  207. * SEE ALSO:
  208. * .pG "Target Shell"
  209. */
  210. STATUS shellInit
  211.     (
  212.     int stackSize,      /* shell stack (0 = previous/default value) */
  213.     int arg             /* argument to shell task */
  214.     )
  215.     {
  216.     if (taskNameToId (shellTaskName) != ERROR)
  217. return (ERROR); /* shell task already active */
  218.     if (stackSize != 0)
  219. shellTaskStackSize = stackSize;
  220.     shellTaskId = taskSpawn (shellTaskName, shellTaskPriority,
  221.      shellTaskOptions, shellTaskStackSize,
  222.      (FUNCPTR) shell, arg, 0, 0, 0, 0 ,0 ,0, 0, 0, 0);
  223.     startRemoteSession = FALSE; /* this is the console, not telnet or rlogin */
  224.     return ((shellTaskId == ERROR) ? ERROR : OK);
  225.     }
  226. /*******************************************************************************
  227. *
  228. * shellRestart - restart the shell task
  229. *
  230. * Used by shellSigHandler; called by excTask().
  231. *
  232. * RETURNS: N/A.
  233. *
  234. * NOMANUAL
  235. */
  236. void shellRestart
  237.     (
  238.     BOOL remoteSession       /* TRUE = non-console, keep shell secure */
  239.     )
  240.     {
  241.     if (remoteSession)
  242. {
  243. startRemoteSession = TRUE;
  244.         }
  245.     if ((taskRestart (shellTaskId)) != ERROR)
  246.         {
  247. printErr ("shell restarted.n");
  248.         }
  249.     else
  250. {
  251. printErr ("spawning new shell.n");
  252. if (shellInit (0, TRUE) == ERROR)
  253.     printErr ("can't restart shell.n");
  254. }
  255.     }
  256. /*******************************************************************************
  257. *
  258. * shellSigHandler - general signal handler for shell task
  259. *
  260. * All signals to the shell task are caught by this handler.
  261. * Any exception info is printed, then the shell's stack is traced.
  262. * Finally the shell is restarted.
  263. *
  264. * RETURNS: N/A
  265. */
  266. LOCAL void shellSigHandler
  267.     (
  268.     int signal,
  269.     int code,
  270.     struct sigcontext *pContext
  271.     )
  272.     {
  273.     extern void dbgPrintCall ();
  274.     /* print any valid exception info */
  275.     if (_func_excInfoShow != NULL) /* default show rtn? */
  276. (*_func_excInfoShow) (&taskIdCurrent->excInfo, FALSE);
  277.     printErr ("07n"); /* ring bell */
  278.     trcStack (pContext->sc_pregs, (FUNCPTR) dbgPrintCall, (int) taskIdCurrent);
  279.     excJobAdd ((VOIDFUNCPTR) shellRestart, FALSE, 0, 0, 0, 0, 0);
  280.     taskSuspend (0); /* wait until excTask restarts us */
  281.     }
  282. /*******************************************************************************
  283. *
  284. * shell - the shell entry point
  285. *
  286. * This routine is the shell task.  It is started with a single parameter
  287. * that indicates whether this is an interactive shell to be used from a
  288. * terminal or a socket, or a shell that executes a script.
  289. *
  290. * Normally, the shell is spawned in interactive mode by the root task,
  291. * usrRoot(), when VxWorks starts up.  After that, shell() is called only
  292. * to execute scripts, or when the shell is restarted after an abort.
  293. *
  294. * The shell gets its input from standard input and sends output to standard
  295. * output.  Both standard input and standard output are initially assigned
  296. * to the console, but are redirected by telnetdTask() and rlogindTask().
  297. *
  298. * The shell is not reentrant, since f3yaccfP does not generate a
  299. * reentrant parser.  Therefore, there can be only a single shell executing
  300. * at one time.
  301. *
  302. * RETURNS: N/A
  303. *
  304. * SEE ALSO:
  305. * .pG "Target Shell"
  306. */
  307. void shell
  308.     (
  309.     BOOL interactive    /* should be TRUE, except for a script */
  310.     )
  311.     {
  312.     int ix;
  313.     struct sigaction sv;
  314.     /* setup default signal handler */
  315.     sv.sa_handler = (VOIDFUNCPTR) shellSigHandler;
  316.     sv.sa_mask    = 0;
  317.     sv.sa_flags   = 0;
  318.     for (ix = 1; ix < 32; ix++)
  319. sigaction (ix, &sv, (struct sigaction *) NULL);
  320.     /* test for new call of shell or restart of aborted shell */
  321.     if (!shellExecuting)
  322. {
  323. /* legitimate call of shell; if interactive save in/out/err fd's */
  324. if (interactive)
  325.     {
  326.     origFd [STD_IN]  = ioGlobalStdGet (STD_IN);
  327.     origFd [STD_OUT] = ioGlobalStdGet (STD_OUT);
  328.     origFd [STD_ERR] = ioGlobalStdGet (STD_ERR); 
  329.     shellLocked = FALSE;
  330.     /*
  331.      * Install Line EDitor interface:
  332.      * This is done only after the first "interactive"
  333.      * invocation of the shell so that a startup
  334.      * script could change some parameters.
  335.      * Eg. ledId to -1 or shellHistSize to > 20.
  336.      */
  337.     if (ledId == (int)NULL &&
  338. (ledId = ledOpen (STD_IN, STD_OUT, shellHistSize)) == ERROR)
  339. {
  340. printErr ("Unable to install Line EDitor interfacen");
  341. }
  342.     }
  343. else
  344.     {
  345.     /* do not allow rlogins while doing a script */
  346.     shellLocked = TRUE;
  347.     }
  348. /* shell should not reference network directly for scalability */
  349. if (_func_remCurIdGet != NULL)
  350.             (* _func_remCurIdGet) (originalUser, originalPasswd);  
  351. shellExecuting = TRUE;
  352. }
  353.     else
  354. {
  355. /* this must be a restart, i.e. via ABORT key;
  356.  * restore original interactive in/out/err fd's */
  357. if (interactive)
  358.     {
  359.     ioGlobalStdSet (STD_IN,  origFd [STD_IN]);
  360.     ioGlobalStdSet (STD_OUT, origFd [STD_OUT]);
  361.     ioGlobalStdSet (STD_ERR, origFd [STD_ERR]); 
  362.     printf ("n");
  363.     }
  364. else
  365.     return;
  366. }
  367.     ioctl (STD_IN, FIOOPTIONS, OPT_TERMINAL);
  368.     (void)execShell (interactive);
  369.     shellExecuting = FALSE;
  370.     }
  371. /*******************************************************************************
  372. *
  373. * execShell - execute stream of shell commands
  374. *
  375. * RETURNS: OK or ERROR.
  376. */
  377. LOCAL STATUS execShell
  378.     (
  379.     FAST BOOL interactive
  380.     )
  381.     {
  382.     char inLine [MAX_SHELL_LINE + 1];
  383.     FAST int i;
  384.     STATUS status = OK;
  385.     if (startRemoteSession) /* execute shell security if required */
  386.         {
  387.         /* 
  388.          * Save user and password information in case it is changed 
  389.          * during the remote session.  It is restored by shellLogout.  
  390.          * Reference network indirectly for scalability.
  391.          */
  392. if (_func_remCurIdGet != NULL)
  393.             (* _func_remCurIdGet) (originalUser, originalPasswd);  
  394.         startRemoteSession = FALSE; /* now that it is started */
  395.         } /* if (startRemoteSession) */
  396.     shellAbort = FALSE;
  397.     while (TRUE)
  398. {
  399. /* read next line */
  400. if (interactive)
  401.     {
  402.     int nchars;
  403.     if (ioGlobalStdGet (STD_IN) == -1)
  404. {
  405. taskDelay (1); /* so that other task can run */
  406. continue;
  407. }
  408.     printf ("%s", promptString);
  409.     if ((ledId == (int)NULL) || (ledId == -1))
  410. nchars = fioRdString (STD_IN, inLine, MAX_SHELL_LINE);
  411.     else
  412. nchars = ledRead (ledId, inLine, MAX_SHELL_LINE);
  413.     if (nchars == EOF)
  414. {
  415. /* start shell over again */
  416. excJobAdd ((VOIDFUNCPTR)taskRestart, shellTaskId, 0, 0, 0, 0, 0);
  417. }
  418.     }
  419. else if (fioRdString (STD_IN, inLine, MAX_SHELL_LINE) != EOF)
  420.     printf ("%sn", inLine);
  421. else
  422.     break; /* end of script - bye */
  423. /* got a line of input:
  424.  *   ignore comments, blank lines, and null lines */
  425. inLine [MAX_SHELL_LINE] = EOS; /* make sure inLine has EOS */
  426. for (i = 0; inLine [i] == ' '; i++) /* skip leading blanks */
  427.     ;
  428. if (inLine [i] != '#' && inLine [i] != EOS)
  429.     {
  430.     /* Eliminate trailing space */
  431.     stringTrimRight (&inLine[i]);
  432.     if (inLine[i] == EOS)
  433. continue;
  434.     /* parse & execute command */
  435.             /* The exit command is intercepted and if 
  436.              * a user has telnetted or rlogged in to the shell,
  437.              * logout is executed instead of exit. This allows 
  438.              * proper cleanup of the rlogin or telnet 
  439.              * session and allows control to return to the 
  440.              * local shell console.*/
  441.                 
  442.             if (strcmp (&inLine [i],"exit") == 0 && 
  443.                 shellIsRemoteConnected)
  444.                 status = execute ("logout");
  445.             else
  446.                 status = execute (&inLine [i]);
  447.     if (status != OK && !interactive)
  448. {
  449. status = ERROR;
  450. break;
  451. }
  452.     /* check for script aborted;
  453.      *   note that "shellAbort" is a static variable and
  454.      *   is not reset until we get back up to an interactive
  455.      *   shell.  Thus all levels of nested scripts are aborted. */
  456.     if (shellAbort)
  457. {
  458. if (!interactive)
  459.     {
  460.     status = ERROR;
  461.     break;
  462.     }
  463. else
  464.     shellAbort = FALSE;
  465. }
  466.     }
  467. }
  468.     return (status);
  469.     }
  470. /*******************************************************************************
  471. *
  472. * shellScriptAbort - signal the shell to stop processing a script
  473. *
  474. * This routine signals the shell to abort processing a script file.
  475. * It can be called from within a script if an error is detected.
  476. *
  477. * RETURNS: N/A
  478. *
  479. * SEE ALSO:
  480. * .pG "Target Shell"
  481. */
  482. void shellScriptAbort (void)
  483.     {
  484.     shellAbort = TRUE;
  485.     }
  486. /*******************************************************************************
  487. *
  488. * shellHistory - display or set the size of shell history
  489. *
  490. * This routine displays shell history, or resets the default number of
  491. * commands displayed by shell history to <size>.  By default, history size
  492. * is 20 commands.  Shell history is actually maintained by ledLib.
  493. *
  494. * RETURNS: N/A
  495. *
  496. * SEE ALSO: ledLib, h(),
  497. * .pG "Target Shell,"
  498. * windsh,
  499. * .tG "Shell"
  500. */
  501. void shellHistory
  502.     (
  503.     int size    /* 0 = display, >0 = set history to new size */
  504.     )
  505.     {
  506.     ledControl (ledId, NONE, NONE, size);
  507.     }
  508. /*******************************************************************************
  509. *
  510. * execute - interpret and execute a source line
  511. *
  512. * This routine parses and executes the specified source line.
  513. * First any I/O redirection is cracked, then if any text remains,
  514. * that text is parsed and executed via the yacc-based interpreter.
  515. * If no text remains after the I/O redirection, then the shell itself
  516. * is invoked (recursively) with the appropriate redirection.
  517. * Note that blank lines, null lines, and comment lines should NOT
  518. * be passed to this routine.  Initial blanks should be stripped too!
  519. *
  520. * RETURNS: OK or ERROR.
  521. *
  522. * NOMANUAL
  523. */
  524. STATUS execute
  525.     (
  526.     FAST char *line
  527.     )
  528.     {
  529.     int newInFd;
  530.     int newOutFd;
  531.     int oldInFd  = ioGlobalStdGet (STD_IN);
  532.     int oldOutFd = ioGlobalStdGet (STD_OUT);
  533.     STATUS status;
  534.     /* get any redirection specs */
  535.     if (getRedir (line, &newInFd, &newOutFd) != OK)
  536. return (ERROR);
  537.     if (*line == EOS)
  538. {
  539.         /* set any redirections specified, call shell, and restore streams */
  540. if (newInFd >= 0)
  541.     ioGlobalStdSet (STD_IN, newInFd);
  542. if (newOutFd >= 0)
  543.     ioGlobalStdSet (STD_OUT, newOutFd);
  544. status = execShell (FALSE);
  545. ioGlobalStdSet (STD_IN, oldInFd);
  546. ioGlobalStdSet (STD_OUT, oldOutFd);
  547. }
  548.     else
  549. {
  550. /* set global stream fds for redirection of function calls;
  551.  * a -1 means no redirection
  552.  */
  553. redirInFd = newInFd;
  554. redirOutFd = newOutFd;
  555. /* initialize parse variables and parse and execute line */
  556. yystart (line);
  557. status = (yyparse () == 0) ? OK : ERROR;
  558. }
  559.     /* close redirection files */
  560.     if (newInFd >= 0)
  561. close (newInFd);
  562.     if (newOutFd >= 0 && close (newOutFd) == ERROR)
  563. printf ("can't close output.n");
  564.     return (status);
  565.     }
  566. /*******************************************************************************
  567. *
  568. * getRedir - establish redirection specified on input line
  569. *
  570. * This routines picks the redirection specs off the end of the input line.
  571. * The values pointed to by pInFd and pOutFd are set to -1 if the input and
  572. * output respectively are not redirected, and to the file descriptor (fd) of
  573. * the redirection stream if they are redirected.  Note that this routine
  574. * also trucates from the end of the input line any successfully cracked
  575. * redirection specs, i.e. an EOS is inserted in the input line at the point
  576. * where the redirection specs began.
  577. *
  578. * RETURNS: ERROR if error in redirection spec or opening stream,
  579. * OK if successful redirection found, or no redirection found.
  580. */
  581. LOCAL STATUS getRedir
  582.     (
  583.     char *line,
  584.     FAST int *pInFd,    /* -1, or fd of of input redirection */
  585.     FAST int *pOutFd    /* -1, or fd of of output redirection */
  586.     )
  587.     {
  588.     *pInFd = *pOutFd = -1;
  589.     if (get1Redir (line, pInFd, pOutFd) != OK ||
  590.         get1Redir (line, pInFd, pOutFd) != OK)
  591. {
  592. if (*pInFd >= 0)
  593.     close (*pInFd);
  594. if (*pOutFd >= 0)
  595.     close (*pOutFd);
  596. return (ERROR);
  597. }
  598.     return (OK);
  599.     }
  600. /*******************************************************************************
  601. *
  602. * get1Redir - get a redirection from a line
  603. *
  604. * This routine picks a single redirection specification off the end
  605. * of the specified line.
  606. *
  607. * RETURNS: ERROR if error in redirection spec or opening stream,
  608. * OK if successful redirection found, or no redirection found.
  609. */
  610. LOCAL STATUS get1Redir
  611.     (
  612.     char *line,         /* line to scan */
  613.     int *pInFd,         /* if '<' found then fd is assigned here */
  614.     int *pOutFd         /* if '>' found then fd is assigned here */
  615.     )
  616.     {
  617.     FAST char *p;        /* position in line */
  618.     char *name;        /* name of redirection file if found  */
  619.     char *errnoString = NULL;  /* pointer to symTbl's copy of string */ 
  620.     int  ourErrno; 
  621.     if (strlen (line) == 0)
  622. return (OK);
  623.     /* Set p == end of line */
  624.     p = line + strlen (line) - 1;
  625.     /* pick off last word and back up to previous non-blank before that */
  626.     while (p > line && *p == ' ')
  627. {
  628. p--; /* skip trailing blanks */
  629. }
  630.     *(p + 1) = EOS;
  631.     /* stop searching if:
  632.      *   reached beginning of line,
  633.      *   reached a blank,
  634.      *   reached a redirection token,
  635.      *   hit a semicolon or quote.
  636.      */
  637.     while (p > line  && *p != ' ' &&
  638.    *p != '<' && *p != '>' &&
  639.    *p != ')' && *p != ';' &&
  640.    *p != '"')
  641. {
  642. p--; /* skip back to start of word */
  643. }
  644.     name = p + 1; /* name must begin here */
  645.     while (p > line && *p == ' ')
  646. p--; /* skip back to previous non-blank */
  647.     /* is this a redirection? */
  648.     if (*p == '>' && *(p -1) != '>')
  649. {
  650. if (*pOutFd >= 0)
  651.     {
  652.     printf ("ambiguous output redirect.n");
  653.     return (ERROR);
  654.     }
  655. if ((*pOutFd = creat (name, O_WRONLY)) < 0)
  656.     {
  657.     printf ("can't create output '%s'n", name);
  658.     ourErrno = errno;
  659.     if ((errnoStringGet (ourErrno, errnoString) == OK) &&
  660. (errnoString != NULL))
  661. printf (redirErrMsgWithString, ourErrno, errnoString);
  662.     else
  663. printf (redirErrMsg, ourErrno);
  664.     return (ERROR);
  665.     }
  666. *p = EOS; /* truncate to exclude the redirection stuff just used */
  667. }
  668.     else if (*p == '<' && (p == line || *(p -1) != '<'))
  669. {
  670. if (*pInFd >= 0)
  671.     {
  672.     printf ("ambiguous input redirect.n");
  673.     return (ERROR);
  674.     }
  675. if ((*pInFd = open (name, O_RDONLY, 0)) < 0)
  676.     {
  677.     printf ("can't open input '%s'n", name);
  678.     ourErrno = errno;
  679.     if ((errnoStringGet (ourErrno, errnoString) == OK) &&
  680. (errnoString != NULL))
  681. printf (redirErrMsgWithString, ourErrno, errnoString);
  682.     else
  683. printf (redirErrMsg, ourErrno);
  684.     return (ERROR);
  685.     }
  686. *p = EOS; /* truncate to exclude the redirection stuff just used */
  687. }
  688.     return (OK);
  689.     }
  690. /*******************************************************************************
  691. *
  692. * shellPromptSet - change the shell prompt
  693. *
  694. * This routine changes the shell prompt string to <newPrompt>.
  695. *
  696. * RETURNS: N/A
  697. *
  698. * SEE ALSO:
  699. * .pG "Target Shell,"
  700. * windsh,
  701. * .tG "Shell"
  702. */
  703. void shellPromptSet
  704.     (
  705.     char *newPrompt     /* string to become new shell prompt */
  706.     )
  707.     {
  708.     strncpy (promptString, newPrompt, MAX_PROMPT_LEN);
  709.     }
  710. /*******************************************************************************
  711. *
  712. * shellOrigStdSet - set the shell's default input/output/error file descriptors
  713. *
  714. * This routine is called to change the shell's default standard
  715. * input/output/error file descriptor.  Normally, it is used only by the
  716. * shell, rlogindTask(), and telnetdTask().  Values for <which> can be
  717. * STD_IN, STD_OUT, or STD_ERR, as defined in vxWorks.h.  Values for <fd> can
  718. * be the file descriptor for any file or device.
  719. *
  720. * RETURNS: N/A
  721. */
  722. void shellOrigStdSet
  723.     (
  724.     int which,  /* STD_IN, STD_OUT, STD_ERR */
  725.     int fd      /* fd to be default */
  726.     )
  727.     {
  728.     origFd [which] = fd;
  729.     }
  730. /*******************************************************************************
  731. *
  732. * shellLock - lock access to the shell
  733. *
  734. * This routine locks or unlocks access to the shell.  When locked, cooperating
  735. * tasks, such as telnetdTask() and rlogindTask(), will not take the shell.
  736. *
  737. * RETURNS:
  738. * TRUE if <request> is "lock" and the routine successfully locks the shell,
  739. * otherwise FALSE.  TRUE if <request> is "unlock" and the routine
  740. * successfully unlocks the shell, otherwise FALSE.
  741. *
  742. * SEE ALSO:
  743. * .pG "Target Shell"
  744. */
  745. BOOL shellLock
  746.     (
  747.     BOOL request        /* TRUE = lock, FALSE = unlock */
  748.     )
  749.     {
  750.     if (request == shellLocked)
  751. return (FALSE);
  752.     shellLocked = request;
  753.     return (TRUE);
  754.     }
  755. /********************************************************************************
  756. *
  757. * shellLogin - login using the user-supplied login routine
  758. *
  759. * RETURNS: OK or ERROR
  760. *
  761. * NOMANUAL
  762. */
  763. STATUS shellLogin
  764.     (
  765.     int fd   /* i/o file descriptor passed from telnetd */
  766.     )
  767.     {
  768.     if (loginRtn != NULL)
  769.         {
  770.         /* 
  771.          * The standard i/o of this task context will now be that of the 
  772.          * specified descriptor.
  773.          */
  774.         ioTaskStdSet (0, STD_IN, fd);
  775.         ioTaskStdSet (0, STD_OUT, fd);
  776.         /* Call the user-installed login routine */
  777.         if ((*loginRtn)(loginRtnVar) == ERROR)
  778.             {
  779.     return (ERROR);
  780.             }
  781.         printf("nn"); /* user already logged in at this point */
  782. return (OK);
  783.         } /* if (loginRtn != NULL) */
  784. return (OK); /* No login routine provided */
  785.     }
  786. /********************************************************************************
  787. * shellLoginInstall - login hook for network login routine
  788. *
  789. * RETURNS: N/A.
  790. *
  791. * NOMANUAL
  792. */
  793. void shellLoginInstall
  794.     (
  795.     FUNCPTR logRtn,
  796.     int logRtnVar
  797.     )
  798.     {
  799.     loginRtn    = logRtn;
  800.     loginRtnVar = logRtnVar;
  801.     }
  802. /*******************************************************************************
  803. *
  804. * shellLogoutInstall - logout hook for telnetdTask and rlogindTask
  805. *
  806. * RETURNS: N/A.
  807. *
  808. * NOMANUAL
  809. */
  810. void shellLogoutInstall
  811.     (
  812.     FUNCPTR logRtn,
  813.     int logVar
  814.     )
  815.     {
  816.     logoutRtn = logRtn;
  817.     logoutVar = logVar;
  818.     }
  819. /*******************************************************************************
  820. *
  821. * shellLogout - log out of the shell
  822. *
  823. * This routine logs out of the VxWorks shell.  If a remote login is active
  824. * (via `rlogin' or `telnet'), it is stopped, and standard I/O is restored
  825. * to the console.
  826. *
  827. * SEE ALSO: rlogindTask(), telnetdTask(), logout()
  828. *
  829. * RETURNS: N/A
  830. *
  831. * NOMANUAL
  832. */
  833. void shellLogout (void)
  834.     {
  835.     /* Restore original user and password information, saved by shell().
  836.      * Reference network indirectly for scalability.
  837.      */
  838.     shellLock (FALSE);
  839.     if (_func_remCurIdSet != NULL)
  840. (* _func_remCurIdSet) (originalUser, originalPasswd);  
  841.     if (logoutRtn != NULL)
  842. (*logoutRtn) (logoutVar);
  843.     }
  844. /*******************************************************************************
  845. *
  846. * shellIsRemoteConnectedSet - notify shell of remote connection/disconnection
  847. *
  848. * This routine allows a remote session like rlogin or telnet to notify
  849. * the shell of a successful remote connection/disconnection.
  850. *
  851. * TRUE = connected to remote session and FALSE = disconnected from remote
  852. * session.
  853. *
  854. * RETURNS: N/A
  855. *
  856. * NOMANUAL
  857. */
  858. void shellIsRemoteConnectedSet
  859.     (
  860.     BOOL remoteConnection    /* TRUE = connected, FALSE = disconnected */
  861.     )
  862.     {
  863.     shellIsRemoteConnected = remoteConnection; 
  864.     }
  865. /*******************************************************************************
  866. *
  867. * shellIsRemoteConnectedGet - get remote connection status of shell
  868. *
  869. * This routine allows a user to get the remote connection status of the shell.
  870. *
  871. * RETURNS: TRUE if shell is remotely connected or FALSE if the shell is not
  872. * remotely connected.
  873. *
  874. * NOMANUAL
  875. */
  876. BOOL shellIsRemoteConnectedGet (void)
  877.     {
  878.     return shellIsRemoteConnected;
  879.     }
  880. /*******************************************************************************
  881. *
  882. * errnoStringGet - get string associated with errno
  883. *
  884. * RETURNS: OK or ERROR.
  885. */
  886. LOCAL STATUS errnoStringGet
  887.     (
  888.     FAST int errnum,     /* status code whose name is to be printed */
  889.     char * errnoString
  890.     )
  891.     {
  892.     void *    val;
  893.     SYMBOL_ID symId;
  894.     /* new symLib api - symbol name lengths are no longer limited */
  895.     if ((statSymTbl != NULL) &&
  896. (symFindSymbol (statSymTbl, NULL, (void *)errnum, 
  897. SYM_MASK_NONE, SYM_MASK_NONE, &symId) == OK) &&
  898. (symNameGet (symId, &errnoString) == OK) &&
  899. (symValueGet (symId, &val) == OK) &&
  900. (val == (void *)errnum))
  901. {
  902. return (OK);
  903. }
  904.     return (ERROR);
  905.     }
  906. /*******************************************************************************
  907. *
  908. * stringTrimRight - remove trailing white space from a string
  909. *
  910. * RETURNS: void.
  911. */
  912. LOCAL void stringTrimRight
  913.     (
  914.     char * strToTrim /* string to trim right */
  915.     )
  916.     {
  917.     register char * strCursor = NULL; /* string cursor */
  918.     strCursor = strToTrim + strlen(strToTrim) - 1;
  919.     while (strCursor > strToTrim)
  920. {
  921. if (isspace ((int)(*strCursor)))
  922.     strCursor--;
  923. else
  924.     break;
  925. }
  926.     if (strCursor == strToTrim)
  927. {
  928. if (isspace ((int)(*strCursor)))   /* whole string is white space */
  929.     {
  930.     *strCursor = EOS;
  931.     return;
  932.     }
  933. }
  934.     /* Normal return, non-empty string */
  935.     *(strCursor+1) = EOS;
  936.     return;
  937.     }