]> andersk Git - moira.git/blame - clients/mrtest/mrtest.c
second code style cleanup: void/void * usage, proper #includes. try to
[moira.git] / clients / mrtest / mrtest.c
CommitLineData
7ac48069 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>
20#include <unistd.h>
f281aa29 21
22#ifdef USE_READLINE
23#include "readline.h"
7ac48069 24#include "history.h"
f281aa29 25#endif
6e6374cb 26
7ac48069 27RCSID("$Header$");
28
fcb0b7fa 29int recursion = 0, interactive;
59af7b90 30extern int sending_version_no;
5eaef520 31int count, quit = 0, cancel = 0;
1a5c774c 32char *whoami;
74c84b52 33sigjmp_buf jb;
1a5c774c 34
35#define MAXARGS 20
6e6374cb 36
7ac48069 37void discard_input(void);
38char *mr_gets(char *prompt, char *buf, size_t len);
39void execute_line(char *cmdbuf);
40int parse(char *buf, char *argv[MAXARGS]);
41int print_reply(int argc, char **argv, void *hint);
42void test_noop(void);
43void test_connect(int argc, char **argv);
44void test_disconnect(void);
45void test_host(void);
46void test_new(void);
47void test_old(void);
48void test_motd(void);
49void test_query(int argc, char **argv);
50void test_auth(void);
51void test_access(int argc, char **argv);
52void test_dcm(void);
53void test_script(int argc, char **argv);
54void test_list_requests(void);
f281aa29 55
5eaef520 56int main(int argc, char **argv)
57{
58 char cmdbuf[BUFSIZ];
59 struct sigaction action;
6e6374cb 60
5eaef520 61 whoami = argv[0];
62 interactive = (isatty(0) && isatty(1));
3442308f 63
5eaef520 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);
74c84b52 70#endif
f281aa29 71
5eaef520 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);
1a5c774c 86}
87
5eaef520 88void discard_input(void)
f281aa29 89{
90 putc('\n', stdout);
fcb0b7fa 91
92 /* if we're inside a script, we have to clean up file descriptors,
93 so don't jump out yet */
5eaef520 94 if (recursion)
95 cancel = 1;
96 else
fcb0b7fa 97 siglongjmp(jb, 1);
f281aa29 98}
99
5eaef520 100char *mr_gets(char *prompt, char *buf, size_t len)
f281aa29 101{
102 char *in;
103#ifdef USE_READLINE
5eaef520 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;
f281aa29 117 }
f281aa29 118#endif
119 printf("%s", prompt);
120 fflush(stdout);
5eaef520 121 in = fgets(buf, len, stdin);
122 if (!in)
123 return in;
124 if (strchr(buf, '\n'))
125 *(strchr(buf, '\n')) = '\0';
f281aa29 126 return buf;
127}
128
7ac48069 129void execute_line(char *cmdbuf)
1a5c774c 130{
131 int argc;
132 char *argv[MAXARGS];
133
5eaef520 134 argc = parse(cmdbuf, argv);
135 if (argc == 0)
136 return;
137 if (!strcmp(argv[0], "noop"))
1a5c774c 138 test_noop();
5eaef520 139 else if (!strcmp(argv[0], "connect") || !strcmp(argv[0], "c"))
1a5c774c 140 test_connect(argc, argv);
5eaef520 141 else if (!strcmp(argv[0], "disconnect") || !strcmp(argv[0], "d"))
1a5c774c 142 test_disconnect();
5eaef520 143 else if (!strcmp(argv[0], "host"))
1a5c774c 144 test_host();
5eaef520 145 else if (!strcmp(argv[0], "new") || !strcmp(argv[0], "2"))
1a5c774c 146 test_new();
5eaef520 147 else if (!strcmp(argv[0], "old") || !strcmp(argv[0], "1"))
1a5c774c 148 test_old();
5eaef520 149 else if (!strcmp(argv[0], "motd"))
1a5c774c 150 test_motd();
5eaef520 151 else if (!strcmp(argv[0], "query") || !strcmp(argv[0], "qy"))
1a5c774c 152 test_query(argc, argv);
5eaef520 153 else if (!strcmp(argv[0], "auth") || !strcmp(argv[0], "a"))
7ac48069 154 test_auth();
5eaef520 155 else if (!strcmp(argv[0], "access"))
1a5c774c 156 test_access(argc, argv);
5eaef520 157 else if (!strcmp(argv[0], "dcm"))
1a5c774c 158 test_dcm();
5eaef520 159 else if (!strcmp(argv[0], "script") || !strcmp(argv[0], "s"))
1a5c774c 160 test_script(argc, argv);
5eaef520 161 else if (!strcmp(argv[0], "list_requests") ||
162 !strcmp(argv[0], "lr") || !strcmp(argv[0], "?"))
1a5c774c 163 test_list_requests();
5eaef520 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 }
1a5c774c 171}
172
5eaef520 173int parse(char *buf, char *argv[MAXARGS])
1a5c774c 174{
175 char *p;
176 int argc, num;
5eaef520 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 }
2c031a2a 221 }
5eaef520 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--;
6e6374cb 229 }
1a5c774c 230 }
5eaef520 231 if (*p == '\n')
232 *p = '\0';
233 return argc + 1;
6e6374cb 234}
235
7ac48069 236void test_noop(void)
6e6374cb 237{
5eaef520 238 int status = mr_noop();
239 if (status)
240 com_err("moira (noop)", status, "");
6e6374cb 241}
242
7ac48069 243void test_new(void)
59af7b90 244{
5eaef520 245 sending_version_no = MR_VERSION_2;
59af7b90 246}
247
7ac48069 248void test_old(void)
59af7b90 249{
5eaef520 250 sending_version_no = MR_VERSION_1;
59af7b90 251}
252
7ac48069 253void test_connect(int argc, char *argv[])
6e6374cb 254{
5eaef520 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, "");
6e6374cb 263}
264
7ac48069 265void test_disconnect(void)
6e6374cb 266{
5eaef520 267 int status = mr_disconnect();
268 if (status)
269 com_err("moira (disconnect)", status, "");
6e6374cb 270}
271
7ac48069 272void test_host(void)
66848930 273{
5eaef520 274 char host[BUFSIZ];
275 int status;
66848930 276
5eaef520 277 memset(host, 0, sizeof(host));
66848930 278
5eaef520 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);
66848930 283}
284
7ac48069 285void test_auth(void)
6e6374cb 286{
5eaef520 287 int status;
59af7b90 288
5eaef520 289 status = mr_auth("mrtest");
290 if (status)
291 com_err("moira (auth)", status, "");
6e6374cb 292}
293
7ac48069 294void test_script(int argc, char *argv[])
58b825a4 295{
5eaef520 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;
58b825a4 304 }
305
5eaef520 306 if (argc < 2)
307 {
308 com_err("moira (script)", 0, "Usage: script input_file [ output_file ]");
309 return;
58b825a4 310 }
311
5eaef520 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;
58b825a4 318 }
319
5eaef520 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);
58b825a4 341 }
342 }
343
5eaef520 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;
6a592314 356 }
5eaef520 357 if (input[0] == '%')
358 {
359 for (cp = &input[1]; *cp && isspace(*cp); cp++)
360 ;
361 printf("Comment: %s\n", cp);
362 continue;
58b825a4 363 }
5eaef520 364 printf("Executing: %s\n", input);
365 execute_line(input);
58b825a4 366 }
367
5eaef520 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);
58b825a4 383 }
384}
385
7ac48069 386int print_reply(int argc, char **argv, void *hint)
6e6374cb 387{
5eaef520 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;
6e6374cb 398}
399
7ac48069 400void test_query(int argc, char **argv)
6e6374cb 401{
5eaef520 402 int status;
403 sigset_t sigs;
fcb0b7fa 404
5eaef520 405 if (argc < 2)
406 {
407 com_err("moira (query)", 0, "Usage: query handle [ args ... ]");
408 return;
409 }
59af7b90 410
5eaef520 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, "");
6e6374cb 422}
423
7ac48069 424void test_access(int argc, char **argv)
6e6374cb 425{
5eaef520 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, "");
6e6374cb 435}
fc3ac28e 436
7ac48069 437void test_dcm()
fc3ac28e 438{
5eaef520 439 int status;
fc3ac28e 440
5eaef520 441 if ((status = mr_do_update()))
442 com_err("moira (dcm)", status, " while triggering dcm");
fc3ac28e 443}
093b57b1 444
7ac48069 445void test_motd()
093b57b1 446{
5eaef520 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");
093b57b1 456}
1a5c774c 457
7ac48069 458void test_list_requests(void)
1a5c774c 459{
5eaef520 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");
1a5c774c 476}
This page took 0.154769 seconds and 5 git commands to generate.