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