1 /*
2 * Copyright (C) 1993 Andrew Scherpbier (Andrew@sdsu.edu)
3 *
4 * This file is part of xpmtp.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include <sys/types.h>
22 #include <sys/stat.h>
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include "xpmtp.h"
27
28 typedef struct
29 {
30 char *name;
31 int min_args;
32 int max_args;
33 #ifdef __STDC__
34 void (*func)(int argc, char **argv);
35 #else
36 void (*func)();
37 #endif
38 char *shorthelp;
39 char *longhelp;
40 } COMMAND;
41
42 #ifdef __STDC__
43 void command_help(int argc, char **argv);
44 void command_send(int argc, char **argv);
45 void command_quit(int argc, char **argv);
46 void command_put(int argc, char **argv);
47 void command_get(int argc, char **argv);
48 void command_geti(int argc, char **argv);
49 void command_unknown(int argc, char **argv);
50 void command_wildmap(int argc, char **argv);
51 void argv_to_command(char **argv);
52 int connected();
53 void done(int exit_value);
54 void usage();
55 #else
56 void command_help(/* int argc, char **argv */);
57 void command_send(/* int argc, char **argv */);
58 void command_quit(/* int argc, char **argv */);
59 void command_put(/* int argc, char **argv */);
60 void command_get(/* int argc, char **argv */);
61 void command_geti(/* int argc, char **argv */);
62 void command_unknown(/* int argc, char **argv */);
63 void command_wildmap(/* int argc, char **argv */);
64 void argv_to_command(/* char **argv */);
65 int connected();
66 void done(/* int exit_value */);
67 void usage();
68 #endif
69
70 COMMAND commands[] =
71 {
72 "help", 0, XPMTP_MAX_ARGS, command_help, "Display this list of commands. HELP HELP will give more info",
73 "usage: help [command]\n\
74 Without the command argument, the HELP command will list all available commmands\n\
75 with a short description. By specifying the command, you get more detailed help",
76 "quit", 0, 0, command_quit, "Quit the connection with the server",
77 "usage: quit\n\
78 This will close the connection with the map server and quit the client program.",
79 "get", 1, 2, command_get, "Get a map",
80 "usage: get mapname [localmapname]\n\
81 This is used to retrieve a map from the map server. The optional localmapname\n\
82 specifies the name you want the map to have on your system.",
83 "geti", 1, 2, command_geti, "Get a PBM image of a map.",
84 "usage: geti mapname [localpbmfilename]\n\
85 Use this to retrieve a small (64x64) pbm image representation of the specified\n\
86 map. If no localpbmfilename is specified, the mapname is used with the .map\n\
87 substitued with .pbm",
88 "submit", 1, 2, command_put, "Submit a map to the server for others to use",
89 "usage: submit localmapname [remotemapname]\n\
90 Send a map to the map server. The localmapname is the name you use on your\n\
91 system. If you don't specify a remote map name, the local map name will be used.\n\
92 Note that you CANNOT overwrite an existing map. If you feel you need to\n\
93 replace a map, contact the map server maintainer. (See the maintainer command)",
94 "list", 0, 2, command_send, "List the currently available maps.",
95 "usage: list [-l] [mapname]\n\
96 List one or all maps in the archive. If mapname is specified, only that map is\n\
97 listed. If the -l option is specified, more information about each map is\n\
98 returned. The fields in this long list are tab seperated so they are easy to\n\
99 parse with a program.",
100 "display", 1, 3, command_send, "Display image of map in a X window.",
101 "usage: display [-display machine:0.0] mapname\n\
102 Create an X window on the specified display. If no display is explicitly\n\
103 specified the machine you are connecting from will be used.\n\
104 The image displayed is a small (128x128) image representation of the specified\n\
105 map. This gives you a quick overview of what the map looks like. Remember\n\
106 that ALL maps are displayed in the same size. The aspect ratio is preserved,\n\
107 however.",
108 "wildmap", 0, XPMTP_MAX_ARGS, command_wildmap,"Generate a random map using the 'wildmap' program and get it.",
109 "usage: wildmap [-options] [localmapname]\n\
110 This will create a random map using the wildmap command. To get a list of the\n\
111 options to the wildmap program, use the 'wildmap -help' command.\n\
112 If no localmapname is specified, wildmap.map is used.",
113 "maintainer",0, 0, command_send, "Show how to get in touch with the maintainer",
114 "usage: maintainer\n\
115 Show how to get in touch with the map server maintainer.\n\
116 You should contact this person if you are having problems of if you want to\n\
117 update/replace an existing map. (You are not allowed to do that using XPMTP)",
118 };
119
120
121 #define NCOMMANDS (sizeof(commands)/sizeof(COMMAND))
122
123 int xpmtp_fd = -1;
124 char xpmtp_buf[4096];
125 char command[XPMTP_MAX_LINE];
126 char response[XPMTP_MAX_LINE];
127
128 extern int optind;
129 extern char *optarg;
130
131 #ifdef __STDC__
main(int argc,char ** argv)132 main(int argc, char **argv)
133 #else
134 main(argc, argv)
135 int argc;
136 char **argv;
137 #endif
138 {
139 char buf[256];
140 int i;
141 int port = XPMTP_PORT;
142 int c;
143 char *av[XPMTP_MAX_ARGS], *p, *host = NULL;
144 int ac, first;
145
146 while ((c = getopt(argc, argv, "h:p:")) != -1)
147 {
148 switch (c)
149 {
150 case 'h':
151 host = optarg;
152 break;
153 case 'p':
154 port = atoi(optarg);
155 break;
156 case '?':
157 usage();
158 done(0);
159 }
160 }
161
162 if (optind != argc)
163 {
164 usage();
165 done(1);
166 }
167
168 if (host == NULL)
169 {
170 host = xpmtp_default_host();
171 }
172
173 printf("Opening XPMTP connection with %s ...\n", host);
174 xpmtp_fd = xpmtp_open(host, port, response, sizeof(response));
175 if (xpmtp_fd < 0)
176 {
177 xpmtp_perror("open");
178 done(1);
179 }
180 else
181 {
182 printf("Connected to %s port %d.\n", host, port);
183 printf("%s\n", response+1);
184 }
185
186 for (;;)
187 {
188 printf("xpmtp> ");
189 fflush(stdout);
190 if (fgets(buf, sizeof(buf), stdin) == NULL)
191 {
192 command_quit(ac, av);
193 }
194 first = 1;
195 ac = 0;
196 while (p = strtok(first ? buf : NULL, " \t\r\n"))
197 {
198 av[ac++] = p;
199 first = 0;
200 }
201 av[ac] = NULL;
202
203 if (av[0] == NULL)
204 {
205 continue;
206 }
207
208 for (i = 0; i < NCOMMANDS; i++)
209 {
210 if (strcasecmp(commands[i].name, av[0]) == 0)
211 {
212 if (commands[i].min_args >= 0 && ac-1 < commands[i].min_args
213 || commands[i].max_args >= 0 && ac-1 > commands[i].max_args)
214 {
215 printf("wrong number of arguments.\n");
216 }
217 else
218 {
219 (*commands[i].func)(ac, av);
220 }
221 break;
222 }
223 }
224 if (i == NCOMMANDS)
225 {
226 command_unknown(ac, av);
227 }
228 }
229 }
230
231 #ifdef __STDC__
argv_to_command(char ** argv)232 void argv_to_command(char **argv)
233 #else
234 void argv_to_command(argv)
235 char **argv;
236 #endif
237 {
238 command[0] = '\0';
239 for (; *argv; argv++)
240 {
241 strcat(command, *argv);
242 if (*(argv+1))
243 {
244 strcat(command, " ");
245 }
246 }
247 }
248
249 #ifdef __STDC__
command_quit(int argc,char ** argv)250 void command_quit(int argc, char **argv)
251 #else
252 void command_quit(argc, argv)
253 int argc;
254 char **argv;
255 #endif
256 {
257 if (xpmtp_fd != -1)
258 {
259 xpmtp_close(xpmtp_fd);
260 printf("Connection closed.\n");
261 }
262 done(0);
263 }
264
265 #ifdef __STDC__
command_help(int argc,char ** argv)266 void command_help(int argc, char **argv)
267 #else
268 void command_help(argc, argv)
269 int argc;
270 char **argv;
271 #endif
272 {
273 int i;
274 int j;
275 int found;
276
277 if (argc == 1)
278 {
279 /*
280 * Short list
281 */
282 for (i = 0; i < NCOMMANDS; i++)
283 printf("%7s -- %s\n\n", commands[i].name, commands[i].shorthelp);
284 }
285 else
286 {
287 for (j = 1; j < argc; j++)
288 {
289 found = 0;
290 for (i = 0; i < NCOMMANDS; i++)
291 {
292 if (strcmp(commands[i].name, argv[j]) == 0)
293 {
294 printf("%7s -- %s\n", commands[i].name, commands[i].shorthelp);
295 printf("%s\n\n", commands[i].longhelp);
296 found = 1;
297 break;
298 }
299 }
300 if (!found)
301 printf("ERR Sorry, '%s' is not a recognized command\n", argv[j]);
302 }
303 }
304 }
305
306 #ifdef __STDC__
command_put(int argc,char ** argv)307 void command_put(int argc, char **argv)
308 #else
309 void command_put(argc, argv)
310 int argc;
311 char **argv;
312 #endif
313 {
314 FILE *fp;
315 char *filename;
316 char *remotefilename;
317 char buffer[1024];
318 int n;
319 struct stat buf;
320
321 if (argc == 3)
322 remotefilename = argv[2];
323 else
324 remotefilename = argv[1];
325 filename = argv[1];
326
327 /*
328 * Make sure that we aren't kidding about sending a map. We need to first
329 * make sure that it really exists locally.
330 */
331 if (stat(filename, &buf) == -1)
332 {
333 printf("ERR: You are trying to send a file which does not exist!\n");
334 return;
335 }
336 fp = fopen(filename, "r");
337 if (fp == NULL)
338 {
339 printf("ERR: Unable to open %s for reading.\n", filename);
340 return;
341 }
342
343 argv[1] = remotefilename;
344 argv[2] = NULL;
345 argv_to_command(argv);
346
347 switch (xpmtp_command(xpmtp_fd, command, response, sizeof(response)))
348 {
349 case -1:
350 xpmtp_perror(argv[0]);
351 command_quit(argc, argv);
352 return;
353 default:
354 if (*response == '-')
355 {
356 printf("%s\n", response+1);
357 return;
358 }
359 }
360
361 /*
362 * We are now ready to send the map over.
363 * First the size, then the map, just like the server were to send a map to
364 * us.
365 */
366 xpmtp_putline(xpmtp_fd, "#%d", buf.st_size);
367
368 n = 1;
369 while (n > 0)
370 {
371 n = fread(buffer, 1, 1024, fp);
372 if (n == 0)
373 break; /* All done writing */
374 n = xpmtp_write(xpmtp_fd, buffer, n);
375 if (n <= 0)
376 {
377 /*
378 * Some problem arized!
379 */
380 printf("ERR: Hmmm... Problems writing\n");
381 return;
382 }
383 }
384
385 fclose(fp);
386 printf("OK Submitted map '%s'\n", remotefilename);
387 }
388
389 #ifdef __STDC__
command_get(int argc,char ** argv)390 void command_get(int argc, char **argv)
391 #else
392 void command_get(argc, argv)
393 int argc;
394 char **argv;
395 #endif
396 {
397 FILE *fp;
398 char *filename;
399 char *p;
400 int size, n, nread;
401 char cmd[100];
402
403 if (argc == 3)
404 {
405 filename = argv[2];
406 argv[2] = NULL;
407 }
408 else
409 {
410 filename = argv[1];
411 }
412
413 argv_to_command(argv);
414
415 switch (xpmtp_command(xpmtp_fd, command, response, sizeof(response)))
416 {
417 case -1:
418 xpmtp_perror(argv[0]);
419 command_quit(argc, argv);
420 return;
421 default:
422 if (*response == '-')
423 {
424 printf("%s\n", response+1);
425 return;
426 }
427 }
428
429 size = atoi(response + 1);
430
431 fp = fopen(filename, "w");
432 if (fp == NULL)
433 {
434 perror(filename);
435 return;
436 }
437
438 while (size > 0)
439 {
440 n = MIN(sizeof(xpmtp_buf), size);
441 nread = xpmtp_read(xpmtp_fd, xpmtp_buf, n);
442 if (nread != n)
443 {
444 xpmtp_perror("get");
445 break;
446 }
447 fwrite(xpmtp_buf, 1, n, fp);
448 size -= n;
449 }
450
451 fclose(fp);
452 printf("OK Retrieved map:\n");
453 sprintf(cmd, "ls -l %s", filename);
454 system(cmd);
455 }
456
457 #ifdef __STDC__
command_geti(int argc,char ** argv)458 void command_geti(int argc, char **argv)
459 #else
460 void command_geti(argc, argv)
461 int argc;
462 char **argv;
463 #endif
464 {
465 FILE *fp;
466 char *filename;
467 char *p;
468 int size, n, nread;
469 char newname[200];
470 char cmd[100];
471
472 if (argc == 3)
473 {
474 filename = argv[2];
475 argv[2] = NULL;
476 }
477 else
478 {
479 strcpy(newname, argv[1]);
480 p = strrchr(newname, '.');
481 if (p)
482 {
483 *p = '\0';
484 }
485 strcat(newname, ".pbm");
486 filename = newname;
487 }
488
489 argv_to_command(argv);
490
491 printf("Getting image for %s. Image will be stored in %s\n", argv[1], filename);
492
493 switch (xpmtp_command(xpmtp_fd, command, response, sizeof(response)))
494 {
495 case -1:
496 xpmtp_perror(argv[0]);
497 command_quit(argc, argv);
498 return;
499 default:
500 if (*response == '-')
501 {
502 printf("%s\n", response+1);
503 return;
504 }
505 }
506
507 size = atoi(response + 1);
508
509 fp = fopen(filename, "w");
510 if (fp == NULL)
511 {
512 perror(filename);
513 return;
514 }
515
516 while (size > 0)
517 {
518 n = MIN(sizeof(xpmtp_buf), size);
519 nread = xpmtp_read(xpmtp_fd, xpmtp_buf, n);
520 if (nread != n)
521 {
522 xpmtp_perror("get");
523 break;
524 }
525 fwrite(xpmtp_buf, 1, n, fp);
526 size -= n;
527 }
528
529 fclose(fp);
530 printf("OK Retrieved image:\n");
531 sprintf(cmd, "ls -l %s", filename);
532 system(cmd);
533 }
534
535 #ifdef __STDC__
command_send(int argc,char ** argv)536 void command_send(int argc, char **argv)
537 #else
538 void command_send(argc, argv)
539 int argc;
540 char **argv;
541 #endif
542 {
543 char *p;
544
545 argv_to_command(argv);
546
547 switch (xpmtp_command(xpmtp_fd, command, response, sizeof(response)))
548 {
549 case -1:
550 xpmtp_perror(argv[0]);
551 command_quit(argc, argv);
552 return;
553 default:
554 switch (*response)
555 {
556 case '-':
557 case '+':
558 printf("%s\n", response+1);
559 break;
560 case '*':
561 printf("%s\n", response+1);
562 while (xpmtp_getline(xpmtp_fd, response, sizeof(response)) >= 0)
563 {
564 if (*response == '.')
565 break;
566 printf("%s\n", response);
567 }
568 break;
569 default:
570 printf("%s\n", response);
571 /*
572 * There are some errors... List until we find either an +OK or -ERR
573 */
574 while (xpmtp_getline(xpmtp_fd, response, sizeof(response)) >= 0)
575 {
576 if (*response == '-' || *response == '+' || *response)
577 {
578 printf("%s\n", response+1);
579 return;
580 }
581 printf("%s\n", response);
582 }
583 break;
584 }
585 return;
586 }
587
588 }
589
590 #ifdef __STDC__
command_unknown(int argc,char ** argv)591 void command_unknown(int argc, char **argv)
592 #else
593 void command_unknown(argc, argv)
594 int argc;
595 char **argv;
596 #endif
597 {
598 printf("Unknown command '%s'.\n", argv[0]);
599 }
600
601 #ifdef __STDC__
command_wildmap(int argc,char ** argv)602 void command_wildmap(int argc, char **argv)
603 #else
604 void command_wildmap(argc, argv)
605 int argc;
606 char **argv;
607 #endif
608 {
609 FILE *fp;
610 char *filename = "wildmap.map";
611 char *p;
612 int size, n, nread;
613 char cmd[100];
614
615 if (argc != 1)
616 {
617 filename = argv[argc - 1];
618 argc--;
619 }
620
621 argv_to_command(argv);
622
623 switch (xpmtp_command(xpmtp_fd, command, response, sizeof(response)))
624 {
625 case -1:
626 xpmtp_perror(argv[0]);
627 command_quit(argc, argv);
628 return;
629 case '*':
630 printf("%s\n", response+1);
631 while (xpmtp_getline(xpmtp_fd, response, sizeof(response)) >= 0)
632 {
633 if (*response == '.')
634 break;
635 printf("%s\n", response);
636 }
637 return;
638 case '-':
639 printf("%s\n", response+1);
640 return;
641 }
642
643 size = atoi(response + 1);
644
645 fp = fopen(filename, "w");
646 if (fp == NULL)
647 {
648 perror(filename);
649 return;
650 }
651
652 while (size > 0)
653 {
654 n = MIN(sizeof(xpmtp_buf), size);
655 nread = xpmtp_read(xpmtp_fd, xpmtp_buf, n);
656 if (nread != n)
657 {
658 xpmtp_perror("get");
659 break;
660 }
661 fwrite(xpmtp_buf, 1, n, fp);
662 size -= n;
663 }
664
665 fclose(fp);
666 printf("OK Retrieved map:\n");
667 sprintf(cmd, "ls -l %s", filename);
668 system(cmd);
669 }
670
usage()671 void usage()
672 {
673 printf("usage: xpmtp [options]\n");
674 printf("\t-h host Specify the XPMTP host, default = %s.\n",
675 xpmtp_default_host());
676 printf("\t-p port Use port instead of the default XPMTP port, default = %d.\n", XPMTP_PORT);
677 printf("\n");
678 }
679
680 #ifdef __STDC__
done(int exit_value)681 void done(int exit_value)
682 #else
683 void done(exit_value)
684 int exit_value;
685 #endif
686 {
687 exit(exit_value);
688 }
689