Minor fiddling, log functions. Still no real testables...
[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 #include <yaz/log.h>
22
23 #define MAX_NO_ARGS 32
24 #define MAX_OUT_BUFF 4096
25 #define MAX_ARG_LEN 1024
26 #define PROMPT "ZebraSh>"
27 #define DEFAULTCONFIG "./zebra.cfg"
28
29 /**************************************
30  * Global variables (yuck!)
31  */
32
33 ZebraService zs=0;  /* our global handle to zebra */
34 ZebraHandle  zh=0;  /* the current session */
35                   /* time being, only one session works */
36
37 /**************************************
38  * Help functions
39  */
40
41  
42 static int split_args( char *line, char** args )
43 { /* splits line into individual null-terminated strings, 
44    * returns pointers to them in args */
45   /* FIXME - do we need to handle quoted args ?? */
46   char *p=line;
47   int i=0;
48   int n=0;
49   args[0]=0; /* by default */
50   while (*p==' ' || *p=='\t' || *p=='\n')
51     p++;
52   while (*p)
53   {
54     while (*p==' ' || *p=='\t' || *p=='\n')
55       p++;
56     if (*p=='#')  /* skip comments */
57       break;  
58     args[i++]=p;
59     args[i]=0;
60     while (*p && *p!=' ' && *p!='\t' && *p!='\n' && *p!='#')
61       p++;
62     *p++='\0';
63   }
64   n=i;
65   while (n<MAX_NO_ARGS)
66     args[n++]=0;
67   return i;
68 }
69
70 static char *defarg( char *arg, char *def )
71 {
72   if (!arg)
73     return def;
74   if (!*arg)
75     return def;
76   return arg;
77 }
78 static int defargint( char *arg, int def )
79 {
80   int v=def;
81   char *a=defarg(arg,0);
82   if (a)
83     sscanf(a," %i", &v);
84   return v;
85 }
86  
87  /**************************************
88  * Simple support commands
89  */
90
91  int cmd_echo( char *args[], char *outbuff)
92  {
93    strcpy(outbuff, args[0]);
94    return 0;
95  }
96  
97  int cmd_quit( char *args[], char *outbuff)
98  {
99    strcpy(outbuff, "bye");
100    return -99; /* special stop signal */
101  }
102
103 /**************************************
104  * Tests for starting and stopping zebra, etc
105  */
106  
107  static int cmd_help( char *args[], char *outbuff); 
108  
109  static int cmd_zebra_start( char *args[], char *outbuff)
110  {
111    char *conf=args[1];
112    if (!conf || !*conf) {
113      strcat(outbuff,"no config file specified, using "
114                      DEFAULTCONFIG "\n" );
115      conf=DEFAULTCONFIG;
116    }
117    zs=zebra_start(conf);
118    if (!zs) {
119      strcpy(outbuff, "zebra_start failed" );
120      return 2;
121    }
122    return 0; /* ok */
123  }
124  
125  static int cmd_zebra_stop( char *args[], char *outbuff)
126  {
127    if (!zs)
128      strcat(outbuff,"zebra seems not to have been started, "
129                     "stopping anyway");
130    zebra_stop(zs);
131    zs=0;
132    return 0; /* ok */
133  }
134
135 static int cmd_zebra_open( char *args[], char *outbuff)
136 {
137   if (!zs)
138     strcat(outbuff,"zebra seems not to have been started, "
139                    "trying anyway");
140   zh=zebra_open(zs);
141   return 0; /* ok */
142 }
143
144 static int cmd_zebra_close( char *args[], char *outbuff)
145 {
146   if (!zh)
147     strcat(outbuff,"Seems like you have not called zebra_open,"
148                    "trying anyway");
149   zebra_close(zh);
150   return 0; /* ok */
151 }
152
153 static int cmd_quickstart( char *args[], char *outbuff)
154 {
155   cmd_zebra_start(args,outbuff);
156   cmd_zebra_open(args,outbuff);
157   yaz_log_init_file("zebrash.log");
158   yaz_log_init_prefix("ZebraSh");
159   strcat(outbuff,"Started zebra, log in zebrash.log");
160   return 0; /* ok */
161 }
162
163 /**************************************
164  * Log file handling
165  */
166
167 static int cmd_yaz_log_file( char *args[], char *outbuff)
168 {
169   char *fn = defarg(args[1],0);
170   char tmp[255];
171   sprintf(tmp, "sending yaz-log to %s ",fn);
172   strcat(outbuff, tmp);
173   yaz_log_init_file(fn);
174   return 0; /* ok */
175 }
176
177 static int cmd_yaz_log_level( char *args[], char *outbuff)
178 {
179   int  lev = defargint(args[1],LOG_DEFAULT_LEVEL);
180   char tmp[255];
181   sprintf(tmp, "setting yaz-log to level %d (ox%x)",lev,lev);
182   strcat(outbuff, tmp);
183   yaz_log_init_level(lev);
184   return 0; /* ok */
185 }
186
187 static int cmd_yaz_log_prefix( char *args[], char *outbuff)
188 {
189   char *pref = defarg(args[1],"ZebraSh");
190   char tmp[255];
191   sprintf(tmp, "setting yaz-log prefix to %s",pref);
192   strcat(outbuff, tmp);
193   yaz_log_init_prefix(pref);
194   return 0; /* ok */
195 }
196
197 static int cmd_logf( char *args[], char *outbuff)
198 {
199   int lev = defargint(args[1],0);
200   char tmp[MAX_OUT_BUFF]="";
201   int i=1;
202   if (lev)
203     i=2;
204   else
205     lev=LOG_LOG; /* this is in the default set!*/
206   while (args[i])
207   {
208     strcat(tmp, args[i++]);
209     strcat(tmp, " ");
210   }
211   logf(lev,tmp);
212   return 0; /* ok */
213 }
214  
215  
216 /**************************************
217  * Command table, parser, and help 
218  */
219
220 struct cmdstruct
221 {
222   char * cmd;
223   char * args;
224   char * explanation;
225   int (*testfunc)(char *args[], char *outbuff);
226 } ;
227
228  
229 struct cmdstruct cmds[] = {
230   /* special cases:
231    *   if text is 0, does not list the command
232    *   if cmd is "", adds the args (and newline) in command listing
233    */
234   { "", "Starting and stopping:", "", 0 },
235   { "zebra_start", 
236     "[configfile]", 
237     "starts the zebra service. You need to call this first\n"
238     "if no configfile is given, assumes " DEFAULTCONFIG, 
239     cmd_zebra_start },
240   { "zebra_stop",   "", 
241     "stops the zebra service", 
242     cmd_zebra_stop },
243   { "zebra_open", "",  
244     "starts a zebra session. Once you have called zebra_start\n"
245     "you can call zebra_open to start working", 
246     cmd_zebra_open },
247   { "zebra_close", "", 
248     "closes a zebra session", 
249     cmd_zebra_close }, 
250   { "quickstart", "[configfile]", 
251     "Does a zebra_start, zebra_open, and sets up the log", 
252     cmd_quickstart }, 
253   
254   { "", "Log file:","", 0},  
255   { "yaz_log_file", 
256     "[filename]",
257     "Directs the log to filename (or stderr)",
258     cmd_yaz_log_file },
259   { "yaz_log_file", 
260     "[level]",
261     "Sets the logging level (or returns to default)",
262     cmd_yaz_log_level },
263   { "yaz_log_prefix", 
264     "[prefix]",
265     "Sets the log prefix",
266     cmd_yaz_log_prefix},    
267   { "logf", 
268     "[level] text...",
269     "writes an entry in the log",
270     cmd_logf},    
271   
272   { "", "Misc:","", 0}, 
273   { "echo", "string", 
274     "ouputs the string", 
275     cmd_echo },
276   { "quit", "", 
277     "exits the program", 
278     cmd_quit },
279   { "help", "[command]", 
280     "Gives help on command, or lists them all", 
281     cmd_help },
282   { "", "help [command] gives more info on command", "",0 },   
283   
284   {0,0,0,0} /* end marker */
285 };
286  
287 int onecommand( char *line, char *outbuff)
288 {
289   int i;
290   char *args[MAX_NO_ARGS];
291   int n;
292   char argbuf[MAX_ARG_LEN];
293   strncpy(argbuf,line, MAX_ARG_LEN-1);
294   argbuf[MAX_ARG_LEN-1]='\0'; /* just to be sure */
295   n=split_args(argbuf, args);
296   if (0==n)
297     return 0; /* no command on line, too bad */
298   for (i=0;cmds[i].cmd;i++)
299     if (0==strcmp(cmds[i].cmd, args[0])) 
300     {
301       if (n>1)
302         args[0]= line + (args[1]-argbuf); /* rest of the line */
303       else
304         args[0]=""; 
305       return ((cmds[i].testfunc)(args,outbuff));
306     }
307   sprintf (outbuff, "Unknown command '%s'. Try help",args[0] );
308   return -1; 
309 }
310  
311  static int cmd_help( char *args[], char *outbuff)
312  { 
313   int i;
314   char tmp[MAX_ARG_LEN];
315   if (args[1])
316   { /* help for a single command */
317     for (i=0;cmds[i].cmd;i++)
318       if (0==strcmp(cmds[i].cmd, args[1])) 
319       {
320         strcat(outbuff,cmds[i].cmd);
321         strcat(outbuff,"  ");
322         strcat(outbuff,cmds[i].args);
323         strcat(outbuff,"\n");
324         strcat(outbuff,cmds[i].explanation);
325         strcat(outbuff,"\n");
326         return 0;
327       }
328     strcat(outbuff, "Unknown command ");
329     strcat(outbuff, args[1] );
330   }
331   else 
332   { /* list all commands */
333     strcpy(tmp,"    ");
334     for (i=0;cmds[i].cmd;i++)
335       if (cmds[i].explanation)
336       {
337        /* sprintf(tmp, "%s %s %s\n",
338           cmds[i].cmd, cmds[i].args, cmds[i].explanation);
339         */
340         strcat(tmp, cmds[i].cmd);
341         strcat(tmp,"  ");
342         if (!*cmds[i].cmd)
343         {
344           strcat(outbuff, tmp);
345           strcat(outbuff,"\n");
346           strcpy(tmp,"    ");
347           if (*cmds[i].args)
348           {
349             strcat(outbuff, cmds[i].args);
350             strcat(outbuff,"\n");
351           }
352         }
353         if (strlen(tmp)>50)
354         {
355           strcat(outbuff,tmp);
356           strcat(outbuff,"\n");
357           strcpy(tmp,"    ");
358         }
359       }
360     strcat(outbuff,tmp);
361   }
362   return 0;
363  }
364  
365  
366 /************************************** 
367  * The shell
368  */
369  
370 void shell()
371 {
372   int rc=0;
373   while (rc!=-99)
374   {
375     char buf[MAX_ARG_LEN];
376     char outbuff[MAX_OUT_BUFF];
377 #if HAVE_READLINE_READLINE_H
378     char* line_in;
379           line_in=readline(PROMPT);
380           if (!line_in)
381             break;
382 #if HAVE_READLINE_HISTORY_H
383           if (*line_in)
384             add_history(line_in);
385 #endif
386           if(strlen(line_in) > MAX_ARG_LEN-1) {
387             fprintf(stderr,"Input line too long\n");
388             break;
389           };
390           strcpy(buf,line_in);
391           free (line_in);
392 #else    
393           printf (PROMPT); 
394           fflush (stdout);
395           if (!fgets (buf, MAX_ARG_LEN-1, stdin))
396             break;
397 #endif 
398     outbuff[0]='\0';
399     rc=onecommand(buf, outbuff);
400         printf("%s\n", outbuff);
401   }
402
403  }
404  
405  
406 /**************************************
407  * Main 
408  */
409  
410 int main (int argc, char ** args)
411 {
412   shell();
413   return 0;
414 } /* main */