+ return 1;
+}
+
+/*VARARGS*/
+quit()
+{
+ (void) call(bye, "bye", 0);
+ exit(0);
+ /*NOTREACHED*/
+}
+
+/*
+ * Print status about the connection.
+ */
+/*ARGSUSED*/
+status(argc, argv)
+int argc;
+char *argv[];
+{
+ if (connected) {
+ printf("Connected to %s.\n", hostname);
+ if (argc < 2) {
+ printf("Operating in %s.\n", modedescriptions[getconnmode()]);
+ if (localchars) {
+ printf("Catching signals locally.\n");
+ }
+ }
+ } else {
+ printf("No connection.\n");
+ }
+ printf("Escape character is '%s'.\n", control(escape));
+ fflush(stdout);
+ return 1;
+}
+
+tn(argc, argv)
+ int argc;
+ char *argv[];
+{
+ register struct hostent *host = 0;
+
+ if (connected) {
+ printf("?Already connected to %s\n", hostname);
+ return 0;
+ }
+ if (argc < 2) {
+ (void) strcpy(line, "Connect ");
+ printf("(to) ");
+ gets(&line[strlen(line)]);
+ makeargv();
+ argc = margc;
+ argv = margv;
+ }
+ if (argc > 3) {
+ printf("usage: %s host-name [port]\n", argv[0]);
+ return 0;
+ }
+ sin.sin_addr.s_addr = inet_addr(argv[1]);
+ if (sin.sin_addr.s_addr != -1) {
+ sin.sin_family = AF_INET;
+ (void) strcpy(hnamebuf, argv[1]);
+ hostname = hnamebuf;
+ } else {
+ host = gethostbyname(argv[1]);
+ if (host) {
+ sin.sin_family = host->h_addrtype;
+#ifndef NOT43
+ bcopy(host->h_addr_list[0], (caddr_t)&sin.sin_addr,
+ host->h_length);
+#else NOT43
+ bcopy(host->h_addr, (caddr_t)&sin.sin_addr,
+ host->h_length);
+#endif NOT43
+ hostname = host->h_name;
+ } else {
+ printf("%s: unknown host\n", argv[1]);
+ return 0;
+ }
+ }
+ sin.sin_port = sp->s_port;
+ if (argc == 3) {
+ sin.sin_port = atoi(argv[2]);
+ if (sin.sin_port == 0) {
+ sp = getservbyname(argv[2], "tcp");
+ if (sp)
+ sin.sin_port = sp->s_port;
+ else {
+ printf("%s: bad port number\n", argv[2]);
+ return 0;
+ }
+ } else {
+ sin.sin_port = atoi(argv[2]);
+ sin.sin_port = htons(sin.sin_port);
+ }
+ telnetport = 0;
+ } else {
+ telnetport = 1;
+ }
+ signal(SIGINT, intr);
+ signal(SIGQUIT, intr2);
+ signal(SIGPIPE, deadpeer);
+ printf("Trying...\n");
+ do {
+ net = socket(AF_INET, SOCK_STREAM, 0);
+ if (net < 0) {
+ perror("telnet: socket");
+ return 0;
+ }
+#ifndef NOT43
+ if (debug &&
+ setsockopt(net, SOL_SOCKET, SO_DEBUG,
+ (char *)&debug, sizeof(debug)) < 0)
+#else NOT43
+ if (debug && setsockopt(net, SOL_SOCKET, SO_DEBUG, 0, 0) < 0)
+#endif NOT43
+ perror("setsockopt (SO_DEBUG)");
+
+ if (connect(net, (struct sockaddr *)&sin, sizeof (sin)) < 0) {
+#ifndef NOT43
+ if (host && host->h_addr_list[1]) {
+ int oerrno = errno;
+
+ fprintf(stderr,
+ "telnet: connect to address %s: ",
+ inet_ntoa(sin.sin_addr));
+ errno = oerrno;
+ perror((char *)0);
+ host->h_addr_list++;
+ bcopy(host->h_addr_list[0],
+ (caddr_t)&sin.sin_addr, host->h_length);
+ fprintf(stderr, "Trying %s...\n",
+ inet_ntoa(sin.sin_addr));
+ (void) close(net);
+ continue;
+ }
+#endif NOT43
+ perror("telnet: connect");
+ signal(SIGINT, SIG_DFL);
+ signal(SIGQUIT, SIG_DFL);
+ return 0;
+ }
+ connected++;
+ } while (connected == 0);
+ call(status, "status", "notmuch", 0);
+ if (setjmp(peerdied) == 0)
+ telnet();
+ fprintf(stderr, "Connection closed by foreign host.\n");
+ exit(1);
+ /*NOTREACHED*/
+}
+
+
+#define HELPINDENT (sizeof ("connect"))
+
+char openhelp[] = "connect to a site";
+char closehelp[] = "close current connection";
+char quithelp[] = "exit telnet";
+char zhelp[] = "suspend telnet";
+char statushelp[] = "print status information";
+char helphelp[] = "print help information";
+char sendhelp[] = "transmit special characters ('send ?' for more)";
+char sethelp[] = "set operating parameters ('set ?' for more)";
+char togglestring[] ="toggle operating parameters ('toggle ?' for more)";
+char displayhelp[] = "display operating parameters";
+char modehelp[] =
+ "try to enter line-by-line or character-at-a-time mode";
+
+int help();
+
+struct cmd cmdtab[] = {
+ { "close", closehelp, bye, 1, 1 },
+ { "display", displayhelp, display, 1, 0 },
+ { "mode", modehelp, modecmd, 1, 1 },
+ { "open", openhelp, tn, 1, 0 },
+ { "quit", quithelp, quit, 1, 0 },
+ { "send", sendhelp, sendcmd, 1, 1 },
+ { "set", sethelp, setcmd, 1, 0 },
+ { "status", statushelp, status, 1, 0 },
+ { "toggle", togglestring, toggle, 1, 0 },
+ { "z", zhelp, suspend, 1, 0 },
+ { "?", helphelp, help, 1, 0 },
+ 0
+};
+
+char crmodhelp[] = "deprecated command -- use 'toggle crmod' instead";
+char escapehelp[] = "deprecated command -- use 'set escape' instead";
+
+struct cmd cmdtab2[] = {
+ { "help", helphelp, help, 0, 0 },
+ { "escape", escapehelp, setescape, 1, 0 },
+ { "crmod", crmodhelp, togcrmod, 1, 0 },
+ 0
+};
+
+/*
+ * Help command.
+ */
+help(argc, argv)
+ int argc;
+ char *argv[];
+{
+ register struct cmd *c;
+
+ if (argc == 1) {
+ printf("Commands may be abbreviated. Commands are:\n\n");
+ for (c = cmdtab; c->name; c++)
+ if (c->dohelp) {
+ printf("%-*s\t%s\n", HELPINDENT, c->name,
+ c->help);
+ }
+ return 0;
+ }
+ while (--argc > 0) {
+ register char *arg;
+ arg = *++argv;
+ c = getcmd(arg);
+ if (c == Ambiguous(struct cmd *))
+ printf("?Ambiguous help command %s\n", arg);
+ else if (c == (struct cmd *)0)
+ printf("?Invalid help command %s\n", arg);
+ else
+ printf("%s\n", c->help);
+ }
+ return 0;
+}
+/*
+ * Call routine with argc, argv set from args (terminated by 0).
+ * VARARGS2
+ */
+call(routine, args)
+ int (*routine)();
+ char *args;
+{
+ register char **argp;
+ register int argc;
+
+ for (argc = 0, argp = &args; *argp++ != 0; argc++)
+ ;
+ return (*routine)(argc, &args);
+}
+
+makeargv()
+{
+ register char *cp;
+ register char **argp = margv;
+
+ margc = 0;
+ for (cp = line; *cp;) {
+ while (isspace(*cp))
+ cp++;
+ if (*cp == '\0')
+ break;
+ *argp++ = cp;
+ margc += 1;
+ while (*cp != '\0' && !isspace(*cp))
+ cp++;
+ if (*cp == '\0')
+ break;
+ *cp++ = '\0';
+ }
+ *argp++ = 0;
+}
+
+char **
+getnextcmd(name)
+char *name;
+{
+ struct cmd *c = (struct cmd *) name;
+
+ return (char **) (c+1);
+}
+
+struct cmd *
+getcmd(name)
+char *name;
+{
+ struct cmd *cm;
+
+ if (cm = (struct cmd *) genget(name, (char **) cmdtab, getnextcmd)) {
+ return cm;
+ } else {
+ return (struct cmd *) genget(name, (char **) cmdtab2, getnextcmd);
+ }
+}
+
+command(top)
+ int top;
+{
+ register struct cmd *c;
+
+ setcommandmode();
+ if (!top) {
+ putchar('\n');
+ } else {
+ signal(SIGINT, SIG_DFL);
+ signal(SIGQUIT, SIG_DFL);
+ }
+ for (;;) {
+ printf("%s> ", prompt);
+ if (gets(line) == 0) {
+ if (feof(stdin))
+ quit();
+ break;
+ }
+ if (line[0] == 0)
+ break;
+ makeargv();
+ c = getcmd(margv[0]);
+ if (c == Ambiguous(struct cmd *)) {
+ printf("?Ambiguous command\n");
+ continue;
+ }
+ if (c == 0) {
+ printf("?Invalid command\n");
+ continue;
+ }
+ if (c->needconnect && !connected) {
+ printf("?Need to be connected first.\n");
+ continue;
+ }
+ if ((*c->handler)(margc, margv)) {
+ break;
+ }
+ }
+ if (!top) {
+ if (!connected) {
+ longjmp(toplevel, 1);
+ /*NOTREACHED*/
+ }
+ setconnmode();
+ }
+}
+\f
+/*
+ * main. Parse arguments, invoke the protocol or command parser.
+ */
+
+
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ sp = getservbyname("telnet", "tcp");
+ if (sp == 0) {
+ fprintf(stderr, "telnet: tcp/telnet: unknown service\n");
+ exit(1);
+ }
+ NetTrace = stdout;
+ ioctl(0, TIOCGETP, (char *)&ottyb);
+ ioctl(0, TIOCGETC, (char *)&otc);
+ ioctl(0, TIOCGLTC, (char *)&oltc);
+#if defined(LNOFLSH)
+ ioctl(0, TIOCLGET, (char *)&autoflush);
+ autoflush = !(autoflush&LNOFLSH); /* if LNOFLSH, no autoflush */
+#else /* LNOFLSH */
+ autoflush = 1;
+#endif /* LNOFLSH */
+ ntc = otc;
+ nltc = oltc;
+ nttyb = ottyb;
+ setbuf(stdin, (char *)0);
+ setbuf(stdout, (char *)0);
+ prompt = argv[0];
+ if (argc > 1 && !strcmp(argv[1], "-d")) {
+ debug = 1;
+ argv++;
+ argc--;
+ }
+ if (argc > 1 && !strcmp(argv[1], "-n")) {
+ argv++;
+ argc--;
+ if (argc > 1) { /* get file name */
+ NetTrace = fopen(argv[1], "w");
+ argv++;
+ argc--;
+ if (NetTrace == NULL) {
+ NetTrace = stdout;
+ }
+ }
+ }
+ if (argc != 1) {
+ if (setjmp(toplevel) != 0)
+ exit(0);
+ tn(argc, argv);
+ }
+ setjmp(toplevel);
+ for (;;)
+ command(1);