home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume26 / pcomm-2.0.2 / part04 / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-04-13  |  9.9 KB  |  446 lines

  1. /*
  2.  * Pcomm is a public domain telecommunication program for Unix that
  3.  * is designed to operate similarly to the MSDOS program, ProComm.
  4.  * ProComm (TM) is copyrighted by Datastorm Technologies, Inc.
  5.  *
  6.  * Emmet P. Gray            US Army, HQ III Corps & Fort Hood
  7.  * ...!uunet!uiucuxc!fthood!egray    Attn: AFZF-DE-ENV
  8.  *                    Directorate of Engineering & Housing
  9.  *                    Environmental Management Office
  10.  *                    Fort Hood, TX 76544-5057
  11.  *
  12.  *    Release v1.0    12 Mar 88
  13.  *    Release v1.1    21 Aug 88
  14.  *    Release v1.2     4 Feb 89
  15.  *    Release v2.0    18 Jul 92
  16.  */
  17.  
  18. #include <stdio.h>
  19. #include <ctype.h>
  20. #include <signal.h>
  21. #include <curses.h>
  22. #include <sys/types.h>
  23. #include <sys/stat.h>
  24. #define    MAIN
  25. #include "config.h"
  26. #include "dial_dir.h"
  27. #include "extrnl.h"
  28. #include "misc.h"
  29. #include "modem.h"
  30. #include "param.h"
  31. #include "status.h"
  32.  
  33. #ifndef OLDCURSES
  34. #include <term.h>
  35. #else /* OLDCURSES */
  36. #ifdef UNIXPC
  37. #include <sgtty.h>
  38. #endif /* UNIXPC */
  39. char tcbuf[1024];
  40. struct sgttyb t_mode, c_mode;
  41. #ifndef cbreak
  42. #define cbreak crmode
  43. #endif
  44. #endif /* OLDCURSES */
  45.  
  46. struct DIAL_DIR *dir;
  47. struct EXTRNL *extrnl;
  48. struct MODEM *modem;
  49. struct PARAM *param;
  50. struct STATUS *status;
  51.  
  52. int fd = -1;                /* file descriptor for port */
  53. int xmc;                /* magic cookie terminal */
  54. int msg_status;                /* read/write permissions on TTY */
  55. char *null_ptr = "";            /* generic char pointer to a null */
  56.  
  57. static int quit(), ci_match();
  58. static void print_usage();
  59.  
  60. main(argc, argv)
  61. int argc;
  62. char *argv[];
  63. {
  64.     extern char *optarg;
  65.     int c, i, data_bits;
  66.     unsigned baud;
  67.     char *mytty, *ttyname(), *term, *getenv(), *sys_name, parity;
  68.     char *extra_dir, buf[80], message[80], *str_dup(), *number;
  69.     char *aux;
  70.     struct DIAL_DIR *read_dir();
  71.     struct EXTRNL *read_extrnl();
  72.     struct MODEM *read_modem();
  73.     struct PARAM *read_param();
  74.     struct STATUS *init();
  75.     struct stat stbuf;
  76.     void exit(), error_win(), vcs_table(), terminal(), free_ptr();
  77.     void info();
  78. #ifdef OLDCURSES
  79.     char *tgetstr(), *t, tb[1024];
  80.     t = tcbuf;
  81. #endif /* OLDCURSES */
  82.  
  83.     signal(SIGINT, SIG_IGN);
  84.     signal(SIGQUIT, SIG_IGN);
  85.     signal(SIGTERM, (SIG_TYPE(*) ()) quit);
  86.     signal(SIGHUP, (SIG_TYPE(*) ()) quit);
  87.  
  88.     extra_dir = NULL;
  89.     sys_name = NULL;
  90.     aux = NULL;
  91.     parity = '\0';
  92.     baud = 0;
  93.     data_bits = 0;
  94.     number = NULL;
  95.                     /* the command line */
  96.     while ((c = getopt(argc, argv, "d:f:a:eonw:b:p:")) != EOF) {
  97.         switch (c) {
  98.             case 'd':    /* the extra directory to search */
  99.                 extra_dir = str_dup(optarg);
  100.                 break;
  101.             case 'f':    /* the short cut into the dialing dir */
  102.                 sys_name = str_dup(optarg);
  103.                 break;
  104.             case 'a':    /* auxiliary (script, TTY, or modem) */
  105.                 aux = str_dup(optarg);
  106.                 break;
  107.             case 'e':
  108.                 if (parity != '\0')
  109.                     print_usage("Parity values are mutually exclusive");
  110.                 parity = 'E';
  111.                 break;
  112.             case 'o':
  113.                 if (parity != '\0')
  114.                     print_usage("Parity values are mutually exclusive");
  115.                 parity = 'O';
  116.                 break;
  117.             case 'n':
  118.                 if (parity != '\0')
  119.                     print_usage("Parity values are mutually exclusive");
  120.                 parity = 'N';
  121.                 break;
  122.             case 'w':
  123.                 data_bits = atoi(optarg);
  124.                 if (data_bits != 7 && data_bits != 8)
  125.                     print_usage("Unsupported number of word length (data bits)");
  126.                 break;
  127.             case 'b':
  128.                 baud = (unsigned int) atoi(optarg);
  129.                 switch (baud) {
  130.                     case 300:
  131.                     case 1200:
  132.                     case 2400:
  133.                     case 4800:
  134.                     case 9600:
  135.                     case 19200:
  136.                     case 38400:
  137.                         break;
  138.                     default:
  139.                         print_usage("Unsupported baud rate");
  140.                         break;
  141.                 }
  142.                 break;
  143.             case 'p':
  144.                 number = str_dup(optarg);
  145.                 break;
  146.             case '?':    /* default */
  147.                 print_usage("");
  148.                 break;
  149.         }
  150.     }
  151.                     /* get terminal type */
  152.     term = getenv("TERM");
  153.     if (term == NULL || *term == '\0') {
  154.         fprintf(stderr, "Windows not supported (TERM not defined)\n");
  155.         exit(1);
  156.     }
  157.                     /* see if terminfo entry exists */
  158. #ifdef OLDCURSES
  159.     i = tgetent(tb, term);
  160. #else /* OLDCURSES */
  161.     setupterm(term, 1, &i);
  162. #endif /* OLDCURSES */
  163.  
  164.     if (i != 1) {
  165.         fprintf(stderr, "Windows not supported (no terminfo data for \"%s\")\n", term);
  166.         exit(1);
  167.     }
  168.                     /* minimum screen size */
  169. #ifdef OLDCURSES
  170.     if (tgetnum("co") < 80 || tgetnum("li") < 24) {
  171. #else /* OLDCURSES */
  172.     if (columns < 80 || lines < 24) {
  173. #endif /* OLDCURSES */
  174.         fprintf(stderr, "Windows not supported (minimum 80x24 screen required)\n");
  175.         exit(1);
  176.     }
  177.                     /* must have cursor movement */
  178. #ifdef OLDCURSES
  179.     if (tgetstr("cm", &t) == NULL) {
  180. #else /* OLDCURSES */
  181.     if (cursor_address == NULL) {
  182. #endif /* OLDCURSES */
  183.         fprintf(stderr, "Windows not supported (terminal too dumb)\n");
  184.         exit(1);
  185.     }
  186.                     /* load magic cookie variable */
  187. #ifdef OLDCURSES
  188.     xmc = tgetnum("sg");
  189. #else /* OLDCURSES */
  190.     xmc = magic_cookie_glitch;
  191. #endif /* OLDCURSES */
  192.                     /* ok... now let's go! */
  193. #ifdef OLDCURSES
  194.     ioctl(0, TIOCGETP, &t_mode);
  195. #endif /* OLDCURSES */
  196.  
  197.     initscr();
  198.     nonl();
  199.     cbreak();
  200.     noecho();
  201.  
  202. #ifdef OLDCURSES
  203.     ioctl(0, TIOCGETP, &c_mode);
  204. #endif /* OLDCURSES */
  205.  
  206.     dir = (struct DIAL_DIR *) NULL;
  207.     extrnl = (struct EXTRNL *) NULL;
  208.     param = (struct PARAM *) NULL;
  209.     modem = (struct MODEM *) NULL;
  210.                     /* display herald if no arguments */
  211.     if (argc == 1) {
  212.         info(AUTO_CLEAR);
  213.         erase();
  214.         refresh();
  215.     }
  216.                     /* get "msgs" status */
  217.     if (mytty = ttyname(0)) {
  218.         stat(mytty, &stbuf);
  219.         msg_status = stbuf.st_mode & 0777;
  220.         chmod(mytty, 0600);
  221.     }
  222.  
  223.     mvaddstr(12, 31, "Initializing...");
  224.     refresh();
  225.                     /* create the VCS table */
  226.     vcs_table();
  227.                     /* create the status structure */
  228.     status = init(extra_dir);
  229.                     /* read the support files */
  230.     param = read_param();
  231.     dir = read_dir();
  232.     extrnl = read_extrnl();
  233.     modem = read_modem();
  234.  
  235.                     /* warning about screen size */
  236.     if (LINES > MAX_ROW || COLS > MAX_COL-1)
  237.         error_win(0, "Your screen size exceeds an internal Pcomm limit",
  238.          "The edges of the screen may contain garbage");
  239.  
  240.                     /* short-cut to dialing window? */
  241.     if (sys_name != NULL) {
  242.         for (i=1; i<dir->d_entries+1; i++) {
  243.             if (ci_match(dir->name[i], sys_name)) {
  244.                 dir->q_num[0] = i;
  245.                 dir->d_cur = i;
  246.                 if (!dial_win(25))
  247.                     aux = dir->aux[dir->d_cur];
  248.                 break;
  249.             }
  250.         }
  251.                     /* if match not found */
  252.         if (dir->q_num[0] == -1) {
  253.             sprintf(buf, "Can't match \"%s\" in dialing directory", sys_name);
  254.             sprintf(message, "file \"%s\"", dir->d_path);
  255.             error_win(0, buf, message);
  256.         }
  257.         free_ptr(sys_name);
  258.     }
  259.                     /* phone number on the command line */
  260.     else if (number != NULL) {
  261.         dir->name[0] = str_dup(number);
  262.         dir->number[0] = str_dup(number);
  263.         if (baud)
  264.             dir->baud[0] = baud;
  265.         if (parity)
  266.             dir->parity[0] = parity;
  267.         if (data_bits)
  268.             dir->data_bits[0] = data_bits;
  269.         dir->q_num[0] = 0;
  270.         dir->d_cur = 0;
  271.  
  272.         dial_win(25);
  273.         free_ptr(number);
  274.     }
  275.                     /* start terminal dialogue */
  276.     terminal(aux);
  277.     exit(0);
  278. }
  279.  
  280. /*
  281.  * Something dreadful happened...  Clean up the mess we made with the
  282.  * TTY driver and release the phone line.
  283.  */
  284.  
  285. static int
  286. quit()
  287. {
  288.     void cleanup();
  289.  
  290.     cleanup(1);
  291.                     /* never returns... */
  292.     return(0);
  293. }
  294.  
  295. /*
  296.  * Check write permission with the real UID and GID.  Returns a 0 on
  297.  * permission denied, 1 on OK, and 2 on OK-but the file already exists.
  298.  */
  299.  
  300. int
  301. can_write(file)
  302. char *file;
  303. {
  304.     char *p, path[256], *strcpy(), *strrchr();
  305.  
  306.     strcpy(path, file);
  307.                     /* dissect the path component */
  308.     if (p = strrchr(path, '/'))
  309.         *p = '\0';
  310.     else
  311.         strcpy(path, ".");
  312.                     /* if it already exists */
  313.     if (!access(file, 0)) {
  314.         if (!access(file, 2))
  315.             return(OK_BUT_EXISTS);
  316.         return(DENIED);
  317.     }
  318.                     /* if path is writable */
  319.     if (!access(path, 2))
  320.         return(WRITE_OK);
  321.     return(DENIED);
  322. }
  323.  
  324. /*
  325.  * Check the read and write permissions before opening a file.  This
  326.  * is a horrible kludge to work around the fact that a lot of systems
  327.  * that claim to be SVID compatible don't treat setuid(2) and setgid(2)
  328.  * properly.  For example, on a Masscomp, you can't flip-flop back and
  329.  * forth between the real and effective UID/GID.
  330.  */
  331.  
  332. FILE *
  333. uid_fopen(file, mode)
  334. char *file, *mode;
  335. {
  336.     FILE *fp;
  337.  
  338. #ifdef SETUID_BROKE
  339.     switch (*mode) {
  340.         case 'a':
  341.         case 'w':
  342.             switch(can_write(file)) {
  343.                 case DENIED:
  344.                     fp = (FILE *) NULL;
  345.                     break;
  346.                 case OK_BUT_EXISTS:
  347.                     fp = fopen(file, mode);
  348.                     break;
  349.                 case WRITE_OK:
  350.                     fp = fopen(file, mode);
  351.                     chown(file, getuid(), getgid());
  352.                     break;
  353.             }
  354.             break;
  355.         case 'r':
  356.             if (access(file, 4))
  357.                 fp = (FILE *) NULL;
  358.             else
  359.                 fp = fopen(file, mode);
  360.             break;
  361.     }
  362. #else /* SETUID_BROKE */
  363.     int euid, egid;
  364.  
  365.     euid = geteuid();
  366.     egid = getegid();
  367.                     /* abdicate the throne */
  368.     setuid(getuid());
  369.     setgid(getgid());
  370.  
  371.     fp = fopen(file, mode);
  372.                     /* put things back */
  373.     setuid(euid);
  374.     setgid(egid);
  375. #endif /* SETUID_BROKE */
  376.     return(fp);
  377. }
  378.  
  379. /*
  380.  * See if s2 in contained in s1 (case insensitive).  Returns a 1 on yes,
  381.  * and a 0 on no.
  382.  */
  383.  
  384. static int
  385. ci_match(s1, s2)
  386. char *s1, *s2;
  387. {
  388.     int i;
  389.     char str1[128], str2[128], *strstr();
  390.  
  391.                     /* copy the strings to lower case */
  392.     i = 0;
  393.     while(*s1) {
  394.         if (isupper(*s1))
  395.             str1[i++] = tolower(*s1);
  396.         else
  397.             str1[i++] = *s1;
  398.  
  399.         if (i >= 127)
  400.             break;
  401.         s1++;
  402.     }
  403.     str1[i] = '\0';
  404.  
  405.     i = 0;
  406.     while(*s2) {
  407.         if (isupper(*s2))
  408.             str2[i++] = tolower(*s2);
  409.         else
  410.             str2[i++] = *s2;
  411.  
  412.         if (i >= 127)
  413.             break;
  414.         s2++;
  415.     }
  416.     str2[i] = '\0';
  417.                     /* do they match? */
  418.     if (strstr(str1, str2))
  419.         return(1);
  420.     return(0);
  421. }
  422.  
  423. static void
  424. print_usage(err_message)
  425. char *err_message;
  426. {
  427.     void exit();
  428.  
  429.     if (*err_message != '\0')
  430.         fprintf(stderr, "Error: %s\n", err_message);
  431.     fprintf(stderr, "\nUsage: pcomm [-d directory] [-f system name] [-a auxiliary file]\n");
  432.     fprintf(stderr, "             [-e|o|n] [-w word length] [-b baud] [-p phone number]\n\n");
  433.     fprintf(stderr, "Command line options:\n");
  434.     fprintf(stderr, "\t-d use this directory to find Pcomm support files\n");
  435.     fprintf(stderr, "\t-f dial the entry that matches this system name\n");
  436.     fprintf(stderr, "\t-a auxiliary file (script, TTY, or modem)\n\n");
  437.     fprintf(stderr, "The following are used for manual dialing:\n");
  438.     fprintf(stderr, "\t-e use even parity\n");
  439.     fprintf(stderr, "\t-o use odd parity\n");
  440.     fprintf(stderr, "\t-n use no parity\n");
  441.     fprintf(stderr, "\t-w word length (number of data bits 7 or 8)\n");
  442.     fprintf(stderr, "\t-b baud rate (300, 1200, 2400, 4800, 9600, 19200, 38400)\n");
  443.     fprintf(stderr, "\t-p phone number to dial\n");
  444.     exit(1);
  445. }
  446.