rlogin.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 1983, 1990 The Regents of the University of California.
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. All advertising materials mentioning features or use of this software
00014  *    must display the following acknowledgement:
00015  *      This product includes software developed by the University of
00016  *      California, Berkeley and its contributors.
00017  * 4. Neither the name of the University nor the names of its contributors
00018  *    may be used to endorse or promote products derived from this software
00019  *    without specific prior written permission.
00020  *
00021  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
00022  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00023  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00024  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
00025  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00026  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00027  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00028  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00029  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00030  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00031  * SUCH DAMAGE.
00032  */
00033 
00034 #ifndef lint
00035 char copyright[] =
00036 "@(#) Copyright (c) 1983, 1990 The Regents of the University of California.\n\
00037  All rights reserved.\n";
00038 #endif /* not lint */
00039 
00040 #ifndef lint
00041 #ifdef ID
00042 static char sccsid[] = "@(#)rlogin.c    5.33 (Berkeley) 3/1/91";
00043 #endif
00044 #endif /* not lint */
00045 
00046 /*
00047  * $Source: /opt/proj/minix/cvsroot/src/commands/simple/rlogin.c,v $
00048  * $Header: mit/rlogin/RCS/rlogin.c,v 5.2 89/07/26 12:11:21 kfall
00049  *      Exp Locker: kfall $
00050  */
00051 
00052 /*
00053  * rlogin - remote login
00054  */
00055 #include <sys/ioctl.h>
00056 #include <sys/types.h>
00057 #include <sys/wait.h>
00058 
00059 #include <net/netlib.h>
00060 #include <net/hton.h>
00061 #include <net/gen/in.h>
00062 #include <net/gen/netdb.h>
00063 #include <net/gen/tcp.h>
00064 #include <net/gen/tcp_io.h>
00065 
00066 #include <termios.h>
00067 #include <setjmp.h>
00068 #include <errno.h>
00069 #include <pwd.h>
00070 #include <stdio.h>
00071 #include <unistd.h>
00072 #include <string.h>
00073 #include <assert.h>
00074 #include <ctype.h>
00075 #include <fcntl.h>
00076 #include <signal.h>
00077 #include <stdlib.h>
00078 
00079 #ifdef KERBEROS
00080 #include <kerberosIV/des.h>
00081 #include <kerberosIV/krb.h>
00082 
00083 CREDENTIALS cred;
00084 Key_schedule schedule;
00085 int use_kerberos = 1, doencrypt;
00086 char dst_realm_buf[REALM_SZ], *dest_realm = NULL;
00087 extern char *krb_realmofhost();
00088 #endif
00089 
00090 #ifndef TIOCPKT_WINDOW
00091 #define TIOCPKT_WINDOW  0x80
00092 #endif
00093 
00094 /* concession to Sun */
00095 #ifndef SIGUSR1
00096 #define SIGUSR1 30
00097 #endif
00098 
00099 extern int errno;
00100 int eight, litout, rem;
00101 
00102 int noescape;
00103 u_char escapechar = '~';
00104 
00105 struct speed
00106 {
00107         speed_t speed;
00108         char *name;
00109 } speeds[] = {
00110         { B0, "0" }, { B50, "50" }, { B75, "75" }, { B110, "110" }, 
00111         { B134, "134" }, { B150, "150" }, { B200, "200" }, { B300, "300" }, 
00112         { B600, "600" }, { B1200, "1200" }, { B1800, "1800" }, 
00113         { B2400, "2400" }, { B4800, "4800" }, { B9600, "9600" }, 
00114         { B19200, "19200" }, { B38400, "38400" }, { B57600, "57600" },
00115         { B115200, "115200" },
00116         { -1, NULL },
00117 };
00118 
00119 #if __minix_vmd
00120 /* flow control variables */
00121 int more2read_0;
00122 int inprogress_0;
00123 int more2write_1;
00124 int inprogress_1;
00125 int more2read_rem;
00126 int inprogress_rd_rem;
00127 int more2write_rem;
00128 int inprogress_wr_rem;
00129 
00130 /* write to remote */
00131 size_t wr_rem_size;
00132 size_t wr_rem_offset;
00133 size_t extra_wr_rem_size;
00134 size_t extra_wr_rem_offset;
00135 char *extra_wr_rem;
00136 size_t extra_wr_rem_new_size;
00137 char *extra_wr_rem_new;
00138 
00139 #endif /* __minix_vmd */
00140 
00141 struct  winsize winsize;
00142 
00143 #define get_window_size(fd, wp) ioctl(fd, TIOCGWINSZ, wp)
00144 
00145 extern int main _ARGS(( int argc, char **argv ));
00146 static void usage _ARGS(( void ));
00147 static u_char getescape _ARGS(( char *p ));
00148 static char *speeds2str _ARGS(( speed_t speed ));
00149 static void lostpeer _ARGS(( int sig ));
00150 static void doit _ARGS(( void ));
00151 static void setsignal _ARGS(( int sig, void (*act)(int sig) ));
00152 static void msg _ARGS(( char *str ));
00153 static void done _ARGS(( int status ));
00154 #if !__minix_vmd
00155 static int reader _ARGS(( void ));
00156 #endif
00157 static void mode _ARGS(( int f ));
00158 #if __minix_vmd
00159 static void mark_async _ARGS(( int fd ));
00160 static void init_0 _ARGS(( void ));
00161 static void init_1 _ARGS(( void ));
00162 static void init_rd_rem _ARGS(( void ));
00163 static void init_wr_rem _ARGS(( void ));
00164 static void restart_0 _ARGS(( void ));
00165 static void restart_1 _ARGS(( void ));
00166 static void restart_rd_rem _ARGS(( void ));
00167 static void restart_wr_rem _ARGS(( void ));
00168 static void completed_0 _ARGS(( int result, int error ));
00169 static void completed_1 _ARGS(( int result, int error ));
00170 static void completed_rd_rem _ARGS(( int result, int error ));
00171 static void completed_wr_rem _ARGS(( int result, int error ));
00172 static void do_urg _ARGS(( int urg_byte ));
00173 #endif
00174 #if !__minix_vmd
00175 static void catch_child _ARGS(( int sig ));
00176 static void writer _ARGS(( void ));
00177 #endif
00178 static void echo _ARGS(( int c ));
00179 #if __minix_vmd
00180 static void finish _ARGS(( void ));
00181 static void sendwindow _ARGS(( void ));
00182 static void sigwinch _ARGS(( int sig ));
00183 static void subshell _ARGS(( void ));
00184 #endif
00185 
00186 int main(argc, argv)
00187         int argc;
00188         char **argv;
00189 {
00190         extern char *optarg;
00191         extern int optind;
00192         struct passwd *pw;
00193         struct servent *sp;
00194         struct termios ttyb;
00195         nwio_tcpopt_t tcpopt;
00196         int error;
00197         int argoff, ch, dflag, one, uid;
00198         char *host, *p, *user, term[1024];
00199 
00200         argoff = dflag = 0;
00201         one = 1;
00202         host = user = NULL;
00203 
00204         if (p = rindex(argv[0], '/'))
00205                 ++p;
00206         else
00207                 p = argv[0];
00208 
00209         if (strcmp(p, "rlogin"))
00210                 host = p;
00211 
00212         /* handle "rlogin host flags" */
00213         if (!host && argc > 2 && argv[1][0] != '-') {
00214                 host = argv[1];
00215                 argoff = 1;
00216         }
00217 
00218 #ifdef KERBEROS
00219 #define OPTIONS "8EKLde:k:l:x"
00220 #else
00221 #define OPTIONS "8EKLde:l:"
00222 #endif
00223         while ((ch = getopt(argc - argoff, argv + argoff, OPTIONS)) != EOF)
00224                 switch(ch) {
00225                 case '8':
00226                         eight = 1;
00227                         break;
00228                 case 'E':
00229                         noescape = 1;
00230                         break;
00231                 case 'K':
00232 #ifdef KERBEROS
00233                         use_kerberos = 0;
00234 #endif
00235                         break;
00236                 case 'L':
00237                         litout = 1;
00238                         break;
00239                 case 'd':
00240                         dflag = 1;
00241                         break;
00242                 case 'e':
00243                         escapechar = getescape(optarg);
00244                         break;
00245 #ifdef KERBEROS
00246                 case 'k':
00247                         dest_realm = dst_realm_buf;
00248                         (void)strncpy(dest_realm, optarg, REALM_SZ);
00249                         break;
00250 #endif
00251                 case 'l':
00252                         user = optarg;
00253                         break;
00254 #ifdef CRYPT
00255 #ifdef KERBEROS
00256                 case 'x':
00257                         doencrypt = 1;
00258                         des_set_key(cred.session, schedule);
00259                         break;
00260 #endif
00261 #endif
00262                 case '?':
00263                 default:
00264                         usage();
00265                 }
00266         optind += argoff;
00267         argc -= optind;
00268         argv += optind;
00269 
00270         /* if haven't gotten a host yet, do so */
00271         if (!host && !(host = *argv++))
00272                 usage();
00273 
00274         if (*argv)
00275                 usage();
00276 
00277         if (!(pw = getpwuid(uid = getuid()))) {
00278                 (void)fprintf(stderr, "rlogin: unknown user id.\n");
00279                 exit(1);
00280         }
00281         if (!user)
00282                 user = pw->pw_name;
00283 
00284         sp = NULL;
00285 #ifdef KERBEROS
00286         if (use_kerberos) {
00287                 sp = getservbyname((doencrypt ? "eklogin" : "klogin"), "tcp");
00288                 if (sp == NULL) {
00289                         use_kerberos = 0;
00290                         warning("can't get entry for %s/tcp service",
00291                             doencrypt ? "eklogin" : "klogin");
00292                 }
00293         }
00294 #endif
00295         if (sp == NULL)
00296                 sp = getservbyname("login", "tcp");
00297         if (sp == NULL) {
00298                 (void)fprintf(stderr, "rlogin: login/tcp: unknown service.\n");
00299                 exit(1);
00300         }
00301 
00302         (void)strncpy(term, (p = getenv("TERM")) ? p : "network", sizeof(term));
00303         term[sizeof(term)-1]= 0;
00304 
00305         if (tcgetattr(0, &ttyb) == 0) {
00306                 (void)strcat(term, "/");
00307                 (void)strcat(term, speeds2str(cfgetospeed(&ttyb)));
00308         }
00309 
00310         (void)get_window_size(0, &winsize);
00311 
00312         (void)signal(SIGPIPE, lostpeer);
00313 
00314 #ifdef KERBEROS
00315 try_connect:
00316         if (use_kerberos) {
00317                 rem = KSUCCESS;
00318                 errno = 0;
00319                 if (dest_realm == NULL)
00320                         dest_realm = krb_realmofhost(host);
00321 
00322 #ifdef CRYPT
00323                 if (doencrypt)
00324                         rem = krcmd_mutual(&host, sp->s_port, user, term, 0,
00325                             dest_realm, &cred, schedule);
00326                 else
00327 #endif /* CRYPT */
00328                         rem = krcmd(&host, sp->s_port, user, term, 0,
00329                             dest_realm);
00330                 if (rem < 0) {
00331                         use_kerberos = 0;
00332                         sp = getservbyname("login", "tcp");
00333                         if (sp == NULL) {
00334                                 (void)fprintf(stderr,
00335                                     "rlogin: unknown service login/tcp.\n");
00336                                 exit(1);
00337                         }
00338                         if (errno == ECONNREFUSED)
00339                                 warning("remote host doesn't support Kerberos");
00340                         if (errno == ENOENT)
00341                                 warning("can't provide Kerberos auth data");
00342                         goto try_connect;
00343                 }
00344         } else {
00345 #ifdef CRYPT
00346                 if (doencrypt) {
00347                         (void)fprintf(stderr,
00348                             "rlogin: the -x flag requires Kerberos authentication.\n");
00349                         exit(1);
00350                 }
00351 #endif /* CRYPT */
00352                 rem = rcmd(&host, sp->s_port, pw->pw_name, user, term, 0);
00353         }
00354 #else
00355         rem = rcmd(&host, sp->s_port, pw->pw_name, user, term, 0);
00356 #endif /* KERBEROS */
00357 
00358         if (rem < 0)
00359                 exit(1);
00360 
00361         /* Enable BSD compatibility for urgent data. */
00362         tcpopt.nwto_flags= NWTO_BSD_URG;
00363         error= ioctl(rem, NWIOSTCPOPT, &tcpopt);
00364         if (error == -1)
00365         {
00366                 fprintf(stderr, "rlogin: NWIOSTCPOPT failed: %s\n",
00367                         strerror(errno));
00368         }
00369 
00370         (void)setuid(uid);
00371         doit();
00372         /*NOTREACHED*/
00373 }
00374 
00375 struct termios defattr, rawattr;
00376 #if __minix_vmd
00377 int mustsendwindow;
00378 #else
00379 int child;
00380 #endif
00381 
00382 static void
00383 doit()
00384 {
00385         struct termios sb;
00386 #if !__minix_vmd
00387         int r;
00388 #else
00389         asio_fd_set_t fd_set;
00390         struct fwait fw;
00391         int result;
00392 #endif
00393 
00394         (void)tcgetattr(0, &sb);
00395         defattr = sb;
00396         rawattr = sb;
00397 
00398         rawattr.c_iflag &= ~(ICRNL | IGNCR | INLCR | ISTRIP | IXOFF | IXON | 
00399                                                         PARMRK | IXANY);
00400         rawattr.c_oflag &= ~(OPOST);
00401         rawattr.c_lflag &= ~(ECHONL | ECHO | ICANON | IEXTEN | ISIG);
00402 
00403         (void)signal(SIGINT, SIG_IGN);
00404         setsignal(SIGHUP, exit);
00405         setsignal(SIGQUIT, exit);
00406 
00407 #if !__minix_vmd
00408         child = fork();
00409         if (child == -1) {
00410                 (void)fprintf(stderr, "rlogin: fork: %s.\n", strerror(errno));
00411                 done(1);
00412         }
00413         if (child == 0) {
00414                 mode(1);
00415                 r = reader();
00416                 if (r == 0) {
00417                         msg("connection closed.");
00418                         exit(0);
00419                 }
00420                 sleep(1);
00421                 msg("\007connection closed.");
00422                 exit(1);
00423         }
00424 
00425         (void)signal(SIGCHLD, catch_child);
00426         writer();
00427 
00428 #else /* __minix_vmd */
00429 
00430         mode(1);
00431         /* mark the file descriptors 0, 1, and rem as asynchronous. */
00432         mark_async(0);
00433         mark_async(1);
00434         mark_async(rem);
00435         init_0();
00436         init_1();
00437         init_rd_rem();
00438         init_wr_rem();
00439 
00440         for (;;)
00441         {
00442                 ASIO_FD_ZERO(&fd_set);
00443                 fw.fw_flags= 0;
00444                 fw.fw_bits= fd_set.afds_bits;
00445                 fw.fw_maxfd= ASIO_FD_SETSIZE;
00446 
00447                 if (more2read_0 && !inprogress_0)
00448                 {
00449                         restart_0();
00450                         fw.fw_flags |= FWF_NONBLOCK;
00451                 }
00452 
00453                 if (more2write_1 && !inprogress_1)
00454                 {
00455                         restart_1();
00456                         fw.fw_flags |= FWF_NONBLOCK;
00457                 }
00458 
00459                 if (more2read_rem && !inprogress_rd_rem)
00460                 {
00461                         restart_rd_rem();
00462                         fw.fw_flags |= FWF_NONBLOCK;
00463                 }
00464 
00465                 if (more2write_rem && !inprogress_wr_rem)
00466                 {
00467                         restart_wr_rem();
00468                         fw.fw_flags |= FWF_NONBLOCK;
00469                 }
00470 
00471                 if (more2read_0 && inprogress_0)
00472                         ASIO_FD_SET(0, ASIO_READ, &fd_set);
00473                 if (more2write_1 && inprogress_1)
00474                         ASIO_FD_SET(1, ASIO_WRITE, &fd_set);
00475                 if (more2read_rem && inprogress_rd_rem)
00476                         ASIO_FD_SET(rem, ASIO_READ, &fd_set);
00477                 if (more2write_rem && inprogress_wr_rem)
00478                         ASIO_FD_SET(rem, ASIO_WRITE, &fd_set);
00479 
00480                 for (;;)
00481                 {
00482                         result= fwait(&fw);
00483                         if (result == -1 && (errno == EAGAIN || 
00484                                                         errno == EINTR))
00485                         {
00486                                 break;
00487                         }
00488                         if (result == -1)
00489                         {
00490                                 fprintf(stderr, "fwait failed (%s)\n", 
00491                                                         strerror(errno));
00492                                 exit(1);
00493                         }
00494                         assert(result == 0);
00495 #if 0
00496 printf("fwait: fw_fw= %d, fw_operation= %d, fw_result= %d, fw.fw_errno= %d\n",
00497         fw.fw_fd, fw.fw_operation, fw.fw_result, fw.fw_errno);
00498 #endif
00499                         if (fw.fw_fd == 0 && fw.fw_operation == ASIO_READ)
00500                         {
00501                                 completed_0(fw.fw_result, fw.fw_errno);
00502                         }
00503                         else if (fw.fw_fd == 1 && 
00504                                         fw.fw_operation == ASIO_WRITE)
00505                         {
00506                                 completed_1(fw.fw_result, fw.fw_errno);
00507                         }
00508                         else if (fw.fw_fd == rem && 
00509                                         fw.fw_operation == ASIO_READ)
00510                         {
00511                                 completed_rd_rem(fw.fw_result, fw.fw_errno);
00512                         }
00513                         else if (fw.fw_fd == rem && 
00514                                         fw.fw_operation == ASIO_WRITE)
00515                         {
00516                                 completed_wr_rem(fw.fw_result, fw.fw_errno);
00517                         }
00518                         else
00519                         {
00520                                 fprintf(stderr,
00521                         "strange result from fwait: fd= %d, operation= %d\n",
00522                                         fw.fw_fd, fw.fw_operation);
00523                                 exit(1);
00524                         }
00525                         if (!(fw.fw_flags & FWF_MORE))
00526                                 break;
00527                 }
00528                 if (mustsendwindow)
00529                 {
00530                         mustsendwindow= 0;
00531                         sendwindow();
00532                 }
00533         }
00534 #endif /* __minix_vmd */
00535         msg("connection closed.");
00536         done(0);
00537 }
00538 
00539 /* trap a signal, unless it is being ignored. */
00540 static void
00541 setsignal(sig, act)
00542         int sig;
00543         void (*act) _ARGS(( int sig ));
00544 {
00545         if (signal(sig, act) == SIG_IGN)
00546                 (void)signal(sig, SIG_IGN);
00547 }
00548 
00549 static void
00550 done(status)
00551         int status;
00552 {
00553         int w, wstatus;
00554 
00555         mode(0);
00556 #if !__minix_vmd
00557         if (child > 0) {
00558                 /* make sure catch_child does not snap it up */
00559                 (void)signal(SIGCHLD, SIG_DFL);
00560                 if (kill(child, SIGKILL) >= 0)
00561                         while ((w = wait(&wstatus)) > 0 && w != child);
00562         }
00563 #endif
00564         exit(status);
00565 }
00566 
00567 int dosigwinch;
00568 #if !__minix
00569 void sigwinch();
00570 #endif
00571 
00572 #if !__minix_vmd
00573 static void
00574 catch_child(sig)
00575         int sig;
00576 {
00577         int status;
00578         int pid;
00579 
00580         for (;;) {
00581                 pid = waitpid(-1, &status, WNOHANG|WUNTRACED);
00582                 if (pid == 0)
00583                         return;
00584                 /* if the child (reader) dies, just quit */
00585                 if (pid < 0 || pid == child && !WIFSTOPPED(status))
00586                         done(WTERMSIG(status) | WEXITSTATUS(status));
00587         }
00588         /* NOTREACHED */
00589 }
00590 #endif
00591 
00592 #if !__minix_vmd
00593 /*
00594  * writer: write to remote: 0 -> line.
00595  * ~.                           terminate
00596  * ~^Z                          suspend rlogin process.
00597  * ~<delayed-suspend char>      suspend rlogin process, but leave reader alone.
00598  */
00599 static void
00600 writer()
00601 {
00602         register int bol, local, n;
00603         u_char ch;
00604         int c;
00605 
00606         bol = 1;                        /* beginning of line */
00607         local = 0;
00608         for (;;) {
00609                 n = read(STDIN_FILENO, &ch, 1);
00610                 if (n <= 0) {
00611                         if (n < 0 && errno == EINTR)
00612                                 continue;
00613                         break;
00614                 }
00615                 c = ch;
00616                 /*
00617                  * If we're at the beginning of the line and recognize a
00618                  * command character, then we echo locally.  Otherwise,
00619                  * characters are echo'd remotely.  If the command character
00620                  * is doubled, this acts as a force and local echo is
00621                  * suppressed.
00622                  */
00623                 if (bol) {
00624                         bol = 0;
00625                         if (!noescape && c == escapechar) {
00626                                 local = 1;
00627                                 continue;
00628                         }
00629                 } else if (local) {
00630                         local = 0;
00631                         if (c == '.' || c == defattr.c_cc[VEOF]) {
00632                                 echo(c);
00633                                 break;
00634                         }
00635 #if !__minix
00636                         if (c == defattr.c_cc[VSUSP]) {
00637                                 bol = 1;
00638                                 echo(c);
00639                                 stop(c);
00640                                 continue;
00641                         }
00642 #endif
00643                         if (c != escapechar)
00644 #ifdef CRYPT
00645 #ifdef KERBEROS
00646                                 if (doencrypt)
00647                                         (void)des_write(rem, &escapechar, 1);
00648                                 else
00649 #endif
00650 #endif
00651                                         (void)write(rem, &escapechar, 1);
00652                 }
00653 
00654                 ch = c;
00655 #ifdef CRYPT
00656 #ifdef KERBEROS
00657                 if (doencrypt) {
00658                         if (des_write(rem, &ch, 1) == 0) {
00659                                 msg("line gone");
00660                                 break;
00661                         }
00662                 } else
00663 #endif
00664 #endif
00665                         if (write(rem, &ch, 1) == 0) {
00666                                 msg("line gone");
00667                                 break;
00668                         }
00669                 bol = c == defattr.c_cc[VKILL] ||
00670                     c == defattr.c_cc[VEOF] ||
00671                     c == defattr.c_cc[VINTR] ||
00672                     c == defattr.c_cc[VSUSP] ||
00673                     c == '\r' || c == '\n';
00674         }
00675 }
00676 #endif
00677 
00678 #if !__minix_vmd
00679 static void
00680 echo(c)
00681 int c;
00682 {
00683         register char *p;
00684         char buf[8];
00685 
00686         p = buf;
00687         c &= 0177;
00688         *p++ = escapechar;
00689         if (c < ' ') {
00690                 *p++ = '^';
00691                 *p++ = c + '@';
00692         } else if (c == 0177) {
00693                 *p++ = '^';
00694                 *p++ = '?';
00695         } else
00696                 *p++ = c;
00697         *p++ = '\r';
00698         *p++ = '\n';
00699         (void)write(STDOUT_FILENO, buf, p - buf);
00700 }
00701 #endif
00702 
00703 #if !__minix
00704 stop(cmdc)
00705         char cmdc;
00706 {
00707         mode(0);
00708         (void)signal(SIGCHLD, SIG_IGN);
00709         (void)kill(cmdc == defltc.t_suspc ? 0 : getpid(), SIGTSTP);
00710         (void)signal(SIGCHLD, catch_child);
00711         mode(1);
00712         sigwinch();                     /* check for size changes */
00713 }
00714 #endif
00715 
00716 #if __minix_vmd
00717 #ifdef SIGWINCH
00718 static void
00719 sigwinch(sig)
00720         int sig;
00721 {
00722         struct winsize ws;
00723 
00724 #if __minix
00725         signal(SIGWINCH, sigwinch);
00726 #endif
00727 
00728         if (dosigwinch && get_window_size(0, &ws) == 0 &&
00729             memcmp(&ws, &winsize, sizeof(ws))) {
00730                 winsize = ws;
00731                 mustsendwindow= 1;
00732         }
00733 }
00734 
00735 /*
00736  * Send the window size to the server via the magic escape
00737  */
00738 static void
00739 sendwindow()
00740 {
00741         struct winsize *wp;
00742         char *obuf, *new_buf;
00743 
00744         new_buf= realloc(extra_wr_rem_new, 
00745                                         extra_wr_rem_new_size+4+sizeof(*wp));
00746         if (new_buf == 0)
00747                 return;
00748         extra_wr_rem_new= new_buf;
00749         obuf= new_buf+extra_wr_rem_new_size;
00750         extra_wr_rem_new_size += 4+sizeof(*wp);
00751 
00752         more2read_0= 0;
00753         more2write_rem= 1;
00754 
00755         wp = (struct winsize *)(obuf+4);
00756         obuf[0] = 0377;
00757         obuf[1] = 0377;
00758         obuf[2] = 's';
00759         obuf[3] = 's';
00760         wp->ws_row = htons(winsize.ws_row);
00761         wp->ws_col = htons(winsize.ws_col);
00762         wp->ws_xpixel = htons(winsize.ws_xpixel);
00763         wp->ws_ypixel = htons(winsize.ws_ypixel);
00764 }
00765 #endif /* SIGWINCH */
00766 #endif
00767 
00768 #if !__minix_vmd
00769 /*
00770  * reader: read from remote: line -> 1
00771  */
00772 #define READING 1
00773 #define WRITING 2
00774 
00775 int rcvcnt, rcvstate;
00776 char rcvbuf[8 * 1024];
00777 
00778 static int
00779 reader()
00780 {
00781         int pid = -getpid();
00782         int n, remaining;
00783         char *bufp = rcvbuf;
00784 
00785         for (;;) {
00786                 while ((remaining = rcvcnt - (bufp - rcvbuf)) > 0) {
00787                         rcvstate = WRITING;
00788                         n = write(STDOUT_FILENO, bufp, remaining);
00789                         if (n < 0) {
00790                                 if (errno != EINTR)
00791                                         return(-1);
00792                                 continue;
00793                         }
00794                         bufp += n;
00795                 }
00796                 bufp = rcvbuf;
00797                 rcvcnt = 0;
00798                 rcvstate = READING;
00799 
00800 #ifdef CRYPT
00801 #ifdef KERBEROS
00802                 if (doencrypt)
00803                         rcvcnt = des_read(rem, rcvbuf, sizeof(rcvbuf));
00804                 else
00805 #endif
00806 #endif
00807                         rcvcnt = read(rem, rcvbuf, sizeof (rcvbuf));
00808                 if (rcvcnt == 0)
00809                         return (0);
00810                 if (rcvcnt < 0) {
00811                         if (errno == EINTR)
00812                                 continue;
00813                         if (errno == EURG) {
00814                                 nwio_tcpopt_t tcpopt;
00815 #if DEBUG
00816 fprintf(stderr, "\n\rEURG\n\r");
00817 #endif
00818                                 tcpopt.nwto_flags= NWTO_RCV_URG;
00819                                 if (ioctl(rem, NWIOSTCPOPT, &tcpopt) == -1) {
00820                                         fprintf(stderr,
00821                                 "rlogin: trouble with urgent data: %s\n",
00822                                                 strerror(errno));
00823                                         return(-1);
00824                                 }
00825                                 continue;
00826                         }
00827                         if (errno == ENOURG) {
00828                                 nwio_tcpopt_t tcpopt;
00829 #if DEBUG
00830 fprintf(stderr, "\n\rENOURG\n\r");
00831 #endif
00832                                 tcpopt.nwto_flags= NWTO_RCV_NOTURG;
00833                                 if (ioctl(rem, NWIOSTCPOPT, &tcpopt) == -1) {
00834                                         fprintf(stderr,
00835                                 "rlogin: trouble with not-urgent data: %s\n",
00836                                                 strerror(errno));
00837                                         return(-1);
00838                                 }
00839                                 continue;
00840                         }
00841                         (void)fprintf(stderr, "rlogin: read: %s\n",
00842                                 strerror(errno));
00843                         return(-1);
00844                 }
00845         }
00846 }
00847 #endif  /* !__minix_vmd */
00848 
00849 static void
00850 mode(f)
00851         int f;
00852 {
00853         struct termios *sb;
00854 
00855         switch(f) {
00856         case 0:
00857                 sb= &defattr;
00858                 break;
00859         case 1:
00860                 sb= &rawattr;
00861                 break;
00862         default:
00863                 return;
00864         }
00865         (void)tcsetattr(0, TCSAFLUSH, sb);
00866 }
00867 
00868 static void
00869 lostpeer(sig)
00870 int sig;
00871 {
00872         (void)signal(SIGPIPE, SIG_IGN);
00873         msg("\007connection closed.");
00874         done(1);
00875 }
00876 
00877 static void
00878 msg(str)
00879         char *str;
00880 {
00881         (void)fprintf(stderr, "rlogin: %s\r\n", str);
00882 }
00883 
00884 #ifdef KERBEROS
00885 /* VARARGS */
00886 warning(va_alist)
00887 va_dcl
00888 {
00889         va_list ap;
00890         char *fmt;
00891 
00892         (void)fprintf(stderr, "rlogin: warning, using standard rlogin: ");
00893         va_start(ap);
00894         fmt = va_arg(ap, char *);
00895         vfprintf(stderr, fmt, ap);
00896         va_end(ap);
00897         (void)fprintf(stderr, ".\n");
00898 }
00899 #endif
00900 
00901 static void
00902 usage()
00903 {
00904         (void)fprintf(stderr,
00905             "Usage: rlogin [-%s]%s[-e char] [-l username] host\n",
00906 #ifdef KERBEROS
00907 #ifdef CRYPT
00908             "8ELx", " [-k realm] ");
00909 #else
00910             "8EL", " [-k realm] ");
00911 #endif
00912 #else
00913             "8EL", " ");
00914 #endif
00915         exit(1);
00916 }
00917 
00918 /*
00919  * The following routine provides compatibility (such as it is) between 4.2BSD
00920  * Suns and others.  Suns have only a `ttysize', so we convert it to a winsize.
00921  */
00922 #ifdef sun
00923 get_window_size(fd, wp)
00924         int fd;
00925         struct winsize *wp;
00926 {
00927         struct ttysize ts;
00928         int error;
00929 
00930         if ((error = ioctl(0, TIOCGSIZE, &ts)) != 0)
00931                 return(error);
00932         wp->ws_row = ts.ts_lines;
00933         wp->ws_col = ts.ts_cols;
00934         wp->ws_xpixel = 0;
00935         wp->ws_ypixel = 0;
00936         return(0);
00937 }
00938 #endif
00939 
00940 static u_char
00941 getescape(p)
00942         register char *p;
00943 {
00944         long val;
00945         int len;
00946 
00947         if ((len = strlen(p)) == 1)     /* use any single char, including '\' */
00948                 return((u_char)*p);
00949                                         /* otherwise, \nnn */
00950         if (*p == '\\' && len >= 2 && len <= 4) {
00951                 val = strtol(++p, (char **)NULL, 8);
00952                 for (;;) {
00953                         if (!*++p)
00954                                 return((u_char)val);
00955                         if (*p < '0' || *p > '8')
00956                                 break;
00957                 }
00958         }
00959         msg("illegal option value -- e");
00960         usage();
00961         /* NOTREACHED */
00962 }
00963 
00964 static char *
00965 speeds2str(speed)
00966         speed_t speed;
00967 {
00968         int i;
00969         for (i= 0; speeds[i].name != NULL && speeds[i].speed != speed; i++) {
00970                 if (speeds[i].speed == speed) return speeds[i].name;
00971         }
00972         return "unknown";
00973 }
00974 
00975 #if __minix_vmd
00976 static void 
00977 mark_async(fd)
00978         int fd;
00979 {
00980         int result;
00981         int v;
00982 
00983         result= fcntl(fd, F_GETFD);
00984         if (result == -1)
00985         {
00986                 fprintf(stderr,
00987                         "rlogin: mark_async: fcntl(%d, GETFD) failed (%s)\n",
00988                         fd, strerror(errno));
00989                 exit(1);
00990         }
00991         v= result | FD_ASYNCHIO;
00992         result= fcntl(fd, F_SETFD, v);
00993         if (result == -1)
00994         {
00995                 fprintf(stderr, 
00996                 "rlogin: mark_async: fcntl(%d, SETFD, %d) failed (%s)\n",
00997                         fd, v, strerror(errno));
00998                 exit(1);
00999         }
01000 }
01001 
01002 #define RD_0_BUFSIZE    256
01003 char rd_0_buf[RD_0_BUFSIZE];
01004 size_t rd_0_offset;
01005 
01006 static void
01007 init_0()
01008 {
01009         more2read_0= 1;
01010         inprogress_0= 0;
01011         rd_0_offset= 0;
01012 }
01013 
01014 size_t wr_1_size;
01015 size_t wr_1_offset;
01016 char *urg_1;
01017 size_t urg_1_size;
01018 char *extra_1;
01019 size_t extra_1_size;
01020 size_t extra_1_offset;
01021 char *extra_1_new;
01022 size_t extra_1_new_size;
01023 #define MAX_EXTRA_1_NEW_SIZE    (16*1024)
01024 
01025 static void
01026 init_1()
01027 {
01028         more2write_1= 0;
01029         inprogress_1= 0;
01030         wr_1_size= 0;
01031         wr_1_offset= 0;
01032         urg_1= NULL;
01033         urg_1_size= 0;
01034         extra_1= NULL;
01035         extra_1_size= 0;
01036         extra_1_offset= 0;
01037         extra_1_new= NULL;
01038         extra_1_new_size= 0;
01039 }
01040 
01041 #define RD_REM_BUFSIZE  (8*1024)
01042 char rd_rem_buf[RD_REM_BUFSIZE];
01043 size_t rd_rem_offset;
01044 int rd_rem_urg;
01045 
01046 static void 
01047 init_rd_rem()
01048 {
01049         more2read_rem= 1;
01050         inprogress_rd_rem= 0;
01051         rd_rem_offset= 0;
01052         rd_rem_urg= 0;
01053 }
01054 
01055 static void 
01056 init_wr_rem()
01057 {
01058         more2write_rem= 0;
01059         inprogress_wr_rem= 0;
01060         wr_rem_size= 0;
01061         wr_rem_offset= 0;
01062         extra_wr_rem_size= 0;
01063         extra_wr_rem_offset= 0;
01064         extra_wr_rem= NULL;
01065         extra_wr_rem_new_size= 0;
01066         extra_wr_rem_new= NULL;
01067 }
01068 
01069 static void
01070 restart_0()
01071 {
01072         size_t offset;
01073         int result, error;
01074 
01075         assert(!inprogress_0);
01076         rd_0_offset= 1;
01077         offset= 0;
01078         while (offset < RD_0_BUFSIZE)
01079         {
01080                 result= read(0, rd_0_buf+rd_0_offset+offset,
01081                                         RD_0_BUFSIZE-rd_0_offset-offset);
01082                 if (result > 0)
01083                 {
01084                         offset += result;
01085                         assert(rd_0_offset+offset <= RD_0_BUFSIZE);
01086                         continue;
01087                 }
01088                 error= errno;
01089 
01090                 if (offset != 0)
01091                         completed_0(offset, 0);
01092                 rd_0_offset += offset;
01093                 if (result == -1 && error == EINPROGRESS)
01094                 {
01095                         inprogress_0= 1;
01096                         return;
01097                 }
01098                 completed_0(result, error);
01099                 return;
01100         }
01101         completed_0(offset, 0);
01102 }
01103 
01104 static void 
01105 restart_1()
01106 {
01107         size_t offset;
01108         int result, error;
01109 
01110         assert(!inprogress_1);
01111 
01112         while (extra_1 != NULL || extra_1_new != NULL)
01113         {
01114                 if (extra_1 == NULL)
01115                 {
01116                         extra_1= extra_1_new;
01117                         extra_1_new= NULL;
01118                         extra_1_size= extra_1_new_size;
01119                         extra_1_new_size= 0;
01120                         extra_1_offset= 0;
01121                 }
01122                 offset= 0;
01123 #if DEBUG
01124                 if (extra_1_size == 0)
01125                         fprintf(stderr, "restart_1: extra_1_size= 0\n");
01126 #endif
01127                 while (offset < extra_1_size)
01128                 {
01129                         result= write(1, extra_1+extra_1_offset+offset, 
01130                                                         extra_1_size-offset);
01131                         if (result > 0)
01132                         {
01133                                 assert (result <= extra_1_size-offset);
01134                                 offset += result;
01135                                 continue;
01136                         }
01137                         error= errno;
01138                         if (offset != 0)
01139                                 completed_1(offset, 0);
01140 
01141                         if (result == -1 && errno == EINPROGRESS)
01142                         {
01143                                 inprogress_1= 1;
01144                                 return;
01145                         }
01146                         completed_1(result, errno);
01147                         return;
01148                 }
01149                 completed_1(offset, 0);
01150         }
01151 
01152         offset= 0;
01153 
01154         if (wr_1_size == 0)
01155         {
01156                 more2write_1= 0;
01157                 more2read_rem= 1;
01158                 return;
01159         }
01160 
01161         while (offset < wr_1_size)
01162         {
01163                 result= write(1, rd_rem_buf+wr_1_offset+offset, 
01164                                                         wr_1_size-offset);
01165                 if (result > 0)
01166                 {
01167                         assert (result <= wr_1_size-offset);
01168                         offset += result;
01169                         continue;
01170                 }
01171                 error= errno;
01172                 if (offset != 0)
01173                         completed_1(offset, 0);
01174 
01175                 if (result == -1 && errno == EINPROGRESS)
01176                 {
01177                         inprogress_1= 1;
01178                         return;
01179                 }
01180                 completed_1(result, errno);
01181                 return;
01182         }
01183         completed_1(offset, 0);
01184 }
01185 
01186 static void
01187 restart_rd_rem()
01188 {
01189         size_t offset;
01190         int result, error;
01191 
01192         assert(!inprogress_rd_rem);
01193         rd_rem_offset= 0;
01194         offset= 0;
01195         while (offset < RD_REM_BUFSIZE)
01196         {
01197                 result= read(rem, rd_rem_buf+offset, RD_REM_BUFSIZE-offset);
01198                 if (result > 0)
01199                 {
01200                         offset += result;
01201                         assert(offset <= RD_REM_BUFSIZE);
01202                         continue;
01203                 }
01204                 error= errno;
01205 
01206                 if (offset != 0)
01207                         completed_rd_rem(offset, 0);
01208                 rd_rem_offset= offset;
01209                 if (result == -1 && error == EINPROGRESS)
01210                 {
01211                         inprogress_rd_rem= 1;
01212                         return;
01213                 }
01214                 completed_rd_rem(result, error);
01215                 return;
01216         }
01217         completed_rd_rem(offset, 0);
01218 }
01219 
01220 static void
01221 restart_wr_rem()
01222 {
01223         size_t offset;
01224         int result, error;
01225 
01226         assert(!inprogress_wr_rem);
01227 
01228         if (extra_wr_rem_new != NULL && extra_wr_rem == NULL)
01229         {
01230                 extra_wr_rem= extra_wr_rem_new;
01231                 extra_wr_rem_size= extra_wr_rem_new_size;
01232                 extra_wr_rem_offset= 0;
01233                 extra_wr_rem_new= NULL;
01234                 extra_wr_rem_new_size= 0;
01235         }
01236         if (extra_wr_rem != NULL)
01237         {
01238                 offset= 0;
01239                 while (offset < extra_wr_rem_size)
01240                 {
01241                         result= write(rem, 
01242                                 extra_wr_rem+extra_wr_rem_offset+offset, 
01243                                                 extra_wr_rem_size-offset);
01244                         if (result > 0)
01245                         {
01246                                 assert (result <= extra_wr_rem_size-offset);
01247                                 offset += result;
01248                                 continue;
01249                         }
01250                         error= errno;
01251                         if (offset != 0)
01252                                 completed_wr_rem(offset, 0);
01253 
01254                         if (result == -1 && errno == EINPROGRESS)
01255                         {
01256                                 inprogress_wr_rem= 1;
01257                                 return;
01258                         }
01259                         completed_wr_rem(result, errno);
01260                         return;
01261                 }
01262                 completed_wr_rem(offset, 0);
01263         }
01264         if (wr_rem_size == 0)
01265                 return;
01266 
01267         offset= 0;
01268         while (offset < wr_rem_size)
01269         {
01270                 result= write(rem, rd_0_buf+wr_rem_offset+offset, 
01271                                                         wr_rem_size-offset);
01272                 if (result > 0)
01273                 {
01274                         assert (result <= wr_rem_size-offset);
01275                         offset += result;
01276                         continue;
01277                 }
01278                 error= errno;
01279                 if (offset != 0)
01280                         completed_wr_rem(offset, 0);
01281 
01282                 if (result == -1 && errno == EINPROGRESS)
01283                 {
01284                         inprogress_wr_rem= 1;
01285                         return;
01286                 }
01287                 completed_wr_rem(result, errno);
01288                 return;
01289         }
01290         completed_wr_rem(offset, 0);
01291 }
01292 
01293 static void
01294 completed_0(result, error)
01295         int result;
01296         int error;
01297 {
01298         static int bol= 0, local= 0;
01299 
01300         char *iptr, *optr;
01301         int i;
01302         u_char c;
01303 
01304         inprogress_0= 0;
01305 
01306         if (result > 0)
01307         {
01308                 assert(rd_0_offset > 0);
01309                 wr_rem_offset= 1;
01310 
01311                 iptr= rd_0_buf+rd_0_offset;
01312                 optr= rd_0_buf+wr_rem_offset;
01313                 for (i= 0; i<result; iptr++, i++)
01314                 {
01315                         c= *iptr;
01316                         if (bol)
01317                         {
01318                                 bol= 0;
01319                                 if (!noescape && c == escapechar)
01320                                 {
01321                                         local= 1;
01322                                         continue;
01323                                 }
01324                         }
01325                         else if (local)
01326                         {
01327                                 local= 0;
01328                                 if (c == '.' || (c != _POSIX_VDISABLE &&
01329                                         c == defattr.c_cc[VEOF]))
01330                                 {
01331                                         echo(c);
01332                                         finish();
01333                                         /* NOTREACHED */
01334                                 }
01335                                 if (c == '!')
01336                                 {
01337                                         subshell();
01338                                         continue;
01339                                 }
01340                                 if (c != escapechar)
01341                                 {
01342                                         if (optr < iptr)
01343                                         {
01344                                                 *(optr++)= escapechar;
01345                                         }
01346                                         else
01347                                         {
01348                                                 assert(optr == iptr);
01349                                                 assert(iptr == rd_0_buf+
01350                                                                 rd_0_offset);
01351                                                 assert(rd_0_offset > 0);
01352                                                 wr_rem_offset--;
01353                                                 optr[-1]= escapechar;
01354                                         }
01355                                 }
01356                         }
01357                         *(optr++)= c;
01358                         bol= (c != _POSIX_VDISABLE) && 
01359                                 (c == defattr.c_cc[VKILL] ||
01360                                 c == defattr.c_cc[VEOF] ||
01361                                 c == defattr.c_cc[VINTR] ||
01362                                 c == defattr.c_cc[VSUSP] ||
01363                                 c == '\r' || c == '\n');
01364                 }
01365                 wr_rem_size += optr-rd_0_buf-wr_rem_offset;
01366                 if (wr_rem_size != 0)
01367                 {
01368                         more2read_0= 0;
01369                         more2write_rem= 1;
01370                 }
01371                 return;
01372         } else
01373         if (result < 0) {
01374                 fprintf(stderr, "rlogin: %s\n", strerror(error));
01375         }
01376         done(1);
01377 }
01378 
01379 static void
01380 completed_1(result, error)
01381         int result;
01382         int error;
01383 {
01384         inprogress_1= 0;
01385 
01386         if (result > 0)
01387         {
01388                 if (extra_1 != NULL)
01389                 {
01390                         assert (result <= extra_1_size);
01391                         extra_1_size -= result;
01392                         extra_1_offset += result;
01393                         if (extra_1_size == 0)
01394                         {
01395                                 more2write_1= 0;
01396                                 more2read_rem= 1;
01397                                 free(extra_1);
01398                                 extra_1= NULL;
01399                         }
01400                         return;
01401                 }
01402                 assert (result <= wr_1_size);
01403                 wr_1_size -= result;
01404                 wr_1_offset += result;
01405                 if (wr_1_size == 0)
01406                 {
01407                         more2write_1= 0;
01408                         more2read_rem= 1;
01409                 }
01410                 return;
01411         } else
01412         if (result < 0) {
01413                 fprintf(stderr, "rlogin: %s\n", strerror(error));
01414         }
01415         done(1);
01416 }
01417 
01418 static void
01419 completed_rd_rem(result, error)
01420         int result;
01421         int error;
01422 {
01423         nwio_tcpopt_t tcpopt;
01424         char *new_buf;
01425         size_t keep_size;
01426         u_char urg_byte;
01427         int i;
01428 
01429         inprogress_rd_rem= 0;
01430 
01431         if (result > 0)
01432         {
01433                 if (rd_rem_urg)
01434                 {
01435 #if DEBUG
01436 fprintf(stderr, "\n\r%d urg bytes\n\r", result);
01437 #endif
01438                         if (urg_1_size > MAX_EXTRA_1_NEW_SIZE)
01439                         {
01440                                 keep_size= MAX_EXTRA_1_NEW_SIZE/2;
01441                                 memmove(urg_1, urg_1+urg_1_size-keep_size, 
01442                                         keep_size);
01443                                 urg_1_size= keep_size;
01444                         }
01445                         new_buf= realloc(urg_1, urg_1_size+result);
01446                         if (new_buf == NULL)
01447                         {
01448                                 fprintf(stderr, 
01449                                         "rlogin: warning realloc %d failed\n",
01450                                         urg_1_size+result);
01451                                 return;
01452                         }
01453                         memcpy(new_buf+urg_1_size, 
01454                                 rd_rem_buf+rd_rem_offset, result);
01455                         urg_1= new_buf;
01456                         urg_1_size += result;
01457                         return;
01458                 }
01459                 more2read_rem= 0;
01460                 more2write_1= 1;
01461                 wr_1_size= result;
01462                 wr_1_offset= rd_rem_offset;
01463                 return;
01464         }
01465         if (result == -1 && error == EURG)
01466         {
01467 #if DEBUG
01468 fprintf(stderr, "\n\rEURG\n\r");
01469 #endif
01470                 rd_rem_urg= 1;
01471                 tcpopt.nwto_flags= NWTO_RCV_URG;
01472                 result= ioctl(rem, NWIOSTCPOPT, &tcpopt);
01473                 if (result == -1)
01474                 {
01475                         fprintf(stderr, 
01476                                 "rlogin: NWIOSTCPOPT on %d failed (%s)\n",
01477                                 rem, strerror(errno));
01478                         exit(1);
01479                 }
01480                 return;
01481         }
01482         if (result == -1 && error == ENOURG)
01483         {
01484 #if DEBUG
01485 fprintf(stderr, "\n\rENOURG\n\r");
01486 #endif
01487                 rd_rem_urg= 0;
01488                 tcpopt.nwto_flags= NWTO_RCV_NOTURG;
01489                 result= ioctl(rem, NWIOSTCPOPT, &tcpopt);
01490                 if (result == -1)
01491                 {
01492                         fprintf(stderr, 
01493                                 "rlogin: NWIOSTCPOPT on %d failed (%s)\n",
01494                                 rem, strerror(errno));
01495                         exit(1);
01496                 }
01497                 if (urg_1_size != 0)
01498                 {
01499                         urg_byte= urg_1[urg_1_size-1];
01500                         urg_1_size--;
01501                         do_urg(urg_byte);
01502                         if (urg_1_size == 0)
01503                                 return;
01504                         if (extra_1_new_size + urg_1_size > MAX_EXTRA_1_NEW_SIZE)
01505                         {
01506                                 extra_1_new_size= 0;
01507                                 free(extra_1_new);
01508                                 extra_1_new= NULL;
01509                         }
01510                         if (extra_1_new_size != 0)
01511                         {
01512                                 new_buf= realloc(extra_1_new, 
01513                                         extra_1_new_size+urg_1_size);
01514                                 if (new_buf == 0)
01515                                 {
01516                                         extra_1_new_size= 0;
01517                                         free(extra_1_new);
01518                                         extra_1_new= NULL;
01519                                 }
01520                                 else
01521                                 {
01522                                         extra_1_new= new_buf;
01523                                         memcpy(extra_1_new+extra_1_new_size,
01524                                                 urg_1, urg_1_size);
01525                                         extra_1_new_size += urg_1_size;
01526                                         urg_1_size= 0;
01527                                         free(urg_1);
01528                                         urg_1= NULL;
01529                                 }
01530                         }
01531                         if (extra_1_new_size == 0)
01532                         {
01533                                 extra_1_new_size= urg_1_size;
01534                                 extra_1_new= urg_1;
01535                                 urg_1_size= 0;
01536                                 urg_1= NULL;
01537                         }
01538                         more2read_rem= 0;
01539                         more2write_1= 1;
01540                 }
01541                 return;
01542         }
01543         if (result == -1 && error == EINTR)
01544         {
01545                 /* Never mind. */
01546                 return;
01547         }
01548         if (result == 0)
01549         {
01550                 msg("connection closed.");
01551                 done(0);
01552         }
01553         if (result < 0) {
01554                 fprintf(stderr, "rlogin: %s\n", strerror(error));
01555         }
01556         done(1);
01557 }
01558 
01559 static void
01560 completed_wr_rem(result, error)
01561         int result;
01562         int error;
01563 {
01564         inprogress_wr_rem= 0;
01565 
01566         if (result > 0)
01567         {
01568                 if (extra_wr_rem != NULL)
01569                 {
01570                         assert (result <= extra_wr_rem_size);
01571                         extra_wr_rem_size -= result;
01572                         extra_wr_rem_offset += result;
01573                         if (extra_wr_rem_size == 0)
01574                         {
01575                                 free(extra_wr_rem);
01576                                 extra_wr_rem= NULL;
01577                                 if (wr_rem_size == 0)
01578                                 {
01579                                         more2write_rem= 0;
01580                                         more2read_0= 1;
01581                                 }
01582                         }
01583                         return;
01584                 }
01585 
01586                 assert (result <= wr_rem_size);
01587                 wr_rem_size -= result;
01588                 wr_rem_offset += result;
01589                 if (wr_rem_size == 0)
01590                 {
01591                         more2write_rem= 0;
01592                         more2read_0= 1;
01593                 }
01594                 return;
01595         }
01596         if (result < 0) {
01597                 fprintf(stderr, "rlogin: %s\n", strerror(error));
01598         }
01599         done(1);
01600 }
01601 
01602 static void
01603 do_urg(urg_byte)
01604         int urg_byte;
01605 {
01606 #if DEBUG
01607         fprintf(stderr, "rlogin: warning got urg_byte 0x%x\r\n", urg_byte);
01608 #endif
01609         if (urg_byte & TIOCPKT_WINDOW)
01610         {
01611                 if (dosigwinch == 0)
01612                 {
01613                         sendwindow();
01614                         signal(SIGWINCH, sigwinch);
01615                 }
01616                 dosigwinch= 1;
01617         }
01618 }
01619 
01620 static void
01621 echo(c)
01622         int c;
01623 {
01624         u_char c1;
01625         char *new_buf;
01626 
01627         new_buf= realloc(extra_1_new, extra_1_new_size+6);
01628         if (new_buf == NULL)
01629                 return;
01630         extra_1_new= new_buf;
01631         new_buf= extra_1_new+extra_1_new_size;
01632 
01633         c1= escapechar;
01634         if (c1 < ' ')
01635         {
01636                 *new_buf++= '^';
01637                 *new_buf++= c1 + '@';
01638         }
01639         else if (c1 == 0x7f)
01640         {
01641                 *new_buf++= '^';
01642                 *new_buf++= '?';
01643         }
01644         else
01645                 *new_buf++= c1;
01646 
01647         if (c < ' ')
01648         {
01649                 *new_buf++= '^';
01650                 *new_buf++= c + '@';
01651         }
01652         else if (c == 0x7f)
01653         {
01654                 *new_buf++= '^';
01655                 *new_buf++= '?';
01656         }
01657         else
01658                 *new_buf++= c;
01659 
01660         *new_buf++= '\r';
01661         *new_buf++= '\n';
01662         extra_1_new_size= new_buf-extra_1_new;
01663         more2write_1= 1;
01664 }
01665 
01666 static void
01667 finish()
01668 {
01669         done(0);
01670 }
01671 
01672 static char cmdbuf[256];
01673 
01674 static void
01675 subshell()
01676 {
01677         /* Start a subshell. Based on the first character of the command,
01678          * the tcp connection will be present at fd 3 ('+'), or at
01679          * fd 0 and fd 1 ('=')
01680          */
01681         int r, pid, stat, len;
01682         char *shell, *cmd;
01683 
01684         /* cancel the reads and writes that are in progress. */
01685         if (inprogress_0)
01686         {
01687                 r= fcancel(0, ASIO_READ);
01688                 if (r != 0) abort();
01689         }
01690         if (inprogress_1)
01691         {
01692                 r= fcancel(1, ASIO_WRITE);
01693                 if (r != 0) abort();
01694         }
01695         if (inprogress_rd_rem)
01696         {
01697                 r= fcancel(rem, ASIO_READ);
01698                 if (r != 0) abort();
01699         }
01700         if (inprogress_wr_rem)
01701         {
01702                 r= fcancel(rem, ASIO_WRITE);
01703                 if (r != 0) abort();
01704         }
01705 
01706         mode(0);
01707 
01708         pid= fork();
01709         if (pid == -1) abort();
01710         if (pid != 0)
01711         {
01712                 r= waitpid(pid, &stat, 0);
01713                 if (r != pid) abort();
01714 
01715 #if DEBUG
01716                 fprintf(stderr, "stat: 0x%x\n", stat);
01717 #endif
01718                 mode(1);
01719                 return;
01720         }
01721 
01722         (void)signal(SIGINT, SIG_DFL);
01723 
01724         shell= getenv("SHELL");
01725         if (shell == NULL)
01726                 shell= "/bin/sh";
01727         printf("~!\ncommand [%s]: ", shell);
01728         cmd= fgets(cmdbuf, sizeof(cmdbuf), stdin);
01729         if (cmd == NULL)
01730                 exit(0);
01731 #if DEBUG
01732         printf("got command '%s'\n", cmd);
01733 #endif
01734 
01735         /* Strip the trailing newline */
01736         len= strlen(cmd);
01737         if (len > 0 && cmd[len-1] == '\n')
01738                 cmd[len-1]= '\0';
01739         else
01740                 printf("\n");
01741 
01742         /* Skip leading white space */
01743         while (*cmd != '\0' && isspace(*cmd))
01744                 cmd++;
01745 
01746         if (*cmd == '+')
01747         {
01748                 if (rem != 3)
01749                 {
01750                         dup2(rem, 3);
01751                         close(rem);
01752                 }
01753                 cmd++;
01754         }
01755         else if (*cmd == '=')
01756         {
01757                 dup2(rem, 0);
01758                 dup2(rem, 1);
01759                 close(rem);
01760                 cmd++;
01761         }
01762         else
01763                 close(rem);
01764         if (*cmd == '\0')
01765         {
01766                 r= execl(shell, shell, NULL);
01767         }
01768         else
01769         {
01770                 r= execl("/bin/sh", "sh", "-c", cmd, NULL);
01771         }
01772         printf("exec failed: %d, %d\n", r, errno);
01773         exit(0);
01774 }
01775 #endif /* __minix_vmd */

Generated on Fri Apr 14 22:57:10 2006 for minix by  doxygen 1.4.6