Minor improvements in the help
[idzebra-moved-to-github.git] / index / zebrash.c
1 /* zebrash.c - command-line interface to zebra API 
2  *  $ID$
3  *
4  * Copyrigth 2003 Index Data Aps
5  *
6  */
7  
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <ctype.h>
12
13 #if HAVE_READLINE_READLINE_H
14 #include <readline/readline.h> 
15 #endif
16 #if HAVE_READLINE_HISTORY_H
17 #include <readline/history.h>
18 #endif
19
20 #include "zebraapi.h"
21
22 #define MAX_NO_ARGS 32
23 #define MAX_OUT_BUFF 4096
24 #define MAX_ARG_LEN 1024
25 #define PROMPT "ZebraSh>"
26 #define DEFAULTCONFIG "./zebra.cfg"
27
28 /**************************************
29  * Global variables (yuck!)
30  */
31
32 ZebraService zs=0;  /* our global handle to zebra */
33 ZebraHandle  zh=0;  /* the current session */
34                   /* time being, only one session works */
35
36 /**************************************
37  * Help functions
38  */
39
40  
41 static int split_args( char *line, char** args )
42 { /* splits line into individual null-terminated strings, 
43    * returns pointers to them in args */
44   char *p=line;
45   int i=0;
46   args[0]=0; /* by default */
47   while (*p==' ' || *p=='\t' || *p=='\n')
48     p++;
49   while (*p)
50   {
51     while (*p==' ' || *p=='\t' || *p=='\n')
52       p++;
53     args[i++]=p;
54     args[i]=0;
55     while (*p && *p!=' ' && *p!='\t' && *p!='\n')
56       p++;
57     *p++='\0';
58   }
59   return i;
60 }
61
62  
63  /**************************************
64  * Individual commands
65  */
66
67  int cmd_echo( char *args[], char *outbuff)
68  {
69    strcpy(outbuff, args[0]);
70    return 0;
71  }
72  
73  int cmd_quit( char *args[], char *outbuff)
74  {
75    strcpy(outbuff, "bye");
76    return -99; /* special stop signal */
77  }
78  
79  int cmd_help( char *args[], char *outbuff); 
80  
81  int cmd_zebra_start( char *args[], char *outbuff)
82  {
83    char *conf=args[1];
84    if (!conf || !*conf) {
85      strcat(outbuff,"no config file specified, using "
86                      DEFAULTCONFIG "\n" );
87      conf=DEFAULTCONFIG;
88    }
89    zs=zebra_start(conf);
90    if (!zs) {
91      strcpy(outbuff, "zebra_open failed" );
92      return 2;
93    }
94    return 0; /* ok */
95  }
96  
97  int cmd_zebra_stop( char *args[], char *outbuff)
98  {
99    if (!zs)
100      strcat(outbuff,"zebra seems not to have been started, "
101                     "stopping anyway");
102    zebra_stop(zs);
103    zs=0;
104    return 0; /* ok */
105  }
106
107 int cmd_zebra_open( char *args[], char *outbuff)
108 {
109   if (!zs)
110     strcat(outbuff,"zebra seems not to have been started, "
111                    "trying anyway");
112   zh=zebra_open(zs);
113   return 0; /* ok */
114 }
115
116 int cmd_zebra_close( char *args[], char *outbuff)
117 {
118   if (!zh)
119     strcat(outbuff,"Seems like you have not called zebra_open,"
120                    "trying anyway");
121   zebra_close(zh);
122   return 0; /* ok */
123 }
124  
125  
126 /**************************************
127  * Command table, parser, and help 
128  */
129
130 struct cmdstruct
131 {
132   char * cmd;
133   char * args;
134   char * explanation;
135   int (*testfunc)(char *args[], char *outbuff);
136 } ;
137
138  
139 struct cmdstruct cmds[] = {
140   /* special cases:
141    *   if text is 0, does not list the command
142    *   if cmd is "", adds the args (and newline) in command listing
143    */
144   { "", "Starting and stopping:", "", 0 },
145   { "zebra_start", 
146     "[configfile]", 
147     "starts the zebra service. You need to call this first\n"
148     "if no configfile is given, assumes " DEFAULTCONFIG, 
149     cmd_zebra_start },
150   { "zebra_stop",   "", 
151     "stops the zebra service", 
152     cmd_zebra_stop },
153   { "zebra_open", "", 
154     "starts a zebra session. Once you have called zebra_start\n"
155     "you can call zebra_open to start working", 
156     cmd_zebra_open },
157   { "zebra_close", "", 
158     "closes a zebra session", 
159     cmd_zebra_close },
160   { "", "Misc:","", 0},
161   { "echo", "string", 
162     "ouputs the string", 
163     cmd_echo },
164   { "quit", "", 
165     "exits the program", 
166     cmd_quit },
167   { "help", "[command]", 
168     "Gives help on command, or lists them all", 
169     cmd_help },
170   { "", "help [command] gives more info on command", "",0 },   
171   {0,0,0,0} /* end marker */
172 };
173  
174 int onecommand( char *line, char *outbuff)
175 {
176   int i;
177   char *args[MAX_NO_ARGS];
178   int n;
179   char argbuf[MAX_ARG_LEN];
180   strncpy(argbuf,line, MAX_ARG_LEN-1);
181   argbuf[MAX_ARG_LEN-1]='\0'; /* just to be sure */
182   n=split_args(argbuf, args);
183   if (0==n)
184     return 0; /* no command on line, too bad */
185   for (i=0;cmds[i].cmd;i++)
186     if (0==strcmp(cmds[i].cmd, args[0])) 
187     {
188       if (n>1)
189         args[0]= line + (args[1]-argbuf); /* rest of the line */
190       else
191         args[0]=""; 
192       return ((cmds[i].testfunc)(args,outbuff));
193     }
194   sprintf (outbuff, "Unknown command '%s'. Try help",args[0] );
195   return -1; 
196 }
197  
198  int cmd_help( char *args[], char *outbuff)
199  { 
200   int i;
201   char tmp[MAX_ARG_LEN];
202   if (args[1])
203   { /* help for a single command */
204    for (i=0;cmds[i].cmd;i++)
205      if (0==strcmp(cmds[i].cmd, args[0])) 
206      {
207        strcat(outbuff,cmds[i].cmd);
208        strcat(outbuff,"  ");
209        strcat(outbuff,cmds[i].args);
210        strcat(outbuff,"\n");
211        strcat(outbuff,cmds[i].explanation);
212        strcat(outbuff,"\n");
213      }
214   }
215   else 
216   { /* list all commands */
217     strcpy(tmp,"    ");
218     for (i=0;cmds[i].cmd;i++)
219       if (cmds[i].explanation)
220       {
221        /* sprintf(tmp, "%s %s %s\n",
222           cmds[i].cmd, cmds[i].args, cmds[i].explanation);
223         */
224         strcat(tmp, cmds[i].cmd);
225         strcat(tmp,"  ");
226         if (!*cmds[i].cmd)
227         {
228           strcat(outbuff, tmp);
229           strcat(outbuff,"\n");
230           strcpy(tmp,"    ");
231           if (*cmds[i].args)
232           {
233             strcat(outbuff, cmds[i].args);
234             strcat(outbuff,"\n");
235           }
236         }
237         if (strlen(tmp)>50)
238         {
239           strcat(outbuff,tmp);
240           strcat(outbuff,"\n");
241           strcpy(tmp,"    ");
242         }
243       }
244     strcat(outbuff,tmp);
245   }
246   return 0;
247  }
248  
249  
250 /************************************** 
251  * The shell
252  */
253  
254 void shell()
255 {
256   int rc=0;
257   while (rc!=-99)
258   {
259     char buf[MAX_ARG_LEN];
260     char outbuff[MAX_OUT_BUFF];
261 #if HAVE_READLINE_READLINE_H
262     char* line_in;
263           line_in=readline(PROMPT);
264           if (!line_in)
265             break;
266 #if HAVE_READLINE_HISTORY_H
267           if (*line_in)
268             add_history(line_in);
269 #endif
270           if(strlen(line_in) > MAX_ARG_LEN-1) {
271             fprintf(stderr,"Input line too long\n");
272             break;
273           };
274           strcpy(buf,line_in);
275           free (line_in);
276 #else    
277           printf (PROMPT); 
278           fflush (stdout);
279           if (!fgets (buf, MAX_ARG_LEN-1, stdin))
280             break;
281 #endif 
282     outbuff[0]='\0';
283     rc=onecommand(buf, outbuff);
284         printf("%s\n", outbuff);
285   }
286
287  }
288  
289  
290 /**************************************
291  * Main 
292  */
293  
294 int main (int argc, char ** args)
295 {
296   shell();
297   return 0;
298 } /* main */