1 #ifndef lint 2 static char sccsid[] = "@(#)rlogin.c 4.1 82/04/02"; 3 #endif 4 5 #include <stdio.h> 6 #include <sgtty.h> 7 #include <sys/types.h> 8 #include <sys/socket.h> 9 #include <net/in.h> 10 #include <errno.h> 11 #include <pwd.h> 12 13 /* 14 * rlogin - remote login; this is a hacked version of cu 15 */ 16 char *index(), *rindex(), *malloc(), *getenv(); 17 struct passwd *getpwuid(); 18 struct passwd *pwd; 19 char *name, *pass; 20 int rem; 21 char cmdchar = '~'; 22 int rcmdoptions = 0; 23 int eight; 24 char *speeds[] = 25 { "0", "50", "75", "110", "134", "150", "200", "300", 26 "600", "1200", "1800", "2400", "4800", "9600", "19200", "38400" }; 27 char term[64]; 28 29 main(argc, argv) 30 int argc; 31 char **argv; 32 { 33 int pid; 34 char *host, *cp, **ap, buf[BUFSIZ]; 35 register int cc; 36 struct sgttyb ttyb; 37 struct passwd *pwd; 38 39 host = rindex(argv[0], '/'); 40 if (host) 41 host++; 42 else 43 host = argv[0]; 44 argv++, --argc; 45 if (!strcmp(host, "rlogin")) 46 host = *argv++, --argc; 47 another: 48 if (!strcmp(*argv, "-d")) { 49 argv++, argc--; 50 rcmdoptions |= SO_DEBUG; 51 goto another; 52 } 53 if (!strcmp(*argv, "-l")) { 54 argv++, argc--; 55 if (argc == 0) 56 goto usage; 57 name = *argv++; argc--; 58 goto another; 59 } 60 if (!strncmp(*argv, "-e", 2)) { 61 cmdchar = argv[0][2]; 62 argv++, argc--; 63 goto another; 64 } 65 if (!strcmp(*argv, "-8")) { 66 eight = 1; 67 argv++, argc--; 68 goto another; 69 } 70 if (host == 0) 71 goto usage; 72 if (argc > 0) 73 goto usage; 74 pwd = getpwuid(getuid()); 75 if (pwd == 0) { 76 fprintf(stderr, "Who are you?\n"); 77 exit(1); 78 } 79 cc = 0; 80 strcpy(term, getenv("TERM")); 81 if (gtty(0, &ttyb)==0) { 82 strcat(term, "/"); 83 strcat(term, speeds[ttyb.sg_ospeed]); 84 } 85 rem = rcmd(&host, IPPORT_LOGINSERVER, pwd->pw_name, 86 name ? name : pwd->pw_name, term, 0); 87 if (rem < 0) 88 exit(1); 89 setuid(getuid()); 90 cumain(); 91 exit(0); 92 usage: 93 fprintf(stderr, 94 "usage: rlogin host [ -ex ] [ -l username ]\n"); 95 exit(1); 96 } 97 98 #include <ctype.h> 99 #include <signal.h> 100 101 #define CRLF "\r\n" 102 #define wrc(ds) write(ds,&c,1) 103 104 char tkill, terase; /* current input kill & erase */ 105 int efk; /* process of id of listener */ 106 char c, oc; 107 int pipes[] = {-1,-1}; 108 int intr, sig2(); 109 int parent; 110 111 int nhup; 112 int done(); 113 114 struct tchars deftchars; 115 struct tchars notchars = { 0377, 0377, 'q'&037, 's'&037, 0377, 0377 }; 116 struct ltchars defltchars; 117 struct ltchars noltchars = { 0377, 0377, 0377, 0377, 0377, 0377 }; 118 char defkill, deferase; 119 120 cumain() 121 { 122 int fk; 123 int speed; 124 char *telno; 125 struct sgttyb stbuf; 126 int exit(); 127 128 gtty(0, &stbuf); 129 defkill = stbuf.sg_kill; 130 deferase = stbuf.sg_erase; 131 ioctl(0, TIOCGETC, &deftchars); 132 ioctl(0, TIOCGLTC, &defltchars); 133 signal(SIGINT, exit); 134 signal(SIGHUP, exit); 135 signal(SIGQUIT, exit); 136 pipe(pipes); 137 parent = getpid(); 138 fk = fork(); 139 nhup = (int)signal(SIGINT, SIG_IGN); 140 if (fk == 0) { 141 rd(); 142 sleep(1); 143 prf("\007Lost connection."); 144 exit(3); 145 } 146 signal(SIGCHLD, done); 147 mode(1); 148 efk = fk; 149 wr(); 150 if (fk != -1) kill(fk, SIGKILL); 151 prf("Disconnected."); 152 done(); 153 } 154 155 done() 156 { 157 158 mode(0); 159 wait((int *)NULL); 160 exit(0); 161 } 162 163 /* 164 * wr: write to remote: 0 -> line. 165 * ~. terminate 166 * ~<file send file 167 * ~! local login-style shell 168 * ~!cmd execute cmd locally 169 * ~$proc execute proc locally, send output to line 170 * ~%cmd execute builtin cmd (put and take) 171 * ~^Z suspend cu process. 172 */ 173 174 wr() 175 { 176 int ds,fk,lcl,x; 177 char *p,b[600]; 178 for (;;) { 179 p=b; 180 while (rdc(0) == 1) { 181 if (p == b) lcl=(c == cmdchar); 182 if (p == b+1 && b[0] == cmdchar) lcl=(c!=cmdchar); 183 if (!lcl) { 184 c = oc; 185 if (wrc(rem) == 0) { 186 prf("line gone"); return; 187 } 188 if (eight == 0) 189 c &= 0177; 190 } 191 if (lcl) { 192 if (c == 0177) c=tkill; 193 if (c == '\r' || c == '\n') goto A; 194 wrc(0); 195 } 196 *p++=c; 197 if (c == terase) { 198 p=p-2; 199 if (p<b) p=b; 200 } 201 if (c == tkill || c == 0177 || c == '\4' || c == '\r' || c == '\n') p=b; 202 } 203 return; 204 A: 205 echo(""); 206 *p=0; 207 switch (b[1]) { 208 case '.': 209 case '\004': 210 return; 211 case '!': 212 case '$': 213 fk = fork(); 214 signal(SIGCHLD, SIG_DFL); 215 if (fk == 0) { 216 char *shell = getenv("SHELL"); 217 if (shell == 0) shell = "/bin/sh"; 218 close(1); 219 dup(b[1] == '$'? rem:2); 220 close(rem); 221 mode(0); 222 if (!nhup) signal(SIGINT, SIG_DFL); 223 if (b[2] == 0) execl(shell,shell,0); 224 /* if (b[2] == 0) execl(shell,"-",0); */ 225 else execl(shell,"sh","-c",b+2,0); 226 prf("Can't execute shell"); 227 exit(~0); 228 } 229 if (fk!=(-1)) { 230 while (wait(&x)!=fk); 231 } 232 signal(SIGCHLD, done); 233 mode(1); 234 if (b[1] == '!') echo("!"); 235 break; 236 case '<': 237 if (b[2] == 0) break; 238 if ((ds=open(b+2,0))<0) { 239 prf("Can't divert %s",b+1); 240 break; 241 } 242 intr=x=0; 243 mode(2); 244 if (!nhup) signal(SIGINT, sig2); 245 while (!intr && rdc(ds) == 1) { 246 if (wrc(rem) == 0) { 247 x=1; 248 break; 249 } 250 } 251 signal(SIGINT, SIG_IGN); 252 close(ds); 253 mode(1); 254 if (x) return; 255 break; 256 case '>': 257 case ':': 258 { 259 register char *q; 260 261 q = b+1; 262 if(*q=='>') q++; 263 write(pipes[1],q,strlen(q)+1); 264 if (efk != -1) kill(efk,SIGEMT); 265 } 266 break; 267 #ifdef SIGTSTP 268 #define CTRLZ 26 269 case CTRLZ: 270 mode(0); 271 signal(SIGCHLD, SIG_IGN); 272 kill(0, SIGTSTP); 273 signal(SIGCHLD, done); 274 mode(1); 275 break; 276 #endif 277 case '%': 278 dopercen(&b[2]); 279 break; 280 default: 281 prf("Use `%c%c' to start line with `%c'", cmdchar, cmdchar, cmdchar); 282 } 283 continue; 284 } 285 } 286 287 dopercen(line) 288 register char *line; 289 { 290 char *args[10]; 291 register narg, f; 292 int rcount; 293 for (narg = 0; narg < 10;) { 294 while(*line == ' ' || *line == '\t') 295 line++; 296 if (*line == '\0') 297 break; 298 args[narg++] = line; 299 while(*line != '\0' && *line != ' ' && *line != '\t') 300 line++; 301 if (*line == '\0') 302 break; 303 *line++ = '\0'; 304 } 305 if (equal(args[0], "take")) { 306 if (narg < 2) { 307 prf("usage: %c%%take from [to]", cmdchar); 308 return; 309 } 310 if (narg < 3) 311 args[2] = args[1]; 312 write(pipes[1], ">/dev/null",sizeof(">/dev/null")); 313 if (efk != -1) kill(efk,SIGEMT); 314 sleep(5); 315 wrln("echo '%c>:", cmdchar); 316 wrln(args[2]); 317 wrln("'; tee /dev/null <"); 318 wrln(args[1]); 319 wrln(";echo '%c>'\n", cmdchar); 320 return; 321 } else if (equal(args[0], "put")) { 322 prf("%c%%put doesn't work yet (use rsh)", cmdchar); 323 return; 324 /* 325 if (narg < 2) { 326 prf("usage: %c%%put from [to]", cmdchar); 327 return; 328 } 329 if (narg < 3) 330 args[2] = args[1]; 331 if ((f = open(args[1], 0)) < 0) { 332 prf("cannot open: %s", args[1]); 333 return; 334 } 335 wrln("stty -echo;cat >"); 336 wrln(args[2]); 337 wrln(";stty echo\n"); 338 sleep(5); 339 intr = 0; 340 if (!nhup) 341 signal(SIGINT, sig2); 342 mode(2); 343 rcount = 0; 344 while(!intr && rdc(f) == 1) { 345 rcount++; 346 if (c == tkill || c == terase) 347 wrln("\\"); 348 if (wrc(rem) != 1) { 349 sleep(2); 350 if (wrc(rem) != 1) { 351 prf("character missed"); 352 intr = 1; 353 break; 354 } 355 } 356 } 357 signal(SIGINT, SIG_IGN); 358 close(f); 359 if (intr) { 360 wrln("\n"); 361 prf("stopped after %d bytes", rcount); 362 } 363 wrln("\004"); 364 sleep(5); 365 mode(1); 366 return; 367 */ 368 } 369 prf("%c%%%s unknown\n", cmdchar, args[0]); 370 } 371 372 equal(s1, s2) 373 register char *s1, *s2; 374 { 375 while (*s1++ == *s2) 376 if (*s2++ == '\0') 377 return(1); 378 return(0); 379 } 380 381 wrln(s, p1, p2, p3) 382 register char *s; 383 int p1, p2, p3; 384 { 385 char wbuf[256]; 386 387 sprintf(wbuf, s, p1, p2, p3); 388 s = wbuf; 389 while (*s) 390 write(rem, s++, 1); 391 } 392 int ds,slnt; 393 int justrung; 394 395 /* 396 * rd: read from remote: line -> 1 397 * catch: 398 * ~>[>][:][file] 399 * stuff from file... 400 * ~> (ends diversion) 401 */ 402 403 int ds,slnt,taking; 404 int justrung; 405 readmsg(){ 406 static char dobuff[128], morejunk[256]; 407 int n; 408 justrung = 1; 409 signal(SIGEMT,readmsg); 410 n = read(pipes[0],morejunk,256); 411 dodiver(morejunk); 412 } 413 414 dodiver(msg) 415 char *msg; 416 { 417 register char *cp = msg; 418 419 if (*cp=='>') cp++; 420 if (*cp==':') { 421 cp++; 422 if(*cp==0) { 423 slnt ^= 1; 424 return; 425 } else { 426 slnt = 1; 427 } 428 } 429 if (ds >= 0) close(ds); 430 if (*cp==0) { 431 slnt = 0; 432 ds = -1; 433 return; 434 } 435 if (*msg!='>' || (ds=open(cp,1))<0) ds=creat(cp,0644); 436 lseek(ds, (long)0, 2); 437 if(ds < 0) prf("Creat failed:"), prf(cp); 438 if (ds<0) prf("Can't divert %s",cp+1); 439 } 440 441 442 /* 443 * rd: read from remote: line -> 1 444 * catch: diversion caught by interrupt routine 445 */ 446 447 #define ORDIN 0 448 #define SAWCR 1 449 #define EOL 2 450 #define SAWTL 3 451 #define DIVER 4 452 453 oob() 454 { 455 int mark, cc, out = 1+1; 456 char waste[512]; 457 458 signal(SIGURG, oob); 459 ioctl(1, TIOCFLUSH, &out); 460 for (;;) { 461 if (ioctl(rem, SIOCATMARK, &mark) < 0) { 462 perror("ioctl"); 463 break; 464 } 465 if (mark) 466 break; 467 cc = read(rem, waste, 512); 468 } 469 ioctl(rem, SIOCRCVOOB, &mark); 470 if (mark & TIOCPKT_NOSTOP) { 471 notchars.t_stopc = 0377; 472 notchars.t_startc = 0377; 473 ioctl(0, TIOCSETC, ¬chars); 474 } 475 if (mark & TIOCPKT_DOSTOP) { 476 notchars.t_stopc = 's'&037; 477 notchars.t_startc = 'q'&037; 478 ioctl(0, TIOCSETC, ¬chars); 479 } 480 } 481 482 rd() 483 { 484 extern int ds,slnt; 485 char rb[600], lb[600], *rlim, *llim, c; 486 register char *p,*q; 487 int cnt, state = 0, mustecho, oldslnt, readmsg(); 488 489 signal(SIGEMT,readmsg); /* set up child for catching diversion msgs 490 from parent */ 491 signal(SIGURG,oob); 492 { int pid = -getpid(); 493 ioctl(rem, SIOCSPGRP, &pid); } 494 ds=(-1); 495 p = lb; llim = lb+600; 496 agin: 497 for (;;) { 498 extern errno; 499 errno = 0; 500 cnt = read(rem,rb,600); 501 if (cnt <= 0) { 502 if (errno == EINTR) { 503 errno = 0; 504 continue; 505 } 506 break; 507 } 508 if(!slnt) write(1,rb,cnt); 509 if(ds < 0) continue; 510 oldslnt = slnt; 511 for( q=rb, rlim = rb + cnt - 1; q <= rlim; ) { 512 if (eight == 0) 513 c &= 0177; 514 if(p < llim) *p++ = c; 515 switch(state) { 516 case ORDIN: 517 if(c=='\r') state = SAWCR; 518 break; 519 case SAWCR: 520 if(c=='\n') { 521 state = EOL; 522 p--; 523 p[-1] = '\n'; 524 } else state = ORDIN; 525 break; 526 case EOL: 527 state = (c==cmdchar ? SAWTL : 528 (c=='\r' ? SAWCR : ORDIN)); 529 break; 530 case SAWTL: 531 state = (c=='>' ? DIVER : 532 (c=='\r' ? SAWCR : ORDIN)); 533 break; 534 case DIVER: 535 if(c=='\r') { 536 p--; 537 } else if (c=='\n') { 538 state = ORDIN; 539 p[-1] = 0; 540 dodiver(lb+2); 541 c = 0; p = lb; 542 } 543 } 544 if(slnt==0 && oldslnt) { 545 if(c=='\n') { 546 write(rem,lb,p-lb-1); 547 write(rem,CRLF,sizeof(CRLF)); 548 } else if(q==rlim) { 549 write(rem,lb,p-lb); 550 c = '\n'; /*force flush to file*/ 551 } 552 } 553 if(c=='\n') { 554 if(ds >= 0) 555 write(ds,lb,p-lb); 556 p = lb; 557 } 558 } 559 } 560 if(justrung) { 561 justrung = 0; 562 goto agin; 563 } 564 } 565 566 struct {char lobyte; char hibyte;}; 567 mode(f) 568 { 569 struct sgttyb stbuf; 570 ioctl(0, TIOCGETP, &stbuf); 571 if (f == 0) { 572 stbuf.sg_flags &= ~CBREAK; 573 stbuf.sg_flags |= ECHO|CRMOD; 574 ioctl(0, TIOCSETC, &deftchars); 575 ioctl(0, TIOCSLTC, &defltchars); 576 stbuf.sg_kill = defkill; 577 stbuf.sg_erase = deferase; 578 } 579 if (f == 1) { 580 stbuf.sg_flags |= CBREAK; 581 stbuf.sg_flags &= ~(ECHO|CRMOD); 582 ioctl(0, TIOCSETC, ¬chars); 583 ioctl(0, TIOCSLTC, &noltchars); 584 stbuf.sg_kill = 0377; 585 stbuf.sg_erase = 0377; 586 } 587 if (f == 2) { 588 stbuf.sg_flags &= ~CBREAK; 589 stbuf.sg_flags &= ~(ECHO|CRMOD); 590 ioctl(0, TIOCSETC, &deftchars); 591 ioctl(0, TIOCSLTC, &defltchars); 592 stbuf.sg_kill = 0377; 593 stbuf.sg_erase = 0377; 594 } 595 ioctl(0, TIOCSETN, &stbuf); 596 } 597 598 echo(s) 599 char *s; 600 { 601 char *p; 602 for (p=s;*p;p++); 603 if (p>s) write(0,s,p-s); 604 write(0,CRLF, sizeof(CRLF)); 605 } 606 607 prf(f, a1, a2, a3) 608 char *f; 609 { 610 fprintf(stderr, f, a1, a2, a3); 611 fprintf(stderr, CRLF); 612 } 613 614 exists(devname) 615 char *devname; 616 { 617 if (access(devname, 0)==0) 618 return(1); 619 prf("%s does not exist", devname); 620 return(0); 621 } 622 623 rdc(ds) 624 { 625 626 ds=read(ds,&c,1); 627 oc = c; 628 if (eight == 0) 629 c &= 0177; 630 return (ds); 631 } 632 633 sig2() 634 { 635 signal(SIGINT, SIG_IGN); 636 intr = 1; 637 } 638