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