|
|
1.1 ! root 1: # This is a shell archive. ! 2: # Remove everything above and including the cut line. ! 3: # Then run the rest of the file through sh. ! 4: -----cut here-----cut here-----cut here-----cut here----- ! 5: #!/bin/sh ! 6: # shar: Shell Archiver ! 7: # Run the following text with /bin/sh to create: ! 8: # rb.1 ! 9: # rb.c ! 10: # rbsb.c ! 11: # sb.1 ! 12: # sb.c ! 13: # undos.1 ! 14: # undos.c ! 15: # This archive created: Fri Jan 10 12:33:41 1986 ! 16: cat << \SHAR_EOF > rb.1 ! 17: '\" Revision Level ! 18: '\" Last Delta 12-16-85 ! 19: .TH RB 1 OMEN ! 20: .SH NAME ! 21: rb \- YMODEM batch file receive ! 22: .SH SYNOPSIS ! 23: .B rb ! 24: [ ! 25: .B \-bquv ! 26: ] ! 27: .PP ! 28: .B rb ! 29: [ ! 30: .B \-bcquv ! 31: ] ! 32: .B file ! 33: .PP ! 34: .B [-][v]rbCOMMAND ! 35: .SH DESCRIPTION ! 36: .B Rb ! 37: receives 0 or more files in batch mode. ! 38: Iff ! 39: .B file ! 40: is speficied, ! 41: a single file is received in XMODEM single file mode. ! 42: ! 43: Normally, the file contents are converted to ! 44: .SM Unix ! 45: conventions by stripping carriage returns and all characters ! 46: beginning with Control Z (CP/M end of file). ! 47: If the raw pathname ends in ! 48: ".A", ! 49: ".ARC", ! 50: ".CCC", ! 51: ".CL", ! 52: ".CMD", ! 53: ".COM", ! 54: ".CRL", ! 55: ".DAT", ! 56: ".DIR", ! 57: ".EXE", ! 58: ".O", ! 59: ".OBJ", ! 60: ".OVL", ! 61: ".PAG", ! 62: ".REL", ! 63: ".SAV", ! 64: ".SUB", ! 65: ".SWP", ! 66: ".SYS", ! 67: ".TAR", ! 68: ".UTL", ! 69: ".a", ! 70: ".o", ! 71: ".tar", ! 72: or if the first sector contains ! 73: data that suggest a binary file ! 74: (parity bits or characters in the range 000 to 006 before the first ^Z), ! 75: or if the file mode is transmitted and the 0100000 bit is set, ! 76: that file will be received in binary mode anyway. ! 77: ! 78: Otherwise, ! 79: if the raw pathname ends in .MSG, or .TXT, any existing file will ! 80: be appended to rather than replaced. ! 81: ! 82: Normally, each file name is converted to lower case ! 83: unless it contains one or more lower case letters. ! 84: ! 85: Rb works with either standard 128 byte sectors or ! 86: 1024 byte sectors ! 87: (YAM ! 88: .B k ! 89: option). ! 90: The user should determine experimentally ! 91: the conditions under which use of 1k blocks ! 92: actually improves throughput without causing ! 93: problems. ! 94: ! 95: If extended file information (file length, etc.) ! 96: is received, ! 97: the file length controls the number of bytes written to ! 98: the output dataset, ! 99: and the modify time and file mode ! 100: (iff non zero) ! 101: are set accordingly. ! 102: ! 103: If no extended file information is received, ! 104: slashes in the pathname are changed to underscore, ! 105: and any trailing period in the pathname is eliminated. ! 106: ! 107: If rb is invoked with stdout and stderr to different datasets, ! 108: Verbose is set to 2, causing frame by frame progress reports ! 109: to stderr. ! 110: This may be disabled with the ! 111: .B q ! 112: option. ! 113: ! 114: If the SHELL environment variable includes ! 115: .I "rsh" ! 116: or ! 117: .I "rksh" ! 118: (restricted shell), ! 119: rb will not accept pathnames containing referenced to absolute paths ! 120: or to a parent directory, will not receive to an existing file, and ! 121: removes any files received in error. ! 122: ! 123: .PP ! 124: The meanings of the available options are: ! 125: .PP ! 126: .PD 0 ! 127: .TP ! 128: .B b ! 129: transfer all files in binary ! 130: (tell it like it is) ! 131: mode. ! 132: This option disables any append mode special processing. ! 133: .TP ! 134: .B c ! 135: Request 16 bit cyclic redundancy check ! 136: (8 bit checksum default). ! 137: .TP ! 138: .B q ! 139: Quiet suppresses verbosity. ! 140: .TP ! 141: .B v ! 142: .IR Verbose ! 143: causes a list of file ! 144: names to be appended to ! 145: /tmp/rblog . ! 146: More v's generate more output. ! 147: .TP ! 148: .B u ! 149: Retain upper case letters in file names unconditionally. ! 150: .PD ! 151: .SH EXAMPLES ! 152: ( ! 153: .SM Unix ! 154: command) ! 155: .RS ! 156: $rb ! 157: .br ! 158: rb: ready C ! 159: .br ! 160: .RE ! 161: (Pro-YAM command) ! 162: .RS ! 163: <F1> ! 164: .br ! 165: >>>c: sbt *.h *.c ! 166: .br ! 167: .RE ! 168: .SH SEE ALSO ! 169: YMODEM.DOC, ! 170: IMP(CP/M), ! 171: ncu(1), ! 172: Professional-YAM manual, ! 173: sb(omen), ! 174: usq(omen), ! 175: undos(omen) ! 176: ! 177: Compile time options for various operating systems are described in the ! 178: program source file. ! 179: .SH NOTES ! 180: If rb is invoked as ! 181: .B rbCOMMAND ! 182: (with an optional leading \- as generated by login(1)), ! 183: rb will pipe each received file to ``COMMAND filename'' ! 184: (filename is the name of the transmitted file) ! 185: with the file contents as standard input. ! 186: A typical usage for this form is rbrmail which calls rmail ! 187: to post mail. ! 188: On some ! 189: .SM Unix ! 190: systems, the login directory must contain ! 191: COMMAND as login sets SHELL=rsh which disallows absolute ! 192: pathnames. ! 193: If invoked with a leading ``v'' rb will report progress to LOGFILE. ! 194: The following entry works for ! 195: .SM Unix ! 196: 3.0. ! 197: rbrmail::5:1::/bin:/usr/local/rbrmail ! 198: .PP ! 199: The following (in a shell script) ! 200: may be used to fetch file(s) from a remote computer connected to /dev/tty7 ! 201: once sb has been started on the remote. ! 202: rb -v >/dev/tty7 </dev/tty7 ! 203: .SH BUGS ! 204: Pathnames are restricted to 127 characters. ! 205: ! 206: In XMODEM single file mode, the pathname given on the command line ! 207: is still processed as described above. ! 208: ! 209: The CR/LF to NL translation merely deletes CR\'s; ! 210: undos(omen) performs a more intelligent translation. ! 211: .SH "VMS VERSION" ! 212: Some of the #includes with file names enclosed with angle brackets <> ! 213: may need to have the angle brackets removed, or vice versa. ! 214: ! 215: The VMS version does not set binary mode according to the incoming ! 216: file type. ! 217: Non binary file processing consists of stripping all characters beginning ! 218: with CPMEOF (^Z). ! 219: ! 220: The VMS version does not set the file time. ! 221: ! 222: VMS occaisonally loses incoming characters, resulting in retries ! 223: and degradation of throughput. ! 224: ! 225: There may be unknown interactions between the VMS C standard i/o ! 226: package and RMS. ! 227: ! 228: The VMS version does not support invocation as ! 229: .B rbCOMMAND . ! 230: SHAR_EOF ! 231: cat << \SHAR_EOF > rb.c ! 232: #define VERSION "2.17 12-07-85" ! 233: #define PUBDIR "/usr/spool/uucppublic" ! 234: ! 235: /*% cc -DUSG -DNFGVMIN -O -K % -o rb ! 236: * ! 237: * rb.c By Chuck Forsberg ! 238: * ! 239: * USG UNIX (3.0) ioctl conventions courtesy Jeff Martin ! 240: * cc -O -DV7 rb.c -o rb Unix V7, BSD 2.8 - 4.2 ! 241: * cc -O -DUSG rb.c -o rb USG (3.0) Unix ! 242: * cc -o rb.c Regulus ! 243: * (Don't try this on Unix, you'll clobber the source!) ! 244: * Unix is a trademark of Western Electric Company ! 245: * ! 246: * Regulus conventions 1-10-83 CAF ! 247: * ! 248: * Some systems (Venix, Coherent, Regulus) do not support tty raw mode ! 249: * read(2) the same way as Unix. ONEREAD must be defined to force one ! 250: * character reads for these systems. Added 7-01-84 CAF ! 251: * ! 252: * Alarm signal handling changed to work with 4.2 BSD 7-15-84 CAF ! 253: * ! 254: * NFGVMIN Added 1-13-85 CAF for PC-AT Xenix systems where c_cc[VMIN] ! 255: * doesn't seem to work (even though it compiles without error!). ! 256: * ! 257: * A program for Unix which can receive ! 258: * files from computers running YAM or MODEM. ! 259: * rb uses Unix System III buffered input to reduce CPU time. ! 260: * If no filename is given, YAM batch mode is assumed. ! 261: * ! 262: * Iff the program is invoked by rbCOMMAND, output is piped to ! 263: * "COMMAND filename" ! 264: * ! 265: * Supports the CRC option or regular checksum. ! 266: * Received pathnames containing no lowercase letters will be changed to lower ! 267: * case unless -u option is given. ! 268: * ! 269: * Unless the -b (binary) option is given, \r is discarded and ! 270: * ^Z (which is also discarded) acts as end of file. ! 271: * ! 272: * Any slashes in the pathname are changed to underscore. ! 273: * If the raw pathname ends in .MSG or .TXT, any existing file will ! 274: * be appended to rather than replaced. Trailing periods are eliminated. ! 275: * ! 276: * If the raw pathname ends in any of the extensions in Extensions, ! 277: * or .?Q* (squeezed file), or if the first sector contains binary-like ! 278: * data (parity bits or characters in the range 0 to 6 before ^Z is seen), ! 279: * or if the transmitted file mode has the 0100000 but set, ! 280: * that file will be received in binary mode anyway. ! 281: * ! 282: * ! 283: * A log of activities is appended to LOGFILE with the -v option ! 284: * If stdout and stderr refer to different devices, progress is displayed to ! 285: * stderr. ! 286: * ! 287: * rb is derived from yam2.c and sb.c ! 288: */ ! 289: #define LOGFILE "/tmp/rblog" ! 290: ! 291: #include <stdio.h> ! 292: #include <signal.h> ! 293: #include <setjmp.h> ! 294: #include <ctype.h> ! 295: FILE *popen(); ! 296: ! 297: #define OK 0 ! 298: #define FALSE 0 ! 299: #define TRUE 1 ! 300: #define ERROR (-1) ! 301: ! 302: #define HOWMANY 133 ! 303: #include "rbsb.c" /* most of the system dependent stuff here */ ! 304: ! 305: char *substr(); ! 306: FILE *fout; ! 307: ! 308: char *Extensions[] = { ! 309: ".A", ! 310: ".ARC", ! 311: ".CCC", ! 312: ".CL", ! 313: ".CMD", ! 314: ".COM", ! 315: ".CRL", ! 316: ".DAT", ! 317: ".DIR", ! 318: ".EXE", ! 319: ".O", ! 320: ".OBJ", ! 321: ".OVL", ! 322: ".PAG", ! 323: ".REL", ! 324: ".SAV", ! 325: ".SUB", ! 326: ".SWP", ! 327: ".SYS", ! 328: ".TAR", ! 329: ".UTL", ! 330: ".a", ! 331: ".o", ! 332: ".tar", ! 333: "" ! 334: }; ! 335: ! 336: /* Ward Christensen / CP/M parameters - Don't change these! */ ! 337: #define ENQ 005 ! 338: #define CAN ('X'&037) ! 339: #define XOFF ('s'&037) ! 340: #define XON ('q'&037) ! 341: #define SOH 1 ! 342: #define STX 2 ! 343: #define EOT 4 ! 344: #define ACK 6 ! 345: #define NAK 025 ! 346: #define CPMEOF 032 ! 347: #define WANTCRC 0103 /* send C not NAK to get crc not checksum */ ! 348: #define TIMEOUT (-2) ! 349: #define ERRORMAX 5 ! 350: #define RETRYMAX 5 ! 351: #define WCEOT (-10) ! 352: #define SECSIZ 128 /* cp/m's Magic Number record size */ ! 353: #define PATHLEN 257 /* ready for 4.2 bsd ? */ ! 354: #define KSIZE 1024 /* record size with k option */ ! 355: #define UNIXFILE 0x8000 /* happens to the the S_IFREG file mask bit for stat */ ! 356: ! 357: int Lastrx; ! 358: int Crcflg; ! 359: int Firstsec; ! 360: int Eofseen; /* indicates cpm eof (^Z) has been received */ ! 361: int totblocks; /* total number of blocks received */ ! 362: int errors; ! 363: int Restricted=0; /* restricted; no /.. or ../ in filenames */ ! 364: ! 365: #define DEFBYTL 2000000000L /* default rx file size */ ! 366: long Bytesleft; /* number of bytes of incoming file left */ ! 367: long Modtime; /* Unix style mod time for incoming file */ ! 368: short Filemode; /* Unix style mode for incoming file */ ! 369: char Pathname[PATHLEN]; ! 370: char *Progname; /* the name by which we were called */ ! 371: ! 372: int Batch=0; ! 373: int Wcsmask=0377; ! 374: int Topipe=0; ! 375: int MakeLCPathname=TRUE; /* make received pathname lower case */ ! 376: int Verbose=0; ! 377: int Quiet=0; /* overrides logic that would otherwise set verbose */ ! 378: int Rxbinary=FALSE; /* receive all files in bin mode */ ! 379: int Thisbinary; /* current file is to be received in bin mode */ ! 380: int Blklen; /* record length of received packets */ ! 381: char secbuf[KSIZE]; ! 382: char linbuf[KSIZE]; ! 383: int Lleft=0; /* number of characters in linbuf */ ! 384: ! 385: jmp_buf tohere; /* For the interrupt on RX timeout */ ! 386: ! 387: unsigned short updcrc(); ! 388: ! 389: alrm() ! 390: { ! 391: longjmp(tohere, -1); ! 392: } ! 393: ! 394: /* called by signal interrupt or terminate to clean things up */ ! 395: bibi(n) ! 396: { ! 397: canit(); mode(0); ! 398: fprintf(stderr, "sb: caught signal %d; exiting", n); ! 399: exit(128+n); ! 400: } ! 401: ! 402: main(argc, argv) ! 403: char *argv[]; ! 404: { ! 405: register char *cp; ! 406: register npats; ! 407: char *virgin, **patts; ! 408: char *getenv(); ! 409: int exitcode; ! 410: ! 411: setbuf(stderr, NULL); ! 412: if ((cp=getenv("SHELL")) && (substr(cp, "rsh") || substr(cp, "rsh"))) ! 413: Restricted=TRUE; ! 414: ! 415: chkinvok(virgin=argv[0]); /* if called as [-]rbCOMMAND set flag */ ! 416: npats = 0; ! 417: while (--argc) { ! 418: cp = *++argv; ! 419: if (*cp == '-') { ! 420: while( *++cp) { ! 421: switch(*cp) { ! 422: case '1': ! 423: iofd = 1; break; ! 424: case '7': ! 425: Wcsmask = 0177; ! 426: case 'b': ! 427: Rxbinary=TRUE; break; ! 428: case 'k': ! 429: case 'c': ! 430: Crcflg=TRUE; break; ! 431: case 'q': ! 432: Quiet=TRUE; Verbose=0; break; ! 433: case 'u': ! 434: MakeLCPathname=FALSE; break; ! 435: case 'v': ! 436: ++Verbose; break; ! 437: default: ! 438: usage(); ! 439: } ! 440: } ! 441: } ! 442: else if ( !npats && argc>0) { ! 443: if (argv[0][0]) { ! 444: npats=argc; ! 445: patts=argv; ! 446: } ! 447: } ! 448: } ! 449: if (npats > 1) ! 450: usage(); ! 451: if (Verbose) { ! 452: if (freopen(LOGFILE, "a", stderr)==NULL) { ! 453: printf("Can't open log file %s\n",LOGFILE); ! 454: exit(0200); ! 455: } ! 456: setbuf(stderr, NULL); ! 457: fprintf(stderr, "argv[0]=%s Progname=%s\n", virgin, Progname); ! 458: } ! 459: if (fromcu() && !Quiet) { ! 460: if (Verbose == 0) ! 461: Verbose = 2; ! 462: } ! 463: mode(1); ! 464: if (signal(SIGINT, bibi) == SIG_IGN) { ! 465: signal(SIGINT, SIG_IGN); signal(SIGKILL, SIG_IGN); ! 466: } ! 467: else { ! 468: signal(SIGINT, bibi); signal(SIGKILL, bibi); ! 469: } ! 470: if (wcreceive(npats, patts)==ERROR) { ! 471: exitcode=0200; ! 472: canit(); ! 473: } ! 474: mode(0); ! 475: if (exitcode != 0) /* bellow again with all thy might. */ ! 476: canit(); ! 477: #ifdef REGULUS ! 478: else ! 479: printf("\6\6\6\6\6\n"); /* Regulus doesn't wait ... */ ! 480: #endif ! 481: exit(exitcode); ! 482: } ! 483: ! 484: ! 485: usage() ! 486: { ! 487: fprintf(stderr,"%s %s by Chuck Forsberg\n", Progname, VERSION); ! 488: fprintf(stderr,"Usage: rb [-17buv]\n\tor rb [-1bcuv] file\n"); ! 489: exit(1); ! 490: } ! 491: ! 492: wcreceive(argc, argp) ! 493: char **argp; ! 494: { ! 495: if (Batch || argc==0) { ! 496: Crcflg=(Wcsmask==0377); ! 497: fprintf(stderr, "rb: ready "); ! 498: for (;;) { ! 499: totblocks=0; ! 500: if (wcrxpn(secbuf)== ERROR) ! 501: goto fubar; ! 502: if (secbuf[0]==0) ! 503: return OK; ! 504: if (procheader(secbuf) == ERROR) ! 505: goto fubar; ! 506: if (wcrx()==ERROR) ! 507: goto fubar; ! 508: } ! 509: } else { ! 510: totblocks=0; Bytesleft = DEFBYTL; Filemode = 0; Modtime = 0L; ! 511: ! 512: strcpy(Pathname, *argp); ! 513: checkpath(Pathname); ! 514: fprintf(stderr, "\nrb: ready to receive %s ", Pathname); ! 515: if ((fout=fopen(Pathname, "w")) == NULL) ! 516: return ERROR; ! 517: if (wcrx()==ERROR) ! 518: goto fubar; ! 519: } ! 520: return OK; ! 521: fubar: ! 522: canit(); ! 523: if (Topipe && fout) { ! 524: pclose(fout); return ERROR; ! 525: } ! 526: if (fout) ! 527: fclose(fout); ! 528: if (Restricted) { ! 529: unlink(Pathname); ! 530: fprintf(stderr, "\r\nrb: %s removed.\r\n", Pathname); ! 531: } ! 532: return ERROR; ! 533: } ! 534: ! 535: ! 536: /* ! 537: * Fetch a pathname from the other end as a C ctyle ASCIZ string. ! 538: * Length is indeterminate as long as less than Blklen ! 539: * a null string represents no more files ! 540: */ ! 541: wcrxpn(rpn) ! 542: char *rpn; /* receive a pathname */ ! 543: { ! 544: register c; ! 545: ! 546: #ifdef NFGVMIN ! 547: readline(1); ! 548: #else ! 549: purgeline(); ! 550: #endif ! 551: ! 552: et_tu: ! 553: Firstsec=TRUE; ! 554: sendline(Crcflg?WANTCRC:NAK); ! 555: while ((c = wcgetsec(rpn, 100)) != 0) { ! 556: log( "Pathname fetch returned %d\n", c); ! 557: if (c == WCEOT) { ! 558: sendline(ACK); readline(1); goto et_tu; ! 559: } ! 560: return ERROR; ! 561: } ! 562: sendline(ACK); ! 563: return OK; ! 564: } ! 565: ! 566: /* ! 567: * Adapted from CMODEM13.C, written by ! 568: * Jack M. Wierda and Roderick W. Hart ! 569: */ ! 570: ! 571: wcrx() ! 572: { ! 573: register int sectnum, sectcurr; ! 574: register char sendchar; ! 575: register char *p; ! 576: int cblklen; /* bytes to dump this block */ ! 577: time_t timep[2]; ! 578: ! 579: Firstsec=TRUE;sectnum=0; Eofseen=FALSE; ! 580: sendchar=Crcflg?WANTCRC:NAK; ! 581: ! 582: for (;;) { ! 583: sendline(sendchar); /* send it now, we're ready! */ ! 584: sectcurr=wcgetsec(secbuf, (sectnum&0177)?50:130); ! 585: report(sectcurr); ! 586: if (sectcurr==(sectnum+1 &Wcsmask)) { ! 587: ! 588: if (sectnum==0 && !Thisbinary) ! 589: for (p=secbuf,sectcurr=Blklen; ! 590: *p != 032 && --sectcurr>=0; ++p) ! 591: if (*p < 07 || (*p & 0200)) { ! 592: Thisbinary++; ! 593: if (Verbose) ! 594: fprintf(stderr, "Changed to BIN\n"); ! 595: break; ! 596: } ! 597: sectnum++; ! 598: cblklen = Bytesleft>Blklen ? Blklen:Bytesleft; ! 599: if (putsec(secbuf, cblklen)==ERROR) ! 600: return ERROR; ! 601: if ((Bytesleft-=cblklen) < 0) ! 602: Bytesleft = 0; ! 603: sendchar=ACK; ! 604: } ! 605: else if (sectcurr==(sectnum&Wcsmask)) { ! 606: log( "Received dup Sector\n"); ! 607: sendchar=ACK; ! 608: } ! 609: else if (sectcurr==WCEOT) { ! 610: if (Topipe) { ! 611: if (pclose(fout)!=ERROR) { ! 612: sendline(ACK); ! 613: return OK; ! 614: } ! 615: canit(); return ERROR; ! 616: } ! 617: if (fclose(fout)==ERROR) { ! 618: canit(); ! 619: fprintf(stderr, "file close ERROR\n"); ! 620: return ERROR; ! 621: } ! 622: if (Modtime) { ! 623: timep[0] = time(NULL); ! 624: timep[1] = Modtime; ! 625: utime(Pathname, timep); ! 626: } ! 627: if (Filemode) ! 628: chmod(Pathname, (07777 & Filemode)); ! 629: sendline(ACK); ! 630: return OK; ! 631: } ! 632: else if (sectcurr==ERROR) ! 633: return ERROR; ! 634: else { ! 635: log( "Sync Error\n"); ! 636: return ERROR; ! 637: } ! 638: } ! 639: } ! 640: ! 641: /* ! 642: * wcgetsec fetches a Ward Christensen type sector. ! 643: * Returns sector number encountered or ERROR if valid sector not received, ! 644: * or CAN CAN received ! 645: * or WCEOT if eot sector ! 646: * time is timeout for first char, set to 4 seconds thereafter ! 647: ***************** NO ACK IS SENT IF SECTOR IS RECEIVED OK ************** ! 648: * (Caller must do that when he is good and ready to get next sector) ! 649: */ ! 650: ! 651: wcgetsec(rxbuf, maxtime) ! 652: char *rxbuf; ! 653: int maxtime; ! 654: { ! 655: register checksum, wcj, firstch; ! 656: register unsigned short oldcrc; ! 657: register char *p; ! 658: int sectcurr; ! 659: ! 660: for (Lastrx=errors=0; errors<RETRYMAX; errors++) { ! 661: ! 662: if ((firstch=readline(maxtime))==STX) { ! 663: Blklen=KSIZE; goto get2; ! 664: } ! 665: if (firstch==SOH) { ! 666: Blklen=SECSIZ; ! 667: get2: ! 668: sectcurr=readline(1); ! 669: if ((sectcurr+(oldcrc=readline(1)))==Wcsmask) { ! 670: oldcrc=checksum=0; ! 671: for (p=rxbuf,wcj=Blklen; --wcj>=0; ) { ! 672: if ((firstch=readline(1)) < 0) ! 673: goto bilge; ! 674: oldcrc=updcrc(firstch, oldcrc); ! 675: checksum += (*p++ = firstch); ! 676: } ! 677: if ((firstch=readline(1)) < 0) ! 678: goto bilge; ! 679: if (Crcflg) { ! 680: oldcrc=updcrc(firstch, oldcrc); ! 681: if ((firstch=readline(1)) < 0) ! 682: goto bilge; ! 683: oldcrc=updcrc(firstch, oldcrc); ! 684: if (oldcrc) ! 685: log("CRC=0%o\n", oldcrc); ! 686: else { ! 687: Firstsec=FALSE; ! 688: return sectcurr; ! 689: } ! 690: } ! 691: else if (((checksum-firstch)&Wcsmask)==0) { ! 692: Firstsec=FALSE; ! 693: return sectcurr; ! 694: } ! 695: else ! 696: log( "Checksum Error\n"); ! 697: } ! 698: else ! 699: log("Sector number garbled 0%o 0%o\n", ! 700: sectcurr, oldcrc); ! 701: } ! 702: /* make sure eot really is eot and not just mixmash */ ! 703: #ifdef NFGVMIN ! 704: else if (firstch==EOT && readline(1)==TIMEOUT) ! 705: return WCEOT; ! 706: #else ! 707: else if (firstch==EOT && Lleft==0) ! 708: return WCEOT; ! 709: #endif ! 710: else if (firstch==CAN) { ! 711: if (Lastrx==CAN) { ! 712: log( "Sender CANcelled\n"); ! 713: return ERROR; ! 714: } else { ! 715: Lastrx=CAN; ! 716: continue; ! 717: } ! 718: } ! 719: else if (firstch==TIMEOUT) { ! 720: if (Firstsec) ! 721: goto humbug; ! 722: bilge: ! 723: log( "Timeout\n"); ! 724: } ! 725: else ! 726: log( "Got 0%o sector header\n", firstch); ! 727: ! 728: humbug: ! 729: Lastrx=0; ! 730: while(readline(1)!=TIMEOUT) ! 731: ; ! 732: if (Firstsec) ! 733: sendline(Crcflg?WANTCRC:NAK); ! 734: else { ! 735: maxtime=40; sendline(NAK); ! 736: } ! 737: } ! 738: /* try to stop the bubble machine. */ ! 739: canit(); ! 740: return ERROR; ! 741: } ! 742: ! 743: /* ! 744: * This version of readline is reasoably well suited for ! 745: * reading many characters. ! 746: * (except, currently, for the Regulus version!) ! 747: * ! 748: * timeout is in tenths of seconds ! 749: */ ! 750: readline(timeout) ! 751: int timeout; ! 752: { ! 753: register n; ! 754: static char *cdq; /* pointer for removing chars from linbuf */ ! 755: ! 756: if (--Lleft >= 0) { ! 757: if (Verbose > 8) { ! 758: fprintf(stderr, "%02x ", *cdq&0377); ! 759: } ! 760: return (*cdq++ & Wcsmask); ! 761: } ! 762: n = timeout/10; ! 763: if (n < 2) ! 764: n = 3; ! 765: if (Verbose > 3) ! 766: fprintf(stderr, "Calling read: n=%d ", n); ! 767: if (setjmp(tohere)) { ! 768: #ifdef TIOCFLUSH ! 769: /* ioctl(iofd, TIOCFLUSH, 0); */ ! 770: #endif ! 771: Lleft = 0; ! 772: if (Verbose>1) ! 773: fprintf(stderr, "Readline:TIMEOUT\n"); ! 774: return TIMEOUT; ! 775: } ! 776: signal(SIGALRM, alrm); alarm(n); ! 777: #ifdef ONEREAD ! 778: /* Sorry, Regulus and some others don't work right in raw mode! */ ! 779: Lleft=read(iofd, cdq=linbuf, 1); ! 780: #else ! 781: Lleft=read(iofd, cdq=linbuf, KSIZE); ! 782: #endif ! 783: alarm(0); ! 784: if (Verbose > 3) { ! 785: fprintf(stderr, "Read returned %d bytes\n", Lleft); ! 786: } ! 787: if (Lleft < 1) ! 788: return TIMEOUT; ! 789: --Lleft; ! 790: if (Verbose > 8) { ! 791: fprintf(stderr, "%02x ", *cdq&0377); ! 792: } ! 793: return (*cdq++ & Wcsmask); ! 794: } ! 795: ! 796: ! 797: ! 798: ! 799: purgeline() ! 800: { ! 801: Lleft = 0; ! 802: #ifdef USG ! 803: ioctl(iofd, TCFLSH, 0); ! 804: #else ! 805: lseek(iofd, 0L, 2); ! 806: #endif ! 807: } ! 808: ! 809: /* update CRC */ ! 810: unsigned short ! 811: updcrc(c, crc) ! 812: register c; ! 813: register unsigned crc; ! 814: { ! 815: register count; ! 816: ! 817: for (count=8; --count>=0;) { ! 818: if (crc & 0x8000) { ! 819: crc <<= 1; ! 820: crc += (((c<<=1) & 0400) != 0); ! 821: crc ^= 0x1021; ! 822: } ! 823: else { ! 824: crc <<= 1; ! 825: crc += (((c<<=1) & 0400) != 0); ! 826: } ! 827: } ! 828: return crc; ! 829: } ! 830: ! 831: /* ! 832: * process incoming header ! 833: */ ! 834: procheader(name) ! 835: char *name; ! 836: { ! 837: register char *openmode, *p, **pp; ! 838: ! 839: /* set default parameters */ ! 840: openmode = "w"; Thisbinary=Rxbinary; ! 841: Bytesleft = DEFBYTL; Filemode = 0; Modtime = 0L; ! 842: ! 843: p = name + 1 + strlen(name); ! 844: if (*p) { /* file coming from Unix or DOS system */ ! 845: sscanf(p, "%ld%lo%o", &Bytesleft, &Modtime, &Filemode); ! 846: if (Filemode & UNIXFILE) ! 847: ++Thisbinary; ! 848: if (Verbose) { ! 849: fprintf(stderr, "Incoming: %s %ld %lo %o\n", ! 850: name, Bytesleft, Modtime, Filemode); ! 851: } ! 852: } ! 853: else { /* File coming from CP/M system */ ! 854: for (p=name; *p; ++p) /* change / to _ */ ! 855: if ( *p == '/') ! 856: *p = '_'; ! 857: ! 858: if ( *--p == '.') /* zap trailing period */ ! 859: *p = 0; ! 860: } ! 861: ! 862: /* scan for extensions that signify a binary file */ ! 863: if (p=substr(name, ".")) ! 864: for (pp=Extensions; **pp; ++pp) ! 865: if (strcmp(p, *pp)==0) { ! 866: Thisbinary=TRUE; break; ! 867: } ! 868: ! 869: /* scan for files which should be appended */ ! 870: if ( !Thisbinary ! 871: && (substr(name, ".TXT") ! 872: || substr(name, ".txt") ! 873: || substr(name, ".MSG"))) ! 874: openmode = "a"; ! 875: if (MakeLCPathname && !IsAnyLower(name)) ! 876: uncaps(name); ! 877: if (Topipe) { ! 878: sprintf(Pathname, "%s %s", Progname+2, name); ! 879: if (Verbose) ! 880: fprintf(stderr, "Topipe: %s %s\n", ! 881: Pathname, Thisbinary?"BIN":"ASCII"); ! 882: if ((fout=popen(Pathname, "w")) == NULL) ! 883: return ERROR; ! 884: } else { ! 885: strcpy(Pathname, name); ! 886: if (Verbose) { ! 887: fprintf(stderr, "Receiving %s %s %s\n", ! 888: name, Thisbinary?"BIN":"ASCII", openmode); ! 889: } ! 890: checkpath(name); ! 891: if ((fout=fopen(name, openmode)) == NULL) ! 892: return ERROR; ! 893: } ! 894: return OK; ! 895: } ! 896: ! 897: /* make string s lower case */ ! 898: uncaps(s) ! 899: register char *s; ! 900: { ! 901: for ( ; *s; ++s) ! 902: if (isupper(*s)) ! 903: *s = tolower(*s); ! 904: } ! 905: ! 906: ! 907: /* ! 908: * IsAnyLower returns TRUE if string s has lower case letters. ! 909: */ ! 910: IsAnyLower(s) ! 911: register char *s; ! 912: { ! 913: for ( ; *s; ++s) ! 914: if (islower(*s)) ! 915: return TRUE; ! 916: return FALSE; ! 917: } ! 918: /* ! 919: * putsec writes the n characters of buf to receive file fout. ! 920: * If not in binary mode, carriage returns, and all characters ! 921: * starting with CPMEOF are discarded. ! 922: */ ! 923: putsec(buf, n) ! 924: char *buf; ! 925: register n; ! 926: { ! 927: register char *p; ! 928: ! 929: ++totblocks; ! 930: if (Thisbinary) ! 931: { ! 932: for (p=buf; --n>=0; ) ! 933: putc( *p++, fout); ! 934: } ! 935: else { ! 936: if (Eofseen) ! 937: return OK; ! 938: for (p=buf; --n>=0; ++p ) { ! 939: if ( *p == '\r') ! 940: continue; ! 941: if (*p == CPMEOF) { ! 942: Eofseen=TRUE; return OK; ! 943: } ! 944: putc(*p ,fout); ! 945: } ! 946: } ! 947: return OK; ! 948: } ! 949: sendline(c) ! 950: { ! 951: char d; ! 952: ! 953: d = c; ! 954: if (Verbose>2) ! 955: fprintf(stderr, "Sendline: %x\n", c); ! 956: write(1, &d, 1); ! 957: Lleft=0; /* Do read next time ... */ ! 958: } ! 959: ! 960: ! 961: /* ! 962: * substr(string, token) searches for token in string s ! 963: * returns pointer to token within string if found, NULL otherwise ! 964: */ ! 965: char * ! 966: substr(s, t) ! 967: register char *s,*t; ! 968: { ! 969: register char *ss,*tt; ! 970: /* search for first char of token */ ! 971: for (ss=s; *s; s++) ! 972: if (*s == *t) ! 973: /* compare token with substring */ ! 974: for (ss=s,tt=t; ;) { ! 975: if (*tt == 0) ! 976: return s; ! 977: if (*ss++ != *tt++) ! 978: break; ! 979: } ! 980: return NULL; ! 981: } ! 982: ! 983: /*VARARGS1*/ ! 984: log(s,p,u) ! 985: char *s, *p, *u; ! 986: { ! 987: if (!Verbose) ! 988: return; ! 989: fprintf(stderr, "error %d: ", errors); ! 990: fprintf(stderr, s, p, u); ! 991: } ! 992: ! 993: /* send 10 CAN's to try to get the other end to shut up */ ! 994: canit() ! 995: { ! 996: register n; ! 997: for (n=10; --n>=0; ) ! 998: sendline(CAN); ! 999: } ! 1000: ! 1001: #ifdef REGULUS ! 1002: /* ! 1003: * copies count bytes from s to d ! 1004: * (No structure assignment in Regulus C compiler) ! 1005: */ ! 1006: ! 1007: movmem(s, d, count) ! 1008: register char *s, *d; ! 1009: register count; ! 1010: { ! 1011: while (--count >= 0) ! 1012: *d++ = *s++; ! 1013: } ! 1014: #endif ! 1015: ! 1016: /* ! 1017: * return 1 iff stdout and stderr are different devices ! 1018: * indicating this program operating with a modem on a ! 1019: * different line ! 1020: */ ! 1021: fromcu() ! 1022: { ! 1023: struct stat a, b; ! 1024: fstat(1, &a); fstat(2, &b); ! 1025: return (a.st_rdev != b.st_rdev); ! 1026: } ! 1027: ! 1028: report(sct) ! 1029: int sct; ! 1030: { ! 1031: if (Verbose>1) ! 1032: fprintf(stderr,"%03d%c",sct,sct%10? ' ' : '\r'); ! 1033: } ! 1034: ! 1035: /* ! 1036: * if called as [-][dir/../]vrbCOMMAND set Verbose to 1 ! 1037: * if called as [-][dir/../]rbCOMMAND set the pipe flag ! 1038: */ ! 1039: chkinvok(s) ! 1040: char *s; ! 1041: { ! 1042: register char *p; ! 1043: ! 1044: p = s; ! 1045: while (*p == '-') ! 1046: s = ++p; ! 1047: while (*p) ! 1048: if (*p++ == '/') ! 1049: s = p; ! 1050: if (*s == 'v') { ! 1051: Verbose=1; ++s; ! 1052: } ! 1053: Progname = s; ! 1054: if (s[2] && s[0]=='r' && s[1]=='b') ! 1055: Topipe=TRUE; ! 1056: } ! 1057: ! 1058: checkpath(name) ! 1059: char *name; ! 1060: { ! 1061: if (Restricted) { ! 1062: if (fopen(name, "r") != NULL) { ! 1063: canit(); ! 1064: fprintf(stderr, "\r\nrb: %s exists\n", name); ! 1065: bibi(); ! 1066: } ! 1067: /* restrict pathnames to current tree or uucppublic */ ! 1068: if ( substr(name, "../") ! 1069: || (name[0]== '/' && strncmp(name, PUBDIR, strlen(PUBDIR))) ) { ! 1070: canit(); ! 1071: fprintf(stderr,"\r\nrb:\tSecurity Violation\r\n"); ! 1072: bibi(); ! 1073: } ! 1074: } ! 1075: } ! 1076: ! 1077: SHAR_EOF ! 1078: cat << \SHAR_EOF > rbsb.c ! 1079: /* -rev 09-13-85 ! 1080: * mode function and most of the rest of the system dependent ! 1081: * stuff for rb.c and sb.c This file is #included so the includer ! 1082: * can set parameters such as HOWMANY. ! 1083: */ ! 1084: ! 1085: #ifdef USG ! 1086: #include <sys/types.h> ! 1087: #include <sys/stat.h> ! 1088: #include <termio.h> ! 1089: #include <sys/ioctl.h> ! 1090: #define OS "USG" ! 1091: #endif ! 1092: ! 1093: #ifdef V7 ! 1094: #include <sys/types.h> ! 1095: #include <sys/stat.h> ! 1096: #include <sgtty.h> ! 1097: #define OS "V7" ! 1098: #endif ! 1099: ! 1100: #ifndef OS ! 1101: #include <termio.h> ! 1102: #include <sys/ioctl.h> ! 1103: #include <stat.h> ! 1104: #define REGULUS ! 1105: #define ONEREAD ! 1106: #define OS "REGULUS" ! 1107: #define void int ! 1108: #define time_t long ! 1109: #endif ! 1110: ! 1111: ! 1112: #ifdef ICANON ! 1113: struct termio oldtty, tty; ! 1114: #else ! 1115: struct sgttyb oldtty, tty; ! 1116: struct tchars oldtch, tch; ! 1117: #endif ! 1118: ! 1119: int iofd = 0; /* File descriptor for ioctls & reads */ ! 1120: ! 1121: /* ! 1122: * mode(n) ! 1123: * 2: set a cbreak, XON/XOFF control mode if using Pro-YAM's -g option ! 1124: * 1: save old tty stat, set raw mode ! 1125: * 0: restore original tty mode ! 1126: */ ! 1127: mode(n) ! 1128: { ! 1129: static did0 = FALSE; ! 1130: ! 1131: switch(n) { ! 1132: #ifdef USG ! 1133: case 2: /* Cbreak mode used by sb when -g detected */ ! 1134: if(!did0) ! 1135: (void) ioctl(iofd, TCGETA, &oldtty); ! 1136: tty = oldtty; ! 1137: ! 1138: tty.c_iflag = BRKINT|IXON; ! 1139: ! 1140: tty.c_oflag = 0; /* Transparent output */ ! 1141: ! 1142: tty.c_cflag &= ~PARENB; /* Disable parity */ ! 1143: tty.c_cflag |= CS8; /* Set character size = 8 */ ! 1144: ! 1145: #ifdef XCLUDE ! 1146: tty.c_lflag = XCLUDE | ISIG; ! 1147: #else ! 1148: tty.c_lflag = ISIG; ! 1149: #endif ! 1150: ! 1151: tty.c_cc[VINTR] = 030; /* Interrupt on CANCEL */ ! 1152: tty.c_cc[VMIN] = 1; ! 1153: ! 1154: (void) ioctl(iofd, TCSETAW, &tty); ! 1155: did0 = TRUE; ! 1156: return OK; ! 1157: case 1: ! 1158: if(!did0) ! 1159: (void) ioctl(iofd, TCGETA, &oldtty); ! 1160: tty = oldtty; ! 1161: ! 1162: tty.c_iflag = IGNBRK; ! 1163: ! 1164: /* No echo, crlf mapping, INTR, QUIT, delays, no erase/kill */ ! 1165: tty.c_lflag &= ~(ECHO | ICANON | ISIG); ! 1166: #ifdef XCLUDE ! 1167: tty.c_lflag |= XCLUDE; ! 1168: #endif ! 1169: ! 1170: tty.c_oflag = 0; /* Transparent output */ ! 1171: ! 1172: tty.c_cflag &= ~PARENB; /* Leave baud rate alone, disable parity */ ! 1173: tty.c_cflag |= CS8; /* Set character size = 8 */ ! 1174: tty.c_cc[VMIN] = HOWMANY; /* Satisfy reads when this many chars in */ ! 1175: tty.c_cc[VTIME] = 1; /* ... or in this many tenths of seconds */ ! 1176: (void) ioctl(iofd, TCSETAW, &tty); ! 1177: did0 = TRUE; ! 1178: return OK; ! 1179: #endif ! 1180: #ifdef V7 ! 1181: case 2: ! 1182: if(!did0) { ! 1183: ioctl(iofd, TIOCEXCL, 0); ! 1184: ioctl(iofd, TIOCGETP, &oldtty); ! 1185: ioctl(iofd, TIOCGETC, &oldtch); ! 1186: } ! 1187: tty = oldtty; ! 1188: tch = oldtch; ! 1189: tch.t_intrc = 030; ! 1190: tty.sg_flags |= CBREAK; ! 1191: tty.sg_flags &= ~ECHO; ! 1192: ioctl(iofd, TIOCSETP, &tty); ! 1193: ioctl(iofd, TIOCSETC, &tch); ! 1194: did0 = TRUE; ! 1195: return OK; ! 1196: case 1: ! 1197: if(!did0) { ! 1198: ioctl(iofd, TIOCEXCL, 0); ! 1199: ioctl(iofd, TIOCGETP, &oldtty); ! 1200: ioctl(iofd, TIOCGETC, &oldtch); ! 1201: } ! 1202: tty = oldtty; ! 1203: tty.sg_flags |= RAW; ! 1204: tty.sg_flags &= ~ECHO; ! 1205: ioctl(iofd, TIOCSETP, &tty); ! 1206: did0 = TRUE; ! 1207: return OK; ! 1208: #endif ! 1209: #ifdef REGULUS ! 1210: case 2: ! 1211: return ERROR; ! 1212: case 1: ! 1213: if(!did0) { ! 1214: ioctl(iofd, TCGETA, &oldtty); ! 1215: } ! 1216: tty = oldtty; ! 1217: ! 1218: tty.c_lflag = 0; ! 1219: tty.c_iflag = IGNBRK; ! 1220: tty.c_oflag = 0; /* Transparent output */ ! 1221: ! 1222: tty.c_cflag &= ~PARENB; /* Leave baud rate alone, disable parity */ ! 1223: tty.c_cflag |= CS8; /* Set character size = 8 */ ! 1224: tty.c_cc[VMIN] = HOWMANY; /* Satisfy reads when this many chars in */ ! 1225: tty.c_cc[VTIME] = 1; /* ... or in this many tenths of seconds */ ! 1226: ioctl(iofd, TCSETA, &tty); ! 1227: did0 = TRUE; ! 1228: return OK; ! 1229: #endif ! 1230: #ifdef REGULUS10 ! 1231: if(!did0) { ! 1232: ioctl(iofd, TIOCGETP, &oldtty); ! 1233: } ! 1234: /* Sorry, No structure assignment in Regulus C */ ! 1235: movmem( (char *)&oldtty, (char *)&tty, sizeof(tty)); ! 1236: tty.sg_flags |= (EIGHTBIT|RAW); ! 1237: tty.sg_flags &= ~ECHO; ! 1238: tty.sg_ledit &= ~LEDIT; ! 1239: ioctl(iofd, TIOCSETP, &tty); ! 1240: did0 = TRUE; ! 1241: return OK; ! 1242: #endif ! 1243: case 0: ! 1244: if(!did0) ! 1245: return ERROR; ! 1246: #ifdef USG ! 1247: (void) ioctl(iofd, TCSBRK, 1); /* Wait for output to drain */ ! 1248: (void) ioctl(iofd, TCFLSH, 1); /* Flush input queue */ ! 1249: (void) ioctl(iofd, TCSETAW, &oldtty); /* Restore original modes */ ! 1250: (void) ioctl(iofd, TCXONC,1); /* Restart output */ ! 1251: #endif ! 1252: #ifdef V7 ! 1253: ioctl(iofd, TIOCSETP, &oldtty); ! 1254: ioctl(iofd, TIOCSETC, &oldtch); ! 1255: ioctl(iofd, TIOCNXCL, 0); ! 1256: #endif ! 1257: #ifdef REGULUS ! 1258: ioctl(iofd, TCSETAW, &oldtty); /* Restore original modes */ ! 1259: #endif ! 1260: #ifdef REGULUS10 ! 1261: ioctl(iofd, TIOCSETP, &oldtty); ! 1262: #endif ! 1263: return OK; ! 1264: default: ! 1265: return ERROR; ! 1266: } ! 1267: } ! 1268: ! 1269: SHAR_EOF ! 1270: cat << \SHAR_EOF > sb.1 ! 1271: '\" Revision Level ! 1272: '\" Last Delta 12-07-85 ! 1273: .TH SB 1 OMEN ! 1274: .SH NAME ! 1275: sb \- send files in batch mode ! 1276: .SH SYNOPSIS ! 1277: .B sb ! 1278: [ ! 1279: .B \-1dfkquv ! 1280: ] ! 1281: .B file ... ! 1282: .br ! 1283: .B "sb -X" ! 1284: [ ! 1285: .B \-1kquv ! 1286: ] ! 1287: .B file ! 1288: .SH DESCRIPTION ! 1289: .B Sb ! 1290: sends one or more files with YMODEM batch protocol. ! 1291: Normally, only the file name part of the pathname is transmitted. ! 1292: On ! 1293: .SM Unix ! 1294: systems, additional information about the file is transmitted. ! 1295: If the receiving program uses this information, ! 1296: the transmitted file length controls the exact number of bytes written to ! 1297: the output dataset, ! 1298: and the modify time and file mode ! 1299: are set accordingly. ! 1300: ! 1301: With the ! 1302: .B -X ! 1303: flag, ! 1304: .B sb ! 1305: sends a single file using XMODEM protocol. ! 1306: The received file name must be supplied by the user. ! 1307: ! 1308: If sb is invoked with stdout and stderr to different datasets, ! 1309: Verbose is set to 2, causing frame by frame progress reports ! 1310: to stderr. ! 1311: This may be disabled with the ! 1312: .B q ! 1313: option. ! 1314: ! 1315: Iff sb is invoked with $SHELL set and iff that variable contains the ! 1316: string ! 1317: .I "rsh" ! 1318: or ! 1319: .I "rksh" ! 1320: (restricted shell), sb operates in restricted mode. ! 1321: Restricted mode restricts pathnames to the current directory and ! 1322: PUBDIR (conventionally, /usr/spool/uucppublic) and/or subdirectories ! 1323: thereof. ! 1324: ! 1325: Sb supports YMODEM ! 1326: .B g ! 1327: mode by switching to "cbreak" tty mode with XON/XOFF folow control ! 1328: and the interrupt character set to CAN. ! 1329: The YMODEM ! 1330: .B g ! 1331: mode ! 1332: (Pro-YAM ! 1333: .B g ! 1334: option) ! 1335: increases throughput over error free channels ! 1336: (direct connection, X.PC, etc.) ! 1337: by not acknowledging each transmitted sector. ! 1338: .PP ! 1339: The meanings of the available options are: ! 1340: .PP ! 1341: .PD 0 ! 1342: .TP ! 1343: .B 1 ! 1344: Use file descriptor 1 for ioctls and reads. ! 1345: By default, file descriptor 0 is used. ! 1346: .TP ! 1347: .B X ! 1348: (XMODEM protocol) ! 1349: Send a single file without the filename packet. ! 1350: .TP ! 1351: .B d ! 1352: Change all instances of "." to "/" in the transmitted pathname. ! 1353: Thus, C.omenB0000 (which is unacceptable to MSDOS or CP/M) ! 1354: is transmitted as C/omenB0000. ! 1355: If the resultant filename has more than 8 characters in the stem, ! 1356: a "." in inserted to allow a total of eleven. ! 1357: .TP ! 1358: .B f ! 1359: Send Full pathnname. ! 1360: Normally directory prefices are stripped from the transmitted ! 1361: filename. ! 1362: .TP ! 1363: .B k ! 1364: Send files using 1024 byte blocks ! 1365: rather than the default 128 byte blocks. ! 1366: The user should determine experimentally ! 1367: the conditions under which use of 1k blocks ! 1368: actually improves throughput without causing ! 1369: problems. ! 1370: .TP ! 1371: .B q ! 1372: Quiet suppresses verbosity. ! 1373: .TP ! 1374: .B u ! 1375: Unlink the file after successful transmission. ! 1376: .TP ! 1377: .B v ! 1378: .IR Verbose ! 1379: causes a list of file ! 1380: names to be appended to ! 1381: /tmp/sblog . ! 1382: More v's generate more output. ! 1383: .PD ! 1384: .SH EXAMPLES ! 1385: (Unix command) ! 1386: .RS ! 1387: sb -k *.c ! 1388: .br ! 1389: .RE ! 1390: (Pro-YAM command) ! 1391: .RS ! 1392: <F3> ! 1393: .br ! 1394: .RE ! 1395: (8-bit YAM Commands) ! 1396: .br ! 1397: .RS ! 1398: ^E ! 1399: .br ! 1400: >>>c: rt -y ! 1401: .br ! 1402: .RE ! 1403: .SH SEE ALSO ! 1404: rb(omen), ! 1405: YMODEM.DOC, ! 1406: Professional-YAM manual, ! 1407: IMP(CP/M), ! 1408: ncu(1), ! 1409: sq(omen), ! 1410: todos(omen), ! 1411: tocpm(omen), ! 1412: tomac(omen) ! 1413: ! 1414: Compile time options for various operating systems are described in the ! 1415: program source file. ! 1416: .SH BUGS ! 1417: On VMS, ! 1418: some of the #includes with file names enclosed with angle brackets <> ! 1419: may need to have the angle brackets removed, or vice versa. ! 1420: ! 1421: The VMS version does not transmit the file date. ! 1422: ! 1423: The VMS version does not recognize Pro-YAM\'s ! 1424: .B g ! 1425: option (YMODEM-g protocol). ! 1426: ! 1427: The VMS version calculates the file length by counting the bytes therin. ! 1428: ! 1429: When VMS is lightly loaded, the response time may be too quick for MODEM7 ! 1430: unless the MODEM7 ! 1431: .B "q" ! 1432: modifier is used. ! 1433: ! 1434: There may be unknown interactions between the VMS C standard i/o ! 1435: package and RMS. ! 1436: SHAR_EOF ! 1437: cat << \SHAR_EOF > sb.c ! 1438: #define VERSION "sb 2.24 01-04-86" ! 1439: #define PUBDIR "/usr/spool/uucppublic" ! 1440: ! 1441: /*% cc -K -O -DUSG sb.c -o sb ! 1442: ! 1443: * sb.c By Chuck Forsberg ! 1444: * ! 1445: * USG UNIX (3.0) ioctl conventions courtesy Jeff Martin ! 1446: * cc -O -DV7 sb.c -o sb Unix version 7, 2.8 - 4.3 BSD ! 1447: * cc -O -DUSG sb.c -o sb USG (3.0) Unix ! 1448: * ******* Some systems (Venix, Coherent, Regulus) do not ******* ! 1449: * ******* support tty raw mode read(2) identically to ******* ! 1450: * ******* Unix. ONEREAD must be defined to force one ******* ! 1451: * ******* character reads for these systems. ******* ! 1452: * ! 1453: * A small program for Unix which can send 1 or more ! 1454: * files in Batch mode to computers running YAM. (Use "rb" in YAM.) ! 1455: * Supports the CRC option or regular checksum. ! 1456: * Exit status is 0 for all transfers completed successfully, ! 1457: * 1 for 1 or more unreadable files or'd with 200 for incomplete file xfer. ! 1458: * ! 1459: * accepts -k option for 1kb record length. ! 1460: * ! 1461: * sb is derived from yam2.c ! 1462: * Uses buffered i/o to reduce the CPU time compared to UMODEM. ! 1463: */ ! 1464: ! 1465: #define LOGFILE "/tmp/sblog" ! 1466: ! 1467: #include <stdio.h> ! 1468: #include <signal.h> ! 1469: #include <setjmp.h> ! 1470: #include <ctype.h> ! 1471: ! 1472: #define PATHLEN 256 ! 1473: #define OK 0 ! 1474: #define FALSE 0 ! 1475: #define TRUE 1 ! 1476: #define ERROR (-1) ! 1477: ! 1478: #define HOWMANY 2 ! 1479: #include "rbsb.c" /* most of the system dependent stuff here */ ! 1480: ! 1481: FILE *in; ! 1482: ! 1483: /* Ward Christensen / CP/M parameters - Don't change these! */ ! 1484: #define ENQ 005 ! 1485: #define CAN ('X'&037) ! 1486: #define XOFF ('s'&037) ! 1487: #define XON ('q'&037) ! 1488: #define SOH 1 ! 1489: #define STX 2 ! 1490: #define EOT 4 ! 1491: #define ACK 6 ! 1492: #define NAK 025 ! 1493: #define CPMEOF 032 ! 1494: #define WANTCRC 0103 /* send C not NAK to get crc not checksum */ ! 1495: #define WANTG 0107 /* Send G not NAK to get nonstop batch xmsn */ ! 1496: #define TIMEOUT (-2) ! 1497: #define RETRYMAX 10 ! 1498: #define SECSIZ 128 /* cp/m's Magic Number record size */ ! 1499: #define KSIZE 1024 ! 1500: ! 1501: char Lastrx; ! 1502: char Crcflg; ! 1503: int Wcsmask=0377; ! 1504: int Verbose=0; ! 1505: int Modem=0; /* MODEM - don't send pathnames */ ! 1506: int Restricted=0; /* restricted; no /.. or ../ in filenames */ ! 1507: int Quiet=0; /* overrides logic that would otherwise set verbose */ ! 1508: int Fullname=0; /* transmit full pathname */ ! 1509: int Unlinkafter=0; /* Unlink file after it is sent */ ! 1510: int Dottoslash=0; /* Change foo.bar.baz to foo/bar/baz */ ! 1511: int firstsec; ! 1512: int errcnt=0; /* number of files unreadable */ ! 1513: int blklen=SECSIZ; /* length of transmitted records */ ! 1514: int Optiong; /* Let it rip no wait for sector ACK's */ ! 1515: int Noeofseen; ! 1516: int Totsecs; /* total number of sectors this file */ ! 1517: char txbuf[KSIZE]; ! 1518: int Filcnt=0; /* count of number of files opened */ ! 1519: ! 1520: jmp_buf tohere; /* For the interrupt on RX timeout */ ! 1521: ! 1522: unsigned updcrc(); ! 1523: char *substr(), *getenv(); ! 1524: ! 1525: /* called by signal interrupt or terminate to clean things up */ ! 1526: bibi(n) ! 1527: { ! 1528: canit(); fflush(stdout); mode(0); ! 1529: fprintf(stderr, "sb: caught signal %d; exiting\n", n); ! 1530: if (n == SIGQUIT) ! 1531: abort(); ! 1532: exit(128+n); ! 1533: } ! 1534: ! 1535: #ifdef REGULUS ! 1536: sendline(c) ! 1537: { ! 1538: static char d[2]; ! 1539: ! 1540: d[0] = c&Wcsmask; ! 1541: write(1, d, 1); ! 1542: } ! 1543: #else ! 1544: #define sendline(c) putchar(c & Wcsmask) ! 1545: #endif ! 1546: ! 1547: main(argc, argv) ! 1548: char *argv[]; ! 1549: { ! 1550: register char *cp; ! 1551: register npats; ! 1552: int agcnt; char **agcv; ! 1553: char **patts; ! 1554: int exitcode; ! 1555: #ifndef REGULUS ! 1556: static char xXbuf[BUFSIZ]; ! 1557: #endif ! 1558: ! 1559: if ((cp=getenv("SHELL")) && (substr(cp, "rsh") || substr(cp, "rsh"))) ! 1560: Restricted=TRUE; ! 1561: ! 1562: npats=0; ! 1563: if (argc<2) ! 1564: usage(); ! 1565: #ifndef REGULUS ! 1566: setbuf(stdout, xXbuf); ! 1567: #endif ! 1568: while (--argc) { ! 1569: cp = *++argv; ! 1570: if (*cp++ == '-' && *cp) { ! 1571: while ( *cp) { ! 1572: switch(*cp++) { ! 1573: case '1': ! 1574: iofd = 1; break; ! 1575: case '7': ! 1576: Wcsmask=0177; break; ! 1577: case 'd': ! 1578: ++Dottoslash; ! 1579: /* **** FALL THROUGH TO **** */ ! 1580: case 'f': ! 1581: Fullname=TRUE; break; ! 1582: case 'k': ! 1583: blklen=KSIZE; break; ! 1584: case 'q': ! 1585: Quiet=TRUE; Verbose=0; break; ! 1586: case 'u': ! 1587: ++Unlinkafter; break; ! 1588: case 'v': ! 1589: ++Verbose; break; ! 1590: case 'X': ! 1591: ++Modem; break; ! 1592: default: ! 1593: usage(); ! 1594: } ! 1595: } ! 1596: } ! 1597: else if ( !npats && argc>0) { ! 1598: if (argv[0][0]) { ! 1599: npats=argc; ! 1600: patts=argv; ! 1601: if ( !strcmp(*patts, "-")) ! 1602: iofd = 1; ! 1603: } ! 1604: } ! 1605: } ! 1606: if (npats < 1) ! 1607: usage(); ! 1608: if (Verbose) { ! 1609: if (freopen(LOGFILE, "a", stderr)==NULL) { ! 1610: printf("Can't open log file %s\n",LOGFILE); ! 1611: exit(0200); ! 1612: } ! 1613: setbuf(stderr, NULL); ! 1614: } ! 1615: if (fromcu() && !Quiet) { ! 1616: if (Verbose == 0) ! 1617: Verbose = 2; ! 1618: } ! 1619: if (Verbose != 1) { ! 1620: fprintf(stderr, "sb: %d file%s requested:\r\n", ! 1621: npats, npats>1?"s":""); ! 1622: for ( agcnt=npats, agcv=patts; --agcnt>=0; ) { ! 1623: fprintf(stderr, "%s ", *agcv++); ! 1624: } ! 1625: } ! 1626: ! 1627: mode(1); ! 1628: if (signal(SIGINT, bibi) == SIG_IGN) { ! 1629: signal(SIGINT, SIG_IGN); signal(SIGKILL, SIG_IGN); ! 1630: } ! 1631: else { ! 1632: signal(SIGINT, bibi); signal(SIGKILL, bibi); ! 1633: signal(SIGQUIT, bibi); ! 1634: } ! 1635: ! 1636: if (wcsend(npats, patts)==ERROR) { ! 1637: exitcode=0200; ! 1638: canit(); ! 1639: } ! 1640: fflush(stdout); ! 1641: mode(0); ! 1642: exit((errcnt != 0) | exitcode); ! 1643: } ! 1644: ! 1645: wcsend(argc, argp) ! 1646: char *argp[]; ! 1647: { ! 1648: register n; ! 1649: ! 1650: Crcflg=FALSE; ! 1651: firstsec=TRUE; ! 1652: for (n=0; n<argc; ++n) { ! 1653: Totsecs = 0; ! 1654: if (wcs(argp[n])==ERROR) ! 1655: goto fubar; ! 1656: } ! 1657: Totsecs = 0; ! 1658: if (Filcnt==0) { /* bitch if we couldn't open ANY files */ ! 1659: fprintf(stderr,"\r\nCan't open any requested files.\n"); ! 1660: return ERROR; ! 1661: } ! 1662: else if (wctxpn("")==ERROR) ! 1663: goto fubar; ! 1664: return OK; ! 1665: fubar: ! 1666: canit(); return ERROR; ! 1667: } ! 1668: ! 1669: wcs(oname) ! 1670: char *oname; ! 1671: { ! 1672: register c; ! 1673: register char *p; ! 1674: struct stat f; ! 1675: char name[PATHLEN]; ! 1676: ! 1677: strcpy(name, oname); ! 1678: ! 1679: if (Restricted) { ! 1680: /* restrict pathnames to current tree or uucppublic */ ! 1681: if ( substr(name, "../") ! 1682: || (name[0]== '/' && strncmp(name, PUBDIR, strlen(PUBDIR))) ) { ! 1683: canit(); ! 1684: fprintf(stderr,"\r\nsb:\tSecurity Violation\r\n"); ! 1685: return ERROR; ! 1686: } ! 1687: } ! 1688: ! 1689: if ( !strcmp(oname, "-")) { ! 1690: sprintf(name, "s%d.sb", getpid()); ! 1691: in = stdin; ! 1692: } ! 1693: else if ((in=fopen(oname, "r"))==NULL) { ! 1694: ++errcnt; ! 1695: return OK; /* pass over it, there may be others */ ! 1696: } ! 1697: ++Noeofseen; ! 1698: /* Check for directory or block special files */ ! 1699: #ifndef REGULUS /* This doesn't seem to work on Regulus */ ! 1700: fstat(fileno(in), &f); ! 1701: c = f.st_mode & S_IFMT; ! 1702: if (c == S_IFDIR || c == S_IFBLK) { ! 1703: fclose(in); ! 1704: return OK; ! 1705: } ! 1706: #endif ! 1707: ++Filcnt; ! 1708: if (wctxpn(name)== ERROR) ! 1709: return ERROR; ! 1710: if (wctx()==ERROR) ! 1711: return ERROR; ! 1712: if (Unlinkafter) ! 1713: unlink(oname); ! 1714: return 0; ! 1715: } ! 1716: ! 1717: /* ! 1718: * generate and transmit pathname block consisting of ! 1719: * pathname (null terminated), ! 1720: * file length, mode time and file mode in octal ! 1721: * as provided by the Unix fstat call. ! 1722: * N.B.: modifies the passed name, may extend it! ! 1723: */ ! 1724: wctxpn(name) ! 1725: char *name; ! 1726: { ! 1727: register firstch; ! 1728: register char *p, *q; ! 1729: char name2[PATHLEN]; ! 1730: struct stat f; ! 1731: ! 1732: if (Modem) ! 1733: return OK; ! 1734: logent("\r\nAwaiting pathname nak for %s\r\n", *name?name:"<END>"); ! 1735: if (getnak()) ! 1736: return ERROR; ! 1737: ! 1738: q = (char *) 0; ! 1739: if (Dottoslash) { /* change . to . */ ! 1740: for (p=name; *p; ++p) { ! 1741: if (*p == '/') ! 1742: q = p; ! 1743: else if (*p == '.') ! 1744: *(q=p) = '/'; ! 1745: } ! 1746: if (q && strlen(++q) > 8) { /* If name>8 chars */ ! 1747: q += 8; /* make it .ext */ ! 1748: strcpy(name2, q); /* save excess of name */ ! 1749: *q = '.'; ! 1750: strcpy(++q, name2); /* add it back */ ! 1751: } ! 1752: } ! 1753: ! 1754: for (p=name, q=txbuf ; *p; ) ! 1755: if ((*q++ = *p++) == '/' && !Fullname) ! 1756: q = txbuf; ! 1757: *q++ = 0; ! 1758: p=q; ! 1759: while (q < (txbuf + KSIZE)) ! 1760: *q++ = 0; ! 1761: if (in == stdin) ! 1762: strcpy(p, "1999999999"); ! 1763: #ifndef REGULUS /* This doesn't seem to work on Regulus */ ! 1764: else if (*name && fstat(fileno(in), &f)!= -1) ! 1765: sprintf(p, "%lu %lo %o", f.st_size, f.st_mtime, f.st_mode); ! 1766: #endif ! 1767: /* force 1k blocks if name won't fit in 128 byte block */ ! 1768: if (txbuf[125]) ! 1769: blklen=KSIZE; ! 1770: else { /* A little goodie for IMP/KMD */ ! 1771: txbuf[127] = f.st_size >>7; ! 1772: txbuf[126] = f.st_size >>15; ! 1773: } ! 1774: if (wcputsec(txbuf, 0, SECSIZ)==ERROR) ! 1775: return ERROR; ! 1776: return OK; ! 1777: } ! 1778: ! 1779: getnak() ! 1780: { ! 1781: register firstch; ! 1782: ! 1783: Lastrx = 0; ! 1784: for (;;) { ! 1785: switch (firstch = readock(800,2)) { ! 1786: case TIMEOUT: ! 1787: logent("Timeout on pathname\n"); ! 1788: return TRUE; ! 1789: case WANTG: ! 1790: mode(2); /* Set cbreak, XON/XOFF, etc. */ ! 1791: Optiong = TRUE; ! 1792: blklen=KSIZE; ! 1793: case WANTCRC: ! 1794: Crcflg = TRUE; ! 1795: case NAK: ! 1796: return FALSE; ! 1797: case CAN: ! 1798: if (Lastrx == CAN) ! 1799: return TRUE; ! 1800: default: ! 1801: break; ! 1802: } ! 1803: Lastrx = firstch; ! 1804: } ! 1805: } ! 1806: ! 1807: ! 1808: wctx() ! 1809: { ! 1810: register int sectnum, attempts, firstch; ! 1811: ! 1812: firstsec=TRUE; ! 1813: ! 1814: while ((firstch=readock(400, 2))!=NAK && firstch != WANTCRC ! 1815: && firstch != WANTG && firstch!=TIMEOUT && firstch!=CAN) ! 1816: ; ! 1817: if (firstch==CAN) { ! 1818: logent("Receiver CANcelled\n"); ! 1819: return ERROR; ! 1820: } ! 1821: if (firstch==WANTCRC) ! 1822: Crcflg=TRUE; ! 1823: if (firstch==WANTG) ! 1824: Crcflg=TRUE; ! 1825: sectnum=1; ! 1826: while (filbuf(txbuf, blklen)) { ! 1827: if (wcputsec(txbuf, sectnum, blklen)==ERROR) { ! 1828: return ERROR; ! 1829: } else ! 1830: sectnum++; ! 1831: } ! 1832: if (Verbose>1) ! 1833: fprintf(stderr, " Closing "); ! 1834: fclose(in); ! 1835: attempts=0; ! 1836: do { ! 1837: logent(" EOT "); ! 1838: purgeline(); ! 1839: sendline(EOT); ! 1840: fflush(stdout); ! 1841: ++attempts; ! 1842: } ! 1843: while ((firstch=(readock(100, 2)) != ACK) && attempts < RETRYMAX); ! 1844: if (attempts == RETRYMAX) { ! 1845: logent("No ACK on EOT\n"); ! 1846: return ERROR; ! 1847: } ! 1848: else ! 1849: return OK; ! 1850: } ! 1851: ! 1852: wcputsec(buf, sectnum, cseclen) ! 1853: char *buf; ! 1854: int sectnum; ! 1855: int cseclen; /* data length of this sector to send */ ! 1856: { ! 1857: register checksum, wcj; ! 1858: register char *cp; ! 1859: unsigned oldcrc; ! 1860: int firstch; ! 1861: int attempts; ! 1862: ! 1863: firstch=0; /* part of logic to detect CAN CAN */ ! 1864: ! 1865: if (Verbose>1) ! 1866: fprintf(stderr, "\rSector %3d %2dk ", Totsecs, Totsecs/8 ); ! 1867: for (attempts=0; attempts <= RETRYMAX; attempts++) { ! 1868: Lastrx= firstch; ! 1869: sendline(cseclen==KSIZE?STX:SOH); ! 1870: sendline(sectnum); ! 1871: sendline(-sectnum -1); ! 1872: oldcrc=checksum=0; ! 1873: for (wcj=cseclen,cp=buf; --wcj>=0; ) { ! 1874: sendline(*cp); ! 1875: oldcrc=updcrc(*cp, oldcrc); ! 1876: checksum += *cp++; ! 1877: } ! 1878: if (Crcflg) { ! 1879: oldcrc=updcrc(0,updcrc(0,oldcrc)); ! 1880: sendline((int)oldcrc>>8); ! 1881: sendline((int)oldcrc); ! 1882: } ! 1883: else ! 1884: sendline(checksum); ! 1885: ! 1886: if (Optiong) { ! 1887: firstsec = FALSE; return OK; ! 1888: } ! 1889: firstch = readock(400, (Noeofseen&§num) ? 2:1); ! 1890: gotnak: ! 1891: switch (firstch) { ! 1892: case CAN: ! 1893: if(Lastrx == CAN) { ! 1894: cancan: ! 1895: logent("Cancelled\n"); return ERROR; ! 1896: } ! 1897: break; ! 1898: case TIMEOUT: ! 1899: logent("Timeout on sector ACK\n"); continue; ! 1900: case WANTCRC: ! 1901: if (firstsec) ! 1902: Crcflg = TRUE; ! 1903: case NAK: ! 1904: logent("NAK on sector\n"); continue; ! 1905: case ACK: ! 1906: firstsec=FALSE; ! 1907: Totsecs += (cseclen>>7); ! 1908: return OK; ! 1909: case ERROR: ! 1910: logent("Got burst for sector ACK\n"); break; ! 1911: default: ! 1912: logent("Got %02x for sector ACK\n", firstch); break; ! 1913: } ! 1914: for (;;) { ! 1915: Lastrx = firstch; ! 1916: if ((firstch = readock(400, 2)) == TIMEOUT) ! 1917: break; ! 1918: if (firstch == NAK || firstch == WANTCRC) ! 1919: goto gotnak; ! 1920: if (firstch == CAN && Lastrx == CAN) ! 1921: goto cancan; ! 1922: } ! 1923: } ! 1924: logent("Retry Count Exceeded\n"); ! 1925: return ERROR; ! 1926: } ! 1927: ! 1928: ! 1929: /* fill buf with count chars padding with ^Z for CPM */ ! 1930: filbuf(buf, count) ! 1931: register char *buf; ! 1932: { ! 1933: register c, m; ! 1934: static lfseen=0; ! 1935: ! 1936: m=count; ! 1937: while ((c=getc(in))!=EOF) { ! 1938: *buf++ =c; ! 1939: if (--m == 0) ! 1940: break; ! 1941: } ! 1942: if (m==count) ! 1943: return (Noeofseen=0); ! 1944: else ! 1945: while (--m>=0) ! 1946: *buf++ = CPMEOF; ! 1947: return count; ! 1948: } ! 1949: ! 1950: ! 1951: alrm() ! 1952: { ! 1953: longjmp(tohere, -1); ! 1954: } ! 1955: ! 1956: ! 1957: /* ! 1958: * readock(timeout, count) reads character(s) from file descriptor 0 ! 1959: * (1 <= count <= 3) ! 1960: * it attempts to read count characters. If it gets more than one, ! 1961: * it is an error unless all are CAN ! 1962: * (otherwise, only normal response is ACK, CAN, or C) ! 1963: * Only looks for one if Optiong, which signifies cbreak, not raw input ! 1964: * ! 1965: * timeout is in tenths of seconds ! 1966: */ ! 1967: readock(timeout, count) ! 1968: { ! 1969: register int c; ! 1970: static char byt[5]; ! 1971: ! 1972: if (Optiong) ! 1973: count = 1; /* Special hack for cbreak */ ! 1974: ! 1975: fflush(stdout); ! 1976: if (setjmp(tohere)) { ! 1977: logent("TIMEOUT\n"); ! 1978: return TIMEOUT; ! 1979: } ! 1980: c = timeout/10; ! 1981: if (c<2) ! 1982: c=2; ! 1983: if (Verbose>3) { ! 1984: fprintf(stderr, "Timeout=%d Calling alarm(%d) ", timeout, c); ! 1985: byt[1] = 0; ! 1986: } ! 1987: signal(SIGALRM, alrm); alarm(c); ! 1988: #ifdef ONEREAD ! 1989: c=read(iofd, byt, 1); /* regulus raw read is unique */ ! 1990: #else ! 1991: c=read(iofd, byt, count); ! 1992: #endif ! 1993: alarm(0); ! 1994: if (Verbose>5) ! 1995: fprintf(stderr, "ret cnt=%d %x %x\n", c, byt[0], byt[1]); ! 1996: if (c<1) ! 1997: return TIMEOUT; ! 1998: if (c==1) ! 1999: return (byt[0]&0377); ! 2000: else ! 2001: while (c) ! 2002: if (byt[--c] != CAN) ! 2003: return ERROR; ! 2004: return CAN; ! 2005: } ! 2006: ! 2007: purgeline() ! 2008: { ! 2009: #ifdef USG ! 2010: ioctl(iofd, TCFLSH, 0); ! 2011: #else ! 2012: lseek(iofd, 0L, 2); ! 2013: #endif ! 2014: } ! 2015: ! 2016: /* update CRC */ ! 2017: unsigned updcrc(c, crc) ! 2018: register c; ! 2019: register unsigned crc; ! 2020: { ! 2021: register count; ! 2022: ! 2023: for (count=8; --count>=0;) { ! 2024: if (crc & 0x8000) { ! 2025: crc <<= 1; ! 2026: crc += (((c<<=1) & 0400) != 0); ! 2027: crc ^= 0x1021; ! 2028: } ! 2029: else { ! 2030: crc <<= 1; ! 2031: crc += (((c<<=1) & 0400) != 0); ! 2032: } ! 2033: } ! 2034: return crc; ! 2035: } ! 2036: ! 2037: /* send 10 CAN's to try to get the other end to shut up */ ! 2038: canit() ! 2039: { ! 2040: register n; ! 2041: for (n=10; --n>=0; ) ! 2042: sendline(CAN); ! 2043: } ! 2044: ! 2045: #ifdef REGULUS ! 2046: /* ! 2047: * copies count bytes from s to d ! 2048: * (No structure assignment in Regulus C compiler) ! 2049: */ ! 2050: movmem(s, d, count) ! 2051: register char *s, *d; ! 2052: register count; ! 2053: { ! 2054: while (--count >= 0) ! 2055: *d++ = *s++; ! 2056: } ! 2057: #endif ! 2058: ! 2059: /*VARARGS1*/ ! 2060: logent(a, b, c) ! 2061: char *a, *b, *c; ! 2062: { ! 2063: if(Verbose) ! 2064: fprintf(stderr, a, b, c); ! 2065: } ! 2066: ! 2067: /* ! 2068: * return 1 iff stdout and stderr are different devices ! 2069: * indicating this program operating with a modem on a ! 2070: * different line ! 2071: */ ! 2072: fromcu() ! 2073: { ! 2074: struct stat a, b; ! 2075: fstat(1, &a); fstat(2, &b); ! 2076: return (a.st_rdev != b.st_rdev); ! 2077: } ! 2078: ! 2079: /* ! 2080: * substr(string, token) searches for token in string s ! 2081: * returns pointer to token within string if found, NULL otherwise ! 2082: */ ! 2083: char * ! 2084: substr(s, t) ! 2085: register char *s,*t; ! 2086: { ! 2087: register char *ss,*tt; ! 2088: /* search for first char of token */ ! 2089: for (ss=s; *s; s++) ! 2090: if (*s == *t) ! 2091: /* compare token with substring */ ! 2092: for (ss=s,tt=t; ;) { ! 2093: if (*tt == 0) ! 2094: return s; ! 2095: if (*ss++ != *tt++) ! 2096: break; ! 2097: } ! 2098: return NULL; ! 2099: } ! 2100: ! 2101: usage() ! 2102: { ! 2103: fprintf(stderr,"%s by Chuck Forsberg\n", VERSION); ! 2104: fprintf(stderr,"Usage: sb [-17dfkquvX] [-] file ...\n"); ! 2105: fprintf(stderr," 1 Use stdout for all modem i/o\n"); ! 2106: fprintf(stderr," 7 Use 7 bits only\n"); ! 2107: fprintf(stderr," d Change '.' to '/' in pathnames\n"); ! 2108: fprintf(stderr," f Send full pathname\n"); ! 2109: fprintf(stderr," k Send 1024 byte packets\n"); ! 2110: fprintf(stderr," q Quiet (no progress reports)\n"); ! 2111: fprintf(stderr," u Unlink file after transmission\n"); ! 2112: fprintf(stderr," v Verbose - give more information\n"); ! 2113: fprintf(stderr," X XMODEM protocol - send no pathnames\n"); ! 2114: fprintf(stderr,"- as pathname sends standard input, filename=sPID.sb, requires -1 flag\n"); ! 2115: exit(1); ! 2116: } ! 2117: SHAR_EOF ! 2118: cat << \SHAR_EOF > undos.1 ! 2119: .TH UNDOS 1 OMEN ! 2120: .SH NAME ! 2121: undos,tounix,todos,tocpm,tomac,unmac \- Change file format for target operating system ! 2122: .SH SYNOPSIS ! 2123: .B undos ! 2124: [ ! 2125: .B -s ! 2126: ] ! 2127: file ... ! 2128: .br ! 2129: .B tounix ! 2130: [ ! 2131: .B -s ! 2132: ] ! 2133: file ... ! 2134: .br ! 2135: .B todos ! 2136: [ ! 2137: .B -s ! 2138: ] ! 2139: file ... ! 2140: .br ! 2141: .B tocpm ! 2142: [ ! 2143: .B -s ! 2144: ] ! 2145: file ... ! 2146: .br ! 2147: .B unmac ! 2148: [ ! 2149: .B -s ! 2150: ] ! 2151: file ... ! 2152: .br ! 2153: .B tomac ! 2154: [ ! 2155: .B -s ! 2156: ] ! 2157: file ... ! 2158: .SH DESCRIPTION ! 2159: .B Undos ! 2160: and ! 2161: .B tounix ! 2162: convert DOS or CP/M format source files to Unix format by deleting ! 2163: carriage returns preceding linefeeds and eliminating characters ! 2164: starting with CPMEOF (^Z). ! 2165: .PP ! 2166: .B Todos ! 2167: converts Unix format source files to DOS format by adding a carriage return ! 2168: (if not already present) before each linefeed, ! 2169: and eliminates characters ! 2170: starting with CPMEOF (^Z). ! 2171: .B Tocpm ! 2172: additionally appends CPMEOF (^Z) characters to the resulting file ! 2173: to make the file length a multiple of the 128 byte CP/M record length. ! 2174: ! 2175: Any combination of ! 2176: .B undos, todos, ! 2177: or ! 2178: .B tocpm ! 2179: (without flags) ! 2180: may be applied to a proper ASCII ! 2181: file without destroying information. ! 2182: Lone carriage returns used to force overprinting are not translated ! 2183: to CR/LF pairs. ! 2184: ! 2185: .B Unmac ! 2186: converts files with lines terminated only by carriage return ! 2187: to Unix format. ! 2188: .B Unmac ! 2189: should only be used to translate files whose lines are terminated ! 2190: by lone carriage returns. ! 2191: ! 2192: .B Tomac ! 2193: converts Unix format files to Macintosh format ! 2194: (lines terminated by carriage return only). ! 2195: ! 2196: The optional flag ! 2197: .B -s ! 2198: Strips the parity bit on all characters ! 2199: and discards all resulting characters with values less than 7. ! 2200: ! 2201: The access and modification times of the modified files are set ! 2202: to those of the original files. ! 2203: .SH DIAGNOSTICS ! 2204: Refuses to translate files in which "binary" characters (less than 7 ! 2205: or greater than 127) are seen before CPMEOF. ! 2206: Refuses to translate files ! 2207: with ultra long lines. ! 2208: Refuses to translate special files. ! 2209: .SH NOTES ! 2210: Should be executed with the current directory in the same filesystem ! 2211: as the target files for minimum disk i/o. ! 2212: .SH BUGS ! 2213: Does not detect short files without linefeeds. ! 2214: .B Unmac ! 2215: and ! 2216: .B tomac ! 2217: cannot handle files with CR-only overprinting. ! 2218: (Files whose lines end with CR only violate the ASCII code!). ! 2219: .SH SEE ALSO ! 2220: lar(1), yam(1), sq(1), usq(1), rb(omen), sb(omen) ! 2221: SHAR_EOF ! 2222: cat << \SHAR_EOF > undos.c ! 2223: /*% cc -O -K % -o undos ! 2224: * ! 2225: * Undos - change DOS format files to Unix, etc. ! 2226: */ ! 2227: char ID[] = ! 2228: "Undos Rev 12-07-85 (C)Copyright Omen Technology Inc All Rights Reserved\n"; ! 2229: /* ! 2230: * This program and documentation may be copied, used, or modified ! 2231: * by Professional-YAM and POWERCOMM licensees provided these notices are ! 2232: * not removed. Others may use this program for non-profit purposes only. ! 2233: */ ! 2234: ! 2235: #include <stdio.h> ! 2236: #include <sys/types.h> ! 2237: #include <sys/stat.h> ! 2238: ! 2239: #define LL 1024 ! 2240: #define SUB 032 ! 2241: ! 2242: char Lbuf[LL]; ! 2243: char *Progname; ! 2244: int Todos = 0; ! 2245: int Tocpm = 0; ! 2246: int Tomac = 0; ! 2247: int Unmac = 0; ! 2248: int Strip = 0; ! 2249: ! 2250: main(argc, argv) ! 2251: char **argv; ! 2252: { ! 2253: Progname = *argv; ! 2254: if (! strcmp(Progname, "tocpm")) ! 2255: Todos = Tocpm = 1; ! 2256: if (! strcmp(Progname, "todos")) ! 2257: Todos = 1; ! 2258: if (! strcmp(Progname, "unmac")) ! 2259: Unmac = 1; ! 2260: if (! strcmp(Progname, "tomac")) ! 2261: Tomac = 1; ! 2262: ! 2263: if (! strcmp(argv[1], "-s")) { ! 2264: ++Strip; --argc; ++argv; ! 2265: } ! 2266: ! 2267: ! 2268: if (argc<2 || *argv[1]== '-') ! 2269: usage(); ! 2270: while (--argc >= 1) ! 2271: chngfmt(*++argv); ! 2272: exit(0); ! 2273: } ! 2274: usage() ! 2275: { ! 2276: fprintf(stderr, ID); ! 2277: fprintf(stderr, "Usage: {undos|tounix|todos|tocpm|unmac} [-s] file ...\n"); ! 2278: fprintf(stderr, " -s Strip parity bit, ignore bytes < 007\n"); ! 2279: exit(1); ! 2280: } ! 2281: ! 2282: ! 2283: chngfmt(name) ! 2284: char *name; ! 2285: { ! 2286: register c; ! 2287: register char *p; ! 2288: register n; ! 2289: register long fpos; ! 2290: struct stat st; ! 2291: FILE *fin, *fout; ! 2292: int linno = 0; ! 2293: long ftell(); ! 2294: char *mktemp(); ! 2295: char outnam[64]; ! 2296: ! 2297: if (stat(name, &st)) { ! 2298: xperror(name); return; ! 2299: } ! 2300: if ((st.st_mode & S_IFMT) != S_IFREG) { ! 2301: fprintf(stderr, "%s: %s is not a regular file\n", Progname, name); ! 2302: return; ! 2303: } ! 2304: if ((fin = fopen(name, "r")) == NULL) { ! 2305: xperror(name); return; ! 2306: } ! 2307: strcpy(outnam, "undosXXXXXX"); ! 2308: mktemp(outnam); ! 2309: if ((fout = fopen(outnam, "w")) == NULL) { ! 2310: xperror(outnam); exit(1); ! 2311: } ! 2312: ! 2313: for (;;) { ! 2314: ++linno; ! 2315: for (p=Lbuf, n=LL; --n>0; ) { ! 2316: ignore: ! 2317: if ((c = getc(fin)) == EOF) ! 2318: break; ! 2319: if ( !c) ! 2320: goto ignore; ! 2321: if (c < '\7' || (c & 0200)) { ! 2322: if (Strip) { ! 2323: if ((c &= 0177) < 7) ! 2324: goto ignore; ! 2325: } else ! 2326: goto thisbin; ! 2327: } ! 2328: if (c == SUB) ! 2329: break; ! 2330: if (c == '\r' && Unmac) ! 2331: c = '\n'; ! 2332: *p++ = c; ! 2333: if (c == '\n') ! 2334: break; ! 2335: } ! 2336: *p = '\0'; ! 2337: ! 2338: if (n == 0) { ! 2339: thisbin: ! 2340: if (n) { ! 2341: fprintf(stderr, "%s: %s is a binary file", Progname, name); ! 2342: fprintf(stderr, " line=%d char =%2X\n", linno, c); ! 2343: } else ! 2344: fprintf(stderr, "%s: %s has no linefeeds: try unmac?\n", Progname, name); ! 2345: fclose(fout); ! 2346: unlink(outnam); ! 2347: return; ! 2348: } ! 2349: ! 2350: if (Todos) { ! 2351: if (*--p == '\n' && p[-1] != '\r') { ! 2352: *p++ = '\r'; *p++ = '\n'; *p = 0; ! 2353: } ! 2354: } else if (Tomac) { ! 2355: if (*--p == '\n') { ! 2356: if (p[-1] == '\r') ! 2357: --p; ! 2358: *p++ = '\r'; *p = 0; ! 2359: } ! 2360: } else { ! 2361: if (*--p == '\n' && *--p == '\r') { ! 2362: *p++ = '\n'; *p = 0; ! 2363: } ! 2364: } ! 2365: if (fputs(Lbuf, fout) == EOF) { ! 2366: xperror(outnam); exit(1); ! 2367: } ! 2368: switch (c) { ! 2369: case EOF: ! 2370: if (ferror(fin)) { ! 2371: xperror(name); exit(0200); ! 2372: } ! 2373: case SUB: ! 2374: if (Tocpm) { ! 2375: fpos = ftell(fout); ! 2376: do { ! 2377: putc(SUB, fout); ! 2378: } while (++fpos & 127); ! 2379: } ! 2380: fclose(fout); fclose(fin); ! 2381: if (st.st_nlink > 1) ! 2382: sprintf(Lbuf, "cp %s %s", outnam, name); ! 2383: else ! 2384: sprintf(Lbuf, "mv %s %s", outnam, name); ! 2385: system(Lbuf); ! 2386: utime(name, (struct utimbuf *) &st.st_atime); ! 2387: if (st.st_nlink > 1) ! 2388: unlink(outnam); ! 2389: return; ! 2390: } ! 2391: } ! 2392: } ! 2393: ! 2394: xperror(s) ! 2395: char *s; ! 2396: { ! 2397: register char *p; ! 2398: extern int sys_nerr; ! 2399: extern char *sys_errlist[]; ! 2400: extern errno; ! 2401: ! 2402: if (errno >= sys_nerr) ! 2403: p = "Gloryovsky: a New Error!"; ! 2404: else ! 2405: p = sys_errlist[errno]; ! 2406: fprintf(stderr, "%s: %s: %s\n", Progname, s, p); ! 2407: } ! 2408: SHAR_EOF ! 2409: # End of shell archive ! 2410: exit 0
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.