352 |
#endif |
#endif |
353 |
break; |
break; |
354 |
|
|
|
case 'u': |
|
|
#ifdef HAVE_UTMP_UT_HOST |
|
|
utmp_len = atoi(optarg); |
|
|
#endif |
|
|
break; |
|
|
|
|
355 |
case 'U': |
case 'U': |
356 |
registerd_host_only = 1; |
registerd_host_only = 1; |
357 |
break; |
break; |
784 |
char host_name[MAXHOSTNAMELEN]; |
char host_name[MAXHOSTNAMELEN]; |
785 |
char remote_host_name[MAXHOSTNAMELEN]; |
char remote_host_name[MAXHOSTNAMELEN]; |
786 |
|
|
|
#ifndef convex |
|
|
extern void telnet P((int, int)); |
|
|
#else |
|
787 |
extern void telnet P((int, int, char *)); |
extern void telnet P((int, int, char *)); |
|
#endif |
|
788 |
|
|
789 |
/* |
/* |
790 |
* Get a pty, scan input lines. |
* Get a pty, scan input lines. |
791 |
*/ |
*/ |
792 |
int |
int |
793 |
doit(struct sockaddr_in *who) |
doit (struct sockaddr_in *who) |
794 |
{ |
{ |
795 |
char *host, *inet_ntoa(); |
char *host, *inet_ntoa(); |
796 |
int t; |
int t; |
797 |
struct hostent *hp; |
struct hostent *hp; |
798 |
int level; |
int level; |
799 |
int ptynum; |
char user_name[256]; |
800 |
char user_name[256]; |
|
801 |
|
/* get name of connected client */ |
802 |
/* |
hp = gethostbyaddr((char *)&who->sin_addr, sizeof (struct in_addr), |
803 |
* Find an available pty to use. |
who->sin_family); |
804 |
*/ |
|
805 |
#ifndef convex |
if (hp == NULL && registerd_host_only) |
806 |
pty = getpty(&ptynum); |
fatal(net, "Couldn't resolve your address into a host name.\r\n\ |
807 |
if (pty < 0) |
Please contact your net administrator"); |
808 |
fatal(net, "All network ports in use"); |
else if (hp) |
809 |
#else |
host = hp->h_name; |
810 |
for (;;) { |
else |
811 |
char *lp; |
host = inet_ntoa (who->sin_addr); |
812 |
extern char *line, *getpty(); |
|
813 |
|
/* |
814 |
if ((lp = getpty()) == NULL) |
* We must make a copy because Kerberos is probably going |
815 |
fatal(net, "Out of ptys"); |
* to also do a gethost* and overwrite the static data... |
816 |
|
*/ |
817 |
if ((pty = open(lp, O_RDWR)) >= 0) { |
strncpy (remote_host_name, host, sizeof (remote_host_name)-1); |
818 |
strcpy(line,lp); |
remote_host_name[sizeof (remote_host_name)-1] = 0; |
819 |
line[5] = 't'; |
host = remote_host_name; |
820 |
break; |
|
821 |
} |
gethostname (host_name, sizeof (host_name)); |
822 |
} |
hostname = host_name; |
823 |
#endif |
|
824 |
|
#if defined(AUTHENTICATION) || defined(ENCRYPTION) |
825 |
#if defined(_SC_CRAY_SECURE_SYS) |
auth_encrypt_init (hostname, host, "TELNETD", 1); |
826 |
/* |
#endif |
827 |
* set ttyp line security label |
|
828 |
*/ |
init_env (); |
829 |
if (secflag) { |
|
830 |
char slave_dev[16]; |
/* get terminal type. */ |
831 |
|
*user_name = 0; |
832 |
sprintf(tty_dev, "/dev/pty/%03d", ptynum); |
level = getterminaltype (user_name); |
833 |
if (setdevs(tty_dev, &dv) < 0) |
setenv ("TERM", terminaltype ? terminaltype : "network", 1); |
|
fatal(net, "cannot set pty security"); |
|
|
sprintf(slave_dev, "/dev/ttyp%03d", 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 |
|
|
#ifdef HAVE_UTMP_UT_HOST |
|
|
&& (strlen(hp->h_name) <= |
|
|
(unsigned int)((utmp_len < 0) ? -utmp_len : utmp_len)) |
|
|
#endif |
|
|
) { |
|
|
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)); |
|
|
hostname = host_name; |
|
|
|
|
|
#if defined(AUTHENTICATION) || defined(ENCRYPTION) |
|
|
auth_encrypt_init(hostname, host, "TELNETD", 1); |
|
|
#endif |
|
|
|
|
|
init_env(); |
|
|
/* |
|
|
* get terminal type. |
|
|
*/ |
|
|
*user_name = 0; |
|
|
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); |
|
834 |
|
|
835 |
#if defined(_SC_CRAY_SECURE_SYS) |
pty = startslave (host, level, user_name); |
836 |
if (secflag) { |
telnet(net, pty, host); |
|
if (setulvl(dv.dv_actlvl) < 0) |
|
|
fatal(net,"cannot setulvl()"); |
|
|
if (setucmp(dv.dv_actcmp) < 0) |
|
|
fatal(net, "cannot setucmp()"); |
|
|
} |
|
|
#endif /* _SC_CRAY_SECURE_SYS */ |
|
|
|
|
|
telnet(net, pty); /* begin server processing */ |
|
|
#else |
|
|
telnet(net, pty, host); |
|
|
#endif |
|
|
/*NOTREACHED*/ |
|
837 |
} /* end of doit */ |
} /* end of doit */ |
838 |
|
|
839 |
#if defined(CRAY2) && defined(UNICOS5) && defined(UNICOS50) |
#if defined(CRAY2) && defined(UNICOS5) && defined(UNICOS50) |
854 |
* hand data to telnet receiver finite state machine. |
* hand data to telnet receiver finite state machine. |
855 |
*/ |
*/ |
856 |
void |
void |
857 |
#ifndef convex |
telnet (int f, int p, char *host) |
|
telnet(int f, int p) |
|
|
#else |
|
|
telnet(int f, int p, char *host) |
|
|
#endif |
|
858 |
{ |
{ |
859 |
int on = 1; |
int on = 1; |
860 |
#define TABBUFSIZ 512 |
#define TABBUFSIZ 512 |
861 |
char defent[TABBUFSIZ]; |
char defent[TABBUFSIZ]; |
862 |
char defstrs[TABBUFSIZ]; |
char defstrs[TABBUFSIZ]; |
863 |
#undef TABBUFSIZ |
#undef TABBUFSIZ |
864 |
#undef HE /* Make sure its not defined as a macro. */ |
#undef HE /* Make sure its not defined as a macro. */ |
865 |
char *HE; |
char *HE; |
866 |
char *HN; |
char *HN; |
867 |
char *IM; |
char *IM; |
868 |
void netflush(); |
void netflush(); |
869 |
int nfd; |
int nfd; |
870 |
|
|
871 |
/* |
/* |
872 |
* Initialize the slc mapping table. |
* Initialize the slc mapping table. |
873 |
*/ |
*/ |
874 |
get_slc_defaults(); |
get_slc_defaults (); |
875 |
|
|
876 |
/* |
/* |
877 |
* Do some tests where it is desireable to wait for a response. |
* Do some tests where it is desireable to wait for a response. |
878 |
* Rather than doing them slowly, one at a time, do them all |
* Rather than doing them slowly, one at a time, do them all |
879 |
* at once. |
* at once. |
880 |
*/ |
*/ |
881 |
if (my_state_is_wont(TELOPT_SGA)) |
if (my_state_is_wont (TELOPT_SGA)) |
882 |
send_will(TELOPT_SGA, 1); |
send_will (TELOPT_SGA, 1); |
883 |
/* |
/* |
884 |
* Is the client side a 4.2 (NOT 4.3) system? We need to know this |
* Is the client side a 4.2 (NOT 4.3) system? We need to know this |
885 |
* because 4.2 clients are unable to deal with TCP urgent data. |
* because 4.2 clients are unable to deal with TCP urgent data. |
886 |
* |
* |
887 |
* To find out, we send out a "DO ECHO". If the remote system |
* To find out, we send out a "DO ECHO". If the remote system |
888 |
* answers "WILL ECHO" it is probably a 4.2 client, and we note |
* answers "WILL ECHO" it is probably a 4.2 client, and we note |
889 |
* that fact ("WILL ECHO" ==> that the client will echo what |
* that fact ("WILL ECHO" ==> that the client will echo what |
890 |
* WE, the server, sends it; it does NOT mean that the client will |
* WE, the server, sends it; it does NOT mean that the client will |
891 |
* echo the terminal input). |
* echo the terminal input). |
892 |
*/ |
*/ |
893 |
send_do(TELOPT_ECHO, 1); |
send_do (TELOPT_ECHO, 1); |
894 |
|
|
895 |
#ifdef LINEMODE |
#ifdef LINEMODE |
896 |
if (his_state_is_wont(TELOPT_LINEMODE)) { |
if (his_state_is_wont (TELOPT_LINEMODE)) |
897 |
/* Query the peer for linemode support by trying to negotiate |
{ |
898 |
* the linemode option. |
/* Query the peer for linemode support by trying to negotiate |
899 |
*/ |
* the linemode option. |
900 |
linemode = 0; |
*/ |
901 |
editmode = 0; |
linemode = 0; |
902 |
send_do(TELOPT_LINEMODE, 1); /* send do linemode */ |
editmode = 0; |
903 |
} |
send_do (TELOPT_LINEMODE, 1); /* send do linemode */ |
904 |
|
} |
905 |
#endif /* LINEMODE */ |
#endif /* LINEMODE */ |
906 |
|
|
907 |
/* |
/* |
908 |
* Send along a couple of other options that we wish to negotiate. |
* Send along a couple of other options that we wish to negotiate. |
909 |
*/ |
*/ |
910 |
send_do(TELOPT_NAWS, 1); |
send_do (TELOPT_NAWS, 1); |
911 |
send_will(TELOPT_STATUS, 1); |
send_will (TELOPT_STATUS, 1); |
912 |
flowmode = 1; /* default flow control state */ |
flowmode = 1; /* default flow control state */ |
913 |
restartany = -1; /* uninitialized... */ |
restartany = -1; /* uninitialized... */ |
914 |
send_do(TELOPT_LFLOW, 1); |
send_do (TELOPT_LFLOW, 1); |
915 |
|
|
916 |
/* |
/* |
917 |
* Spin, waiting for a response from the DO ECHO. However, |
* Spin, waiting for a response from the DO ECHO. However, |
918 |
* some REALLY DUMB telnets out there might not respond |
* some REALLY DUMB telnets out there might not respond |
919 |
* to the DO ECHO. So, we spin looking for NAWS, (most dumb |
* to the DO ECHO. So, we spin looking for NAWS, (most dumb |
920 |
* telnets so far seem to respond with WONT for a DO that |
* telnets so far seem to respond with WONT for a DO that |
921 |
* they don't understand...) because by the time we get the |
* they don't understand...) because by the time we get the |
922 |
* response, it will already have processed the DO ECHO. |
* response, it will already have processed the DO ECHO. |
923 |
* Kludge upon kludge. |
* Kludge upon kludge. |
924 |
*/ |
*/ |
925 |
while (his_will_wont_is_changing(TELOPT_NAWS)) |
while (his_will_wont_is_changing (TELOPT_NAWS)) |
926 |
ttloop(); |
ttloop (); |
927 |
|
|
928 |
/* |
/* |
929 |
* But... |
* But... |
930 |
* The client might have sent a WILL NAWS as part of its |
* The client might have sent a WILL NAWS as part of its |
931 |
* startup code; if so, we'll be here before we get the |
* startup code; if so, we'll be here before we get the |
932 |
* response to the DO ECHO. We'll make the assumption |
* response to the DO ECHO. We'll make the assumption |
933 |
* that any implementation that understands about NAWS |
* that any implementation that understands about NAWS |
934 |
* is a modern enough implementation that it will respond |
* is a modern enough implementation that it will respond |
935 |
* to our DO ECHO request; hence we'll do another spin |
* to our DO ECHO request; hence we'll do another spin |
936 |
* waiting for the ECHO option to settle down, which is |
* waiting for the ECHO option to settle down, which is |
937 |
* what we wanted to do in the first place... |
* what we wanted to do in the first place... |
938 |
*/ |
*/ |
939 |
if (his_want_state_is_will(TELOPT_ECHO) && |
if (his_want_state_is_will (TELOPT_ECHO) |
940 |
his_state_is_will(TELOPT_NAWS)) { |
&& his_state_is_will(TELOPT_NAWS)) |
941 |
while (his_will_wont_is_changing(TELOPT_ECHO)) |
{ |
942 |
ttloop(); |
while (his_will_wont_is_changing (TELOPT_ECHO)) |
943 |
} |
ttloop (); |
944 |
/* |
} |
|
* On the off chance that the telnet client is broken and does not |
|
|
* respond to the DO ECHO we sent, (after all, we did send the |
|
|
* DO NAWS negotiation after the DO ECHO, and we won't get here |
|
|
* until a response to the DO NAWS comes back) simulate the |
|
|
* receipt of a will echo. This will also send a WONT ECHO |
|
|
* to the client, since we assume that the client failed to |
|
|
* respond because it believes that it is already in DO ECHO |
|
|
* 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);}); |
|
|
willoption(TELOPT_ECHO); |
|
|
} |
|
945 |
|
|
946 |
/* |
/* |
947 |
* Finally, to clean things up, we turn on our echo. This |
* On the off chance that the telnet client is broken and does not |
948 |
* will break stupid 4.2 telnets out of local terminal echo. |
* respond to the DO ECHO we sent, (after all, we did send the |
949 |
*/ |
* DO NAWS negotiation after the DO ECHO, and we won't get here |
950 |
|
* until a response to the DO NAWS comes back) simulate the |
951 |
|
* receipt of a will echo. This will also send a WONT ECHO |
952 |
|
* to the client, since we assume that the client failed to |
953 |
|
* respond because it believes that it is already in DO ECHO |
954 |
|
* mode, which we do not want. |
955 |
|
*/ |
956 |
|
if (his_want_state_is_will (TELOPT_ECHO)) |
957 |
|
{ |
958 |
|
DIAG (TD_OPTIONS, |
959 |
|
{sprintf (nfrontp, "td: simulating recv\r\n"); |
960 |
|
nfrontp += strlen (nfrontp);}); |
961 |
|
willoption (TELOPT_ECHO); |
962 |
|
} |
963 |
|
|
964 |
if (my_state_is_wont(TELOPT_ECHO)) |
/* |
965 |
send_will(TELOPT_ECHO, 1); |
* Finally, to clean things up, we turn on our echo. This |
966 |
|
* will break stupid 4.2 telnets out of local terminal echo. |
967 |
|
*/ |
968 |
|
|
969 |
|
if (my_state_is_wont (TELOPT_ECHO)) |
970 |
|
send_will (TELOPT_ECHO, 1); |
971 |
|
|
972 |
#ifndef HAVE_STREAMSPTY |
#ifndef HAVE_STREAMSPTY |
973 |
/* |
/* |
974 |
* Turn on packet mode |
* Turn on packet mode |
975 |
*/ |
*/ |
976 |
(void) ioctl(p, TIOCPKT, (char *)&on); |
ioctl(p, TIOCPKT, (char *)&on); |
977 |
#endif |
#endif |
978 |
|
|
979 |
#if defined(LINEMODE) && defined(KLUDGELINEMODE) |
#if defined(LINEMODE) && defined(KLUDGELINEMODE) |
980 |
/* |
/* |
981 |
* Continuing line mode support. If client does not support |
* Continuing line mode support. If client does not support |
982 |
* real linemode, attempt to negotiate kludge linemode by sending |
* real linemode, attempt to negotiate kludge linemode by sending |
983 |
* the do timing mark sequence. |
* the do timing mark sequence. |
984 |
*/ |
*/ |
985 |
if (lmodetype < REAL_LINEMODE) |
if (lmodetype < REAL_LINEMODE) |
986 |
send_do(TELOPT_TM, 1); |
send_do (TELOPT_TM, 1); |
987 |
#endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ |
#endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ |
988 |
|
|
989 |
/* |
/* |
990 |
* Call telrcv() once to pick up anything received during |
* Call telrcv() once to pick up anything received during |
991 |
* terminal type negotiation, 4.2/4.3 determination, and |
* terminal type negotiation, 4.2/4.3 determination, and |
992 |
* linemode negotiation. |
* linemode negotiation. |
993 |
*/ |
*/ |
994 |
telrcv(); |
telrcv (); |
995 |
|
|
996 |
(void) ioctl(f, FIONBIO, (char *)&on); |
ioctl (f, FIONBIO, (char *)&on); |
997 |
(void) ioctl(p, FIONBIO, (char *)&on); |
ioctl (p, FIONBIO, (char *)&on); |
998 |
#if defined(CRAY2) && defined(UNICOS5) |
#if defined(CRAY2) && defined(UNICOS5) |
999 |
init_termdriver(f, p, interrupts, sendbrk); |
init_termdriver (f, p, interrupts, sendbrk); |
1000 |
#endif |
#endif |
1001 |
|
|
1002 |
#if defined(SO_OOBINLINE) |
#if defined(SO_OOBINLINE) |
1003 |
(void) setsockopt(net, SOL_SOCKET, SO_OOBINLINE, |
setsockopt (net, SOL_SOCKET, SO_OOBINLINE, (char *)&on, sizeof on); |
|
(char *)&on, sizeof on); |
|
1004 |
#endif /* defined(SO_OOBINLINE) */ |
#endif /* defined(SO_OOBINLINE) */ |
1005 |
|
|
1006 |
#ifdef SIGTSTP |
#ifdef SIGTSTP |
1007 |
(void) signal(SIGTSTP, SIG_IGN); |
signal (SIGTSTP, SIG_IGN); |
1008 |
#endif |
#endif |
1009 |
#ifdef SIGTTOU |
#ifdef SIGTTOU |
1010 |
/* |
/* |
1011 |
* Ignoring SIGTTOU keeps the kernel from blocking us |
* Ignoring SIGTTOU keeps the kernel from blocking us |
1012 |
* in ttioct() in /sys/tty.c. |
* in ttioct() in /sys/tty.c. |
1013 |
*/ |
*/ |
1014 |
(void) signal(SIGTTOU, SIG_IGN); |
signal (SIGTTOU, SIG_IGN); |
1015 |
#endif |
#endif |
1016 |
|
|
1017 |
(void) signal(SIGCHLD, cleanup); |
signal (SIGCHLD, cleanup); |
1018 |
|
|
1019 |
#if defined(CRAY2) && defined(UNICOS5) |
#if defined(CRAY2) && defined(UNICOS5) |
1020 |
/* |
/* |
1021 |
* Cray-2 will send a signal when pty modes are changed by slave |
* Cray-2 will send a signal when pty modes are changed by slave |
1022 |
* side. Set up signal handler now. |
* side. Set up signal handler now. |
1023 |
*/ |
*/ |
1024 |
if ((int)signal(SIGUSR1, termstat) < 0) |
if ((int)signal (SIGUSR1, termstat) < 0) |
1025 |
perror("signal"); |
perror ("signal"); |
1026 |
else if (ioctl(p, TCSIGME, (char *)SIGUSR1) < 0) |
else if (ioctl (p, TCSIGME, (char *)SIGUSR1) < 0) |
1027 |
perror("ioctl:TCSIGME"); |
perror ("ioctl:TCSIGME"); |
1028 |
/* |
/* |
1029 |
* Make processing loop check terminal characteristics early on. |
* Make processing loop check terminal characteristics early on. |
1030 |
*/ |
*/ |
1031 |
termstat(); |
termstat (); |
1032 |
#endif |
#endif |
1033 |
|
|
1034 |
#ifdef TIOCNOTTY |
#ifdef TIOCNOTTY |
1035 |
{ |
{ |
1036 |
register int t; |
register int t; |
1037 |
t = open(PATH_TTY, O_RDWR); |
t = open(PATH_TTY, O_RDWR); |
1038 |
if (t >= 0) { |
if (t >= 0) |
1039 |
(void) ioctl(t, TIOCNOTTY, (char *)0); |
{ |
1040 |
(void) close(t); |
ioctl (t, TIOCNOTTY, (char *)0); |
1041 |
} |
close (t); |
1042 |
} |
} |
1043 |
|
} |
1044 |
#endif |
#endif |
1045 |
|
|
1046 |
#if defined(CRAY) && defined(NEWINIT) && defined(TIOCSCTTY) |
#if defined(CRAY) && defined(NEWINIT) && defined(TIOCSCTTY) |
1047 |
(void) setsid(); |
setsid (); |
1048 |
ioctl(p, TIOCSCTTY, 0); |
ioctl (p, TIOCSCTTY, 0); |
1049 |
#endif |
#endif |
1050 |
|
|
1051 |
/* |
/* |
1052 |
* Show banner that getty never gave. |
* Show banner that getty never gave. |
1053 |
* |
* |
1054 |
* We put the banner in the pty input buffer. This way, it |
* We put the banner in the pty input buffer. This way, it |
1055 |
* gets carriage return null processing, etc., just like all |
* gets carriage return null processing, etc., just like all |
1056 |
* other pty --> client data. |
* other pty --> client data. |
1057 |
*/ |
*/ |
1058 |
|
|
1059 |
#if !defined(CRAY) || !defined(NEWINIT) |
#if !defined(CRAY) || !defined(NEWINIT) |
1060 |
if (getenv("USER")) |
if (getenv ("USER")) |
1061 |
hostinfo = 0; |
hostinfo = 0; |
1062 |
#endif |
#endif |
1063 |
|
|
1064 |
if (getent(defent, "default") == 1) { |
if (getent (defent, "default") == 1) |
1065 |
char *getstr(); |
{ |
1066 |
char *cp=defstrs; |
char *getstr (); |
1067 |
|
char *cp=defstrs; |
1068 |
HE = getstr("he", &cp); |
|
1069 |
HN = getstr("hn", &cp); |
HE = getstr ("he", &cp); |
1070 |
IM = getstr("im", &cp); |
HN = getstr ("hn", &cp); |
1071 |
if (HN && *HN) |
IM = getstr ("im", &cp); |
1072 |
(void) strcpy(host_name, HN); |
if (HN && *HN) |
1073 |
if (IM == 0) |
strcpy (host_name, HN); |
1074 |
IM = ""; |
if (IM == 0) |
1075 |
} else { |
IM = ""; |
1076 |
|
} |
1077 |
|
else |
1078 |
|
{ |
1079 |
#ifdef HAVE_UNAME |
#ifdef HAVE_UNAME |
1080 |
struct utsname u; |
struct utsname u; |
1081 |
#endif |
#endif |
1082 |
|
|
1083 |
#ifdef DEFAULT_IM |
#ifdef DEFAULT_IM |
1084 |
IM = DEFAULT_IM; |
IM = DEFAULT_IM; |
1085 |
#else |
#else |
1086 |
IM = 0; |
IM = 0; |
1087 |
#ifdef HAVE_UNAME |
#ifdef HAVE_UNAME |
1088 |
if (uname (&u) == 0) { |
if (uname (&u) == 0) |
1089 |
IM = malloc (strlen (UNAME_IM_PREFIX) |
{ |
1090 |
+ strlen (u.sysname) |
IM = malloc (strlen (UNAME_IM_PREFIX) |
1091 |
+ 1 + strlen (u.release) |
+ strlen (u.sysname) |
1092 |
+ strlen (UNAME_IM_SUFFIX) + 1); |
+ 1 + strlen (u.release) |
1093 |
if (IM) |
+ strlen (UNAME_IM_SUFFIX) + 1); |
1094 |
sprintf (IM, "%s%s %s%s", |
if (IM) |
1095 |
UNAME_IM_PREFIX, |
sprintf (IM, "%s%s %s%s", |
1096 |
u.sysname, u.release, |
UNAME_IM_PREFIX, |
1097 |
UNAME_IM_SUFFIX); |
u.sysname, u.release, |
1098 |
} |
UNAME_IM_SUFFIX); |
1099 |
|
} |
1100 |
#endif /* HAVE_UNAME */ |
#endif /* HAVE_UNAME */ |
1101 |
if (! IM) |
if (! IM) |
1102 |
IM = "\r\n\nUNIX (%h) (%t)\r\n\n"; |
IM = "\r\n\nUNIX (%h) (%t)\r\n\n"; |
1103 |
#endif /* DEFAULT_IM */ |
#endif /* DEFAULT_IM */ |
1104 |
|
|
1105 |
HE = 0; |
HE = 0; |
1106 |
} |
} |
1107 |
|
|
1108 |
edithost(HE, host_name); |
edithost (HE, host_name); |
1109 |
if (hostinfo && *IM) |
if (hostinfo && *IM) |
1110 |
putf(IM, ptyibuf2); |
putf (IM, ptyibuf2); |
1111 |
|
|
1112 |
if (pcc) |
if (pcc) |
1113 |
(void) strncat(ptyibuf2, ptyip, pcc+1); |
strncat (ptyibuf2, ptyip, pcc+1); |
1114 |
ptyip = ptyibuf2; |
ptyip = ptyibuf2; |
1115 |
pcc = strlen(ptyip); |
pcc = strlen (ptyip); |
1116 |
#ifdef LINEMODE |
#ifdef LINEMODE |
1117 |
/* |
/* |
1118 |
* Last check to make sure all our states are correct. |
* Last check to make sure all our states are correct. |
1119 |
*/ |
*/ |
1120 |
init_termbuf(); |
init_termbuf (); |
1121 |
localstat(); |
localstat (); |
1122 |
#endif /* LINEMODE */ |
#endif /* LINEMODE */ |
1123 |
|
|
1124 |
DIAG(TD_REPORT, |
DIAG (TD_REPORT, |
1125 |
{sprintf(nfrontp, "td: Entering processing loop\r\n"); |
{sprintf (nfrontp, "td: Entering processing loop\r\n"); |
1126 |
nfrontp += strlen(nfrontp);}); |
nfrontp += strlen (nfrontp);}); |
1127 |
|
|
1128 |
#ifdef convex |
nfd = ((f > p) ? f : p) + 1; |
1129 |
startslave(host); |
for (;;) |
1130 |
#endif |
{ |
1131 |
|
fd_set ibits, obits, xbits; |
1132 |
nfd = ((f > p) ? f : p) + 1; |
register int c; |
|
for (;;) { |
|
|
fd_set ibits, obits, xbits; |
|
|
register int c; |
|
1133 |
|
|
1134 |
if (ncc < 0 && pcc < 0) |
if (ncc < 0 && pcc < 0) |
1135 |
break; |
break; |
1136 |
|
|
1137 |
#if defined(CRAY2) && defined(UNICOS5) |
#if defined(CRAY2) && defined(UNICOS5) |
1138 |
if (needtermstat) |
if (needtermstat) |
1139 |
_termstat(); |
_termstat (); |
1140 |
#endif /* defined(CRAY2) && defined(UNICOS5) */ |
#endif /* defined(CRAY2) && defined(UNICOS5) */ |
1141 |
FD_ZERO(&ibits); |
FD_ZERO (&ibits); |
1142 |
FD_ZERO(&obits); |
FD_ZERO (&obits); |
1143 |
FD_ZERO(&xbits); |
FD_ZERO (&xbits); |
1144 |
/* |
/* |
1145 |
* Never look for input if there's still |
* Never look for input if there's still |
1146 |
* stuff in the corresponding output buffer |
* stuff in the corresponding output buffer |
1147 |
*/ |
*/ |
1148 |
if (nfrontp - nbackp || pcc > 0) { |
if (nfrontp - nbackp || pcc > 0) |
1149 |
FD_SET(f, &obits); |
FD_SET (f, &obits); |
1150 |
} else { |
else |
1151 |
FD_SET(p, &ibits); |
FD_SET(p, &ibits); |
1152 |
} |
|
1153 |
if (pfrontp - pbackp || ncc > 0) { |
if (pfrontp - pbackp || ncc > 0) |
1154 |
FD_SET(p, &obits); |
FD_SET (p, &obits); |
1155 |
} else { |
else |
1156 |
FD_SET(f, &ibits); |
FD_SET (f, &ibits); |
1157 |
} |
|
1158 |
if (!SYNCHing) { |
if (!SYNCHing) |
1159 |
FD_SET(f, &xbits); |
FD_SET (f, &xbits); |
|
} |
|
|
if ((c = select(nfd, &ibits, &obits, &xbits, |
|
|
(struct timeval *)0)) < 1) { |
|
|
if (c == -1) { |
|
|
if (errno == EINTR) { |
|
|
continue; |
|
|
} |
|
|
} |
|
|
sleep(5); |
|
|
continue; |
|
|
} |
|
1160 |
|
|
1161 |
/* |
c = select (nfd, &ibits, &obits, &xbits, NULL); |
1162 |
* Any urgent data? |
if (c == -1) |
1163 |
*/ |
{ |
1164 |
if (FD_ISSET(net, &xbits)) { |
if (errno != EINTR) |
1165 |
SYNCHing = 1; |
sleep(5); |
1166 |
} |
continue; |
1167 |
|
} |
1168 |
|
|
1169 |
/* |
/* |
1170 |
* Something to read from the network... |
* Any urgent data? |
1171 |
*/ |
*/ |
1172 |
if (FD_ISSET(net, &ibits)) { |
if (FD_ISSET (net, &xbits)) |
1173 |
#if !defined(SO_OOBINLINE) |
SYNCHing = 1; |
|
/* |
|
|
* In 4.2 (and 4.3 beta) systems, the |
|
|
* OOB indication and data handling in the kernel |
|
|
* is such that if two separate TCP Urgent requests |
|
|
* come in, one byte of TCP data will be overlaid. |
|
|
* This is fatal for Telnet, but we try to live |
|
|
* with it. |
|
|
* |
|
|
* In addition, in 4.2 (and...), a special protocol |
|
|
* is needed to pick up the TCP Urgent data in |
|
|
* the correct sequence. |
|
|
* |
|
|
* What we do is: if we think we are in urgent |
|
|
* mode, we look to see if we are "at the mark". |
|
|
* If we are, we do an OOB receive. If we run |
|
|
* this twice, we will do the OOB receive twice, |
|
|
* but the second will fail, since the second |
|
|
* time we were "at the mark", but there wasn't |
|
|
* any data there (the kernel doesn't reset |
|
|
* "at the mark" until we do a normal read). |
|
|
* Once we've read the OOB data, we go ahead |
|
|
* and do normal reads. |
|
|
* |
|
|
* There is also another problem, which is that |
|
|
* since the OOB byte we read doesn't put us |
|
|
* out of OOB state, and since that byte is most |
|
|
* likely the TELNET DM (data mark), we would |
|
|
* stay in the TELNET SYNCH (SYNCHing) state. |
|
|
* So, clocks to the rescue. If we've "just" |
|
|
* received a DM, then we test for the |
|
|
* presence of OOB data when the receive OOB |
|
|
* fails (and AFTER we did the normal mode read |
|
|
* to clear "at the mark"). |
|
|
*/ |
|
|
if (SYNCHing) { |
|
|
int atmark; |
|
1174 |
|
|
1175 |
(void) ioctl(net, SIOCATMARK, (char *)&atmark); |
|
1176 |
if (atmark) { |
/* |
1177 |
ncc = recv(net, netibuf, sizeof (netibuf), MSG_OOB); |
* Something to read from the network... |
1178 |
if ((ncc == -1) && (errno == EINVAL)) { |
*/ |
1179 |
ncc = read(net, netibuf, sizeof (netibuf)); |
if (FD_ISSET (net, &ibits)) |
1180 |
if (sequenceIs(didnetreceive, gotDM)) { |
{ |
1181 |
SYNCHing = stilloob(net); |
#if !defined(SO_OOBINLINE) |
1182 |
} |
/* |
1183 |
} |
* In 4.2 (and 4.3 beta) systems, the |
1184 |
} else { |
* OOB indication and data handling in the kernel |
1185 |
ncc = read(net, netibuf, sizeof (netibuf)); |
* is such that if two separate TCP Urgent requests |
1186 |
} |
* come in, one byte of TCP data will be overlaid. |
1187 |
} else { |
* This is fatal for Telnet, but we try to live |
1188 |
ncc = read(net, netibuf, sizeof (netibuf)); |
* with it. |
1189 |
|
* |
1190 |
|
* In addition, in 4.2 (and...), a special protocol |
1191 |
|
* is needed to pick up the TCP Urgent data in |
1192 |
|
* the correct sequence. |
1193 |
|
* |
1194 |
|
* What we do is: if we think we are in urgent |
1195 |
|
* mode, we look to see if we are "at the mark". |
1196 |
|
* If we are, we do an OOB receive. If we run |
1197 |
|
* this twice, we will do the OOB receive twice, |
1198 |
|
* but the second will fail, since the second |
1199 |
|
* time we were "at the mark", but there wasn't |
1200 |
|
* any data there (the kernel doesn't reset |
1201 |
|
* "at the mark" until we do a normal read). |
1202 |
|
* Once we've read the OOB data, we go ahead |
1203 |
|
* and do normal reads. |
1204 |
|
* |
1205 |
|
* There is also another problem, which is that |
1206 |
|
* since the OOB byte we read doesn't put us |
1207 |
|
* out of OOB state, and since that byte is most |
1208 |
|
* likely the TELNET DM (data mark), we would |
1209 |
|
* stay in the TELNET SYNCH (SYNCHing) state. |
1210 |
|
* So, clocks to the rescue. If we've "just" |
1211 |
|
* received a DM, then we test for the |
1212 |
|
* presence of OOB data when the receive OOB |
1213 |
|
* fails (and AFTER we did the normal mode read |
1214 |
|
* to clear "at the mark"). |
1215 |
|
*/ |
1216 |
|
if (SYNCHing) |
1217 |
|
{ |
1218 |
|
int atmark; |
1219 |
|
|
1220 |
|
ioctl (net, SIOCATMARK, (char *)&atmark); |
1221 |
|
if (atmark) |
1222 |
|
{ |
1223 |
|
ncc = recv (net, netibuf, sizeof (netibuf), MSG_OOB); |
1224 |
|
if (ncc == -1 && errno == EINVAL) |
1225 |
|
{ |
1226 |
|
ncc = read (net, netibuf, sizeof (netibuf)); |
1227 |
|
if (sequenceIs (didnetreceive, gotDM)) |
1228 |
|
SYNCHing = stilloob (net); |
1229 |
} |
} |
1230 |
settimer(didnetreceive); |
} |
1231 |
|
else |
1232 |
|
{ |
1233 |
|
ncc = read (net, netibuf, sizeof (netibuf)); |
1234 |
|
} |
1235 |
|
} |
1236 |
|
else |
1237 |
|
{ |
1238 |
|
ncc = read (net, netibuf, sizeof (netibuf)); |
1239 |
|
} |
1240 |
|
settimer (didnetreceive); |
1241 |
#else /* !defined(SO_OOBINLINE)) */ |
#else /* !defined(SO_OOBINLINE)) */ |
1242 |
ncc = read(net, netibuf, sizeof (netibuf)); |
ncc = read (net, netibuf, sizeof (netibuf)); |
1243 |
#endif /* !defined(SO_OOBINLINE)) */ |
#endif /* !defined(SO_OOBINLINE)) */ |
1244 |
if (ncc < 0 && errno == EWOULDBLOCK) |
if (ncc < 0 && errno == EWOULDBLOCK) |
1245 |
ncc = 0; |
ncc = 0; |
1246 |
else { |
else |
1247 |
if (ncc <= 0) |
{ |
1248 |
break; |
if (ncc <= 0) |
1249 |
netip = netibuf; |
break; |
1250 |
} |
netip = netibuf; |
1251 |
DIAG((TD_REPORT | TD_NETDATA), |
} |
1252 |
{sprintf(nfrontp, "td: netread %d chars\r\n", ncc); |
DIAG ((TD_REPORT | TD_NETDATA), |
1253 |
nfrontp += strlen(nfrontp);}); |
{sprintf (nfrontp, "td: netread %d chars\r\n", ncc); |
1254 |
DIAG(TD_NETDATA, printdata("nd", netip, ncc)); |
nfrontp += strlen (nfrontp);}); |
1255 |
} |
DIAG (TD_NETDATA, printdata ("nd", netip, ncc)); |
1256 |
|
} |
1257 |
|
|
1258 |
/* |
/* |
1259 |
* Something to read from the pty... |
* Something to read from the pty... |
1260 |
*/ |
*/ |
1261 |
if (FD_ISSET(p, &ibits)) { |
if (FD_ISSET (p, &ibits)) |
1262 |
#ifndef HAVE_STREAMSPTY |
{ |
1263 |
pcc = read(p, ptyibuf, BUFSIZ); |
pcc = readstream (p, ptyibuf, BUFSIZ); |
1264 |
#else |
/* |
1265 |
pcc = readstream(p, ptyibuf, BUFSIZ); |
* On some systems, if we try to read something |
1266 |
#endif |
* off the master side before the slave side is |
1267 |
/* |
* opened, we get EIO. |
1268 |
* On some systems, if we try to read something |
*/ |
1269 |
* off the master side before the slave side is |
if (pcc < 0 && |
1270 |
* opened, we get EIO. |
(errno == EWOULDBLOCK |
|
*/ |
|
|
if (pcc < 0 && (errno == EWOULDBLOCK || |
|
1271 |
#ifdef EAGAIN |
#ifdef EAGAIN |
1272 |
errno == EAGAIN || |
|| errno == EAGAIN |
1273 |
#endif |
#endif |
1274 |
errno == EIO)) { |
|| errno == EIO)) |
1275 |
pcc = 0; |
pcc = 0; |
1276 |
} else { |
else if (pcc <= 0) |
1277 |
if (pcc <= 0) |
break; |
1278 |
break; |
|
1279 |
#if !defined(CRAY2) || !defined(UNICOS5) |
#if !defined(CRAY2) || !defined(UNICOS5) |
1280 |
#if defined (LINEMODE) && defined (TIOCPKT_IOCTL) |
#if defined (LINEMODE) && defined (TIOCPKT_IOCTL) |
1281 |
/* |
/* |
1282 |
* If ioctl from pty, pass it through net |
* If ioctl from pty, pass it through net |
1283 |
*/ |
*/ |
1284 |
if (ptyibuf[0] & TIOCPKT_IOCTL) { |
if (ptyibuf[0] & TIOCPKT_IOCTL) |
1285 |
copy_termbuf(ptyibuf+1, pcc-1); |
{ |
1286 |
localstat(); |
copy_termbuf(ptyibuf+1, pcc-1); |
1287 |
pcc = 1; |
localstat(); |
1288 |
} |
pcc = 1; |
1289 |
|
} |
1290 |
#endif /* LINEMODE && TIOCPKT_IOCTL */ |
#endif /* LINEMODE && TIOCPKT_IOCTL */ |
1291 |
if (ptyibuf[0] & TIOCPKT_FLUSHWRITE) { |
if (ptyibuf[0] & TIOCPKT_FLUSHWRITE) |
1292 |
netclear(); /* clear buffer back */ |
{ |
1293 |
|
netclear (); /* clear buffer back */ |
1294 |
#ifndef NO_URGENT |
#ifndef NO_URGENT |
1295 |
/* |
/* |
1296 |
* There are client telnets on some |
* There are client telnets on some |
1297 |
* operating systems get screwed up |
* operating systems get screwed up |
1298 |
* royally if we send them urgent |
* royally if we send them urgent |
1299 |
* mode data. |
* mode data. |
1300 |
*/ |
*/ |
1301 |
*nfrontp++ = IAC; |
*nfrontp++ = IAC; |
1302 |
*nfrontp++ = DM; |
*nfrontp++ = DM; |
1303 |
neturg = nfrontp-1; /* off by one XXX */ |
neturg = nfrontp-1; /* off by one XXX */ |
1304 |
DIAG(TD_OPTIONS, |
DIAG(TD_OPTIONS, |
1305 |
printoption("td: send IAC", DM)); |
printoption ("td: send IAC", DM)); |
1306 |
|
|
1307 |
#endif |
#endif |
1308 |
} |
} |
1309 |
if (his_state_is_will(TELOPT_LFLOW) && |
|
1310 |
(ptyibuf[0] & |
if (his_state_is_will (TELOPT_LFLOW) |
1311 |
(TIOCPKT_NOSTOP|TIOCPKT_DOSTOP))) { |
&& (ptyibuf[0] &(TIOCPKT_NOSTOP|TIOCPKT_DOSTOP))) |
1312 |
int newflow = |
{ |
1313 |
ptyibuf[0] & TIOCPKT_DOSTOP ? 1 : 0; |
int newflow = ptyibuf[0] & TIOCPKT_DOSTOP ? 1 : 0; |
1314 |
if (newflow != flowmode) { |
if (newflow != flowmode) |
1315 |
flowmode = newflow; |
{ |
1316 |
(void) sprintf(nfrontp, |
flowmode = newflow; |
1317 |
"%c%c%c%c%c%c", |
sprintf(nfrontp, |
1318 |
IAC, SB, TELOPT_LFLOW, |
"%c%c%c%c%c%c", |
1319 |
flowmode ? LFLOW_ON |
IAC, SB, TELOPT_LFLOW, |
1320 |
: LFLOW_OFF, |
flowmode ? LFLOW_ON |
1321 |
IAC, SE); |
: LFLOW_OFF, |
1322 |
nfrontp += 6; |
IAC, SE); |
1323 |
DIAG(TD_OPTIONS, printsub('>', |
nfrontp += 6; |
1324 |
(unsigned char *)nfrontp-4, |
DIAG (TD_OPTIONS, |
1325 |
4);); |
printsub ('>', (unsigned char *)nfrontp-4, 4);); |
1326 |
} |
} |
1327 |
} |
} |
1328 |
pcc--; |
pcc--; |
1329 |
ptyip = ptyibuf+1; |
ptyip = ptyibuf+1; |
1330 |
|
|
1331 |
#else /* defined(CRAY2) && defined(UNICOS5) */ |
#else /* defined(CRAY2) && defined(UNICOS5) */ |
1332 |
if (!uselinemode) { |
if (!uselinemode) |
1333 |
unpcc = pcc; |
{ |
1334 |
unptyip = ptyibuf; |
unpcc = pcc; |
1335 |
pcc = term_output(&unptyip, ptyibuf2, |
unptyip = ptyibuf; |
1336 |
&unpcc, BUFSIZ); |
pcc = term_output (&unptyip, ptyibuf2, &unpcc, BUFSIZ); |
1337 |
ptyip = ptyibuf2; |
ptyip = ptyibuf2; |
1338 |
} else |
} |
1339 |
ptyip = ptyibuf; |
else |
1340 |
|
ptyip = ptyibuf; |
1341 |
#endif /* defined(CRAY2) && defined(UNICOS5) */ |
#endif /* defined(CRAY2) && defined(UNICOS5) */ |
1342 |
} |
} |
|
} |
|
1343 |
|
|
1344 |
while (pcc > 0) { |
while (pcc > 0) |
1345 |
if ((&netobuf[BUFSIZ] - nfrontp) < 2) |
{ |
1346 |
break; |
if ((&netobuf[BUFSIZ] - nfrontp) < 2) |
1347 |
c = *ptyip++ & 0377, pcc--; |
break; |
1348 |
if (c == IAC) |
c = *ptyip++ & 0377; |
1349 |
*nfrontp++ = c; |
pcc--; |
1350 |
|
if (c == IAC) |
1351 |
|
*nfrontp++ = c; |
1352 |
#if defined(CRAY2) && defined(UNICOS5) |
#if defined(CRAY2) && defined(UNICOS5) |
1353 |
else if (c == '\n' && |
else if (c == '\n' && my_state_is_wont(TELOPT_BINARY) && newmap) |
1354 |
my_state_is_wont(TELOPT_BINARY) && newmap) |
*nfrontp++ = '\r'; |
|
*nfrontp++ = '\r'; |
|
1355 |
#endif /* defined(CRAY2) && defined(UNICOS5) */ |
#endif /* defined(CRAY2) && defined(UNICOS5) */ |
1356 |
*nfrontp++ = c; |
*nfrontp++ = c; |
1357 |
if ((c == '\r') && (my_state_is_wont(TELOPT_BINARY))) { |
if (c == '\r' && (my_state_is_wont(TELOPT_BINARY))) |
1358 |
if (pcc > 0 && ((*ptyip & 0377) == '\n')) { |
{ |
1359 |
*nfrontp++ = *ptyip++ & 0377; |
if (pcc > 0 && (*ptyip & 0377) == '\n') |
1360 |
pcc--; |
{ |
1361 |
} else |
*nfrontp++ = *ptyip++ & 0377; |
1362 |
*nfrontp++ = '\0'; |
pcc--; |
|
} |
|
1363 |
} |
} |
1364 |
|
else |
1365 |
|
*nfrontp++ = '\0'; |
1366 |
|
} |
1367 |
|
} |
1368 |
#if defined(CRAY2) && defined(UNICOS5) |
#if defined(CRAY2) && defined(UNICOS5) |
1369 |
/* |
/* |
1370 |
* If chars were left over from the terminal driver, |
* If chars were left over from the terminal driver, |
1371 |
* note their existence. |
* note their existence. |
1372 |
*/ |
*/ |
1373 |
if (!uselinemode && unpcc) { |
if (!uselinemode && unpcc) |
1374 |
pcc = unpcc; |
{ |
1375 |
unpcc = 0; |
pcc = unpcc; |
1376 |
ptyip = unptyip; |
unpcc = 0; |
1377 |
} |
ptyip = unptyip; |
1378 |
|
} |
1379 |
#endif /* defined(CRAY2) && defined(UNICOS5) */ |
#endif /* defined(CRAY2) && defined(UNICOS5) */ |
1380 |
|
|
1381 |
if (FD_ISSET(f, &obits) && (nfrontp - nbackp) > 0) |
if (FD_ISSET (f, &obits) && (nfrontp - nbackp) > 0) |
1382 |
netflush(); |
netflush (); |
1383 |
if (ncc > 0) |
if (ncc > 0) |
1384 |
telrcv(); |
telrcv (); |
1385 |
if (FD_ISSET(p, &obits) && (pfrontp - pbackp) > 0) |
if (FD_ISSET (p, &obits) && (pfrontp - pbackp) > 0) |
1386 |
ptyflush(); |
ptyflush (); |
1387 |
} |
} |
1388 |
cleanup(0); |
cleanup(0); |
1389 |
} /* end of telnet */ |
} /* end of telnet */ |
1390 |
|
|
1391 |
#ifndef TCSIG |
#ifndef TCSIG |
1394 |
# endif |
# endif |
1395 |
#endif |
#endif |
1396 |
|
|
|
#ifdef HAVE_STREAMSPTY |
|
|
|
|
1397 |
int flowison = -1; /* current state of flow: -1 is unknown */ |
int flowison = -1; /* current state of flow: -1 is unknown */ |
1398 |
|
|
1399 |
int |
int |
1400 |
readstream(int p, char *ibuf, int bufsize) |
readstream(int p, char *ibuf, int bufsize) |
1401 |
{ |
{ |
1402 |
int flags = 0; |
#ifndef HAVE_STREAMSPTY |
1403 |
int ret = 0; |
return read (p, ibuf, bufsize); |
1404 |
struct termios *tsp; |
#else |
1405 |
struct termio *tp; |
int flags = 0; |
1406 |
struct iocblk *ip; |
int ret = 0; |
1407 |
char vstop, vstart; |
struct termios *tsp; |
1408 |
int ixon; |
struct termio *tp; |
1409 |
int newflow; |
struct iocblk *ip; |
1410 |
|
char vstop, vstart; |
1411 |
strbufc.maxlen = BUFSIZ; |
int ixon; |
1412 |
strbufc.buf = (char *)ctlbuf; |
int newflow; |
1413 |
strbufd.maxlen = bufsize-1; |
|
1414 |
strbufd.len = 0; |
strbufc.maxlen = BUFSIZ; |
1415 |
strbufd.buf = ibuf+1; |
strbufc.buf = (char *)ctlbuf; |
1416 |
ibuf[0] = 0; |
strbufd.maxlen = bufsize-1; |
1417 |
|
strbufd.len = 0; |
1418 |
ret = getmsg(p, &strbufc, &strbufd, &flags); |
strbufd.buf = ibuf+1; |
1419 |
if (ret < 0) /* error of some sort -- probably EAGAIN */ |
ibuf[0] = 0; |
1420 |
return(-1); |
|
1421 |
|
ret = getmsg(p, &strbufc, &strbufd, &flags); |
1422 |
if (strbufc.len <= 0 || ctlbuf[0] == M_DATA) { |
if (ret < 0) /* error of some sort -- probably EAGAIN */ |
1423 |
/* data message */ |
return -1; |
1424 |
if (strbufd.len > 0) { /* real data */ |
|
1425 |
return(strbufd.len + 1); /* count header char */ |
if (strbufc.len <= 0 || ctlbuf[0] == M_DATA) |
1426 |
} else { |
{ |
1427 |
/* nothing there */ |
/* data message */ |
1428 |
errno = EAGAIN; |
if (strbufd.len > 0) /* real data */ |
1429 |
return(-1); |
return strbufd.len + 1; /* count header char */ |
1430 |
} |
else |
1431 |
|
{ |
1432 |
|
/* nothing there */ |
1433 |
|
errno = EAGAIN; |
1434 |
|
return -1; |
1435 |
} |
} |
1436 |
|
} |
1437 |
|
|
1438 |
/* |
/* |
1439 |
* It's a control message. Return 1, to look at the flag we set |
* It's a control message. Return 1, to look at the flag we set |
1440 |
*/ |
*/ |
1441 |
|
|
1442 |
|
switch (ctlbuf[0]) |
1443 |
|
{ |
1444 |
|
case M_FLUSH: |
1445 |
|
if (ibuf[1] & FLUSHW) |
1446 |
|
ibuf[0] = TIOCPKT_FLUSHWRITE; |
1447 |
|
return 1; |
1448 |
|
|
1449 |
switch (ctlbuf[0]) { |
case M_IOCTL: |
1450 |
case M_FLUSH: |
ip = (struct iocblk *) (ibuf+1); |
|
if (ibuf[1] & FLUSHW) |
|
|
ibuf[0] = TIOCPKT_FLUSHWRITE; |
|
|
return(1); |
|
|
|
|
|
case M_IOCTL: |
|
|
ip = (struct iocblk *) (ibuf+1); |
|
|
|
|
|
switch (ip->ioc_cmd) { |
|
|
case TCSETS: |
|
|
case TCSETSW: |
|
|
case TCSETSF: |
|
|
tsp = (struct termios *) |
|
|
(ibuf+1 + sizeof(struct iocblk)); |
|
|
vstop = tsp->c_cc[VSTOP]; |
|
|
vstart = tsp->c_cc[VSTART]; |
|
|
ixon = tsp->c_iflag & IXON; |
|
|
break; |
|
|
case TCSETA: |
|
|
case TCSETAW: |
|
|
case TCSETAF: |
|
|
tp = (struct termio *) (ibuf+1 + sizeof(struct iocblk)); |
|
|
vstop = tp->c_cc[VSTOP]; |
|
|
vstart = tp->c_cc[VSTART]; |
|
|
ixon = tp->c_iflag & IXON; |
|
|
break; |
|
|
default: |
|
|
errno = EAGAIN; |
|
|
return(-1); |
|
|
} |
|
1451 |
|
|
1452 |
newflow = (ixon && (vstart == 021) && (vstop == 023)) ? 1 : 0; |
switch (ip->ioc_cmd) |
1453 |
if (newflow != flowison) { /* it's a change */ |
{ |
1454 |
flowison = newflow; |
case TCSETS: |
1455 |
ibuf[0] = newflow ? TIOCPKT_DOSTOP : TIOCPKT_NOSTOP; |
case TCSETSW: |
1456 |
return(1); |
case TCSETSF: |
1457 |
} |
tsp = (struct termios *) (ibuf + 1 + sizeof(struct iocblk)); |
1458 |
|
vstop = tsp->c_cc[VSTOP]; |
1459 |
|
vstart = tsp->c_cc[VSTART]; |
1460 |
|
ixon = tsp->c_iflag & IXON; |
1461 |
|
break; |
1462 |
|
|
1463 |
|
case TCSETA: |
1464 |
|
case TCSETAW: |
1465 |
|
case TCSETAF: |
1466 |
|
tp = (struct termio *) (ibuf + 1 + sizeof(struct iocblk)); |
1467 |
|
vstop = tp->c_cc[VSTOP]; |
1468 |
|
vstart = tp->c_cc[VSTART]; |
1469 |
|
ixon = tp->c_iflag & IXON; |
1470 |
|
break; |
1471 |
|
|
1472 |
|
default: |
1473 |
|
errno = EAGAIN; |
1474 |
|
return -1; |
1475 |
} |
} |
1476 |
|
|
1477 |
/* nothing worth doing anything about */ |
newflow = (ixon && (vstart == 021) && (vstop == 023)) ? 1 : 0; |
1478 |
errno = EAGAIN; |
if (newflow != flowison) /* it's a change */ |
1479 |
return(-1); |
{ |
1480 |
} |
flowison = newflow; |
1481 |
|
ibuf[0] = newflow ? TIOCPKT_DOSTOP : TIOCPKT_NOSTOP; |
1482 |
|
return 1; |
1483 |
|
} |
1484 |
|
} |
1485 |
|
|
1486 |
|
/* nothing worth doing anything about */ |
1487 |
|
errno = EAGAIN; |
1488 |
|
return -1; |
1489 |
#endif /* HAVE_STREAMSPTY */ |
#endif /* HAVE_STREAMSPTY */ |
1490 |
|
} |
1491 |
|
|
1492 |
/* |
/* |
1493 |
* Send interrupt to process on other side of pty. |
* Send interrupt to process on other side of pty. |