1 /* $NetBSD: main.c,v 1.26 2008/07/21 14:19:26 lukem Exp $ */ 2 3 /* 4 * Copyright (c) 1983, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 #ifndef lint 34 __COPYRIGHT("@(#) Copyright (c) 1983, 1993\ 35 The Regents of the University of California. All rights reserved."); 36 #if 0 37 static char sccsid[] = "@(#)main.c 8.1 (Berkeley) 6/6/93"; 38 #else 39 __RCSID("$NetBSD: main.c,v 1.26 2008/07/21 14:19:26 lukem Exp $"); 40 #endif 41 #endif /* not lint */ 42 43 /* Many bug fixes are from Jim Guyton <guyton@rand-unix> */ 44 45 /* 46 * TFTP User Program -- Command Interface. 47 */ 48 #include <sys/types.h> 49 #include <sys/socket.h> 50 51 #include <netinet/in.h> 52 53 #include <arpa/inet.h> 54 #include <arpa/tftp.h> 55 56 #include <ctype.h> 57 #include <fcntl.h> 58 #include <err.h> 59 #include <errno.h> 60 #include <netdb.h> 61 #include <setjmp.h> 62 #include <signal.h> 63 #include <stdio.h> 64 #include <stdlib.h> 65 #include <string.h> 66 #include <unistd.h> 67 68 #include "extern.h" 69 70 #define TIMEOUT 5 /* secs between rexmt's */ 71 #define LBUFLEN 200 /* size of input buffer */ 72 73 struct sockaddr_storage peeraddr; 74 int f; 75 int mf; 76 int trace; 77 int verbose; 78 int tsize=0; 79 int tout=0; 80 size_t def_blksize=SEGSIZE; 81 size_t blksize=SEGSIZE; 82 in_addr_t mcaddr = INADDR_NONE; 83 uint16_t mcport; 84 ushort mcmasterslave; 85 int connected; 86 char mode[32]; 87 char line[LBUFLEN]; 88 int margc; 89 char *margv[20]; 90 const char *prompt = "tftp"; 91 jmp_buf toplevel; 92 93 void get __P((int, char **)); 94 void help __P((int, char **)); 95 void modecmd __P((int, char **)); 96 void put __P((int, char **)); 97 void quit __P((int, char **)); 98 void setascii __P((int, char **)); 99 void setbinary __P((int, char **)); 100 void setpeer0 __P((const char *, const char *)); 101 void setpeer __P((int, char **)); 102 void setrexmt __P((int, char **)); 103 void settimeout __P((int, char **)); 104 void settrace __P((int, char **)); 105 void setverbose __P((int, char **)); 106 void setblksize __P((int, char **)); 107 void settsize __P((int, char **)); 108 void settimeoutopt __P((int, char **)); 109 void status __P((int, char **)); 110 char *tail __P((char *)); 111 int main __P((int, char *[])); 112 void intr __P((int)); 113 const struct cmd *getcmd __P((char *)); 114 115 static __dead void command __P((void)); 116 117 static void getusage __P((char *)); 118 static void makeargv __P((void)); 119 static void putusage __P((char *)); 120 static void settftpmode __P((const char *)); 121 122 #define HELPINDENT (sizeof("connect")) 123 124 struct cmd { 125 const char *name; 126 const char *help; 127 void (*handler) __P((int, char **)); 128 }; 129 130 const char vhelp[] = "toggle verbose mode"; 131 const char thelp[] = "toggle packet tracing"; 132 const char tshelp[] = "toggle extended tsize option"; 133 const char tohelp[] = "toggle extended timeout option"; 134 const char blhelp[] = "set an alternative blocksize (def. 512)"; 135 const char chelp[] = "connect to remote tftp"; 136 const char qhelp[] = "exit tftp"; 137 const char hhelp[] = "print help information"; 138 const char shelp[] = "send file"; 139 const char rhelp[] = "receive file"; 140 const char mhelp[] = "set file transfer mode"; 141 const char sthelp[] = "show current status"; 142 const char xhelp[] = "set per-packet retransmission timeout"; 143 const char ihelp[] = "set total retransmission timeout"; 144 const char ashelp[] = "set mode to netascii"; 145 const char bnhelp[] = "set mode to octet"; 146 147 const struct cmd cmdtab[] = { 148 { "connect", chelp, setpeer }, 149 { "mode", mhelp, modecmd }, 150 { "put", shelp, put }, 151 { "get", rhelp, get }, 152 { "quit", qhelp, quit }, 153 { "verbose", vhelp, setverbose }, 154 { "blksize", blhelp, setblksize }, 155 { "tsize", tshelp, settsize }, 156 { "trace", thelp, settrace }, 157 { "status", sthelp, status }, 158 { "binary", bnhelp, setbinary }, 159 { "ascii", ashelp, setascii }, 160 { "rexmt", xhelp, setrexmt }, 161 { "timeout", ihelp, settimeout }, 162 { "tout", tohelp, settimeoutopt }, 163 { "?", hhelp, help }, 164 { .name = NULL } 165 }; 166 167 int 168 main(argc, argv) 169 int argc; 170 char *argv[]; 171 { 172 int c; 173 174 f = mf = -1; 175 (void)strlcpy(mode, "netascii", sizeof(mode)); 176 (void)signal(SIGINT, intr); 177 178 setprogname(argv[0]); 179 while ((c = getopt(argc, argv, "e")) != -1) { 180 switch (c) { 181 case 'e': 182 blksize = MAXSEGSIZE; 183 (void)strlcpy(mode, "octet", sizeof(mode)); 184 tsize = 1; 185 tout = 1; 186 break; 187 default: 188 (void)printf("usage: %s [-e] host-name [port]\n", 189 getprogname()); 190 exit(1); 191 } 192 } 193 argc -= optind; 194 argv += optind; 195 196 if (argc >= 1) { 197 if (setjmp(toplevel) != 0) 198 exit(0); 199 argc++; 200 argv--; 201 setpeer(argc, argv); 202 } 203 if (setjmp(toplevel) != 0) 204 (void)putchar('\n'); 205 command(); 206 return (0); 207 } 208 209 char hostname[100]; 210 211 void 212 setpeer0(host, port) 213 const char *host; 214 const char *port; 215 { 216 struct addrinfo hints, *res0, *res; 217 int error, soopt; 218 struct sockaddr_storage ss; 219 const char *cause = "unknown"; 220 221 if (connected) { 222 (void)close(f); 223 f = -1; 224 } 225 connected = 0; 226 227 (void)memset(&hints, 0, sizeof(hints)); 228 hints.ai_family = PF_UNSPEC; 229 hints.ai_socktype = SOCK_DGRAM; 230 hints.ai_protocol = IPPROTO_UDP; 231 hints.ai_flags = AI_CANONNAME; 232 if (!port) 233 port = "tftp"; 234 error = getaddrinfo(host, port, &hints, &res0); 235 if (error) { 236 warnx("%s", gai_strerror(error)); 237 return; 238 } 239 240 for (res = res0; res; res = res->ai_next) { 241 if (res->ai_addrlen > sizeof(peeraddr)) 242 continue; 243 f = socket(res->ai_family, res->ai_socktype, res->ai_protocol); 244 if (f < 0) { 245 cause = "socket"; 246 continue; 247 } 248 249 (void)memset(&ss, 0, sizeof(ss)); 250 ss.ss_family = res->ai_family; 251 ss.ss_len = res->ai_addrlen; 252 if (bind(f, (struct sockaddr *)(void *)&ss, 253 (socklen_t)ss.ss_len) < 0) { 254 cause = "bind"; 255 (void)close(f); 256 f = -1; 257 continue; 258 } 259 260 break; 261 } 262 263 if (f >= 0) { 264 soopt = 65536; 265 if (setsockopt(f, SOL_SOCKET, SO_SNDBUF, &soopt, sizeof(soopt)) 266 < 0) { 267 (void)close(f); 268 f = -1; 269 cause = "setsockopt SNDBUF"; 270 } 271 else if (setsockopt(f, SOL_SOCKET, SO_RCVBUF, &soopt, sizeof(soopt)) 272 < 0) { 273 (void)close(f); 274 f = -1; 275 cause = "setsockopt RCVBUF"; 276 } 277 } 278 279 if (f < 0 || res == NULL) 280 warn("%s", cause); 281 else { 282 /* res->ai_addr <= sizeof(peeraddr) is guaranteed */ 283 (void)memcpy(&peeraddr, res->ai_addr, res->ai_addrlen); 284 if (res->ai_canonname) { 285 (void)strlcpy(hostname, res->ai_canonname, 286 sizeof(hostname)); 287 } else 288 (void)strlcpy(hostname, host, sizeof(hostname)); 289 connected = 1; 290 } 291 292 freeaddrinfo(res0); 293 } 294 295 void 296 setpeer(argc, argv) 297 int argc; 298 char *argv[]; 299 { 300 301 if (argc < 2) { 302 (void)strlcpy(line, "Connect ", sizeof(line)); 303 (void)printf("(to) "); 304 (void)fgets(&line[strlen(line)], (int)(LBUFLEN-strlen(line)), stdin); 305 makeargv(); 306 argc = margc; 307 argv = margv; 308 } 309 if ((argc < 2) || (argc > 3)) { 310 (void)printf("usage: %s [-e] host-name [port]\n", getprogname()); 311 return; 312 } 313 if (argc == 2) 314 setpeer0(argv[1], NULL); 315 else 316 setpeer0(argv[1], argv[2]); 317 } 318 319 struct modes { 320 const char *m_name; 321 const char *m_mode; 322 } modes[] = { 323 { "ascii", "netascii" }, 324 { "netascii", "netascii" }, 325 { "binary", "octet" }, 326 { "image", "octet" }, 327 { "octet", "octet" }, 328 /* { "mail", "mail" }, */ 329 { 0, 0 } 330 }; 331 332 void 333 modecmd(argc, argv) 334 int argc; 335 char *argv[]; 336 { 337 struct modes *p; 338 const char *sep; 339 340 if (argc < 2) { 341 (void)printf("Using %s mode to transfer files.\n", mode); 342 return; 343 } 344 if (argc == 2) { 345 for (p = modes; p->m_name; p++) 346 if (strcmp(argv[1], p->m_name) == 0) 347 break; 348 if (p->m_name) { 349 settftpmode(p->m_mode); 350 return; 351 } 352 (void)printf("%s: unknown mode\n", argv[1]); 353 /* drop through and print usage message */ 354 } 355 356 (void)printf("usage: %s [", argv[0]); 357 sep = " "; 358 for (p = modes; p->m_name; p++) { 359 (void)printf("%s%s", sep, p->m_name); 360 if (*sep == ' ') 361 sep = " | "; 362 } 363 (void)printf(" ]\n"); 364 return; 365 } 366 367 void 368 /*ARGSUSED*/ 369 setbinary(argc, argv) 370 int argc; 371 char *argv[]; 372 { 373 374 settftpmode("octet"); 375 } 376 377 void 378 /*ARGSUSED*/ 379 setascii(argc, argv) 380 int argc; 381 char *argv[]; 382 { 383 384 settftpmode("netascii"); 385 } 386 387 static void 388 settftpmode(newmode) 389 const char *newmode; 390 { 391 (void)strlcpy(mode, newmode, sizeof(mode)); 392 if (verbose) 393 (void)printf("mode set to %s\n", mode); 394 } 395 396 397 /* 398 * Send file(s). 399 */ 400 void 401 put(argc, argv) 402 int argc; 403 char *argv[]; 404 { 405 int fd; 406 int n; 407 char *targ, *p; 408 409 if (argc < 2) { 410 (void)strlcpy(line, "send ", sizeof(line)); 411 (void)printf("(file) "); 412 (void)fgets(&line[strlen(line)], (int)(LBUFLEN-strlen(line)), stdin); 413 makeargv(); 414 argc = margc; 415 argv = margv; 416 } 417 if (argc < 2) { 418 putusage(argv[0]); 419 return; 420 } 421 targ = argv[argc - 1]; 422 if (strrchr(argv[argc - 1], ':')) { 423 char *cp; 424 425 for (n = 1; n < argc - 1; n++) 426 if (strchr(argv[n], ':')) { 427 putusage(argv[0]); 428 return; 429 } 430 cp = argv[argc - 1]; 431 targ = strrchr(cp, ':'); 432 *targ++ = 0; 433 if (cp[0] == '[' && cp[strlen(cp) - 1] == ']') { 434 cp[strlen(cp) - 1] = '\0'; 435 cp++; 436 } 437 setpeer0(cp, NULL); 438 } 439 if (!connected) { 440 (void)printf("No target machine specified.\n"); 441 return; 442 } 443 if (argc < 4) { 444 char *cp = argc == 2 ? tail(targ) : argv[1]; 445 fd = open(cp, O_RDONLY); 446 if (fd < 0) { 447 warn("%s", cp); 448 return; 449 } 450 if (verbose) 451 (void)printf("putting %s to %s:%s [%s]\n", 452 cp, hostname, targ, mode); 453 sendfile(fd, targ, mode); 454 return; 455 } 456 /* this assumes the target is a directory */ 457 /* on a remote unix system. hmmmm. */ 458 p = strchr(targ, '\0'); 459 *p++ = '/'; 460 for (n = 1; n < argc - 1; n++) { 461 (void)strcpy(p, tail(argv[n])); 462 fd = open(argv[n], O_RDONLY); 463 if (fd < 0) { 464 warn("%s", argv[n]); 465 continue; 466 } 467 if (verbose) 468 (void)printf("putting %s to %s:%s [%s]\n", 469 argv[n], hostname, targ, mode); 470 sendfile(fd, targ, mode); 471 } 472 } 473 474 static void 475 putusage(s) 476 char *s; 477 { 478 (void)printf("usage: %s file ... host:target, or\n", s); 479 (void)printf(" %s file ... target (when already connected)\n", s); 480 } 481 482 /* 483 * Receive file(s). 484 */ 485 void 486 get(argc, argv) 487 int argc; 488 char *argv[]; 489 { 490 int fd; 491 int n; 492 char *p; 493 char *src; 494 495 if (argc < 2) { 496 (void)strlcpy(line, "get ", sizeof(line)); 497 (void)printf("(files) "); 498 (void)fgets(&line[strlen(line)], (int)(LBUFLEN-strlen(line)), stdin); 499 makeargv(); 500 argc = margc; 501 argv = margv; 502 } 503 if (argc < 2) { 504 getusage(argv[0]); 505 return; 506 } 507 if (!connected) { 508 for (n = 1; n < argc ; n++) 509 if (strrchr(argv[n], ':') == 0) { 510 getusage(argv[0]); 511 return; 512 } 513 } 514 for (n = 1; n < argc ; n++) { 515 src = strrchr(argv[n], ':'); 516 if (src == NULL) 517 src = argv[n]; 518 else { 519 char *cp; 520 *src++ = 0; 521 cp = argv[n]; 522 if (cp[0] == '[' && cp[strlen(cp) - 1] == ']') { 523 cp[strlen(cp) - 1] = '\0'; 524 cp++; 525 } 526 setpeer0(cp, NULL); 527 if (!connected) 528 continue; 529 } 530 if (argc < 4) { 531 char *cp = argc == 3 ? argv[2] : tail(src); 532 fd = creat(cp, 0644); 533 if (fd < 0) { 534 warn("%s", cp); 535 return; 536 } 537 if (verbose) 538 (void)printf("getting from %s:%s to %s [%s]\n", 539 hostname, src, cp, mode); 540 recvfile(fd, src, mode); 541 break; 542 } 543 p = tail(src); /* new .. jdg */ 544 fd = creat(p, 0644); 545 if (fd < 0) { 546 warn("%s", p); 547 continue; 548 } 549 if (verbose) 550 (void)printf("getting from %s:%s to %s [%s]\n", 551 hostname, src, p, mode); 552 recvfile(fd, src, mode); 553 } 554 } 555 556 static void 557 getusage(s) 558 char *s; 559 { 560 (void)printf("usage: %s host:file host:file ... file, or\n", s); 561 (void)printf(" %s file file ... file if connected\n", s); 562 } 563 564 void 565 setblksize(argc, argv) 566 int argc; 567 char *argv[]; 568 { 569 int t; 570 571 if (argc < 2) { 572 (void)strlcpy(line, "blksize ", sizeof(line)); 573 (void)printf("(blksize) "); 574 (void)fgets(&line[strlen(line)], (int)(LBUFLEN-strlen(line)), stdin); 575 makeargv(); 576 argc = margc; 577 argv = margv; 578 } 579 if (argc != 2) { 580 (void)printf("usage: %s value\n", argv[0]); 581 return; 582 } 583 t = atoi(argv[1]); 584 if (t < 8 || t > 65464) 585 (void)printf("%s: bad value\n", argv[1]); 586 else 587 blksize = t; 588 } 589 590 unsigned int def_rexmtval = TIMEOUT; 591 unsigned int rexmtval = TIMEOUT; 592 593 void 594 setrexmt(argc, argv) 595 int argc; 596 char *argv[]; 597 { 598 int t; 599 600 if (argc < 2) { 601 (void)strlcpy(line, "Rexmt-timeout ", sizeof(line)); 602 (void)printf("(value) "); 603 (void)fgets(&line[strlen(line)], (int)(LBUFLEN-strlen(line)), stdin); 604 makeargv(); 605 argc = margc; 606 argv = margv; 607 } 608 if (argc != 2) { 609 (void)printf("usage: %s value\n", argv[0]); 610 return; 611 } 612 t = atoi(argv[1]); 613 if (t < 0) 614 (void)printf("%s: bad value\n", argv[1]); 615 else 616 rexmtval = t; 617 } 618 619 int maxtimeout = 5 * TIMEOUT; 620 621 void 622 settimeout(argc, argv) 623 int argc; 624 char *argv[]; 625 { 626 int t; 627 628 if (argc < 2) { 629 (void)strlcpy(line, "Maximum-timeout ", sizeof(line)); 630 (void)printf("(value) "); 631 (void)fgets(&line[strlen(line)], (int)(LBUFLEN-strlen(line)), stdin); 632 makeargv(); 633 argc = margc; 634 argv = margv; 635 } 636 if (argc != 2) { 637 (void)printf("usage: %s value\n", argv[0]); 638 return; 639 } 640 t = atoi(argv[1]); 641 if (t < 0) 642 (void)printf("%s: bad value\n", argv[1]); 643 else 644 maxtimeout = t; 645 } 646 647 void 648 /*ARGSUSED*/ 649 status(argc, argv) 650 int argc; 651 char *argv[]; 652 { 653 if (connected) 654 (void)printf("Connected to %s.\n", hostname); 655 else 656 (void)printf("Not connected.\n"); 657 (void)printf("Mode: %s Verbose: %s Tracing: %s\n", mode, 658 verbose ? "on" : "off", trace ? "on" : "off"); 659 (void)printf("Rexmt-interval: %d seconds, Max-timeout: %d seconds\n", 660 rexmtval, maxtimeout); 661 } 662 663 void 664 /*ARGSUSED*/ 665 intr(dummy) 666 int dummy; 667 { 668 669 (void)signal(SIGALRM, SIG_IGN); 670 (void)alarm(0); 671 longjmp(toplevel, -1); 672 } 673 674 char * 675 tail(filename) 676 char *filename; 677 { 678 char *s; 679 680 while (*filename) { 681 s = strrchr(filename, '/'); 682 if (s == NULL) 683 break; 684 if (s[1]) 685 return (s + 1); 686 *s = '\0'; 687 } 688 return (filename); 689 } 690 691 /* 692 * Command parser. 693 */ 694 static __dead void 695 command() 696 { 697 const struct cmd *c; 698 699 for (;;) { 700 (void)printf("%s> ", prompt); 701 if (fgets(line, LBUFLEN, stdin) == 0) { 702 if (feof(stdin)) { 703 exit(0); 704 } else { 705 continue; 706 } 707 } 708 if ((line[0] == 0) || (line[0] == '\n')) 709 continue; 710 makeargv(); 711 if (margc == 0) 712 continue; 713 c = getcmd(margv[0]); 714 if (c == (struct cmd *)-1) { 715 (void)printf("?Ambiguous command\n"); 716 continue; 717 } 718 if (c == 0) { 719 (void)printf("?Invalid command\n"); 720 continue; 721 } 722 (*c->handler)(margc, margv); 723 } 724 } 725 726 const struct cmd * 727 getcmd(name) 728 char *name; 729 { 730 const char *p, *q; 731 const struct cmd *c, *found; 732 int nmatches, longest; 733 734 longest = 0; 735 nmatches = 0; 736 found = 0; 737 for (c = cmdtab; (p = c->name) != NULL; c++) { 738 for (q = name; *q == *p++; q++) 739 if (*q == 0) /* exact match? */ 740 return (c); 741 if (!*q) { /* the name was a prefix */ 742 if (q - name > longest) { 743 longest = q - name; 744 nmatches = 1; 745 found = c; 746 } else if (q - name == longest) 747 nmatches++; 748 } 749 } 750 if (nmatches > 1) 751 return ((struct cmd *)-1); 752 return (found); 753 } 754 755 /* 756 * Slice a string up into argc/argv. 757 */ 758 static void 759 makeargv() 760 { 761 char *cp; 762 char **argp = margv; 763 764 margc = 0; 765 for (cp = line; *cp;) { 766 while (isspace((unsigned char)*cp)) 767 cp++; 768 if (*cp == '\0') 769 break; 770 *argp++ = cp; 771 margc += 1; 772 while (*cp != '\0' && !isspace((unsigned char)*cp)) 773 cp++; 774 if (*cp == '\0') 775 break; 776 *cp++ = '\0'; 777 } 778 *argp++ = 0; 779 } 780 781 void 782 /*ARGSUSED*/ 783 quit(argc, argv) 784 int argc; 785 char *argv[]; 786 { 787 788 exit(0); 789 } 790 791 /* 792 * Help command. 793 */ 794 void 795 help(argc, argv) 796 int argc; 797 char *argv[]; 798 { 799 const struct cmd *c; 800 801 if (argc == 1) { 802 (void)printf("Commands may be abbreviated. Commands are:\n\n"); 803 for (c = cmdtab; c->name; c++) 804 (void)printf("%-*s\t%s\n", (int)HELPINDENT, c->name, c->help); 805 return; 806 } 807 while (--argc > 0) { 808 char *arg; 809 arg = *++argv; 810 c = getcmd(arg); 811 if (c == (struct cmd *)-1) 812 (void)printf("?Ambiguous help command %s\n", arg); 813 else if (c == (struct cmd *)0) 814 (void)printf("?Invalid help command %s\n", arg); 815 else 816 (void)printf("%s\n", c->help); 817 } 818 } 819 820 void 821 /*ARGSUSED*/ 822 settrace(argc, argv) 823 int argc; 824 char **argv; 825 { 826 trace = !trace; 827 (void)printf("Packet tracing %s.\n", trace ? "on" : "off"); 828 } 829 830 void 831 /*ARGSUSED*/ 832 setverbose(argc, argv) 833 int argc; 834 char **argv; 835 { 836 verbose = !verbose; 837 (void)printf("Verbose mode %s.\n", verbose ? "on" : "off"); 838 } 839 840 void 841 /*ARGSUSED*/ 842 settsize(argc, argv) 843 int argc; 844 char **argv; 845 { 846 tsize = !tsize; 847 (void)printf("Tsize mode %s.\n", tsize ? "on" : "off"); 848 } 849 850 void 851 /*ARGSUSED*/ 852 settimeoutopt(argc, argv) 853 int argc; 854 char **argv; 855 { 856 tout = !tout; 857 (void)printf("Timeout option %s.\n", tout ? "on" : "off"); 858 } 859