home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume14 / pcomm / part06 / x_batch.c next >
Encoding:
C/C++ Source or Header  |  1988-05-18  |  7.6 KB  |  381 lines

  1. /*
  2.  * Routines to support the batch protocols.
  3.  */
  4.  
  5. #include <stdio.h>
  6. #include <ctype.h>
  7. #include <curses.h>
  8. #include "misc.h"
  9. #include "xmodem.h"
  10.  
  11. /*
  12.  * Send the file name for the modem7 batch.  Only uses 11 characters
  13.  * of the filename.
  14.  */
  15.  
  16. int
  17. send_modem7(win, name)
  18. WINDOW *win;
  19. char *name;
  20. {
  21.     char *new_name, *fix_name();
  22.     unsigned char sum, calc_sum();
  23.  
  24.                     /* convert to 11 character name */
  25.     new_name = fix_name(name);
  26.     sum = calc_sum((unsigned char *) new_name, 12);
  27.  
  28.     putc_line(ACK);
  29.                     /* for each character in the name */
  30.     while (*new_name != CTRLZ) {
  31.         putc_line((unsigned char) *new_name);
  32.  
  33.         switch (getc_line(3)) {
  34.             case ACK:    /* got it! */
  35.                 break;
  36.             case CAN:    /* cancel transmission */
  37.                 if (getc_line(2) == CAN) {
  38.                     beep();
  39.                     clear_line(win, 12, 24, 1);
  40.                     wattrstr(win, A_BOLD, "REMOTE ABORTED");
  41.                     wrefresh(win);
  42.                     return(CANCEL);
  43.                 }
  44.                 /* fall thru... */
  45.             default:
  46.                 clear_line(win, 12, 24, 1);
  47.                 waddstr(win, "NAME FAILED");
  48.                 wrefresh(win);
  49.                 return(ERROR);
  50.         }
  51.         new_name++;
  52.     }
  53.     putc_line(CTRLZ);
  54.                     /* verify the checksum */
  55.     if (getc_line(10) != sum) {
  56.         putc_line('u');
  57.         clear_line(win, 12, 24, 1);
  58.         waddstr(win, "CHECKSUM FAILED");
  59.         wrefresh(win);
  60.         return(ERROR);
  61.     }
  62.     putc_line(ACK);
  63.     return(0);
  64. }
  65.  
  66. /*
  67.  * Receive a modem 7 file name.  A return code of 1 means the end of the
  68.  * batch transfers.
  69.  */
  70.  
  71. int
  72. rcv_modem7(win, default_err)
  73. WINDOW *win;
  74. int default_err;
  75. {
  76.     int i, c, err_method, err_count, got_it;
  77.     unsigned char sum, calc_sum();
  78.     char temp_name[13];
  79.     extern char *null_ptr, file_name[15];
  80.     void change_name(), unfix_name();
  81.                     /* send the first char */
  82.     err_method = default_err;
  83.     err_count = 0;
  84.     got_it = 0;
  85.     while (err_count < MAX_ERRORS) {
  86.                     /* switch to checksum? */
  87.         if (default_err == 1 && err_count > MAX_ERRORS/2)
  88.             err_method = 0;
  89.  
  90.         if (err_method)
  91.             putc_line('C');
  92.         else
  93.             putc_line(NAK);
  94.                     /* what'd we get? */
  95.         if (getc_line(10) == ACK) {
  96.             got_it++;
  97.             break;
  98.         }
  99.         err_count++;
  100.     }
  101.     if (!got_it)
  102.         return(ERROR);
  103.                     /* get the name */
  104.     for (i=0; i<12; i++) {
  105.         c = getc_line(3);
  106.  
  107.         switch(c) {
  108.             case EOT:    /* end of batch? */
  109.                 return(-1);
  110.             case CAN:    /* cancel transmission */
  111.                 if (getc_line(2) == CAN) {
  112.                     beep();
  113.                     clear_line(win, 12, 24, 1);
  114.                     wattrstr(win, A_BOLD, "REMOTE ABORTED");
  115.                     wrefresh(win);
  116.                     return(CANCEL);
  117.                 }
  118.                 /* fall thru... */
  119.             case 'u':    /* bad name character */
  120.                 beep();
  121.                 clear_line(win, 12, 24, 1);
  122.                 wattrstr(win, A_BOLD, "BAD NAME");
  123.                 wrefresh(win);
  124.                 return(ERROR);
  125.             default:    /* the name... */
  126.                 temp_name[i] = c;
  127.                 if (c != CTRLZ)
  128.                     putc_line(ACK);
  129.                 break;
  130.         }
  131.     }
  132.     temp_name[12] = NULL;
  133.                     /* send our checksum */
  134.     sum = calc_sum((unsigned char *) temp_name, 12);
  135.     putc_line(sum);
  136.                     /* do they agree ? */
  137.     if (getc_line(10) != ACK) {
  138.         beep();
  139.         clear_line(win, 12, 24, 1);
  140.         wattrstr(win, A_BOLD, "BAD NAME");
  141.         wrefresh(win);
  142.         return(ERROR);
  143.     }
  144.                     /* load the file_name array */
  145.     unfix_name(temp_name);
  146.                     /* any name collisions? */
  147.     change_name(win, file_name);
  148.     return(0);
  149. }
  150.  
  151. /*
  152.  * Send the block 0 information for a ymodem batch transfer.  Uses only
  153.  * the name component of the path and the file size.
  154.  */
  155.  
  156. int
  157. send_ymodem(win, file, size)
  158. WINDOW *win;
  159. char *file;
  160. int size;
  161. {
  162.     int i, crc;
  163.     char *strcpy();
  164.     unsigned char buf[133];
  165.                     /* start with a clean block */
  166.     for (i=0; i<132; i++)
  167.         buf[i] = NULL;
  168.                     /* the header */
  169.     buf[0] = SOH;
  170.     buf[1] = 0;
  171.     buf[2] = 255;
  172.  
  173.     /*
  174.      * The block zero consists of the file name (no path component),
  175.      * a NULL, and the file length (as a string).  The end of batch
  176.      * marker is an empty block.
  177.      */
  178.     if (file != NULL) {
  179.         strcpy((char *) &buf[3], file);
  180.         sprintf((char *) &buf[strlen(file)+4], "%d", size);
  181.     }
  182.                     /* the crc */
  183.     crc = calc_crc(&buf[3], 128);
  184.     buf[131] = crc >> 8;
  185.     buf[132] = crc;
  186.                     /* the block count */
  187.     mvwaddstr(win, 7, 24, "0   ");
  188.  
  189.     return(send_block(win, buf, 133));
  190. }
  191.  
  192. /*
  193.  * Receive the block 0 information for a ymodem batch transfer.  We
  194.  * only use the file name and the size (if present).  Currently doesn't
  195.  * support full path names.
  196.  */
  197.  
  198. int
  199. rcv_ymodem(win)
  200. WINDOW *win;
  201. {
  202.     int code, length_is_at;
  203.     extern unsigned char buf[1029];
  204.     extern int file_length;
  205.     extern char file_name[15];
  206.  
  207.     file_length = 0;
  208.     file_name[0] = NULL;
  209.                     /* read the zero block */
  210.     if (code = rcv_block(win, 1, 1024, 0))
  211.         return(code);
  212.                     /* at end of batch */
  213.     if (buf[3] == NULL)
  214.         return(0);
  215.                     /* get the file name */
  216.     change_name(win, (char *) &buf[3]);
  217.                     /* any trouble ?? */
  218.     if (file_name[0] == NULL) {
  219.         putc_line(CAN);
  220.         return(0);
  221.     }
  222.     /*
  223.      * The file length is placed after the NULL of the file name
  224.      * and is terminated by another NULL.  If the length is missing,
  225.      * atoi() will see a NULL and return 0.
  226.      */
  227.     length_is_at = strlen((char *) &buf[3]) + 4;
  228.     file_length = atoi((char *) &buf[length_is_at]);
  229.     return(0);
  230. }
  231.  
  232. /*
  233.  * Handle file name collisions.  Prepend an 'X' to the name until you find
  234.  * a name that doesn't already exist.  Creates a NULL name on error.
  235.  * Loads the global character array 'file_name'.
  236.  */
  237.  
  238. void
  239. change_name(win, str)
  240. WINDOW *win;
  241. char *str;
  242. {
  243.     int i, modified;
  244.     char temp[15], ans[15], *s, *strrchr(), *strcpy(), *strncat();
  245.     unsigned int sleep();
  246.     extern char file_name[15];
  247.                     /* dissect the name component */
  248.     if ((s = strrchr(str, '/')))
  249.         strcpy(temp, s++);
  250.     else
  251.         strcpy(temp, str);
  252.  
  253.     strcpy(ans, temp);
  254.     file_name[0] = NULL;
  255.                     /* write permission on directory ? */
  256.     if (access(".", 2)) {
  257.         beep();
  258.         clear_line(win, 12, 24, 1);
  259.         wattrstr(win, A_BOLD, "NO WRITE ON DIRECTORY");
  260.         wrefresh(win);
  261.         return;
  262.     }
  263.                     /* prepend up to 13 'X's */
  264.     modified = 0;
  265.     for (i=1; i<14; i++) {
  266.         if (access(ans, 0)) {
  267.             if (modified) {
  268.                 beep();
  269.                 clear_line(win, 12, 24, 1);
  270.                 waddstr(win, "NAME COLLISION");
  271.                 wrefresh(win);
  272.                 sleep(1);
  273.             }
  274.             strcpy(file_name, ans);
  275.             return;
  276.         }
  277.  
  278.         modified++;
  279.         strcpy(temp, "X");
  280.         strncat(temp, ans, 13);
  281.         temp[14] = NULL;
  282.         strcpy(ans, temp);
  283.     }
  284.     beep();
  285.     clear_line(win, 12, 24, 1);
  286.     waddstr(win, "BAD NAME");
  287.     wrefresh(win);
  288.     return;
  289. }
  290.  
  291. /*
  292.  * Convert a perfectly good Unix file name to fit the CP/M file name
  293.  * rules.  Used for the modem7 batch file transfer.  Returns a pointer
  294.  * to the new name.
  295.  */
  296.  
  297. char *
  298. fix_name(path)
  299. char *path;
  300. {
  301.     int dot;
  302.     char *s, *name, temp[15], *ext, *strcpy(), *strrchr();
  303.     static char ans[13];
  304.                      /* ignore the path component */
  305.     if (s = strrchr(path, '/'))
  306.         strcpy(temp, s++);
  307.     else
  308.         strcpy(temp, path);
  309.     name = temp;
  310.  
  311.     ext = NULL;
  312.     dot = 0;
  313.     for (s = name; *s; ++s) {
  314.         if (*s == '.' && !dot) {
  315.             dot = 1;
  316.             *s = NULL;
  317.             ext = s + 1;
  318.         }
  319.         if (islower(*s))
  320.             *s = toupper(*s);
  321.     }
  322.                     /* if null name component */
  323.     if (*name == NULL)
  324.         name = "X";
  325.                     /* if name too long */
  326.     if (strlen(name) > 8) 
  327.         *(name+8) = NULL;
  328.                     /* if extension too long */
  329.     if (strlen(ext) > 3) 
  330.         *(ext+3) = NULL;
  331.  
  332.     sprintf(ans, "%-8.8s%-3.3s%c", temp, ext, CTRLZ);
  333.     return(ans);
  334. }
  335.  
  336. /*
  337.  * Convert a CP/M style filename into a legal Unix file name.  Loads the
  338.  * global character array 'file_name'.
  339.  */
  340.  
  341. void
  342. unfix_name(cpm_name)
  343. char *cpm_name;
  344. {
  345.     int i, n, dot;
  346.     char temp[15];
  347.     extern char file_name[15];
  348.  
  349.     file_name[0] = NULL;
  350.     if (!*cpm_name)
  351.         return;
  352.  
  353.     strcpy(temp, cpm_name);
  354.                     /* 8 character of the name */
  355.     n = 0;
  356.     for (i=0; i<8; i++) {
  357.         if (temp[i] != ' ') {
  358.             if (isupper(temp[i]))
  359.                 file_name[n++] = tolower(temp[i]);
  360.             else
  361.                 file_name[n++] = temp[i];
  362.         }
  363.     }
  364.                     /* 3 character extension */
  365.     dot = 0;
  366.     for (i=8; i<11; i++) {
  367.         if (temp[i] != ' ') {
  368.             if (!dot) {
  369.                 dot++;
  370.                 file_name[n++] = '.';
  371.             }
  372.             if (isupper(temp[i]))
  373.                 file_name[n++] = tolower(temp[i]);
  374.             else
  375.                 file_name[n++] = temp[i];
  376.         }
  377.     }
  378.     file_name[n] = NULL;
  379.     return;
  380. }
  381.