home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 3 / 3598 / xcmain.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-07-11  |  15.3 KB  |  780 lines

  1. /*    xcmain.c -- main module for XC
  2.     This file uses 4-character tabstops
  3. */
  4.  
  5. #include <sys/types.h>
  6. #include <stdio.h>
  7. #include <signal.h>
  8. #include <ctype.h>
  9. #include <termio.h>
  10. #ifdef T6000
  11. #include <sys/ioctl.h>
  12. #endif
  13. #include <setjmp.h>
  14. #include "xc.h"
  15.  
  16. static char version[]="@(#)XC 3.0b JPRadley 08 July 91";
  17.  
  18. #define Resume_Not_Allowed    1
  19.  
  20. jmp_buf erret;            /* non-local error return */
  21.  
  22. short
  23.     autoflag = FALSE,    /* Flag for automatic capturing */
  24.     badline = FALSE,    /* Bad telephone line? */
  25.     cismode = TRUE,        /* Respond to CIS "ENQ" */
  26.     cr_add = TRUE,        /* Add carriage returns for B+ uploads */
  27.     hdplxflag = FALSE,    /* Flag for half-duplex mode */
  28.     nlmode = TRUE,        /* Map newlines to carriage returns */
  29.     reterm = FALSE,        /* No jumping into terminal mode */
  30.     stat_flag = FALSE,    /* Flag for status display */
  31.     eof_flag = FALSE;    /* Flag to quit a script */
  32.  
  33. int s_cis(), s_set(), s_exit(), s_shell();
  34.  
  35. char Msg[SM_BUFF];
  36.  
  37. FILE *tfp;
  38.  
  39. struct termio newmode, oldmode, sigmode;
  40.  
  41. static char    *statfmt = "\t\t%-8s %25s %s\n",
  42.             oldshell[SM_BUFF];
  43.  
  44. static s_script(), s_xmodem(), s_term(), s_help(), s_dial(), puttake(),
  45.         SET_7bit(), SET_cr(), SET_cis(), SET_nl(), SET_purge(), SET_xoff(),
  46.         SET_halfdplx(), SET_bps(), SET_autocapt(), SET_cfile(), SET_pfile();
  47.  
  48. extern short scriptflag;
  49. extern void B_Transfer(), dbglog(), mattach(), terminal(), xreceive(), xsend(),
  50.             get_ttype();
  51.  
  52. static char    *babble[] = {
  53.     "Usage: xc [-l device] [-t] [-g file]",
  54.     "",
  55.     "-l device  Use 'device' as the modem port (eg, -l /dev/tty00)",
  56.     "-t         Enter terminal mode immediately",
  57.     "-s file    Execute script file 'file' immediately",
  58.     "",
  59.     NULLS };
  60.  
  61. static void usage()
  62. {
  63.     char **ptr;
  64.  
  65.     for (ptr = babble; *ptr != NULLS; ptr++)
  66.         fprintf(tfp, "%s\n", *ptr);
  67. }
  68.  
  69. struct kw {                    /* Used by command parsing routines */
  70.     char *keyword;
  71.     int (*rtn)();
  72. };
  73.  
  74. static struct kw cmds[] = { /* Command table */
  75.     {"c",        s_cis},
  76.     {"s",        s_script},
  77.     {"h",        hangup},
  78.     {"rb",        s_xmodem},
  79.     {"rt",        s_xmodem},
  80.     {"sb",        s_xmodem},
  81.     {"st",        s_xmodem},
  82.     {"set",        s_set},
  83.     {"t",        s_term},
  84.     {"d",        s_dial},
  85.     {"q",        s_exit},
  86.     {"x",        s_exit},
  87.     {"exit",    s_exit},
  88.     {"!",        s_shell},
  89.     {"!!",        s_shell},
  90.     {"$",        s_shell},
  91.     {"%p",        puttake},
  92.     {"%t",        puttake},
  93.     {"help",    s_help},
  94.     {"?",        s_help},
  95.     {NULLS,        0}
  96. };
  97.  
  98. /* Catch a signal and jump to main. Reset signal and do a longjmp */
  99. static void catch()
  100. {
  101.     show(2,"XC: Interrupt");
  102.  
  103.     signal(SIGINT,catch);
  104.     signal(SIGQUIT,catch);
  105.     longjmp(erret,1);
  106. }
  107.  
  108. static struct kw setlist[] = {
  109.     {"7bit",    SET_7bit},
  110.     {"auto",    SET_autocapt},
  111.     {"bps",        SET_bps},
  112.     {"cfile",    SET_cfile},
  113.     {"cis",        SET_cis},
  114.     {"cr",        SET_cr},
  115.     {"halfdplx",SET_halfdplx},
  116.     {"nl",        SET_nl},
  117.     {"pfile",    SET_pfile},
  118.     {"purge",    SET_purge},
  119.     {"xoff",    SET_xoff},
  120.     {NULLS,        0}
  121. };
  122.  
  123. /* Print the status of the program */
  124. static void status()
  125. {
  126.     struct kw *ptr;
  127.     char p[30];
  128.     int (*fct)() = 0;
  129.  
  130.     stat_flag = TRUE;
  131.  
  132.     cls();
  133.     cur_off();
  134.     sprintf(p,"Modem Port: %s",mport(NULLS));
  135.     drawline(0, 0, CO);
  136.     ttgoto(1, 9);
  137.     sprintf(Msg,"%-29s%29s",&version[4], p);
  138.     S;
  139.     drawline(2, 0, CO);
  140.     ttgoto(3, 0);
  141.     fprintf(tfp, statfmt, "Keyword", "Description", "Status");
  142.     fprintf(tfp, statfmt, "--------", "-------------------------", "-----------");
  143.  
  144.     for (ptr = setlist; ptr->keyword != NULLS; ptr++)
  145.         if (ptr->rtn != fct) {
  146.             fct = ptr->rtn;
  147.             (*fct)();
  148.         }
  149.  
  150.     ttgoto(18, 25);
  151.     show(1,"Type \"help\" or ? for help");
  152.     stat_flag = FALSE;
  153.     cur_on();
  154. }
  155.  
  156. main(argc, argv)
  157. int argc;
  158. char *argv[];
  159. {
  160.     char *script = NULLS;
  161.     extern char *optarg;
  162.     int c;
  163.     extern int optind;
  164.  
  165.     struct kw *ptr;
  166.     tfp = stderr;
  167.     if (isatty(0))
  168.         get_ttype();
  169.  
  170.     ioctl(0, TCGETA, &oldmode);    /* get current tty mode    */
  171.  
  172.     /* trap for SIGHUP and SIGTERM, make sure LCKfile gets killed */
  173.     signal(SIGHUP,s_exit);
  174.     signal(SIGTERM,s_exit);
  175.  
  176.     newmode = oldmode;
  177.  
  178.     newmode.c_oflag &= (OPOST | ONLCR);
  179.     newmode.c_iflag &= ~(IXON | IXOFF);
  180.     newmode.c_lflag &= ~(ICANON | ISIG | ECHO);
  181.     newmode.c_cc[VMIN] = 1;
  182.     newmode.c_cc[VTIME] = 1;
  183.  
  184.     sigmode = newmode;
  185.     sigmode.c_lflag |= ISIG;
  186.  
  187.     oldshell[0] = '\0';    /* set last command to blank */
  188.     if (setjmp(erret))    /* set error handler to exit */
  189.         exit(0);        /* while parsing command line */
  190.     signal(SIGINT,catch);    /* catch break & quit signals/keys */
  191.     signal(SIGQUIT,catch);
  192.  
  193.     while ((c = getopt(argc, argv, "s:l:t")) != -1)
  194.         switch (c) {
  195.         case 'l':    /* set modem port name */
  196.             mport(optarg);
  197.             break;
  198.         case 's':    /* Execute SCRIPT file */
  199.             script = optarg;
  200.             break;
  201.         case 't':    /* jump into terminal mode */
  202.             reterm = TRUE;
  203.             break;
  204.         default:    /* Bad command .. print help */
  205.             usage();
  206.             exit(1);
  207.         }
  208.  
  209.     setuid((int)geteuid());
  210.     setgid((int)getegid());
  211.  
  212.     mopen();    /* opens and configures modem port, or exits */
  213.  
  214.     setuid((int)getuid());
  215.     setgid((int)getgid());
  216.  
  217.     intdel(FALSE);
  218.     linkflag=2;
  219.     do_script(STARTUP);
  220.  
  221. #ifdef DEBUG
  222.     dbglog();
  223. #endif
  224.  
  225.     if (!script)
  226.         status();
  227.  
  228.     for ( ; ; ) {
  229.         setjmp(erret);
  230.         signal(SIGQUIT,s_exit);
  231.         intdel(FALSE);
  232.  
  233.         if (script)
  234.             do_script(script),
  235.             script = NULLS,
  236.             reterm = TRUE;
  237.  
  238.         if (reterm) {
  239.             s_term();
  240.             continue;
  241.         }
  242.  
  243.         intdel(TRUE);
  244.         fputc('\n',tfp);
  245.         show(-1,"<XC>");
  246.         fputc(' ',tfp);
  247.  
  248.         lptr = line;
  249.         getline();
  250.         intdel(FALSE);
  251.         fputc('\n',tfp);
  252.  
  253.         getword();
  254.         lc_word(word);
  255.         if (word[0] == '\0')        /* If blank line... reprompt */
  256.             continue;
  257.  
  258.         for (ptr = cmds; ptr->keyword != NULLS; ptr++)
  259.             if (strcmp(word, ptr->keyword) == 0)
  260.                 break;
  261.  
  262.         if (ptr->keyword)
  263.             (*ptr->rtn)();
  264.         else
  265.             sprintf(Msg,"Unrecognized command: %s",word),
  266.             S;
  267.     }
  268. }
  269.  
  270. static s_script()
  271. {
  272.     getword();
  273.  
  274.     if (word[0] == '\0') {
  275.         show(1,"Script file not specified");
  276.         return;
  277.     }
  278.  
  279.     sprintf(ddsname,"%s",word);
  280.     do_script(ddsname);
  281.     reterm = TRUE;
  282. }
  283.  
  284. static s_xmodem()
  285. {
  286.     char d = word[0];
  287.     char c = word[1];
  288.  
  289.     getword();
  290.     if (word[0] == '\0')
  291.         show(1,"Transfer file not specified");
  292.     else if (d == 's')
  293.         xsend(c);
  294.     else
  295.         xreceive(c);
  296.  
  297.     reterm = TRUE;
  298. }
  299.  
  300. static s_term()
  301. {
  302.     for ( ; ; ) {
  303.         terminal(FALSE);
  304.         if (cismode != 2)
  305.             return;
  306.         cismode = 1;
  307.         s_cis();
  308.     }
  309. }
  310.  
  311. static s_dial()
  312. {
  313.     for ( ; ; ) {
  314.         terminal(TRUE);
  315.         if (cismode != 2)
  316.             return;
  317.         cismode = 1;
  318.         s_cis();
  319.     }
  320. }
  321.  
  322. s_cis()
  323. {
  324.     B_Transfer();
  325.     reterm = TRUE;
  326. }
  327.  
  328. s_shell()
  329. {
  330.     void (*oldvec)();
  331.     int stat_loc = 0;
  332.     char c = word[0];
  333.     static char *shell = NULLS;
  334.  
  335. #ifdef NOSHELL
  336.     return(0);
  337. #endif
  338.     if (word[0] == word[1])
  339.         strcpy(wptr = word, oldshell);
  340.     else {
  341.         getword();
  342.         if (*wptr)
  343.             strcpy(oldshell, wptr);
  344.     }
  345.  
  346.     if (!shell) {
  347.         shell = getenv("SHELL");
  348.         if (!shell)
  349.             shell = "/bin/sh";
  350.     }
  351.  
  352.     fputc('\n',tfp);
  353.     ioctl(0, TCSETAW, &oldmode);
  354.  
  355.     if ((forkem()) == 0) {
  356.         if (c == '$')    /* Attach modem to stdin, stdout */
  357.             mattach();
  358.         signal(SIGCLD,SIG_DFL);
  359.         signal(SIGINT,SIG_DFL);
  360.         signal(SIGQUIT,SIG_DFL);
  361.         if (word[0] == '\0')
  362.             execl(shell, shell, "-i", NULLS);
  363.         else
  364.             execl(shell, shell, "-c", wptr, NULLS);
  365.         show(1,"Exec failed!");
  366.         exit(2);
  367.     }
  368.  
  369.     oldvec = signal(SIGINT,SIG_IGN);
  370.     wait(&stat_loc);
  371.     signal(SIGINT,oldvec);
  372.  
  373.     intdel(FALSE);
  374.     strcpy(oldshell, wptr);
  375.     return(!!stat_loc);
  376. }
  377.  
  378. static char    *cmdlist[] = {
  379.     "\tXC Command Summary\n\n",
  380.     "\tc\t\tInitiate CIS B+ File Transfer (Upload and Download)\n",
  381.     "\trb file\t\tXMODEM receive (binary mode)\n",
  382.     "\trt file\t\tXMODEM receive (Ascii mode)\n",
  383.     "\tsb file ...\tXMODEM send (binary mode)\n",
  384.     "\tst file ...\tXMODEM send (Ascii mode)\n",
  385.     "\tset ...\t\tXC Parameter set\n\n",
  386.     "\ts file\t\tExecute XC script file\n",
  387.     "\tt\t\tEnter terminal mode\n",
  388.     "\td\t\tDialing directory\n",
  389.     "\th\t\tHang up the modem\n",
  390.     "\tq, x or exit\tExit XC\n\n",
  391. #ifndef NOSHELL
  392.     "\t!\t\tExecute a local interactive shell\n",
  393.     "\t! cmd\t\tExecute shell command string on the local system\n",
  394.     "\t!!\t\tRe-execute the last shell command string\n",
  395.     "\t$ cmd\t\tShell command with stdin and stdout redirected to modem\n",
  396. #endif    
  397.     "\t%p loc [rem]\tPut local file to a UNIX system\n",
  398.     "\t%t rem [loc]\tTake remote file from a UNIX system\n",
  399.     "\t? or help\tPrint this help screen\n",
  400.     "",
  401.     "\tSET Keywords:\n\n",
  402.     "\tset\t\t\tDisplay current XC status\n",
  403.     "\tset 7bit on|off\t\tSet/Reset 7-bit data mask (ignore high bits)\n",
  404.     "\tset auto on|off\t\tSet/Reset automatic capturing\n",
  405.     "\tset bps <value>\t\tSet Bits/Second to <value>\n",
  406.     "\tset cfile name\t\tChange name of capture file\n",
  407.     "\tset cis on|off\t\tSet/Reset CIS <ENQ> mode (Auto up/download)\n",
  408.     "\tset cr on|off\t\tSet/Reset Carriage Return Injection mode\n",
  409.     "\tset halfdplx on|off\tSet/reset half-duplex terminal mode\n",
  410.     "\tset nl on|off\t\tSet/Reset newline translation\n",
  411.     "\tset pfile name\t\tChange name of phonelist file\n",
  412.     "\tset purge on|off\tSet/Reset bad phone line mode\n",
  413.     "\tset xoff on|off\t\tSet/Reset XON/XOFF flow control\n",
  414.     "",
  415.     "\tESCAPE sequences in TERMINAL mode:\n\n",
  416.     "\t",ESC_STR," b\tSend modem break\n",
  417.     "\t",ESC_STR," d\tDialing directory\n",
  418.     "\t",ESC_STR," f\tSend a file through the modem (ASCII transfer)\n",
  419.     "\t",ESC_STR," s\tExecute XC script file\n",
  420.     "\t",ESC_STR," h\tHang up the modem\n",
  421.     "\t",ESC_STR," t\tToggle capture file on and off\n",
  422.     "\t",ESC_STR," x\tExit terminal mode back to XC command mode\n",
  423.     "\t",ESC_STR," q\tQuit XC entirely\n",
  424.     "",
  425.     NULLS };
  426.  
  427. static s_help()
  428. {
  429.     char **ptr = cmdlist;
  430.  
  431.     ioctl(0, TCSETAW, &oldmode);
  432.     cls();
  433.     cur_off();
  434.     for ( ; *ptr != NULLS; ptr++)
  435.         if (**ptr)
  436.             fprintf(tfp, "%s", *ptr);
  437.         else
  438.             show(0,"PRESS ENTER"),
  439.             getline(),
  440.             cls();
  441.     status();
  442. }
  443.  
  444. s_set()
  445. {
  446.     struct kw *ptr;
  447.  
  448.     getword();
  449.  
  450.     if (word[0] == '\0' && !scriptflag) {
  451.         status();
  452.         return;
  453.     } else if (word[0] == '\0') {
  454.         show(1,"SET keyword requires an argument");
  455.         eof_flag++;
  456.         return;
  457.     }
  458.  
  459.     lc_word(word);
  460.  
  461.     for (ptr = setlist; ptr->keyword != NULLS; ptr++)
  462.         if (strcmp(ptr->keyword, word) == 0) {
  463.             (*ptr->rtn)();
  464.             return;
  465.         }
  466.  
  467.     sprintf(Msg,"Invalid SET keyword: %s", word);
  468.     S;
  469.     eof_flag++;
  470. }
  471.  
  472. set_onoff(flag)
  473. short *flag;
  474. {
  475.     char *ptr = strdup(word);
  476.  
  477.     getword();
  478.     lc_word(word);
  479.  
  480.     if (strcmp(word, "on") == 0)
  481.         *flag = TRUE;
  482.     else if (strcmp(word, "off") == 0)
  483.         *flag = FALSE;
  484.     else
  485.         sprintf(Msg,"Set '%s' value must be 'on' or 'off'",ptr),
  486.         S,
  487.         eof_flag++;
  488.  
  489.     free(ptr);
  490. }
  491.  
  492. static SET_7bit()
  493. {
  494.     short val;
  495.  
  496.     if (stat_flag) {
  497.         fprintf(tfp, statfmt, "7bit", "Seven-bit Mask",
  498.             bitmask == 0x7f ? "ON" : "OFF");
  499.         return;
  500.     }
  501.  
  502.     set_onoff(&val);
  503.     bitmask = val ? 0x7f : 0xff;
  504.  
  505.     if (!scriptflag)
  506.         sprintf(Msg,"%s-bit mask enabled", val ? "Seven" : "Eight"),
  507.         S;
  508. }
  509.  
  510. static SET_cr()
  511. {
  512.     if (stat_flag) {
  513.         fprintf(tfp, statfmt, "cr", "Carriage Return Injection",
  514.             cr_add ? "ON" : "OFF");
  515.         return;
  516.     }
  517.  
  518.     set_onoff(&cr_add);
  519.  
  520.     if (!scriptflag)
  521.         sprintf(Msg,"Carriage Returns %s injected in B+ ASCII uploads",
  522.             cr_add ? "ARE" : "are NOT"),
  523.         S;
  524. }
  525.  
  526. static SET_nl()
  527. {
  528.     if (stat_flag) {
  529.         fprintf(tfp, statfmt, "nl", "Newline Translation",
  530.             nlmode ? "ON" : "OFF");
  531.         return;
  532.     }
  533.  
  534.     set_onoff(&nlmode);
  535.  
  536.     if (!scriptflag)
  537.         sprintf(Msg,"Newlines %s changed to Carriage Returns",
  538.             nlmode ? "ARE" : "are NOT"),
  539.         S;
  540. }
  541.  
  542. static SET_cis()
  543. {
  544.     if (stat_flag) {
  545.         fprintf(tfp, statfmt, "cis", "CIS <ENQ> Auto Download",
  546.             cismode ? "ON" : "OFF");
  547.         return;
  548.     }
  549.  
  550.     set_onoff(&cismode);
  551.  
  552.     if (!scriptflag)
  553.         sprintf(Msg,"CIS <ENQ> Auto Download is %s", cismode ? "ON" : "OFF"),
  554.         S;
  555. }
  556.  
  557. static SET_purge()
  558. {
  559.     if (stat_flag) {
  560.         fprintf(tfp, statfmt, "purge", "Bad Telephone line",
  561.             badline ? "ON" : "OFF");
  562.         return;
  563.     }
  564.  
  565.     set_onoff(&badline);
  566.  
  567.     if (!scriptflag)
  568.         sprintf(Msg,"Bad telephone line purging is %s", badline ? "ON" : "OFF"),
  569.         S;
  570. }
  571.  
  572. static SET_xoff()
  573. {
  574.     if (stat_flag) {
  575.         fprintf(tfp, statfmt, "xoff", "Terminal mode XON/XOFF",
  576.             flowflag ? "ON" : "OFF");
  577.         return;
  578.     }
  579.  
  580.     set_onoff(&flowflag);
  581.     xc_setflow(flowflag);
  582.  
  583.     if (!scriptflag)
  584.         sprintf(Msg,"XOFF/XON Flow control is %s", flowflag ? "ON" : "OFF"),
  585.         S;
  586. }
  587.  
  588. static SET_bps()
  589. {
  590.     if (stat_flag) {
  591.         char br[10];
  592.         sprintf(br, "%d", 10*mrate(NULLS));
  593.         fprintf(tfp, statfmt, "bps", "Bits per Second", br);
  594.         return;
  595.     }
  596.  
  597.     getword();
  598.     if (word[0] == '\0')
  599.         show(1,"Set Bps must have a rate");
  600.     else if (mrate(word) < 0)
  601.         sprintf(Msg,"Unsupported bps rate %s",word),
  602.         S;
  603.     eof_flag++;
  604.     if (!scriptflag)
  605.         sprintf(Msg,"Bits/Second set to %d",10*mrate(NULLS)),
  606.         S;
  607. }
  608.  
  609. static SET_halfdplx()
  610. {
  611.     if (stat_flag) {
  612.         fprintf(tfp, statfmt, "halfdplx", "Half-duplex mode",
  613.             hdplxflag ? "ON" : "OFF");
  614.         return;
  615.     }
  616.  
  617.     set_onoff(&hdplxflag);
  618.  
  619.     if (!scriptflag)
  620.         sprintf(Msg,"Half-duplex Mode is %s", hdplxflag ? "ON" : "OFF"),
  621.         S;
  622. }
  623.  
  624. static SET_autocapt()
  625. {
  626.     if (stat_flag) {
  627.         fprintf(tfp, statfmt, "auto", "Auto capture toggle",
  628.             autoflag ? "ON" : "OFF");
  629.         return;
  630.     }
  631.  
  632.     set_onoff(&autoflag);
  633.  
  634.     if (!scriptflag)
  635.         sprintf(Msg,"Auto Capture Toggling is %s", autoflag ? "ON" : "OFF"),
  636.         S;
  637. }
  638.  
  639. static SET_cfile()
  640. {
  641.     if (stat_flag) {
  642.         fprintf(tfp, statfmt, "cfile", "Capture file", captfile);
  643.         return;
  644.     }
  645.  
  646.     getword();
  647.     if (word[0] == '\0') {
  648.         show(1,"Set CFILE must have file name");
  649.         eof_flag++;
  650.         return;
  651.     }
  652.  
  653.     strcpy(captfile, word);
  654.  
  655.     if (!scriptflag)
  656.         sprintf(Msg,"Capture file set to '%s'",captfile),
  657.         S;
  658. }
  659.  
  660. static SET_pfile()
  661. {
  662.     if (stat_flag) {
  663.         fprintf(tfp, statfmt, "pfile", "Phone number file", phonefile);
  664.         return;
  665.     }
  666.  
  667.     getword();
  668.     if (word[0] == '\0') {
  669.         show(1,"Set PFILE must have file name");
  670.         eof_flag++;
  671.         return;
  672.     }
  673.  
  674.     strcpy(phonefile, word);
  675.  
  676.     if (!scriptflag)
  677.         sprintf(Msg,"Phone number file set to '%s'",phonefile),
  678.         S;
  679. }
  680.  
  681. /*    Put and Take a file to/from a UNIX-type "cu" system. Unfortunately,
  682.     the stty command is one of those commands that always gets changed
  683.     with different UNIX systems, so you will get (at least) a file full of
  684.     ^M on the take command for systems later than V7 or work-alikes.
  685.  
  686.     Additionally, the Take command takes a bit too much!
  687.  
  688.     Fixed a lot of this: JPRadley 89/07/27
  689. */
  690.  
  691. static puttake()
  692. {
  693.     FILE * fp;
  694.     int i, Ch;
  695.     char c = word[1], fname[SM_BUFF], tname[SM_BUFF], wrkbuff[SM_BUFF];
  696.  
  697.     getword();
  698.  
  699.     intdel(TRUE);
  700.     signal(SIGINT,catch);
  701.     signal(SIGQUIT,catch);
  702.     xc_setflow(TRUE);
  703.     if (word[0] == '\0') {
  704.         sprintf(Msg,"Must give a filename with the '%%%c' option",c);
  705.         S;
  706.         return;
  707.     }
  708.  
  709.     strcpy(fname, word);
  710.     getword();
  711.     if (word[0] == '\0')
  712.         strcpy(tname, fname);
  713.     else
  714.         strcpy(tname, word);
  715.     switch (c) {
  716.     case 'p':
  717.         if ((fp = fopen(fname, "r")) == NULLF) {
  718.             sprintf(Msg,"Can't access '%s'",fname);
  719.             S;
  720.             break;
  721.         }
  722.  
  723.         fprintf(tfp, "\nPutting file '%s' to '%s' on remote UNIX\n",
  724.             fname, tname);
  725.         sprintf(wrkbuff, "stty -echo;cat >%s;sleep 1;stty echo\n", tname);
  726.         send_slowly(wrkbuff);        /* send command string to remote shell */
  727.         i = 64;
  728.         while ((Ch = getc(fp)) != EOF) {
  729.             if (++i > 64) { /* this prevents an overload on the */
  730.                 i = 0;     /* receiver's input buffer (64=kludge) */
  731.                 msecs((CBAUD-cbaud) * 100);
  732.             }
  733.             send_mbyte(Ch);        /* send characters to cat command */
  734.         }
  735.         fclose(fp);
  736.         send_mbyte('D'-'@');    /* send a ^D to cat */
  737.         purge();                /* get rid of whatever was sent back */
  738.         send_mbyte('\n');
  739.         break;
  740.  
  741.     case 't':
  742.         strcpy(Name, tname);
  743.         if ((fp=QueryCreate(Resume_Not_Allowed)) == NULLF)
  744.             break;
  745.  
  746.         fprintf(tfp, "\nTaking file '%s' from remote UNIX to '%s'\n",
  747.             fname, tname);
  748.                                     /* if 'fname' has a ^E, we'll die */
  749.         sprintf(wrkbuff, "stty nl;cat %s;echo %c;stty -nl;sleep 1\n",
  750.             fname, ENQ);
  751.         send_slowly(wrkbuff);        /* send command string to remote shell */
  752.         while (read_mbyte(3) != '\n'); /* discard up to the \n in wrkbuff */
  753.             ;
  754.         while ((Ch=read_mbyte(3)) != -1 && /* while more chars are being sent */
  755.                     Ch != ENQ)               /* and we haven't seen our ENQ */
  756.             fputc(Ch,fp);
  757.         fclose(fp);
  758.         break;
  759.     }
  760.     intdel(FALSE);
  761.     xc_setflow(flowflag);
  762.     reterm = TRUE;
  763. }
  764.  
  765. s_exit()
  766. {
  767.     signal(SIGHUP,SIG_IGN);
  768.     signal(SIGINT,SIG_IGN);
  769.     signal(SIGQUIT,SIG_IGN);
  770.     signal(SIGTERM,SIG_IGN);
  771.  
  772.     putc('\n',tfp);
  773.  
  774.     unlock_tty();
  775.  
  776.     ioctl(0, TCSETAF, &oldmode);
  777.  
  778.     exit(0);
  779. }
  780.