1 /* 2 * Copyright (c) 1983 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that the above copyright notice and this paragraph are 7 * duplicated in all such forms and that any documentation, 8 * advertising materials, and other materials related to such 9 * distribution and use acknowledge that the software was developed 10 * by the University of California, Berkeley. The name of the 11 * University may not be used to endorse or promote products derived 12 * from this software without specific prior written permission. 13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16 */ 17 18 #ifndef lint 19 static char sccsid[] = "@(#)cmds.c 5.10 (Berkeley) 05/11/89"; 20 #endif /* not lint */ 21 22 #include "tip.h" 23 #include "pathnames.h" 24 25 /* 26 * tip 27 * 28 * miscellaneous commands 29 */ 30 31 int quant[] = { 60, 60, 24 }; 32 33 char null = '\0'; 34 char *sep[] = { "second", "minute", "hour" }; 35 static char *argv[10]; /* argument vector for take and put */ 36 37 int timeout(); /* timeout function called on alarm */ 38 int stopsnd(); /* SIGINT handler during file transfers */ 39 int intprompt(); /* used in handling SIG_INT during prompt */ 40 int intcopy(); /* interrupt routine for file transfers */ 41 42 /* 43 * FTP - remote ==> local 44 * get a file from the remote host 45 */ 46 getfl(c) 47 char c; 48 { 49 char buf[256], *cp, *expand(); 50 51 putchar(c); 52 /* 53 * get the UNIX receiving file's name 54 */ 55 if (prompt("Local file name? ", copyname)) 56 return; 57 cp = expand(copyname); 58 if ((sfd = creat(cp, 0666)) < 0) { 59 printf("\r\n%s: cannot creat\r\n", copyname); 60 return; 61 } 62 63 /* 64 * collect parameters 65 */ 66 if (prompt("List command for remote system? ", buf)) { 67 unlink(copyname); 68 return; 69 } 70 transfer(buf, sfd, value(EOFREAD)); 71 } 72 73 /* 74 * Cu-like take command 75 */ 76 cu_take(cc) 77 char cc; 78 { 79 int fd, argc; 80 char line[BUFSIZ], *expand(), *cp; 81 82 if (prompt("[take] ", copyname)) 83 return; 84 if ((argc = args(copyname, argv)) < 1 || argc > 2) { 85 printf("usage: <take> from [to]\r\n"); 86 return; 87 } 88 if (argc == 1) 89 argv[1] = argv[0]; 90 cp = expand(argv[1]); 91 if ((fd = creat(cp, 0666)) < 0) { 92 printf("\r\n%s: cannot create\r\n", argv[1]); 93 return; 94 } 95 sprintf(line, "cat %s;echo \01", argv[0]); 96 transfer(line, fd, "\01"); 97 } 98 99 static jmp_buf intbuf; 100 /* 101 * Bulk transfer routine -- 102 * used by getfl(), cu_take(), and pipefile() 103 */ 104 transfer(buf, fd, eofchars) 105 char *buf, *eofchars; 106 { 107 register int ct; 108 char c, buffer[BUFSIZ]; 109 register char *p = buffer; 110 register int cnt, eof; 111 time_t start; 112 int (*f)(); 113 114 pwrite(FD, buf, size(buf)); 115 quit = 0; 116 kill(pid, SIGIOT); 117 read(repdes[0], (char *)&ccc, 1); /* Wait until read process stops */ 118 119 /* 120 * finish command 121 */ 122 pwrite(FD, "\r", 1); 123 do 124 read(FD, &c, 1); 125 while ((c&0177) != '\n'); 126 ioctl(0, TIOCSETC, &defchars); 127 128 (void) setjmp(intbuf); 129 f = signal(SIGINT, intcopy); 130 start = time(0); 131 for (ct = 0; !quit;) { 132 eof = read(FD, &c, 1) <= 0; 133 c &= 0177; 134 if (quit) 135 continue; 136 if (eof || any(c, eofchars)) 137 break; 138 if (c == 0) 139 continue; /* ignore nulls */ 140 if (c == '\r') 141 continue; 142 *p++ = c; 143 144 if (c == '\n' && boolean(value(VERBOSE))) 145 printf("\r%d", ++ct); 146 if ((cnt = (p-buffer)) == number(value(FRAMESIZE))) { 147 if (write(fd, buffer, cnt) != cnt) { 148 printf("\r\nwrite error\r\n"); 149 quit = 1; 150 } 151 p = buffer; 152 } 153 } 154 if (cnt = (p-buffer)) 155 if (write(fd, buffer, cnt) != cnt) 156 printf("\r\nwrite error\r\n"); 157 158 if (boolean(value(VERBOSE))) 159 prtime(" lines transferred in ", time(0)-start); 160 ioctl(0, TIOCSETC, &tchars); 161 write(fildes[1], (char *)&ccc, 1); 162 signal(SIGINT, f); 163 close(fd); 164 } 165 166 /* 167 * FTP - remote ==> local process 168 * send remote input to local process via pipe 169 */ 170 pipefile() 171 { 172 int cpid, pdes[2]; 173 char buf[256]; 174 int status, p; 175 extern int errno; 176 177 if (prompt("Local command? ", buf)) 178 return; 179 180 if (pipe(pdes)) { 181 printf("can't establish pipe\r\n"); 182 return; 183 } 184 185 if ((cpid = fork()) < 0) { 186 printf("can't fork!\r\n"); 187 return; 188 } else if (cpid) { 189 if (prompt("List command for remote system? ", buf)) { 190 close(pdes[0]), close(pdes[1]); 191 kill (cpid, SIGKILL); 192 } else { 193 close(pdes[0]); 194 signal(SIGPIPE, intcopy); 195 transfer(buf, pdes[1], value(EOFREAD)); 196 signal(SIGPIPE, SIG_DFL); 197 while ((p = wait(&status)) > 0 && p != cpid) 198 ; 199 } 200 } else { 201 register int f; 202 203 dup2(pdes[0], 0); 204 close(pdes[0]); 205 for (f = 3; f < 20; f++) 206 close(f); 207 execute(buf); 208 printf("can't execl!\r\n"); 209 exit(0); 210 } 211 } 212 213 /* 214 * Interrupt service routine for FTP 215 */ 216 stopsnd() 217 { 218 219 stop = 1; 220 signal(SIGINT, SIG_IGN); 221 } 222 223 /* 224 * FTP - local ==> remote 225 * send local file to remote host 226 * terminate transmission with pseudo EOF sequence 227 */ 228 sendfile(cc) 229 char cc; 230 { 231 FILE *fd; 232 char *fnamex; 233 char *expand(); 234 235 putchar(cc); 236 /* 237 * get file name 238 */ 239 if (prompt("Local file name? ", fname)) 240 return; 241 242 /* 243 * look up file 244 */ 245 fnamex = expand(fname); 246 if ((fd = fopen(fnamex, "r")) == NULL) { 247 printf("%s: cannot open\r\n", fname); 248 return; 249 } 250 transmit(fd, value(EOFWRITE), NULL); 251 if (!boolean(value(ECHOCHECK))) { 252 struct sgttyb buf; 253 254 ioctl(FD, TIOCGETP, &buf); /* this does a */ 255 ioctl(FD, TIOCSETP, &buf); /* wflushtty */ 256 } 257 } 258 259 /* 260 * Bulk transfer routine to remote host -- 261 * used by sendfile() and cu_put() 262 */ 263 transmit(fd, eofchars, command) 264 FILE *fd; 265 char *eofchars, *command; 266 { 267 char *pc, lastc; 268 int c, ccount, lcount; 269 time_t start_t, stop_t; 270 int (*f)(); 271 272 kill(pid, SIGIOT); /* put TIPOUT into a wait state */ 273 stop = 0; 274 f = signal(SIGINT, stopsnd); 275 ioctl(0, TIOCSETC, &defchars); 276 read(repdes[0], (char *)&ccc, 1); 277 if (command != NULL) { 278 for (pc = command; *pc; pc++) 279 send(*pc); 280 if (boolean(value(ECHOCHECK))) 281 read(FD, (char *)&c, 1); /* trailing \n */ 282 else { 283 struct sgttyb buf; 284 285 ioctl(FD, TIOCGETP, &buf); /* this does a */ 286 ioctl(FD, TIOCSETP, &buf); /* wflushtty */ 287 sleep(5); /* wait for remote stty to take effect */ 288 } 289 } 290 lcount = 0; 291 lastc = '\0'; 292 start_t = time(0); 293 while (1) { 294 ccount = 0; 295 do { 296 c = getc(fd); 297 if (stop) 298 goto out; 299 if (c == EOF) 300 goto out; 301 if (c == 0177 && !boolean(value(RAWFTP))) 302 continue; 303 lastc = c; 304 if (c < 040) { 305 if (c == '\n') { 306 if (!boolean(value(RAWFTP))) 307 c = '\r'; 308 } 309 else if (c == '\t') { 310 if (!boolean(value(RAWFTP))) { 311 if (boolean(value(TABEXPAND))) { 312 send(' '); 313 while ((++ccount % 8) != 0) 314 send(' '); 315 continue; 316 } 317 } 318 } else 319 if (!boolean(value(RAWFTP))) 320 continue; 321 } 322 send(c); 323 } while (c != '\r' && !boolean(value(RAWFTP))); 324 if (boolean(value(VERBOSE))) 325 printf("\r%d", ++lcount); 326 if (boolean(value(ECHOCHECK))) { 327 timedout = 0; 328 alarm(value(ETIMEOUT)); 329 do { /* wait for prompt */ 330 read(FD, (char *)&c, 1); 331 if (timedout || stop) { 332 if (timedout) 333 printf("\r\ntimed out at eol\r\n"); 334 alarm(0); 335 goto out; 336 } 337 } while ((c&0177) != character(value(PROMPT))); 338 alarm(0); 339 } 340 } 341 out: 342 if (lastc != '\n' && !boolean(value(RAWFTP))) 343 send('\r'); 344 for (pc = eofchars; *pc; pc++) 345 send(*pc); 346 stop_t = time(0); 347 fclose(fd); 348 signal(SIGINT, f); 349 if (boolean(value(VERBOSE))) 350 if (boolean(value(RAWFTP))) 351 prtime(" chars transferred in ", stop_t-start_t); 352 else 353 prtime(" lines transferred in ", stop_t-start_t); 354 write(fildes[1], (char *)&ccc, 1); 355 ioctl(0, TIOCSETC, &tchars); 356 } 357 358 /* 359 * Cu-like put command 360 */ 361 cu_put(cc) 362 char cc; 363 { 364 FILE *fd; 365 char line[BUFSIZ]; 366 int argc; 367 char *expand(); 368 char *copynamex; 369 370 if (prompt("[put] ", copyname)) 371 return; 372 if ((argc = args(copyname, argv)) < 1 || argc > 2) { 373 printf("usage: <put> from [to]\r\n"); 374 return; 375 } 376 if (argc == 1) 377 argv[1] = argv[0]; 378 copynamex = expand(argv[0]); 379 if ((fd = fopen(copynamex, "r")) == NULL) { 380 printf("%s: cannot open\r\n", copynamex); 381 return; 382 } 383 if (boolean(value(ECHOCHECK))) 384 sprintf(line, "cat>%s\r", argv[1]); 385 else 386 sprintf(line, "stty -echo;cat>%s;stty echo\r", argv[1]); 387 transmit(fd, "\04", line); 388 } 389 390 /* 391 * FTP - send single character 392 * wait for echo & handle timeout 393 */ 394 send(c) 395 char c; 396 { 397 char cc; 398 int retry = 0; 399 400 cc = c; 401 pwrite(FD, &cc, 1); 402 #ifdef notdef 403 if (number(value(CDELAY)) > 0 && c != '\r') 404 nap(number(value(CDELAY))); 405 #endif 406 if (!boolean(value(ECHOCHECK))) { 407 #ifdef notdef 408 if (number(value(LDELAY)) > 0 && c == '\r') 409 nap(number(value(LDELAY))); 410 #endif 411 return; 412 } 413 tryagain: 414 timedout = 0; 415 alarm(value(ETIMEOUT)); 416 read(FD, &cc, 1); 417 alarm(0); 418 if (timedout) { 419 printf("\r\ntimeout error (%s)\r\n", ctrl(c)); 420 if (retry++ > 3) 421 return; 422 pwrite(FD, &null, 1); /* poke it */ 423 goto tryagain; 424 } 425 } 426 427 timeout() 428 { 429 signal(SIGALRM, timeout); 430 timedout = 1; 431 } 432 433 /* 434 * Stolen from consh() -- puts a remote file on the output of a local command. 435 * Identical to consh() except for where stdout goes. 436 */ 437 pipeout(c) 438 { 439 char buf[256]; 440 int cpid, status, p; 441 time_t start; 442 443 putchar(c); 444 if (prompt("Local command? ", buf)) 445 return; 446 kill(pid, SIGIOT); /* put TIPOUT into a wait state */ 447 signal(SIGINT, SIG_IGN); 448 signal(SIGQUIT, SIG_IGN); 449 ioctl(0, TIOCSETC, &defchars); 450 read(repdes[0], (char *)&ccc, 1); 451 /* 452 * Set up file descriptors in the child and 453 * let it go... 454 */ 455 if ((cpid = fork()) < 0) 456 printf("can't fork!\r\n"); 457 else if (cpid) { 458 start = time(0); 459 while ((p = wait(&status)) > 0 && p != cpid) 460 ; 461 } else { 462 register int i; 463 464 dup2(FD, 1); 465 for (i = 3; i < 20; i++) 466 close(i); 467 signal(SIGINT, SIG_DFL); 468 signal(SIGQUIT, SIG_DFL); 469 execute(buf); 470 printf("can't find `%s'\r\n", buf); 471 exit(0); 472 } 473 if (boolean(value(VERBOSE))) 474 prtime("away for ", time(0)-start); 475 write(fildes[1], (char *)&ccc, 1); 476 ioctl(0, TIOCSETC, &tchars); 477 signal(SIGINT, SIG_DFL); 478 signal(SIGQUIT, SIG_DFL); 479 } 480 481 #ifdef CONNECT 482 /* 483 * Fork a program with: 484 * 0 <-> local tty in 485 * 1 <-> local tty out 486 * 2 <-> local tty out 487 * 3 <-> remote tty in 488 * 4 <-> remote tty out 489 */ 490 consh(c) 491 { 492 char buf[256]; 493 int cpid, status, p; 494 time_t start; 495 496 putchar(c); 497 if (prompt("Local command? ", buf)) 498 return; 499 kill(pid, SIGIOT); /* put TIPOUT into a wait state */ 500 signal(SIGINT, SIG_IGN); 501 signal(SIGQUIT, SIG_IGN); 502 ioctl(0, TIOCSETC, &defchars); 503 read(repdes[0], (char *)&ccc, 1); 504 /* 505 * Set up file descriptors in the child and 506 * let it go... 507 */ 508 if ((cpid = fork()) < 0) 509 printf("can't fork!\r\n"); 510 else if (cpid) { 511 start = time(0); 512 while ((p = wait(&status)) > 0 && p != cpid) 513 ; 514 } else { 515 register int i; 516 517 dup2(FD, 3); 518 dup2(3, 4); 519 for (i = 5; i < 20; i++) 520 close(i); 521 signal(SIGINT, SIG_DFL); 522 signal(SIGQUIT, SIG_DFL); 523 execute(buf); 524 printf("can't find `%s'\r\n", buf); 525 exit(0); 526 } 527 if (boolean(value(VERBOSE))) 528 prtime("away for ", time(0)-start); 529 write(fildes[1], (char *)&ccc, 1); 530 ioctl(0, TIOCSETC, &tchars); 531 signal(SIGINT, SIG_DFL); 532 signal(SIGQUIT, SIG_DFL); 533 } 534 #endif 535 536 /* 537 * Escape to local shell 538 */ 539 shell() 540 { 541 int shpid, status; 542 extern char **environ; 543 char *cp; 544 545 printf("[sh]\r\n"); 546 signal(SIGINT, SIG_IGN); 547 signal(SIGQUIT, SIG_IGN); 548 unraw(); 549 if (shpid = fork()) { 550 while (shpid != wait(&status)); 551 raw(); 552 printf("\r\n!\r\n"); 553 signal(SIGINT, SIG_DFL); 554 signal(SIGQUIT, SIG_DFL); 555 return; 556 } else { 557 signal(SIGQUIT, SIG_DFL); 558 signal(SIGINT, SIG_DFL); 559 if ((cp = rindex(value(SHELL), '/')) == NULL) 560 cp = value(SHELL); 561 else 562 cp++; 563 shell_uid(); 564 execl(value(SHELL), cp, 0); 565 printf("\r\ncan't execl!\r\n"); 566 exit(1); 567 } 568 } 569 570 /* 571 * TIPIN portion of scripting 572 * initiate the conversation with TIPOUT 573 */ 574 setscript() 575 { 576 char c; 577 /* 578 * enable TIPOUT side for dialogue 579 */ 580 kill(pid, SIGEMT); 581 if (boolean(value(SCRIPT))) 582 write(fildes[1], value(RECORD), size(value(RECORD))); 583 write(fildes[1], "\n", 1); 584 /* 585 * wait for TIPOUT to finish 586 */ 587 read(repdes[0], &c, 1); 588 if (c == 'n') 589 printf("can't create %s\r\n", value(RECORD)); 590 } 591 592 /* 593 * Change current working directory of 594 * local portion of tip 595 */ 596 chdirectory() 597 { 598 char dirname[80]; 599 register char *cp = dirname; 600 601 if (prompt("[cd] ", dirname)) { 602 if (stoprompt) 603 return; 604 cp = value(HOME); 605 } 606 if (chdir(cp) < 0) 607 printf("%s: bad directory\r\n", cp); 608 printf("!\r\n"); 609 } 610 611 abort(msg) 612 char *msg; 613 { 614 615 kill(pid, SIGTERM); 616 disconnect(msg); 617 if (msg != NOSTR) 618 printf("\r\n%s", msg); 619 printf("\r\n[EOT]\r\n"); 620 daemon_uid(); 621 (void)uu_unlock(uucplock); 622 unraw(); 623 exit(0); 624 } 625 626 finish() 627 { 628 char *dismsg; 629 630 if ((dismsg = value(DISCONNECT)) != NOSTR) { 631 write(FD, dismsg, strlen(dismsg)); 632 sleep(5); 633 } 634 abort(NOSTR); 635 } 636 637 intcopy() 638 { 639 640 raw(); 641 quit = 1; 642 longjmp(intbuf, 1); 643 } 644 645 execute(s) 646 char *s; 647 { 648 register char *cp; 649 650 if ((cp = rindex(value(SHELL), '/')) == NULL) 651 cp = value(SHELL); 652 else 653 cp++; 654 shell_uid(); 655 execl(value(SHELL), cp, "-c", s, 0); 656 } 657 658 args(buf, a) 659 char *buf, *a[]; 660 { 661 register char *p = buf, *start; 662 register char **parg = a; 663 register int n = 0; 664 665 do { 666 while (*p && (*p == ' ' || *p == '\t')) 667 p++; 668 start = p; 669 if (*p) 670 *parg = p; 671 while (*p && (*p != ' ' && *p != '\t')) 672 p++; 673 if (p != start) 674 parg++, n++; 675 if (*p) 676 *p++ = '\0'; 677 } while (*p); 678 679 return(n); 680 } 681 682 prtime(s, a) 683 char *s; 684 time_t a; 685 { 686 register i; 687 int nums[3]; 688 689 for (i = 0; i < 3; i++) { 690 nums[i] = (int)(a % quant[i]); 691 a /= quant[i]; 692 } 693 printf("%s", s); 694 while (--i >= 0) 695 if (nums[i] || i == 0 && nums[1] == 0 && nums[2] == 0) 696 printf("%d %s%c ", nums[i], sep[i], 697 nums[i] == 1 ? '\0' : 's'); 698 printf("\r\n!\r\n"); 699 } 700 701 variable() 702 { 703 char buf[256]; 704 705 if (prompt("[set] ", buf)) 706 return; 707 vlex(buf); 708 if (vtable[BEAUTIFY].v_access&CHANGED) { 709 vtable[BEAUTIFY].v_access &= ~CHANGED; 710 kill(pid, SIGSYS); 711 } 712 if (vtable[SCRIPT].v_access&CHANGED) { 713 vtable[SCRIPT].v_access &= ~CHANGED; 714 setscript(); 715 /* 716 * So that "set record=blah script" doesn't 717 * cause two transactions to occur. 718 */ 719 if (vtable[RECORD].v_access&CHANGED) 720 vtable[RECORD].v_access &= ~CHANGED; 721 } 722 if (vtable[RECORD].v_access&CHANGED) { 723 vtable[RECORD].v_access &= ~CHANGED; 724 if (boolean(value(SCRIPT))) 725 setscript(); 726 } 727 if (vtable[TAND].v_access&CHANGED) { 728 vtable[TAND].v_access &= ~CHANGED; 729 if (boolean(value(TAND))) 730 tandem("on"); 731 else 732 tandem("off"); 733 } 734 if (vtable[LECHO].v_access&CHANGED) { 735 vtable[LECHO].v_access &= ~CHANGED; 736 HD = boolean(value(LECHO)); 737 } 738 if (vtable[PARITY].v_access&CHANGED) { 739 vtable[PARITY].v_access &= ~CHANGED; 740 setparity(); 741 } 742 } 743 744 /* 745 * Turn tandem mode on or off for remote tty. 746 */ 747 tandem(option) 748 char *option; 749 { 750 struct sgttyb rmtty; 751 752 ioctl(FD, TIOCGETP, &rmtty); 753 if (strcmp(option,"on") == 0) { 754 rmtty.sg_flags |= TANDEM; 755 arg.sg_flags |= TANDEM; 756 } else { 757 rmtty.sg_flags &= ~TANDEM; 758 arg.sg_flags &= ~TANDEM; 759 } 760 ioctl(FD, TIOCSETP, &rmtty); 761 ioctl(0, TIOCSETP, &arg); 762 } 763 764 /* 765 * Send a break. 766 */ 767 genbrk() 768 { 769 770 ioctl(FD, TIOCSBRK, NULL); 771 sleep(1); 772 ioctl(FD, TIOCCBRK, NULL); 773 } 774 775 /* 776 * Suspend tip 777 */ 778 suspend(c) 779 char c; 780 { 781 782 unraw(); 783 kill(c == CTRL('y') ? getpid() : 0, SIGTSTP); 784 raw(); 785 } 786 787 /* 788 * expand a file name if it includes shell meta characters 789 */ 790 791 char * 792 expand(name) 793 char name[]; 794 { 795 static char xname[BUFSIZ]; 796 char cmdbuf[BUFSIZ]; 797 register int pid, l, rc; 798 register char *cp, *Shell; 799 int s, pivec[2], (*sigint)(); 800 801 if (!anyof(name, "~{[*?$`'\"\\")) 802 return(name); 803 /* sigint = signal(SIGINT, SIG_IGN); */ 804 if (pipe(pivec) < 0) { 805 perror("pipe"); 806 /* signal(SIGINT, sigint) */ 807 return(name); 808 } 809 sprintf(cmdbuf, "echo %s", name); 810 if ((pid = vfork()) == 0) { 811 Shell = value(SHELL); 812 if (Shell == NOSTR) 813 Shell = _PATH_BSHELL; 814 close(pivec[0]); 815 close(1); 816 dup(pivec[1]); 817 close(pivec[1]); 818 close(2); 819 shell_uid(); 820 execl(Shell, Shell, "-c", cmdbuf, 0); 821 _exit(1); 822 } 823 if (pid == -1) { 824 perror("fork"); 825 close(pivec[0]); 826 close(pivec[1]); 827 return(NOSTR); 828 } 829 close(pivec[1]); 830 l = read(pivec[0], xname, BUFSIZ); 831 close(pivec[0]); 832 while (wait(&s) != pid); 833 ; 834 s &= 0377; 835 if (s != 0 && s != SIGPIPE) { 836 fprintf(stderr, "\"Echo\" failed\n"); 837 return(NOSTR); 838 } 839 if (l < 0) { 840 perror("read"); 841 return(NOSTR); 842 } 843 if (l == 0) { 844 fprintf(stderr, "\"%s\": No match\n", name); 845 return(NOSTR); 846 } 847 if (l == BUFSIZ) { 848 fprintf(stderr, "Buffer overflow expanding \"%s\"\n", name); 849 return(NOSTR); 850 } 851 xname[l] = 0; 852 for (cp = &xname[l-1]; *cp == '\n' && cp > xname; cp--) 853 ; 854 *++cp = '\0'; 855 return(xname); 856 } 857 858 /* 859 * Are any of the characters in the two strings the same? 860 */ 861 862 anyof(s1, s2) 863 register char *s1, *s2; 864 { 865 register int c; 866 867 while (c = *s1++) 868 if (any(c, s2)) 869 return(1); 870 return(0); 871 } 872