1 /* CMDTAB.C     (c) Copyright Roger Bowler, 1999-2009                */
2 /*              (c) Copyright "Fish" (David B. Trout), 2002-2009     */
3 /*              (c) Copyright Jan Jaeger, 2003-2009                  */
4 /*              Route all Hercules configuration statements          */
5 /*              and panel commands to the appropriate functions      */
6 
7 #include "hstdinc.h"
8 
9 #define _CMDTAB_C_
10 #define _HENGINE_DLL_
11 
12 #include "hercules.h"
13 #include "history.h"
14 
15 
16 // Handle externally defined commands...
17 
18 // (for use in CMDTAB COMMAND entry further below)
19 #define      EXT_CMD(xxx_cmd)  call_ ## xxx_cmd
20 
21 // (for defining routing function immediately below)
22 #define CALL_EXT_CMD(xxx_cmd)  \
23 int call_ ## xxx_cmd ( int argc, char *argv[], char *cmdline )  { \
24     return   xxx_cmd (     argc,       argv,         cmdline ); }
25 
26 // Externally defined commands routing functions...
27 
28 CALL_EXT_CMD ( ptt_cmd    )
29 CALL_EXT_CMD ( cache_cmd  )
30 CALL_EXT_CMD ( shared_cmd )
31 
32 /*-------------------------------------------------------------------*/
33 /* Create forward references for all commands in the command table   */
34 /*-------------------------------------------------------------------*/
35 #define _FW_REF
36 #define COMMAND(_stmt, _type, _func, _sdesc, _ldesc)        \
37 int (_func)(int argc, char *argv[], char *cmdline);
38 #define CMDABBR(_stmt, _abbr, _type, _func, _sdesc, _ldesc) \
39 int (_func)(int argc, char *argv[], char *cmdline);
40 #include "cmdtab.h"
41 #undef COMMAND
42 #undef CMDABBR
43 #undef _FW_REF
44 
45 
46 typedef int CMDFUNC(int argc, char *argv[], char *cmdline);
47 
48 /* Layout of command routing table                        */
49 typedef struct _CMDTAB
50 {
51     const char  *statement;        /* statement           */
52     const size_t statminlen;       /* min abbreviation    */
53           int   type;              /* statement type      */
54 #define DISABLED   0x00            /* disabled statement  */
55 #define CONFIG     0x01            /* config statement    */
56 #define PANEL      0x02            /* command statement   */
57     CMDFUNC    *function;          /* handler function    */
58     const char *shortdesc;         /* description         */
59     const char *longdesc;          /* detaled description */
60 } CMDTAB;
61 
62 #define COMMAND(_stmt, _type, _func, _sdesc, _ldesc) \
63 { (_stmt),     (0), (_type), (_func), (_sdesc), (_ldesc) },
64 #define CMDABBR(_stmt, _abbr, _type, _func, _sdesc, _ldesc) \
65 { (_stmt), (_abbr), (_type), (_func), (_sdesc), (_ldesc) },
66 
67 static CMDTAB cmdtab[] =
68 {
69 #include "cmdtab.h"
70 COMMAND ( NULL, 0, NULL, NULL, NULL ) /* End of table */
71 };
72 
73 
74 /*-------------------------------------------------------------------*/
75 /* $zapcmd - internal debug - may cause havoc - use with caution     */
76 /*-------------------------------------------------------------------*/
zapcmd_cmd(int argc,char * argv[],char * cmdline)77 int zapcmd_cmd(int argc, char *argv[], char *cmdline)
78 {
79 CMDTAB* cmdent;
80 int i;
81 
82     UNREFERENCED(cmdline);
83 
84     if (argc > 1)
85     {
86         for (cmdent = cmdtab; cmdent->statement; cmdent++)
87         {
88             if(!strcasecmp(argv[1], cmdent->statement))
89             {
90                 if(argc > 2)
91                     for(i = 2; i < argc; i++)
92                     {
93                         if(!strcasecmp(argv[i],"Cfg"))
94                             cmdent->type |= CONFIG;
95                         else
96                         if(!strcasecmp(argv[i],"NoCfg"))
97                             cmdent->type &= ~CONFIG;
98                         else
99                         if(!strcasecmp(argv[i],"Cmd"))
100                             cmdent->type |= PANEL;
101                         else
102                         if(!strcasecmp(argv[i],"NoCmd"))
103                             cmdent->type &= ~PANEL;
104                         else
105                         {
106                             logmsg(_("Invalid arg: %s: %s %s [(No)Cfg|(No)Cmd]\n"),argv[i],argv[0],argv[1]);
107                             return -1;
108                         }
109                     }
110                 else
111                     logmsg(_("%s: %s(%sCfg,%sCmd)\n"),argv[0],cmdent->statement,
112                       (cmdent->type&CONFIG)?"":"No",(cmdent->type&PANEL)?"":"No");
113                 return 0;
114             }
115         }
116         logmsg(_("%s: %s not in command table\n"),argv[0],argv[1]);
117         return -1;
118     }
119     else
120         logmsg(_("Usage: %s <command> [(No)Cfg|(No)Cmd]\n"),argv[0]);
121     return -1;
122 }
123 
124 CMDT_DLL_IMPORT
ProcessConfigCommand(int argc,char ** argv,char * cmdline)125 int ProcessConfigCommand (int argc, char **argv, char *cmdline)
126 {
127 CMDTAB* cmdent;
128 
129     if (argc)
130         for (cmdent = cmdtab; cmdent->statement; cmdent++)
131             if(cmdent->function && (cmdent->type & CONFIG))
132                 if(!strcasecmp(argv[0], cmdent->statement))
133                     return cmdent->function(argc, argv, cmdline);
134 
135     return -1;
136 }
137 
138 
139 /*-------------------------------------------------------------------*/
140 /* Main panel command processing function                            */
141 /*-------------------------------------------------------------------*/
142 int OnOffCommand(int argc, char *argv[], char *cmdline);
143 int ShadowFile_cmd(int argc, char *argv[], char *cmdline);
144 
145 int    cmd_argc;
146 char*  cmd_argv[MAX_ARGS];
147 
ProcessPanelCommand(char * pszCmdLine)148 int ProcessPanelCommand (char* pszCmdLine)
149 {
150     CMDTAB*  pCmdTab         = NULL;
151     char*    pszSaveCmdLine  = NULL;
152     char*    cl              = NULL;
153     int      rc              = -1;
154     int      cmdl;
155 
156     if (!pszCmdLine || !*pszCmdLine)
157     {
158         /* [enter key] by itself: start the CPU
159            (ignore if not instruction stepping) */
160         if (sysblk.inststep)
161             rc = start_cmd(0,NULL,NULL);
162         goto ProcessPanelCommandExit;
163     }
164 
165 #if defined(OPTION_CONFIG_SYMBOLS)
166     /* Perform variable substitution */
167     /* First, set some 'dynamic' symbols to their own values */
168     set_symbol("CUU","$(CUU)");
169     set_symbol("cuu","$(cuu)");
170     set_symbol("CCUU","$(CCUU)");
171     set_symbol("ccuu","$(ccuu)");
172     cl=resolve_symbol_string(pszCmdLine);
173 #else
174     cl=pszCmdLine;
175 #endif
176 
177     /* Save unmodified copy of the command line in case
178        its format is unusual and needs customized parsing. */
179     pszSaveCmdLine = strdup(cl);
180 
181     /* Parse the command line into its individual arguments...
182        Note: original command line now sprinkled with nulls */
183     parse_args (cl, MAX_ARGS, cmd_argv, &cmd_argc);
184 
185     /* If no command was entered (i.e. they entered just a comment
186        (e.g. "# comment")) then ignore their input */
187     if ( !cmd_argv[0] )
188         goto ProcessPanelCommandExit;
189 
190 #if defined(OPTION_DYNAMIC_LOAD)
191     if(system_command)
192         if((rc = system_command(cmd_argc, (char**)cmd_argv, pszSaveCmdLine)))
193             goto ProcessPanelCommandExit;
194 #endif
195 
196     /* Route standard formatted commands from our routing table... */
197     if (cmd_argc)
198         for (pCmdTab = cmdtab; pCmdTab->function; pCmdTab++)
199         {
200             if(pCmdTab->function && (pCmdTab->type & PANEL))
201             {
202                 if (!pCmdTab->statminlen)
203                 {
204                     if(!strcasecmp(cmd_argv[0], pCmdTab->statement))
205                     {
206                         rc = pCmdTab->function(cmd_argc, (char**)cmd_argv, pszSaveCmdLine);
207                         goto ProcessPanelCommandExit;
208                     }
209                 }
210                 else
211                 {
212                     cmdl=MAX(strlen(cmd_argv[0]),pCmdTab->statminlen);
213                     if(!strncasecmp(cmd_argv[0],pCmdTab->statement,cmdl))
214                     {
215                         rc = pCmdTab->function(cmd_argc, (char**)cmd_argv, pszSaveCmdLine);
216                         goto ProcessPanelCommandExit;
217                     }
218                 }
219             }
220         }
221 
222     /* Route non-standard formatted commands... */
223 
224     /* sf commands - shadow file add/remove/set/compress/display */
225     if (0
226         || !strncasecmp(pszSaveCmdLine,"sf+",3)
227         || !strncasecmp(pszSaveCmdLine,"sf-",3)
228         || !strncasecmp(pszSaveCmdLine,"sfc",3)
229         || !strncasecmp(pszSaveCmdLine,"sfd",3)
230         || !strncasecmp(pszSaveCmdLine,"sfk",3)
231     )
232     {
233         rc = ShadowFile_cmd(cmd_argc,(char**)cmd_argv,pszSaveCmdLine);
234         goto ProcessPanelCommandExit;
235     }
236 
237     /* x+ and x- commands - turn switches on or off */
238     if ('+' == pszSaveCmdLine[1] || '-' == pszSaveCmdLine[1])
239     {
240         rc = OnOffCommand(cmd_argc,(char**)cmd_argv,pszSaveCmdLine);
241         goto ProcessPanelCommandExit;
242     }
243 
244     /* Error: unknown/unsupported command... */
245     ASSERT( cmd_argv[0] );
246 
247     logmsg( _("HHCPN139E Command \"%s\" not found; enter '?' for list.\n"),
248               cmd_argv[0] );
249 
250 ProcessPanelCommandExit:
251 
252     /* Free our saved copy */
253     free(pszSaveCmdLine);
254 
255 #if defined(OPTION_CONFIG_SYMBOLS)
256     if (cl != pszCmdLine)
257         free(cl);
258 #endif
259 
260     return rc;
261 }
262 
263 
264 /*-------------------------------------------------------------------*/
265 /* help command - display additional help for a given command        */
266 /*-------------------------------------------------------------------*/
HelpCommand(int argc,char * argv[],char * cmdline)267 int HelpCommand(int argc, char *argv[], char *cmdline)
268 {
269     CMDTAB* pCmdTab;
270 
271     UNREFERENCED(cmdline);
272 
273     if (argc < 2)
274     {
275         logmsg( _("HHCPN140I Valid panel commands are...\n\n") );
276         logmsg( "  %-9.9s    %s \n", "Command", "Description..." );
277         logmsg( "  %-9.9s    %s \n", "-------", "-----------------------------------------------" );
278 
279         /* List standard formatted commands from our routing table... */
280 
281         for (pCmdTab = cmdtab; pCmdTab->statement; pCmdTab++)
282         {
283             if ( (pCmdTab->type & PANEL) && (pCmdTab->shortdesc))
284                 logmsg( _("  %-9.9s    %s \n"), pCmdTab->statement, pCmdTab->shortdesc );
285         }
286 
287     }
288     else
289     {
290         for (pCmdTab = cmdtab; pCmdTab->statement; pCmdTab++)
291         {
292             if (!strcasecmp(pCmdTab->statement,argv[1]) && (pCmdTab->type & PANEL) )
293             {
294                 logmsg( _("%s: %s\n"),pCmdTab->statement,pCmdTab->shortdesc);
295                 if(pCmdTab->longdesc)
296                     logmsg( _("%s\n"),pCmdTab->longdesc );
297                 return 0;
298             }
299         }
300 
301         logmsg( _("HHCPN142I Command %s not found - no help available\n"),argv[1]);
302         return -1;
303     }
304     return 0;
305 }
306 
307 
308 int scr_recursion_level();
309 
310 #if defined(OPTION_DYNAMIC_LOAD)
panel_command_r(void * cmdline)311 DLL_EXPORT void *panel_command_r (void *cmdline)
312 #else
313 void *panel_command (void *cmdline)
314 #endif
315 {
316 #define MAX_CMD_LEN (32768)
317     char  cmd[MAX_CMD_LEN];             /* Copy of panel command     */
318     char *pCmdLine;
319     unsigned i;
320     int noredisp;
321 
322     pCmdLine = cmdline; ASSERT(pCmdLine);
323     /* every command will be stored in history list */
324     /* except null commands and script commands */
325     if (*pCmdLine != 0 && scr_recursion_level()  == 0)
326         history_add(cmdline);
327 
328     /* Copy panel command to work area, skipping leading blanks */
329 
330     /* If the command starts with a -, then strip it and indicate
331      * we do not want command redisplay
332      */
333 
334     noredisp=0;
335     while (*pCmdLine && isspace(*pCmdLine)) pCmdLine++;
336     i = 0;
337     while (*pCmdLine && i < (MAX_CMD_LEN-1))
338     {
339         if(i==0 && *pCmdLine=='-')
340         {
341             noredisp=1;
342             /* and remove blanks again.. */
343             while (*pCmdLine && isspace(*pCmdLine)) pCmdLine++;
344         }
345         else
346         {
347             cmd[i] = *pCmdLine;
348             i++;
349         }
350         pCmdLine++;
351     }
352     cmd[i] = 0;
353 
354     /* Ignore null commands (just pressing enter)
355        unless instruction stepping is enabled or
356        commands are being sent to the SCP by default. */
357     if (!sysblk.inststep && (sysblk.cmdtgt == 0) && (0 == cmd[0]))
358         return NULL;
359 
360     /* Echo the command to the control panel */
361     if(!noredisp)
362     {
363         logmsg( "%s\n", cmd);
364     }
365 
366 #ifdef OPTION_CMDTGT
367     /* check for herc, scp or pscp command */
368     /* Please note that cmdtgt is a hercules command! */
369     /* Changing the target to her in scp mode is done by using herc cmdtgt herc */
370     if(!strncasecmp(cmd, "herc ", 5) || !strncasecmp(cmd, "scp ", 4) || !strncasecmp(cmd, "pscp ", 5))
371     {
372       ProcessPanelCommand(cmd);
373       return NULL;
374     }
375 
376     /* Send command to the selected command target */
377     switch(sysblk.cmdtgt)
378     {
379       case 0: // cmdtgt herc
380       {
381         /* Stay compatible */
382 #ifdef _FEATURE_SYSTEM_CONSOLE
383         if(cmd[0] == '.' || cmd[0] == '!')
384         {
385           if(!cmd[1])
386           {
387             cmd[1] = ' ';
388             cmd[2] = 0;
389           }
390           scp_command(cmd + 1, cmd[0] == '!');
391         }
392         else
393 #endif /*_FEATURE_SYSTEM_CONSOLE*/
394           ProcessPanelCommand(cmd);
395         break;
396       }
397       case 1: // cmdtgt scp
398       {
399         if(!cmd[0])
400         {
401           cmd[0] = ' ';
402           cmd[1] = 0;
403         }
404         scp_command(cmd, 0);
405         break;
406       }
407       case 2: // cmdtgt pscp
408       {
409         if(!cmd[0])
410         {
411           cmd[0] = ' ';
412           cmd[1] = 0;
413         }
414         scp_command(cmd, 1);
415         break;
416       }
417     }
418 #else // OPTION_CMDTGT
419 #ifdef _FEATURE_SYSTEM_CONSOLE
420     if ('.' == cmd[0] || '!' == cmd[0])
421     {
422         if (!cmd[1]) { cmd[1]=' '; cmd[2]=0; }
423         scp_command (cmd+1, cmd[0] == '!');
424         return NULL;
425     }
426 #endif /*_FEATURE_SYSTEM_CONSOLE*/
427 
428     ProcessPanelCommand(cmd);
429 #endif // OPTION_CMDTGT
430 
431     return NULL;
432 }
433