]> andersk Git - moira.git/blob - clients/mrtest/mrtest.c
fix RCS Id strings
[moira.git] / clients / mrtest / mrtest.c
1 /* $Id $
2  *
3  * Bare-bones Moira client
4  *
5  * Copyright (C) 1987-1998 by the Massachusetts Institute of Technology
6  * For copying and distribution information, please see the file
7  * <mit-copyright.h>.
8  */
9
10 #include <mit-copyright.h>
11 #include <moira.h>
12
13 #include <errno.h>
14 #include <fcntl.h>
15 #include <setjmp.h>
16 #include <signal.h>
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <unistd.h>
21
22 #ifdef USE_READLINE
23 #include "readline.h"
24 #include "history.h"
25 #endif
26
27 RCSID("$Header$");
28
29 int recursion = 0, interactive;
30 extern int sending_version_no;
31 int count, quit = 0, cancel = 0;
32 char *whoami;
33 sigjmp_buf jb;
34
35 #define MAXARGS 20
36
37 void discard_input(void);
38 char *mr_gets(char *prompt, char *buf, size_t len);
39 void execute_line(char *cmdbuf);
40 int parse(char *buf, char *argv[MAXARGS]);
41 int print_reply(int argc, char **argv, void *hint);
42 void test_noop(void);
43 void test_connect(int argc, char **argv);
44 void test_disconnect(void);
45 void test_host(void);
46 void test_new(void);
47 void test_old(void);
48 void test_motd(void);
49 void test_query(int argc, char **argv);
50 void test_auth(void);
51 void test_access(int argc, char **argv);
52 void test_dcm(void);
53 void test_script(int argc, char **argv);
54 void test_list_requests(void);
55
56 int main(int argc, char **argv)
57 {
58   char cmdbuf[BUFSIZ];
59   struct sigaction action;
60
61   whoami = argv[0];
62   interactive = (isatty(0) && isatty(1));
63
64   initialize_sms_error_table();
65   initialize_krb_error_table();
66
67 #ifdef USE_READLINE
68   /* we don't want filename completion */
69   rl_bind_key('\t', rl_insert);
70 #endif
71
72   action.sa_handler = discard_input;
73   action.sa_flags = 0;
74   sigemptyset(&action.sa_mask);
75   sigaction(SIGINT, &action, NULL);
76   sigsetjmp(jb, 1);
77
78   while (!quit)
79     {
80       if (!mr_gets("moira:  ", cmdbuf, BUFSIZ))
81         break;
82       execute_line(cmdbuf);
83     }
84   mr_disconnect();
85   exit(0);
86 }
87
88 void discard_input(void)
89 {
90   putc('\n', stdout);
91
92   /* if we're inside a script, we have to clean up file descriptors,
93      so don't jump out yet */
94   if (recursion)
95     cancel = 1;
96   else
97     siglongjmp(jb, 1);
98 }
99
100 char *mr_gets(char *prompt, char *buf, size_t len)
101 {
102   char *in;
103 #ifdef USE_READLINE
104   if (interactive)
105     {
106       in = readline(prompt);
107
108       if (!in)
109         return NULL;
110       if (*in)
111         add_history(in);
112       strncpy(buf, in, len - 1);
113       buf[len] = 0;
114       free(in);
115
116       return buf;
117     }
118 #endif
119   printf("%s", prompt);
120   fflush(stdout);
121   in = fgets(buf, len, stdin);
122   if (!in)
123     return in;
124   if (strchr(buf, '\n'))
125     *(strchr(buf, '\n')) = '\0';
126   return buf;
127 }
128
129 void execute_line(char *cmdbuf)
130 {
131   int argc;
132   char *argv[MAXARGS];
133
134   argc = parse(cmdbuf, argv);
135   if (argc == 0)
136     return;
137   if (!strcmp(argv[0], "noop"))
138     test_noop();
139   else if (!strcmp(argv[0], "connect") || !strcmp(argv[0], "c"))
140     test_connect(argc, argv);
141   else if (!strcmp(argv[0], "disconnect") || !strcmp(argv[0], "d"))
142     test_disconnect();
143   else if (!strcmp(argv[0], "host"))
144     test_host();
145   else if (!strcmp(argv[0], "new") || !strcmp(argv[0], "2"))
146     test_new();
147   else if (!strcmp(argv[0], "old") || !strcmp(argv[0], "1"))
148     test_old();
149   else if (!strcmp(argv[0], "motd"))
150     test_motd();
151   else if (!strcmp(argv[0], "query") || !strcmp(argv[0], "qy"))
152     test_query(argc, argv);
153   else if (!strcmp(argv[0], "auth") || !strcmp(argv[0], "a"))
154     test_auth();
155   else if (!strcmp(argv[0], "access"))
156     test_access(argc, argv);
157   else if (!strcmp(argv[0], "dcm"))
158     test_dcm();
159   else if (!strcmp(argv[0], "script") || !strcmp(argv[0], "s"))
160     test_script(argc, argv);
161   else if (!strcmp(argv[0], "list_requests") ||
162           !strcmp(argv[0], "lr") || !strcmp(argv[0], "?"))
163     test_list_requests();
164   else if (!strcmp(argv[0], "quit") || !strcmp(argv[0], "Q"))
165     quit = 1;
166   else
167     {
168       fprintf(stderr, "moira: Unknown request \"%s\".  "
169               "Type \"?\" for a request list.\n", argv[0]);
170     }
171 }
172
173 int parse(char *buf, char *argv[MAXARGS])
174 {
175   char *p;
176   int argc, num;
177
178   if (!*buf)
179     return 0;
180
181   for (p = buf, argc = 0, argv[0] = buf; *p && *p != '\n'; p++)
182     {
183       if (*p == '"')
184         {
185           char *d = p++;
186           /* skip to close-quote, copying back over open-quote */
187           while (*p != '"')
188             {
189               if (!*p || *p == '\n')
190                 {
191                   fprintf(stderr,
192                           "moira: Unbalanced quotes in command line\n");
193                   return 0;
194                 }
195               /* deal with \### or \\ */
196               if (*p == '\\')
197                 {
198                   if (*++p != '"' && (*p < '0' || *p > '9') && (*p != '\\'))
199                     {
200                       fprintf(stderr, "moira: Bad use of \\\n");
201                       return 0;
202                     }
203                   else if (*p >= '0' && *p <= '9')
204                     {
205                       num = (*p - '0') * 64 + (*++p - '0') * 8 + (*++p - '0');
206                       *p = num;
207                     }
208                 }
209               *d++ = *p++;
210             }
211           if (p == d + 1)
212             {
213               *d = '\0';
214               p++;
215             }
216           else
217             {
218               while (p >= d)
219                 *p-- = ' ';
220             }
221         }
222       if (*p == ' ' || *p == '\t')
223         {
224           /* skip whitespace */
225           for (*p++ = '\0'; *p == ' ' || *p == '\t'; p++)
226             ;
227           if (*p && *p != '\n')
228             argv[++argc] = p--;
229         }
230     }
231   if (*p == '\n')
232     *p = '\0';
233   return argc + 1;
234 }
235
236 void test_noop(void)
237 {
238   int status = mr_noop();
239   if (status)
240     com_err("moira (noop)", status, "");
241 }
242
243 void test_new(void)
244 {
245   sending_version_no = MR_VERSION_2;
246 }
247
248 void test_old(void)
249 {
250   sending_version_no = MR_VERSION_1;
251 }
252
253 void test_connect(int argc, char *argv[])
254 {
255   char *server = "";
256   int status;
257
258   if (argc > 1)
259     server = argv[1];
260   status = mr_connect(server);
261   if (status)
262     com_err("moira (connect)", status, "");
263 }
264
265 void test_disconnect(void)
266 {
267   int status = mr_disconnect();
268   if (status)
269     com_err("moira (disconnect)", status, "");
270 }
271
272 void test_host(void)
273 {
274   char host[BUFSIZ];
275   int status;
276
277   memset(host, 0, sizeof(host));
278
279   if ((status = mr_host(host, sizeof(host) - 1)))
280     com_err("moira (host)", status, "");
281   else
282     printf("You are connected to host %s\n", host);
283 }
284
285 void test_auth(void)
286 {
287   int status;
288
289   status = mr_auth("mrtest");
290   if (status)
291     com_err("moira (auth)", status, "");
292 }
293
294 void test_script(int argc, char *argv[])
295 {
296   FILE *inp;
297   char input[BUFSIZ], *cp;
298   int status, oldstdout, oldstderr;
299
300   if (recursion > 8)
301     {
302       com_err("moira (script)", 0, "too many levels deep in script files\n");
303       return;
304     }
305
306   if (argc < 2)
307     {
308       com_err("moira (script)", 0, "Usage: script input_file [ output_file ]");
309       return;
310     }
311
312   inp = fopen(argv[1], "r");
313   if (!inp)
314     {
315       sprintf(input, "Cannot open input file %s", argv[1]);
316       com_err("moira (script)", 0, input);
317       return;
318     }
319
320   if (argc == 3)
321     {
322       printf("Redirecting output to %s\n", argv[2]);
323       fflush(stdout);
324       oldstdout = dup(1);
325       close(1);
326       status = open(argv[2], O_CREAT|O_WRONLY|O_APPEND, 0664);
327       if (status != 1)
328         {
329           close(status);
330           dup2(oldstdout, 1);
331           argc = 2;
332           sprintf(input, "Unable to redirect output to %s\n", argv[2]);
333           com_err("moira (script)", errno, input);
334         }
335       else
336         {
337           fflush(stderr);
338           oldstderr = dup(2);
339           close(2);
340           dup2(1, 2);
341         }
342     }
343
344   recursion++;
345
346   while (!cancel)
347     {
348       if (!fgets(input, BUFSIZ, inp))
349         break;
350       if ((cp = strchr(input, '\n')))
351         *cp = '\0';
352       if (input[0] == 0)
353         {
354           printf("\n");
355           continue;
356         }
357       if (input[0] == '%')
358         {
359           for (cp = &input[1]; *cp && isspace(*cp); cp++)
360             ;
361           printf("Comment: %s\n", cp);
362           continue;
363         }
364       printf("Executing: %s\n", input);
365       execute_line(input);
366     }
367
368   recursion--;
369   if (!recursion)
370     cancel = 0;
371
372   fclose(inp);
373   if (argc == 3)
374     {
375       fflush(stdout);
376       close(1);
377       dup2(oldstdout, 1);
378       close(oldstdout);
379       fflush(stderr);
380       close(2);
381       dup2(oldstderr, 2);
382       close(oldstderr);
383     }
384 }
385
386 int print_reply(int argc, char **argv, void *hint)
387 {
388   int i;
389   for (i = 0; i < argc; i++)
390     {
391       if (i != 0)
392         printf(", ");
393       printf("%s", argv[i]);
394     }
395   printf("\n");
396   count++;
397   return MR_CONT;
398 }
399
400 void test_query(int argc, char **argv)
401 {
402   int status;
403   sigset_t sigs;
404
405   if (argc < 2)
406     {
407       com_err("moira (query)", 0, "Usage: query handle [ args ... ]");
408       return;
409     }
410
411   count = 0;
412   /* Don't allow ^C during the query: it will confuse libmoira's
413      internal state. (Yay static variables) */
414   sigemptyset(&sigs);
415   sigaddset(&sigs, SIGINT);
416   sigprocmask(SIG_BLOCK, &sigs, NULL);
417   status = mr_query(argv[1], argc - 2, argv + 2, print_reply, NULL);
418   sigprocmask(SIG_UNBLOCK, &sigs, NULL);
419   printf("%d tuple%s\n", count, ((count == 1) ? "" : "s"));
420   if (status)
421     com_err("moira (query)", status, "");
422 }
423
424 void test_access(int argc, char **argv)
425 {
426   int status;
427   if (argc < 2)
428     {
429       com_err("moira (access)", 0, "Usage: access handle [ args ... ]");
430       return;
431     }
432   status = mr_access(argv[1], argc - 2, argv + 2);
433   if (status)
434     com_err("moira (access)", status, "");
435 }
436
437 void test_dcm()
438 {
439   int status;
440
441   if ((status = mr_do_update()))
442     com_err("moira (dcm)", status, " while triggering dcm");
443 }
444
445 void test_motd()
446 {
447   int status;
448   char *motd;
449
450   if ((status = mr_motd(&motd)))
451     com_err("moira (motd)", status, " while getting motd");
452   if (motd)
453     printf("%s\n", motd);
454   else
455     printf("No message of the day.\n");
456 }
457
458 void test_list_requests(void)
459 {
460   printf("Available moira requests:\n");
461   printf("\n");
462   printf("noop\t\t\tAsk Moira to do nothing\n");
463   printf("connect, c\t\tConnect to Moira server\n");
464   printf("disconnect, d\t\tDisconnect from server\n");
465   printf("host\t\t\tIdentify the server host\n");
466   printf("new, 2\t\t\tUse new protocol\n");
467   printf("old, 1\t\t\tUse old protocol\n");
468   printf("motd, m\t\t\tGet the Message of the Day\n");
469   printf("query, qy\t\tMake a query.\n");
470   printf("auth, a\t\t\tAuthenticate to Moira.\n");
471   printf("access\t\t\tCheck access to a Moira query.\n");
472   printf("dcm\t\t\tTrigger the DCM\n");
473   printf("script, s\t\tRead commands from a script.\n");
474   printf("list_requests, lr, ?\tList available commands.\n");
475   printf("quit, Q\t\t\tLeave the subsystem.\n");
476 }
This page took 0.096509 seconds and 5 git commands to generate.