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