home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume16 / pcomm2 / part04 / input.c < prev    next >
C/C++ Source or Header  |  1988-09-14  |  10KB  |  493 lines

  1. /*
  2.  * The input routines.  This program runs as a child process to the
  3.  * Pcomm program.
  4.  */
  5.  
  6. #define CLIST 64
  7.  
  8. #include <stdio.h>
  9. #include <signal.h>
  10. #include <setjmp.h>
  11. #include "config.h"
  12. #ifdef SHAREDMEM
  13. #include <sys/types.h>
  14. #include <sys/ipc.h>
  15. #include <sys/shm.h>
  16. #endif /* SHAREDMEM */
  17. #define MAIN
  18. #include "misc.h"
  19. #include "status.h"
  20. #include "vcs.h"
  21.  
  22. jmp_buf i_jmp;
  23. int vcs_param[NUM_VCS][5];        /* positional parameters */
  24. int vcs_opt[NUM_VCS][10];        /* options unique to each vcs */
  25. int vcs_codes[NUM_VCS][VCS_SIZE];    /* the vcs codes */
  26. int vcs_leadin[NUM_VCS];        /* unique list of lead-in characters */
  27. int num_leadin;                /* length of lead-in list */
  28. int hold, max_row, max_col, skip_row;
  29. FILE *logfp, *lprfp;
  30. struct STATUS *status;
  31.  
  32. #ifdef SHAREDMEM
  33. #define VROW    status->row
  34. #define VCOL    status->col
  35. #define VS    status->vs
  36. #else /* SHAREDMEM */
  37. int VROW, VCOL;
  38. char VS[MAX_ROW][MAX_COL+2];
  39. struct STATUS s;
  40. #endif /* SHAREDMEM */
  41.  
  42. /*
  43.  * Read the serial port and write the characters to the screen.  Watch
  44.  * for signals from the parent process to toggle the fancy options.
  45.  * Writes the characters received to a virtual screen buffer.
  46.  */
  47.  
  48. main(argc, argv)
  49. int argc;
  50. char *argv[];
  51. {
  52.     FILE *popen();
  53.     int got_sig();
  54.     char c, *strcpy();
  55.     void _exit(), exit(), vcs_table();
  56. #ifdef SHAREDMEM
  57.     int shm_id;
  58.     char *shmat();
  59. #endif /* SHAREDMEM */
  60.                     /* set the trap for the signals */
  61.     signal(SIGALRM, SIG_IGN);
  62.     signal(SIGHUP,  SIG_IGN);
  63.     signal(SIGQUIT, SIG_IGN);
  64.     signal(SIGUSR1, got_sig);
  65.     signal(SIGUSR2, got_sig);
  66.     signal(SIGINT,  got_sig);
  67.     signal(SIGTERM, got_sig);
  68.                     /* unbuffered output */
  69.     setbuf(stdout, (char *) NULL);
  70.                     /* for the curious... */
  71.     if (argc == 1) {
  72.         fprintf(stderr, "This is the input routine for the Pcomm program\n");
  73.         fprintf(stderr, "It is not designed to be run as a separate program\n");
  74.         exit(1);
  75.     }
  76. #ifdef SHAREDMEM
  77.     shm_id = atoi(argv[1]);
  78.     status = (struct STATUS *) shmat(shm_id, (char *) 0, 0);
  79.     if ((int) status == -1) {
  80.         perror("shmat");
  81.         _exit(1);
  82.     }
  83. #else /* SHAREDMEM */
  84.     status = &s;
  85. #endif /* SHAREDMEM */
  86.                     /* load the VCS table */
  87.     vcs_table();
  88.     if (max_row > MAX_ROW)
  89.         max_row = MAX_ROW;
  90.     if (max_col > MAX_COL)
  91.         max_col = MAX_COL;
  92.                     /* parse the command line */
  93. #ifndef SHAREDMEM
  94.     status->fd = atoi(argv[1]);
  95.     status->add_lf = atoi(argv[2]);
  96.     status->log = atoi(argv[3]);
  97.     status->print = atoi(argv[4]);
  98.     strcpy(status->log_path, argv[5]);
  99.     strcpy(status->vs_path, argv[6]);
  100. #endif /* SHAREDMEM */
  101.  
  102.     skip_row = 0;
  103. #ifdef SHAREDMEM
  104.     if (status->clr)
  105.         skip_row = 1;
  106. #else /* SHAREDMEM */
  107.                     /* read previous screen */
  108.     if (!access(status->vs_path, 0))
  109.         read_vs();
  110.     else
  111.         skip_row = 1;
  112. #endif /* SHAREDMEM */
  113.  
  114.     hold = 0;
  115.                     /* start up file pointers */
  116.     lprfp = (FILE *) NULL;
  117.     logfp = (FILE *) NULL;
  118.  
  119.     switch (setjmp(i_jmp)) {
  120.         case 0:            /* no signal */
  121.             break;
  122.         case 1:            /* toggle the data logging */
  123.             status->log = status->log ? 0 : 1;
  124.             break;
  125.         case 2:            /* toggle the printer */
  126.             status->print = status->print ? 0 : 1;
  127.             break;
  128.         case 3:            /* suspend the input */
  129.             hold = hold ? 0 : 1;
  130. #ifndef SHAREDMEM
  131.             if (hold)
  132.                 write_vs();
  133. #endif /* SHAREDMEM */
  134.             break;
  135.         case 4:            /* clean up and go home */
  136.             if (status->log)
  137.                 fclose(logfp);
  138.             if (status->print) {
  139.                 putc('\f', lprfp);
  140.                 pclose(lprfp);
  141.             }
  142. #ifdef SHAREDMEM
  143.                     /* detach shared memory */
  144.             shmdt((char *) status);
  145. #endif /* SHAREDMEM */
  146.             _exit(0);
  147.             break;
  148.     }
  149.                     /* any signal will awaken pause() */
  150.     if (hold)
  151.         pause();
  152.                     /* open or close the printer */
  153.     if (status->print && lprfp == NULL)
  154.         lprfp = popen(LPR, "w");
  155.  
  156.     if (!status->print && lprfp != NULL) {
  157.         putc('\f', lprfp);
  158.         pclose(lprfp);
  159.         lprfp = (FILE *) NULL;
  160.     }
  161.                     /* open or close the log file */
  162.     if (status->log && logfp == NULL) {
  163.         if (strcmp(status->log_path, "NOT_DEFINED")) {
  164.             if (!(logfp = fopen(status->log_path, "a")))
  165.                 status->log = 0;
  166.         }
  167.         else
  168.             status->log = 0;
  169.     }
  170.     if (!status->log && logfp != NULL) {
  171.         fclose(logfp);
  172.         logfp = (FILE *) NULL;
  173.     }
  174.  
  175. #ifdef SHAREDMEM
  176.     if (status->clr) {
  177.         status->clr = 0;
  178.         vs_clear();
  179.     }
  180. #else /* SHAREDMEM */
  181.                     /* clear if vs_path doesn't exist */
  182.     if (access(status->vs_path, 0))
  183.         vs_clear();
  184. #endif /* SHAREDMEM */
  185.     /*
  186.      * The very first screen we see after dialing has the "Connected to..."
  187.      * message at row 0, therefore we start our virtual screen at row 1.
  188.      */
  189.     if (skip_row) {
  190.         skip_row = 0;
  191.         VROW = 1;
  192.     }
  193.  
  194.     while (1) {
  195.         if ((int) (c = readbyte()) <= 0)
  196.             continue;
  197.                     /* send to logfile */
  198.         if (status->log) {
  199.             if (c == '\r' && status->add_lf)
  200.                 putc('\n', logfp);
  201.                     /* no carriage returns in logfile */
  202.             if (c != '\r')
  203.                 putc(c, logfp);
  204.         }
  205.                     /* send to printer too? */
  206.         if (status->print)
  207.             putc(c, lprfp);
  208.  
  209.                     /* put a char in virtual screen */
  210.         vs_putchar(c);
  211.  
  212.         putchar(c);
  213.                     /* add LF to CR? */
  214.         if (c == '\r' && status->add_lf)
  215.             putchar('\n');
  216.     }
  217. }
  218.  
  219. /*
  220.  * Figure out which signal we just received, and fix the return code of
  221.  * the setjmp function above to the proper value.
  222.  */
  223.  
  224. int
  225. got_sig(sig)
  226. int sig;
  227. {
  228.     void longjmp();
  229.     switch (sig) {
  230.         case SIGUSR1:
  231.             signal(SIGUSR1, got_sig);
  232.             longjmp(i_jmp, 1);
  233.         case SIGUSR2:
  234.             signal(SIGUSR2, got_sig);
  235.             longjmp(i_jmp, 2);
  236.         case SIGINT:
  237.             signal(SIGINT, got_sig);
  238.             longjmp(i_jmp, 3);
  239.         case SIGTERM:
  240.             signal(SIGTERM, got_sig);
  241.             longjmp(i_jmp, 4);
  242.     }
  243. }
  244.  
  245. /*
  246.  * Put a character in the virtual screen.  This routine saves incoming
  247.  * characters in a two dimensional buffer designed to mimic the real
  248.  * screen.
  249.  */
  250.  
  251. int
  252. vs_putchar(c)
  253. char c;
  254. {
  255.     register int j, i;
  256.     int tab_stop;
  257.  
  258.     switch (vcs_filter(c)) {
  259.         case MAYBE:        /* wait and see... */
  260.             break;
  261.         case 256+HOME:        /* home virtual screen "cursor" */
  262.             VROW = 0;
  263.             VCOL = 0;
  264.             break;
  265.         case 256+CLR_EOL:    /* clear to end of line */
  266.             for (i=VCOL; i<max_col; i++)
  267.                 VS[VROW][i] = ' ';
  268.             break;
  269.         case 256+CLR_EOS:    /* clear to end of screen */
  270.             for (j=VCOL; j<max_col; j++)
  271.                 VS[VROW][j] = ' ';
  272.             for (i=VROW+1; i<max_row; i++) {
  273.                 for (j=0; j<max_col; j++)
  274.                     VS[i][j] = ' ';
  275.             }
  276.             break;
  277.         case 256+CLEAR:        /* clear all and home "cursor" */
  278.             for (i=0; i<max_row; i++) {
  279.                 for (j=0; j<max_col; j++)
  280.                     VS[i][j] = ' ';
  281.             }
  282.             VROW = 0;
  283.             VCOL = 0;
  284.             break;
  285.         case 256+MV_UP:        /* move "cursor" up */
  286.             VROW--;
  287.             if (VROW < 0)
  288.                 VROW = 0;
  289.             break;
  290.         case 256+MV_DOWN:    /* move "cursor" down */
  291.             VROW++;
  292.             if (VROW >= max_row)
  293.                 VROW = max_row -1;
  294.             break;
  295.         case 256+MV_RIGHT:    /* move "cursor" right */
  296.             VCOL++;
  297.             if (VCOL >= max_col)
  298.                 VCOL = max_col -1;
  299.             break;
  300.         case 256+MV_LEFT:    /* move "cursor" left */
  301.         case BS:        /* non destructive back space */
  302.             VCOL--;
  303.             if (VCOL < 0)
  304.                 VCOL = 0;
  305.             break;
  306.         case 256+MV_DIRECT:    /* direct cursor movement */
  307.             VROW = vcs_param[MV_DIRECT][0];
  308.             VCOL = vcs_param[MV_DIRECT][1];
  309.  
  310.                     /* if "add one" and "decimal" */
  311.             if (vcs_opt[MV_DIRECT][0] && vcs_opt[MV_DIRECT][1]) {
  312.                 VROW--;
  313.                 VCOL--;
  314.             }
  315.                     /* if "character" */
  316.             if (vcs_opt[MV_DIRECT][2]) {
  317.                     /* if "add offset" */
  318.                 if (vcs_opt[MV_DIRECT][3]) {
  319.                     VROW -= vcs_opt[MV_DIRECT][5];
  320.                     VCOL -= vcs_opt[MV_DIRECT][5];
  321.                 }
  322.                     /* if "subtract offset" */
  323.                 if (vcs_opt[MV_DIRECT][4]) {
  324.                     VROW += vcs_opt[MV_DIRECT][5];
  325.                     VCOL += vcs_opt[MV_DIRECT][5];
  326.                 }
  327.                 VROW--;
  328.                 VCOL--;
  329.             }
  330.             break;
  331.         case '\t':        /* tab character */
  332.             tab_stop = VCOL + 8 - (VCOL % 8);
  333.                     /* if wrap around */
  334.             if (tab_stop >= max_col) {
  335.                     /* spaces up to eol */
  336.                 for (; VCOL<max_col; VCOL++)
  337.                     VS[VROW][VCOL] = ' ';
  338.                 VROW++;
  339.                 if (VROW >= max_row)
  340.                     vs_scroll();
  341.  
  342.                     /* the remainder of the tab */
  343.                 VCOL = tab_stop - max_col;
  344.             }
  345.             else {
  346.                 for (; VCOL<tab_stop; VCOL++)
  347.                     VS[VROW][VCOL] = ' ';
  348.             }
  349.             break;
  350.         case '\r':        /* carriage return */
  351.             VCOL = 0;
  352.             if (!status->add_lf)
  353.                 break;
  354.             /* fall thru...*/
  355.         case '\n':        /* line feed */
  356.             VROW++;
  357.             if (VROW >= max_row)
  358.                 vs_scroll();
  359.             break;
  360.         default:        /* a normal character */
  361.             VS[VROW][VCOL] = c;
  362.             VCOL++;
  363.                     /* wrap around */
  364.             if (VCOL >= max_col) {
  365.                 VCOL = 0;
  366.                 VROW++;
  367.                 if (VROW >= max_row)
  368.                     vs_scroll();
  369.             }
  370.             break;
  371.     }
  372.     return(0);
  373. }
  374.  
  375. #ifndef SHAREDMEM
  376. /*
  377.  * Save the virtual screen to a file.
  378.  */
  379.  
  380. int
  381. write_vs()
  382. {
  383.     FILE *fp;
  384.     register int i;
  385.  
  386.     if (!(fp = fopen(status->vs_path, "w")))
  387.         return(1);
  388.                     /* current x y coordinates */
  389.     fprintf(fp, "%d,%d\n", VROW, VCOL);
  390.  
  391.     for (i=0; i<max_row; i++) {
  392.         VS[i][max_col] = NULL;
  393.         fprintf(fp, "%s\n", VS[i]);
  394.     }
  395.     fclose(fp);
  396.     return(0);
  397. }
  398.  
  399. /*
  400.  * Get the virtual screen image from the file.  Since input() gets
  401.  * killed from time to time, the vs_path file is the only way to retain
  402.  * the screen image.
  403.  */
  404.  
  405. int
  406. read_vs()
  407. {
  408.     FILE *fp;
  409.     register int i;
  410.     char buf[10];
  411.                 /* in case the fopen fails... */
  412.     VROW = 0;
  413.     VCOL = 0;
  414.                 /* not guaranteed to exist yet */
  415.     if (!(fp = fopen(status->vs_path, "r")))
  416.         return(1);
  417.                 /* get the x, y coordinates */
  418.     fgets(buf, 10, fp);
  419.     scanf(buf, "%d,%d\n", VROW, VCOL);
  420.  
  421.                 /* read the file into the vs array */
  422.     for (i=0; i<max_row; i++) {
  423.         fgets(VS[i], MAX_COL+2, fp);
  424.         VS[i][max_col] = NULL;
  425.     }
  426.     fclose(fp);
  427.     return(0);
  428. }
  429. #endif /* SHAREDMEM */
  430.  
  431. /*
  432.  * If the user clears the screen with the ^A-C command, the input
  433.  * has to be in sync.
  434.  */
  435.  
  436. int
  437. vs_clear()
  438. {
  439.     register int j, i;
  440.  
  441.     for (i=0; i<max_row; i++) {
  442.         VS[i][max_col] = NULL;
  443.         for (j=0; j<max_col; j++)
  444.             VS[i][j] = ' ';
  445.     }
  446.                     /* home the "cursor" */
  447.     VROW = 0;
  448.     VCOL = 0;
  449.     return(0);
  450. }
  451.  
  452. /*
  453.  * Do a software scroll on the virtual screen.  Does not alter the
  454.  * "col" variable.
  455.  */
  456.  
  457. int
  458. vs_scroll()
  459. {
  460.     register int i;
  461.     char *strcpy();
  462.                     /* move 'em up 1 line */
  463.     for (i=0; i<max_row-1; i++)
  464.         strcpy(VS[i], VS[i+1]);
  465.                     /* clear the bottom line */
  466.     for (i=0; i<max_col; i++)
  467.         VS[max_row-1][i] = ' ';
  468.  
  469.     VROW = max_row -1;
  470.     return(0);
  471. }
  472.  
  473. /*
  474.  * Do a buffered read from the serial port.
  475.  */
  476.  
  477. int
  478. readbyte()
  479. {
  480.     static char buf[CLIST];
  481.     static char *bufp = buf;
  482.     static int n = 0;
  483.  
  484.     if (n <= 0) {
  485.         if ((n = read(status->fd, buf, CLIST)) <= 0)
  486.             return(-1);
  487.         bufp = buf;
  488.     }
  489.     while (--n >= 0)
  490.         return(*bufp++ & 0xff);
  491.     return(-1);
  492. }
  493.