]> andersk Git - moira.git/blame - clients/mrtest/mrtest.c
Allow spaces in container names.
[moira.git] / clients / mrtest / mrtest.c
CommitLineData
c441a31a 1/* $Id$
6e6374cb 2 *
7ac48069 3 * Bare-bones Moira client
6e6374cb 4 *
7ac48069 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>.
6e6374cb 8 */
9
c801de4c 10#include <mit-copyright.h>
8defc06b 11#include <moira.h>
7ac48069 12
13#include <errno.h>
14#include <fcntl.h>
f281aa29 15#include <setjmp.h>
16#include <signal.h>
7ac48069 17#include <stdio.h>
18#include <stdlib.h>
19#include <string.h>
533bacb3 20#ifdef HAVE_UNISTD_H
7ac48069 21#include <unistd.h>
533bacb3 22#endif
23
24#ifdef HAVE_GETOPT_H
25#include <getopt.h>
26#endif
27
28#ifdef _WIN32
29#include <windows.h>
30#include <io.h>
31#define dup _dup
32#define dup2 _dup2
33#define isatty _isatty
34#define close _close
35#define open _open
36#define sigjmp_buf jmp_buf
37#define siglongjmp longjmp
38#define sigsetjmp(env, save) setjmp(env)
39#endif /* _WIN32 */
f281aa29 40
ea0caf4a 41#ifdef HAVE_READLINE
c5c5a18d 42#include "readline/readline.h"
43#include "readline/history.h"
f281aa29 44#endif
6e6374cb 45
7ac48069 46RCSID("$Header$");
47
71da1922 48int recursion = 0, quote_output = 0, interactive;
5eaef520 49int count, quit = 0, cancel = 0;
1a5c774c 50char *whoami;
533bacb3 51
74c84b52 52sigjmp_buf jb;
1a5c774c 53
54#define MAXARGS 20
6e6374cb 55
533bacb3 56void discard_input(int sig);
7ac48069 57char *mr_gets(char *prompt, char *buf, size_t len);
58void execute_line(char *cmdbuf);
59int parse(char *buf, char *argv[MAXARGS]);
8c9b31a9 60int print_reply(int argc, char **argv, void *help);
7ac48069 61void test_noop(void);
62void test_connect(int argc, char **argv);
63void test_disconnect(void);
64void test_host(void);
7ac48069 65void test_motd(void);
66void test_query(int argc, char **argv);
67void test_auth(void);
e7138c1c 68void test_proxy(int argc, char **argv);
7ac48069 69void test_access(int argc, char **argv);
70void test_dcm(void);
71void test_script(int argc, char **argv);
72void test_list_requests(void);
acde26f0 73void test_version(int argc, char **argv);
533bacb3 74void set_signal_handler(int, void (*handler)(int));
75void set_signal_blocking(int, int);
f281aa29 76
5eaef520 77int main(int argc, char **argv)
78{
79 char cmdbuf[BUFSIZ];
71da1922 80 int c;
6e6374cb 81
5eaef520 82 whoami = argv[0];
83 interactive = (isatty(0) && isatty(1));
3442308f 84
71da1922 85 while ((c = getopt(argc, argv, "q")) != -1)
86 {
87 switch (c)
88 {
89 case 'q':
90 quote_output = 1;
91 break;
92
93 default:
94 fprintf(stderr, "Usage: mrtest [-q]\n");
95 exit (1);
96 }
97 }
98
5eaef520 99 initialize_sms_error_table();
100 initialize_krb_error_table();
101
ea0caf4a 102#ifdef HAVE_READLINE
5eaef520 103 /* we don't want filename completion */
104 rl_bind_key('\t', rl_insert);
74c84b52 105#endif
f281aa29 106
533bacb3 107 set_signal_handler(SIGINT, discard_input);
5eaef520 108 sigsetjmp(jb, 1);
109
110 while (!quit)
111 {
112 if (!mr_gets("moira: ", cmdbuf, BUFSIZ))
113 break;
114 execute_line(cmdbuf);
115 }
116 mr_disconnect();
117 exit(0);
1a5c774c 118}
119
533bacb3 120void discard_input(int sig)
f281aa29 121{
122 putc('\n', stdout);
fcb0b7fa 123
124 /* if we're inside a script, we have to clean up file descriptors,
125 so don't jump out yet */
5eaef520 126 if (recursion)
127 cancel = 1;
128 else
fcb0b7fa 129 siglongjmp(jb, 1);
f281aa29 130}
131
5eaef520 132char *mr_gets(char *prompt, char *buf, size_t len)
f281aa29 133{
134 char *in;
ea0caf4a 135#ifdef HAVE_READLINE
5eaef520 136 if (interactive)
137 {
138 in = readline(prompt);
139
140 if (!in)
141 return NULL;
142 if (*in)
143 add_history(in);
144 strncpy(buf, in, len - 1);
145 buf[len] = 0;
146 free(in);
147
148 return buf;
f281aa29 149 }
f281aa29 150#endif
151 printf("%s", prompt);
152 fflush(stdout);
5eaef520 153 in = fgets(buf, len, stdin);
154 if (!in)
155 return in;
156 if (strchr(buf, '\n'))
157 *(strchr(buf, '\n')) = '\0';
f281aa29 158 return buf;
159}
160
7ac48069 161void execute_line(char *cmdbuf)
1a5c774c 162{
163 int argc;
164 char *argv[MAXARGS];
165
5eaef520 166 argc = parse(cmdbuf, argv);
167 if (argc == 0)
168 return;
169 if (!strcmp(argv[0], "noop"))
1a5c774c 170 test_noop();
5eaef520 171 else if (!strcmp(argv[0], "connect") || !strcmp(argv[0], "c"))
1a5c774c 172 test_connect(argc, argv);
5eaef520 173 else if (!strcmp(argv[0], "disconnect") || !strcmp(argv[0], "d"))
1a5c774c 174 test_disconnect();
5eaef520 175 else if (!strcmp(argv[0], "host"))
1a5c774c 176 test_host();
059d3dc2 177 else if (!strcmp(argv[0], "motd") || !strcmp(argv[0], "m"))
1a5c774c 178 test_motd();
5eaef520 179 else if (!strcmp(argv[0], "query") || !strcmp(argv[0], "qy"))
1a5c774c 180 test_query(argc, argv);
5eaef520 181 else if (!strcmp(argv[0], "auth") || !strcmp(argv[0], "a"))
7ac48069 182 test_auth();
e7138c1c 183 else if (!strcmp(argv[0], "proxy") || !strcmp(argv[0], "p"))
184 test_proxy(argc, argv);
5eaef520 185 else if (!strcmp(argv[0], "access"))
1a5c774c 186 test_access(argc, argv);
5eaef520 187 else if (!strcmp(argv[0], "dcm"))
1a5c774c 188 test_dcm();
5eaef520 189 else if (!strcmp(argv[0], "script") || !strcmp(argv[0], "s"))
1a5c774c 190 test_script(argc, argv);
5eaef520 191 else if (!strcmp(argv[0], "list_requests") ||
192 !strcmp(argv[0], "lr") || !strcmp(argv[0], "?"))
1a5c774c 193 test_list_requests();
5eaef520 194 else if (!strcmp(argv[0], "quit") || !strcmp(argv[0], "Q"))
195 quit = 1;
acde26f0 196 else if (!strcmp(argv[0], "version") || !strcmp(argv[0], "v"))
197 test_version(argc, argv);
5eaef520 198 else
199 {
200 fprintf(stderr, "moira: Unknown request \"%s\". "
201 "Type \"?\" for a request list.\n", argv[0]);
202 }
1a5c774c 203}
204
5eaef520 205int parse(char *buf, char *argv[MAXARGS])
1a5c774c 206{
207 char *p;
208 int argc, num;
5eaef520 209
210 if (!*buf)
211 return 0;
212
213 for (p = buf, argc = 0, argv[0] = buf; *p && *p != '\n'; p++)
214 {
215 if (*p == '"')
216 {
217 char *d = p++;
218 /* skip to close-quote, copying back over open-quote */
219 while (*p != '"')
220 {
221 if (!*p || *p == '\n')
222 {
223 fprintf(stderr,
224 "moira: Unbalanced quotes in command line\n");
225 return 0;
226 }
227 /* deal with \### or \\ */
228 if (*p == '\\')
229 {
230 if (*++p != '"' && (*p < '0' || *p > '9') && (*p != '\\'))
231 {
232 fprintf(stderr, "moira: Bad use of \\\n");
233 return 0;
234 }
235 else if (*p >= '0' && *p <= '9')
236 {
237 num = (*p - '0') * 64 + (*++p - '0') * 8 + (*++p - '0');
238 *p = num;
239 }
240 }
241 *d++ = *p++;
242 }
243 if (p == d + 1)
244 {
245 *d = '\0';
246 p++;
247 }
248 else
249 {
250 while (p >= d)
251 *p-- = ' ';
252 }
2c031a2a 253 }
5eaef520 254 if (*p == ' ' || *p == '\t')
255 {
256 /* skip whitespace */
257 for (*p++ = '\0'; *p == ' ' || *p == '\t'; p++)
258 ;
259 if (*p && *p != '\n')
260 argv[++argc] = p--;
6e6374cb 261 }
1a5c774c 262 }
5eaef520 263 if (*p == '\n')
264 *p = '\0';
265 return argc + 1;
6e6374cb 266}
267
7ac48069 268void test_noop(void)
6e6374cb 269{
5eaef520 270 int status = mr_noop();
271 if (status)
272 com_err("moira (noop)", status, "");
6e6374cb 273}
274
7ac48069 275void test_connect(int argc, char *argv[])
6e6374cb 276{
5eaef520 277 char *server = "";
278 int status;
279
280 if (argc > 1)
281 server = argv[1];
282 status = mr_connect(server);
283 if (status)
284 com_err("moira (connect)", status, "");
acde26f0 285 mr_version(-1);
6e6374cb 286}
287
7ac48069 288void test_disconnect(void)
6e6374cb 289{
5eaef520 290 int status = mr_disconnect();
291 if (status)
292 com_err("moira (disconnect)", status, "");
6e6374cb 293}
294
7ac48069 295void test_host(void)
66848930 296{
5eaef520 297 char host[BUFSIZ];
298 int status;
66848930 299
5eaef520 300 memset(host, 0, sizeof(host));
66848930 301
5eaef520 302 if ((status = mr_host(host, sizeof(host) - 1)))
303 com_err("moira (host)", status, "");
304 else
305 printf("You are connected to host %s\n", host);
66848930 306}
307
7ac48069 308void test_auth(void)
6e6374cb 309{
5eaef520 310 int status;
59af7b90 311
5eaef520 312 status = mr_auth("mrtest");
313 if (status)
314 com_err("moira (auth)", status, "");
6e6374cb 315}
316
e7138c1c 317void test_proxy(int argc, char *argv[])
318{
319 int status;
320
321 if (argc != 3)
322 {
323 com_err("moira (proxy)", 0, "Usage: proxy principal authtype");
324 return;
325 }
326 status = mr_proxy(argv[1], argv[2]);
327 if (status)
328 com_err("moira (proxy)", status, "");
329}
330
7ac48069 331void test_script(int argc, char *argv[])
58b825a4 332{
5eaef520 333 FILE *inp;
334 char input[BUFSIZ], *cp;
335 int status, oldstdout, oldstderr;
336
337 if (recursion > 8)
338 {
339 com_err("moira (script)", 0, "too many levels deep in script files\n");
340 return;
58b825a4 341 }
342
5eaef520 343 if (argc < 2)
344 {
345 com_err("moira (script)", 0, "Usage: script input_file [ output_file ]");
346 return;
58b825a4 347 }
348
5eaef520 349 inp = fopen(argv[1], "r");
350 if (!inp)
351 {
352 sprintf(input, "Cannot open input file %s", argv[1]);
353 com_err("moira (script)", 0, input);
354 return;
58b825a4 355 }
356
5eaef520 357 if (argc == 3)
358 {
359 printf("Redirecting output to %s\n", argv[2]);
360 fflush(stdout);
361 oldstdout = dup(1);
362 close(1);
363 status = open(argv[2], O_CREAT|O_WRONLY|O_APPEND, 0664);
364 if (status != 1)
365 {
366 close(status);
367 dup2(oldstdout, 1);
368 argc = 2;
369 sprintf(input, "Unable to redirect output to %s\n", argv[2]);
370 com_err("moira (script)", errno, input);
371 }
372 else
373 {
374 fflush(stderr);
375 oldstderr = dup(2);
376 close(2);
377 dup2(1, 2);
58b825a4 378 }
379 }
380
5eaef520 381 recursion++;
382
383 while (!cancel)
384 {
385 if (!fgets(input, BUFSIZ, inp))
386 break;
387 if ((cp = strchr(input, '\n')))
388 *cp = '\0';
389 if (input[0] == 0)
390 {
391 printf("\n");
392 continue;
6a592314 393 }
5eaef520 394 if (input[0] == '%')
395 {
396 for (cp = &input[1]; *cp && isspace(*cp); cp++)
397 ;
398 printf("Comment: %s\n", cp);
399 continue;
58b825a4 400 }
5eaef520 401 printf("Executing: %s\n", input);
402 execute_line(input);
58b825a4 403 }
404
5eaef520 405 recursion--;
406 if (!recursion)
407 cancel = 0;
408
409 fclose(inp);
410 if (argc == 3)
411 {
412 fflush(stdout);
413 close(1);
414 dup2(oldstdout, 1);
415 close(oldstdout);
416 fflush(stderr);
417 close(2);
418 dup2(oldstderr, 2);
419 close(oldstderr);
58b825a4 420 }
421}
422
8c9b31a9 423int print_reply(int argc, char **argv, void *help)
6e6374cb 424{
5eaef520 425 int i;
426 for (i = 0; i < argc; i++)
427 {
428 if (i != 0)
429 printf(", ");
8c9b31a9 430 if (quote_output && !*(int *)help)
71da1922 431 {
432 unsigned char *p;
433
434 for (p = (unsigned char *)argv[i]; *p; p++)
435 {
436 if (isprint(*p) && *p != '\\' && *p != ',')
437 putc(*p, stdout);
438 else
439 printf("\\%03o", *p);
440 }
441 }
442 else
443 printf("%s", argv[i]);
5eaef520 444 }
445 printf("\n");
446 count++;
447 return MR_CONT;
6e6374cb 448}
449
7ac48069 450void test_query(int argc, char **argv)
6e6374cb 451{
6fedb0a4 452 int status, help;
fcb0b7fa 453
5eaef520 454 if (argc < 2)
455 {
456 com_err("moira (query)", 0, "Usage: query handle [ args ... ]");
457 return;
458 }
6fedb0a4 459 help = !strcmp(argv[1], "_help");
59af7b90 460
5eaef520 461 count = 0;
462 /* Don't allow ^C during the query: it will confuse libmoira's
463 internal state. (Yay static variables) */
533bacb3 464 set_signal_blocking(SIGINT, 1);
8c9b31a9 465 status = mr_query(argv[1], argc - 2, argv + 2, print_reply, &help);
533bacb3 466 set_signal_blocking(SIGINT, 0);
5eaef520 467 printf("%d tuple%s\n", count, ((count == 1) ? "" : "s"));
468 if (status)
469 com_err("moira (query)", status, "");
6e6374cb 470}
471
7ac48069 472void test_access(int argc, char **argv)
6e6374cb 473{
5eaef520 474 int status;
475 if (argc < 2)
476 {
477 com_err("moira (access)", 0, "Usage: access handle [ args ... ]");
478 return;
479 }
480 status = mr_access(argv[1], argc - 2, argv + 2);
481 if (status)
482 com_err("moira (access)", status, "");
6e6374cb 483}
fc3ac28e 484
7ac48069 485void test_dcm()
fc3ac28e 486{
5eaef520 487 int status;
fc3ac28e 488
5eaef520 489 if ((status = mr_do_update()))
490 com_err("moira (dcm)", status, " while triggering dcm");
fc3ac28e 491}
093b57b1 492
7ac48069 493void test_motd()
093b57b1 494{
5eaef520 495 int status;
496 char *motd;
497
498 if ((status = mr_motd(&motd)))
499 com_err("moira (motd)", status, " while getting motd");
500 if (motd)
501 printf("%s\n", motd);
502 else
503 printf("No message of the day.\n");
093b57b1 504}
1a5c774c 505
7ac48069 506void test_list_requests(void)
1a5c774c 507{
5eaef520 508 printf("Available moira requests:\n");
509 printf("\n");
510 printf("noop\t\t\tAsk Moira to do nothing\n");
511 printf("connect, c\t\tConnect to Moira server\n");
512 printf("disconnect, d\t\tDisconnect from server\n");
513 printf("host\t\t\tIdentify the server host\n");
5eaef520 514 printf("motd, m\t\t\tGet the Message of the Day\n");
515 printf("query, qy\t\tMake a query.\n");
516 printf("auth, a\t\t\tAuthenticate to Moira.\n");
e7138c1c 517 printf("proxy, p\t\tProxy authenticate to Moira.\n");
5eaef520 518 printf("access\t\t\tCheck access to a Moira query.\n");
519 printf("dcm\t\t\tTrigger the DCM\n");
520 printf("script, s\t\tRead commands from a script.\n");
521 printf("list_requests, lr, ?\tList available commands.\n");
522 printf("quit, Q\t\t\tLeave the subsystem.\n");
1a5c774c 523}
acde26f0 524
525void test_version(int argc, char **argv)
526{
527 int status;
528
529 if (argc != 2)
530 {
531 com_err("moira (version)", 0, "Usage: version versionnumber");
532 return;
533 }
534 status = mr_version(atoi(argv[1]));
535 if (status)
536 com_err("moira (version)", status, "");
537}
533bacb3 538
539#ifdef HAVE_POSIX_SIGNALS
540
541void set_signal_handler(int sig, void (*handler)(int))
542{
543 struct sigaction action;
544
545 sigemptyset(&action.sa_mask);
546 action.sa_flags = 0;
547 action.sa_handler = handler;
548 sigaction(sig, &action, NULL);
549}
550
551void set_signal_blocking(int sig, int block)
552{
553 sigset_t sigs;
554 sigemptyset(&sigs);
555 sigaddset(&sigs, sig);
556 sigprocmask(block ? SIG_BLOCK : SIG_UNBLOCK, &sigs, NULL);
557}
558
559#else
560
561void set_signal_handler(int sig, void (*handler)(int))
562{
563 signal(sig, handler);
564}
565
566#ifdef _WIN32
567BOOL WINAPI blocking_handler(DWORD dwCtrlType)
568{
569 return(TRUE);
570}
571
572void set_signal_blocking(int sig, int block)
573{
574 SetConsoleCtrlHandler(blocking_handler, block ? TRUE : FALSE);
575}
576#endif /* _WIN32 */
577
578#endif /* HAVE_POSIX_SIGNALS */
This page took 0.235073 seconds and 5 git commands to generate.