X-Git-Url: https://git.saurik.com/apple/network_cmds.git/blobdiff_plain/b7080c8e96625177072137d504eb8e9c9d748e49..44d75bbf245e7a9e4b9d47cda6a7696ef781e19f:/telnetd.tproj/telnetd.c diff --git a/telnetd.tproj/telnetd.c b/telnetd.tproj/telnetd.c index 01943a4..6f7777f 100644 --- a/telnetd.tproj/telnetd.c +++ b/telnetd.tproj/telnetd.c @@ -1,26 +1,3 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights - * Reserved. This file contains Original Code and/or Modifications of - * Original Code as defined in and that are subject to the Apple Public - * Source License Version 1.0 (the 'License'). You may not use this file - * except in compliance with the License. Please obtain a copy of the - * License at http://www.apple.com/publicsource and read it before using - * this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License." - * - * @APPLE_LICENSE_HEADER_END@ - */ /* * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. @@ -55,13 +32,17 @@ */ #ifndef lint -static char copyright[] = +static const char copyright[] = "@(#) Copyright (c) 1989, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #ifndef lint -static char sccsid[] = "@(#)telnetd.c 8.4 (Berkeley) 5/30/95"; +#if 0 +static char sccsid[] = "@(#)telnetd.c 8.2 (Berkeley) 12/15/93"; +#endif +static const char rcsid[] = + "$FreeBSD: src/libexec/telnetd/telnetd.c,v 1.28 2001/07/20 15:14:03 ru Exp $"; #endif /* not lint */ #include "telnetd.h" @@ -76,6 +57,14 @@ static char sccsid[] = "@(#)telnetd.c 8.4 (Berkeley) 5/30/95"; # undef _SC_CRAY_SECURE_SYS #endif +#include +#include +#include +#include +#include +#include +#include + #if defined(_SC_CRAY_SECURE_SYS) #include #include @@ -83,6 +72,12 @@ static char sccsid[] = "@(#)telnetd.c 8.4 (Berkeley) 5/30/95"; #include #include # endif /* SO_SEC_MULTI */ + +/* wrapper for KAME-special getnameinfo() */ +#ifndef NI_WITHSCOPEID +#define NI_WITHSCOPEID 0 +#endif + int secflag; char tty_dev[16]; struct secdev dv; @@ -102,7 +97,8 @@ int auth_level = 0; int require_SecurID = 0; #endif -extern int utmp_len; +char remote_hostname[MAXHOSTNAMELEN]; +int utmp_len = sizeof(remote_hostname) - 1; int registerd_host_only = 0; #ifdef STREAMSPTY @@ -114,7 +110,7 @@ int registerd_host_only = 0; /* * Because of the way ptyibuf is used with streams messages, we need - * ptyibuf+1 to be on a full-word boundary. The following wierdness + * ptyibuf+1 to be on a full-word boundary. The following weirdness * is simply to make that happen. */ long ptyibufbuf[BUFSIZ/sizeof(long)+1]; @@ -146,13 +142,12 @@ int lowpty = 0, highpty; /* low, high pty numbers */ int debug = 0; int keepalive = 1; -char *progname; +char *altlogin; +void doit __P((struct sockaddr *)); +int terminaltypeok __P((char *)); +void startslave __P((char *, int, char *)); extern void usage P((void)); -void doit(struct sockaddr_in *); -int terminaltypeok(char *); -void startslave(char *, int, char *); - /* * The string to pass to getopt(). We do it this way so @@ -160,7 +155,8 @@ void startslave(char *, int, char *); * passed off to getopt(). */ char valid_opts[] = { - 'd', ':', 'h', 'k', 'n', 'S', ':', 'u', ':', 'U', + 'd', ':', 'h', 'k', 'n', 'p', ':', 'S', ':', 'u', ':', 'U', + '4', '6', #ifdef AUTHENTICATION 'a', ':', 'X', ':', #endif @@ -170,9 +166,6 @@ char valid_opts[] = { #ifdef DIAGNOSTICS 'D', ':', #endif -#ifdef ENCRYPTION - 'e', ':', -#endif #if defined(CRAY) && defined(NEWINIT) 'I', ':', #endif @@ -188,15 +181,15 @@ char valid_opts[] = { '\0' }; +int family = AF_INET; + int main(argc, argv) char *argv[]; { - struct sockaddr_in from; + struct sockaddr_storage from; int on = 1, fromlen; register int ch; - extern char *optarg; - extern int optind; #if defined(IPPROTO_IP) && defined(IP_TOS) int tos = -1; #endif @@ -204,11 +197,22 @@ main(argc, argv) pfrontp = pbackp = ptyobuf; netip = netibuf; nfrontp = nbackp = netobuf; -#ifdef ENCRYPTION - nclearto = 0; -#endif /* ENCRYPTION */ - progname = *argv; + /* + * This initialization causes linemode to default to a configuration + * that works on all telnet clients, including the FreeBSD client. + * This is not quite the same as the telnet client issuing a "mode + * character" command, but has most of the same benefits, and is + * preferable since some clients (like usofts) don't have the + * mode character command anyway and linemode breaks things. + * The most notable symptom of fix is that csh "set filec" operations + * like (filename completion) and ^D (choices) keys now work + * in telnet sessions and can be used more than once on the same line. + * CR/LF handling is also corrected in some termio modes. This + * change resolves problem reports bin/771 and bin/1037. + */ + + linemode=1; /*Default to mode that works on bulk of clients*/ #ifdef CRAY /* @@ -218,7 +222,7 @@ main(argc, argv) highpty = getnpty(); #endif /* CRAY */ - while ((ch = getopt(argc, argv, valid_opts)) != EOF) { + while ((ch = getopt(argc, argv, valid_opts)) != -1) { switch(ch) { #ifdef AUTHENTICATION @@ -243,8 +247,7 @@ main(argc, argv) */ auth_level = -1; } else { - fprintf(stderr, - "telnetd: unknown authorization level for -a\n"); + warnx("unknown authorization level for -a"); } break; #endif /* AUTHENTICATION */ @@ -286,17 +289,6 @@ main(argc, argv) break; #endif /* DIAGNOSTICS */ -#ifdef ENCRYPTION - case 'e': - if (strcmp(optarg, "debug") == 0) { - extern int encrypt_debug_mode; - encrypt_debug_mode = 1; - break; - } - usage(); - /* NOTREACHED */ - break; -#endif /* ENCRYPTION */ case 'h': hostinfo = 0; @@ -329,6 +321,10 @@ main(argc, argv) keepalive = 0; break; + case 'p': + altlogin = optarg; + break; + #ifdef CRAY case 'r': { @@ -366,17 +362,20 @@ main(argc, argv) case 'S': #ifdef HAS_GETTOS if ((tos = parsetos(optarg, "tcp")) < 0) - fprintf(stderr, "%s%s%s\n", - "telnetd: Bad TOS argument '", optarg, + warnx("%s%s%s", + "bad TOS argument '", optarg, "'; will try to use default TOS"); #else - fprintf(stderr, "%s%s\n", "TOS option unavailable; ", - "-S flag not supported\n"); + warnx("TOS option unavailable; -S flag not supported"); #endif break; case 'u': utmp_len = atoi(optarg); + if (utmp_len < 0) + utmp_len = -utmp_len; + if (utmp_len >= sizeof(remote_hostname)) + utmp_len = sizeof(remote_hostname) - 1; break; case 'U': @@ -392,8 +391,18 @@ main(argc, argv) break; #endif /* AUTHENTICATION */ + case '4': + family = AF_INET; + break; + +#ifdef INET6 + case '6': + family = AF_INET6; + break; +#endif + default: - fprintf(stderr, "telnetd: %c: unknown option\n", ch); + warnx("%c: unknown option", ch); /* FALLTHROUGH */ case '?': usage(); @@ -405,55 +414,43 @@ main(argc, argv) argv += optind; if (debug) { - int s, ns, foo; - struct servent *sp; - static struct sockaddr_in sin = { AF_INET }; + int s, ns, foo, error; + char *service = "telnet"; + struct addrinfo hints, *res; if (argc > 1) { usage(); /* NOT REACHED */ - } else if (argc == 1) { - if (sp = getservbyname(*argv, "tcp")) { - sin.sin_port = sp->s_port; - } else { - sin.sin_port = atoi(*argv); - if ((int)sin.sin_port <= 0) { - fprintf(stderr, "telnetd: %s: bad port #\n", *argv); - usage(); - /* NOT REACHED */ - } - sin.sin_port = htons((u_short)sin.sin_port); - } - } else { - sp = getservbyname("telnet", "tcp"); - if (sp == 0) { - fprintf(stderr, "telnetd: tcp/telnet: unknown service\n"); - exit(1); - } - sin.sin_port = sp->s_port; + } else if (argc == 1) + service = *argv; + + memset(&hints, 0, sizeof(hints)); + hints.ai_flags = AI_PASSIVE; + hints.ai_family = family; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = 0; + error = getaddrinfo(NULL, service, &hints, &res); + + if (error) { + errx(1, "tcp/%s: %s\n", service, gai_strerror(error)); + if (error == EAI_SYSTEM) + errx(1, "tcp/%s: %s\n", service, strerror(errno)); + usage(); } - s = socket(AF_INET, SOCK_STREAM, 0); - if (s < 0) { - perror("telnetd: socket");; - exit(1); - } + s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + if (s < 0) + err(1, "socket"); (void) setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)); - if (bind(s, (struct sockaddr *)&sin, sizeof sin) < 0) { - perror("bind"); - exit(1); - } - if (listen(s, 1) < 0) { - perror("listen"); - exit(1); - } - foo = sizeof sin; - ns = accept(s, (struct sockaddr *)&sin, &foo); - if (ns < 0) { - perror("accept"); - exit(1); - } + if (bind(s, res->ai_addr, res->ai_addrlen) < 0) + err(1, "bind"); + if (listen(s, 1) < 0) + err(1, "listen"); + foo = res->ai_addrlen; + ns = accept(s, res->ai_addr, &foo); + if (ns < 0) + err(1, "accept"); (void) dup2(ns, 0); (void) close(ns); (void) close(s); @@ -479,12 +476,10 @@ main(argc, argv) int szi = sizeof(int); #endif /* SO_SEC_MULTI */ - memset((char *)&dv, 0, sizeof(dv)); + bzero((char *)&dv, sizeof(dv)); - if (getsysv(&sysv, sizeof(struct sysv)) != 0) { - perror("getsysv"); - exit(1); - } + if (getsysv(&sysv, sizeof(struct sysv)) != 0) + err(1, "getsysv"); /* * Get socket security label and set device values @@ -495,8 +490,7 @@ main(argc, argv) (char *)&ss, &szss) < 0) || (getsockopt(0, SOL_SOCKET, SO_SEC_MULTI, (char *)&sock_multi, &szi) < 0)) { - perror("getsockopt"); - exit(1); + err(1, "getsockopt"); } else { dv.dv_actlvl = ss.ss_actlabel.lt_level; dv.dv_actcmp = ss.ss_actlabel.lt_compart; @@ -526,8 +520,7 @@ main(argc, argv) openlog("telnetd", LOG_PID | LOG_ODELAY, LOG_DAEMON); fromlen = sizeof (from); if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) { - fprintf(stderr, "%s: ", progname); - perror("getpeername"); + warn("getpeername"); _exit(1); } if (keepalive && @@ -537,7 +530,7 @@ main(argc, argv) } #if defined(IPPROTO_IP) && defined(IP_TOS) - { + if (from.ss_family == AF_INET) { # if defined(HAS_GETTOS) struct tosent *tp; if (tos < 0 && (tp = gettosbyname("telnet", "tcp"))) @@ -553,15 +546,15 @@ main(argc, argv) } #endif /* defined(IPPROTO_IP) && defined(IP_TOS) */ net = 0; - doit(&from); + doit((struct sockaddr *)&from); /* NOTREACHED */ - exit(0); + return(0); } /* end of main */ void usage() { - fprintf(stderr, "Usage: telnetd"); + fprintf(stderr, "usage: telnetd"); #ifdef AUTHENTICATION fprintf(stderr, " [-a (debug|other|user|valid|off|none)]\n\t"); #endif @@ -634,18 +627,12 @@ getterminaltype(name) } #endif -#ifdef ENCRYPTION - send_will(TELOPT_ENCRYPT, 1); -#endif /* ENCRYPTION */ send_do(TELOPT_TTYPE, 1); send_do(TELOPT_TSPEED, 1); send_do(TELOPT_XDISPLOC, 1); send_do(TELOPT_NEW_ENVIRON, 1); send_do(TELOPT_OLD_ENVIRON, 1); while ( -#ifdef ENCRYPTION - his_do_dont_is_changing(TELOPT_ENCRYPT) || -#endif /* ENCRYPTION */ his_will_wont_is_changing(TELOPT_TTYPE) || his_will_wont_is_changing(TELOPT_TSPEED) || his_will_wont_is_changing(TELOPT_XDISPLOC) || @@ -653,53 +640,33 @@ getterminaltype(name) his_will_wont_is_changing(TELOPT_OLD_ENVIRON)) { ttloop(); } -#ifdef ENCRYPTION - /* - * Wait for the negotiation of what type of encryption we can - * send with. If autoencrypt is not set, this will just return. - */ - if (his_state_is_will(TELOPT_ENCRYPT)) { - encrypt_wait(); - } -#endif /* ENCRYPTION */ if (his_state_is_will(TELOPT_TSPEED)) { static unsigned char sb[] = { IAC, SB, TELOPT_TSPEED, TELQUAL_SEND, IAC, SE }; - memmove(nfrontp, sb, sizeof sb); - nfrontp += sizeof sb; - DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2);); + output_datalen(sb, sizeof sb); } if (his_state_is_will(TELOPT_XDISPLOC)) { static unsigned char sb[] = { IAC, SB, TELOPT_XDISPLOC, TELQUAL_SEND, IAC, SE }; - memmove(nfrontp, sb, sizeof sb); - nfrontp += sizeof sb; - DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2);); + output_datalen(sb, sizeof sb); } if (his_state_is_will(TELOPT_NEW_ENVIRON)) { static unsigned char sb[] = { IAC, SB, TELOPT_NEW_ENVIRON, TELQUAL_SEND, IAC, SE }; - memmove(nfrontp, sb, sizeof sb); - nfrontp += sizeof sb; - DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2);); + output_datalen(sb, sizeof sb); } else if (his_state_is_will(TELOPT_OLD_ENVIRON)) { static unsigned char sb[] = { IAC, SB, TELOPT_OLD_ENVIRON, TELQUAL_SEND, IAC, SE }; - memmove(nfrontp, sb, sizeof sb); - nfrontp += sizeof sb; - DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2);); + output_datalen(sb, sizeof sb); } if (his_state_is_will(TELOPT_TTYPE)) { - memmove(nfrontp, ttytype_sbbuf, sizeof ttytype_sbbuf); - nfrontp += sizeof ttytype_sbbuf; - DIAG(TD_OPTIONS, printsub('>', ttytype_sbbuf + 2, - sizeof ttytype_sbbuf - 2);); + output_datalen(ttytype_sbbuf, sizeof ttytype_sbbuf); } if (his_state_is_will(TELOPT_TSPEED)) { while (sequenceIs(tspeedsubopt, baseline)) @@ -728,12 +695,14 @@ getterminaltype(name) * we have to just go with what we (might) have already gotten. */ if (his_state_is_will(TELOPT_TTYPE) && !terminaltypeok(terminaltype)) { - (void) strncpy(first, terminaltype, sizeof(first)); + (void) strncpy(first, terminaltype, sizeof(first)-1); + first[sizeof(first)-1] = '\0'; for(;;) { /* * Save the unknown name, and request the next name. */ - (void) strncpy(last, terminaltype, sizeof(last)); + (void) strncpy(last, terminaltype, sizeof(last)-1); + last[sizeof(last)-1] = '\0'; _gettermname(); if (terminaltypeok(terminaltype)) break; @@ -751,8 +720,10 @@ getterminaltype(name) * the start of the list. */ _gettermname(); - if (strncmp(first, terminaltype, sizeof(first)) != 0) - (void) strncpy(terminaltype, first, sizeof(first)); + if (strncmp(first, terminaltype, sizeof(first)) != 0) { + (void) strncpy(terminaltype, first, sizeof(terminaltype)-1); + terminaltype[sizeof(terminaltype)-1] = '\0'; + } break; } } @@ -772,10 +743,7 @@ _gettermname() if (his_state_is_wont(TELOPT_TTYPE)) return; settimer(baseline); - memmove(nfrontp, ttytype_sbbuf, sizeof ttytype_sbbuf); - nfrontp += sizeof ttytype_sbbuf; - DIAG(TD_OPTIONS, printsub('>', ttytype_sbbuf + 2, - sizeof ttytype_sbbuf - 2);); + output_datalen(ttytype_sbbuf, sizeof ttytype_sbbuf); while (sequenceIs(ttypesubopt, baseline)) ttloop(); } @@ -802,31 +770,27 @@ terminaltypeok(s) } #ifndef MAXHOSTNAMELEN -#define MAXHOSTNAMELEN 64 +#define MAXHOSTNAMELEN 256 #endif /* MAXHOSTNAMELEN */ char *hostname; char host_name[MAXHOSTNAMELEN]; -char remote_host_name[MAXHOSTNAMELEN]; -#ifndef convex -extern void telnet P((int, int)); -#else extern void telnet P((int, int, char *)); -#endif +int level; +char user_name[256]; /* * Get a pty, scan input lines. */ -void + void doit(who) - struct sockaddr_in *who; + struct sockaddr *who; { - char *host = NULL, *inet_ntoa(); + char *host = NULL; + int err; struct hostent *hp; - int level; int ptynum; - char user_name[256]; /* * Find an available pty to use. @@ -838,14 +802,12 @@ doit(who) #else for (;;) { char *lp; - extern char *line, *getpty(); if ((lp = getpty()) == NULL) fatal(net, "Out of ptys"); - if ((pty = open(lp, O_RDWR)) >= 0) { - strncpy(line,lp, sizeof(line)-1); - line[sizeof(line)-1] = '\0'; + if ((pty = open(lp, 2)) >= 0) { + strlcpy(line,lp,sizeof(line)); line[5] = 't'; break; } @@ -859,42 +821,43 @@ doit(who) if (secflag) { char slave_dev[16]; - sprintf(tty_dev, "/dev/pty/%03d", ptynum); + sprintf(tty_dev, "%spty/%03d", _PATH_DEV, ptynum); if (setdevs(tty_dev, &dv) < 0) fatal(net, "cannot set pty security"); - sprintf(slave_dev, "/dev/ttyp%03d", ptynum); + sprintf(slave_dev, "%sp%03d", _PATH_TTY, ptynum); if (setdevs(slave_dev, &dv) < 0) fatal(net, "cannot set tty security"); } #endif /* _SC_CRAY_SECURE_SYS */ - /* get name of connected client */ - hp = gethostbyaddr((char *)&who->sin_addr, sizeof (struct in_addr), - who->sin_family); - - if (hp == NULL && registerd_host_only) { - fatal(net, "Couldn't resolve your address into a host name.\r\n\ - Please contact your net administrator"); - } else if (hp && - (strlen(hp->h_name) <= (unsigned int)((utmp_len < 0) ? -utmp_len - : utmp_len))) { - host = hp->h_name; - } else { - host = inet_ntoa(who->sin_addr); - } - /* - * We must make a copy because Kerberos is probably going - * to also do a gethost* and overwrite the static data... - */ - strncpy(remote_host_name, host, sizeof(remote_host_name)-1); - remote_host_name[sizeof(remote_host_name)-1] = 0; - host = remote_host_name; - - (void) gethostname(host_name, sizeof (host_name)); + /* get name of connected client */ + hp = gethostbyaddr((char *)&((struct sockaddr_in *)who)->sin_addr, sizeof (struct in_addr), + ((struct sockaddr_in *)who)->sin_family); + + if (hp == NULL && registerd_host_only) { + fatal(net, "Couldn't resolve your address into a host name.\r\n\ + Please contact your net administrator"); + } else if (hp && + (strlen(hp->h_name) <= (unsigned int)((utmp_len < 0) ? -utmp_len + : utmp_len))) { + host = hp->h_name; + } else { + host = inet_ntoa(((struct sockaddr_in *)who)->sin_addr); + } + /* + * We must make a copy because Kerberos is probably going + * to also do a gethost* and overwrite the static data... + */ + strncpy(remote_hostname, host, sizeof(remote_hostname)-1); + remote_hostname[sizeof(remote_hostname)-1] = 0; + host = remote_hostname; + + (void) gethostname(host_name, sizeof(host_name) - 1); + host_name[sizeof(host_name) - 1] = '\0'; hostname = host_name; -#if defined(AUTHENTICATION) || defined(ENCRYPTION) - auth_encrypt_init(hostname, host, "TELNETD", 1); +#if defined(AUTHENTICATION) + auth_encrypt_init(hostname, remote_hostname, "TELNETD", 1); #endif init_env(); @@ -905,12 +868,6 @@ doit(who) level = getterminaltype(user_name); setenv("TERM", terminaltype ? terminaltype : "network", 1); - /* - * Start up the login process on the slave side of the terminal - */ -#ifndef convex - startslave(host, level, user_name); - #if defined(_SC_CRAY_SECURE_SYS) if (secflag) { if (setulvl(dv.dv_actlvl) < 0) @@ -920,10 +877,8 @@ doit(who) } #endif /* _SC_CRAY_SECURE_SYS */ - telnet(net, pty); /* begin server processing */ -#else - telnet(net, pty, host); -#endif + telnet(net, pty, remote_hostname); /* begin server process */ + /*NOTREACHED*/ } /* end of doit */ @@ -947,15 +902,9 @@ Xterm_output(ibufp, obuf, icountp, ocount) * hand data to telnet receiver finite state machine. */ void -#ifndef convex -telnet(f, p) -#else telnet(f, p, host) -#endif int f, p; -#ifdef convex char *host; -#endif { int on = 1; #define TABBUFSIZ 512 @@ -965,8 +914,12 @@ telnet(f, p, host) char *HE; char *HN; char *IM; + char *IF; + char *if_buf; + int if_fd; + struct stat statbuf; + void netflush(); - int nfd; /* * Initialize the slc mapping table. @@ -1051,9 +1004,7 @@ telnet(f, p, host) * mode, which we do not want. */ if (his_want_state_is_will(TELOPT_ECHO)) { - DIAG(TD_OPTIONS, - {sprintf(nfrontp, "td: simulating recv\r\n"); - nfrontp += strlen(nfrontp);}); + DIAG(TD_OPTIONS, output_data("td: simulating recv\r\n")); willoption(TELOPT_ECHO); } @@ -1119,9 +1070,9 @@ telnet(f, p, host) * side. Set up signal handler now. */ if ((int)signal(SIGUSR1, termstat) < 0) - perror("signal"); + warn("signal"); else if (ioctl(p, TCSIGME, (char *)SIGUSR1) < 0) - perror("ioctl:TCSIGME"); + warn("ioctl:TCSIGME"); /* * Make processing loop check terminal characteristics early on. */ @@ -1164,10 +1115,11 @@ telnet(f, p, host) HE = Getstr("he", &cp); HN = Getstr("hn", &cp); IM = Getstr("im", &cp); - if (HN && *HN) { - (void) strncpy(host_name, HN, sizeof(host_name)-1); - hostname[sizeof(host_name)-1] = '\0'; - } + IF = Getstr("if", &cp); + if (HN && *HN) + (void) strlcpy(host_name, HN, sizeof(host_name)); + if (IF && (if_fd = open(IF, O_RDONLY, 000)) != -1) + IM = 0; if (IM == 0) IM = ""; } else { @@ -1177,6 +1129,14 @@ telnet(f, p, host) edithost(HE, host_name); if (hostinfo && *IM) putf(IM, ptyibuf2); + else if (IF && if_fd != -1) { + fstat (if_fd, &statbuf); + if_buf = (char *) mmap (0, statbuf.st_size, PROT_READ, + 0, if_fd, 0); + putf(if_buf, ptyibuf2); + munmap (if_buf, statbuf.st_size); + close (if_fd); + } if (pcc) (void) strncat(ptyibuf2, ptyip, pcc+1); @@ -1190,15 +1150,15 @@ telnet(f, p, host) localstat(); #endif /* LINEMODE */ - DIAG(TD_REPORT, - {sprintf(nfrontp, "td: Entering processing loop\r\n"); - nfrontp += strlen(nfrontp);}); + DIAG(TD_REPORT, output_data("td: Entering processing loop\r\n")); -#ifdef convex - startslave(host); -#endif + /* + * Startup the login process on the slave side of the terminal + * now. We delay this until here to insure option negotiation + * is complete. + */ + startslave(host, level, user_name); - nfd = ((f > p) ? f : p) + 1; for (;;) { fd_set ibits, obits, xbits; register int c; @@ -1230,7 +1190,7 @@ telnet(f, p, host) if (!SYNCHing) { FD_SET(f, &xbits); } - if ((c = select(nfd, &ibits, &obits, &xbits, + if ((c = select(16, &ibits, &obits, &xbits, (struct timeval *)0)) < 1) { if (c == -1) { if (errno == EINTR) { @@ -1318,8 +1278,7 @@ telnet(f, p, host) netip = netibuf; } DIAG((TD_REPORT | TD_NETDATA), - {sprintf(nfrontp, "td: netread %d chars\r\n", ncc); - nfrontp += strlen(nfrontp);}); + output_data("td: netread %d chars\r\n", ncc)); DIAG(TD_NETDATA, printdata("nd", netip, ncc)); } @@ -1366,12 +1325,8 @@ telnet(f, p, host) * royally if we send them urgent * mode data. */ - *nfrontp++ = IAC; - *nfrontp++ = DM; + output_data("%c%c", IAC, DM); neturg = nfrontp-1; /* off by one XXX */ - DIAG(TD_OPTIONS, - printoption("td: send IAC", DM)); - #endif } if (his_state_is_will(TELOPT_LFLOW) && @@ -1381,16 +1336,11 @@ telnet(f, p, host) ptyibuf[0] & TIOCPKT_DOSTOP ? 1 : 0; if (newflow != flowmode) { flowmode = newflow; - (void) sprintf(nfrontp, - "%c%c%c%c%c%c", + output_data("%c%c%c%c%c%c", IAC, SB, TELOPT_LFLOW, flowmode ? LFLOW_ON : LFLOW_OFF, IAC, SE); - nfrontp += 6; - DIAG(TD_OPTIONS, printsub('>', - (unsigned char *)nfrontp-4, - 4);); } } pcc--; @@ -1413,19 +1363,19 @@ telnet(f, p, host) break; c = *ptyip++ & 0377, pcc--; if (c == IAC) - *nfrontp++ = c; + output_data("%c", c); #if defined(CRAY2) && defined(UNICOS5) else if (c == '\n' && my_state_is_wont(TELOPT_BINARY) && newmap) - *nfrontp++ = '\r'; + output_data("\r"); #endif /* defined(CRAY2) && defined(UNICOS5) */ - *nfrontp++ = c; + output_data("%c", c); if ((c == '\r') && (my_state_is_wont(TELOPT_BINARY))) { if (pcc > 0 && ((*ptyip & 0377) == '\n')) { - *nfrontp++ = *ptyip++ & 0377; + output_data("%c", *ptyip++ & 0377); pcc--; } else - *nfrontp++ = '\0'; + output_data("%c", '\0'); } } #if defined(CRAY2) && defined(UNICOS5) @@ -1556,14 +1506,6 @@ interrupt() { ptyflush(); /* half-hearted */ -#if defined(STREAMSPTY) && defined(TIOCSIGNAL) - /* Streams PTY style ioctl to post a signal */ - { - int sig = SIGINT; - (void) ioctl(pty, TIOCSIGNAL, &sig); - (void) ioctl(pty, I_FLUSH, FLUSHR); - } -#else #ifdef TCSIG (void) ioctl(pty, TCSIG, (char *)SIGINT); #else /* TCSIG */ @@ -1571,7 +1513,6 @@ interrupt() *pfrontp++ = slctab[SLC_IP].sptr ? (unsigned char)*slctab[SLC_IP].sptr : '\177'; #endif /* TCSIG */ -#endif } /* @@ -1619,8 +1560,7 @@ recv_ayt() return; } #endif - (void) strcpy(nfrontp, "\r\n[Yes]\r\n"); - nfrontp += 9; + output_data("\r\n[Yes]\r\n"); } void