📄 main.c
字号:
/* * Pcomm is a public domain telecommunication program for Unix that * is designed to operate similarly to the MSDOS program, ProComm. * ProComm (TM) is copyrighted by Datastorm Technologies, Inc. * * Emmet P. Gray US Army, HQ III Corps & Fort Hood * ...!uunet!uiucuxc!fthood!egray Attn: AFZF-DE-ENV * Directorate of Engineering & Housing * Environmental Management Office * Fort Hood, TX 76544-5057 * * Release v1.0 12 Mar 88 * Release v1.1 21 Aug 88 * Release v1.2 4 Feb 89 * Release v2.0 18 Jul 92 */#include <stdio.h>#include <ctype.h>#include <signal.h>#include <curses.h>#include <sys/types.h>#include <sys/stat.h>#define MAIN#include "config.h"#include "dial_dir.h"#include "extrnl.h"#include "misc.h"#include "modem.h"#include "param.h"#include "status.h"#ifndef OLDCURSES#include <term.h>#else /* OLDCURSES */#ifdef UNIXPC#include <sgtty.h>#endif /* UNIXPC */char tcbuf[1024];struct sgttyb t_mode, c_mode;#ifndef cbreak#define cbreak crmode#endif#endif /* OLDCURSES */struct DIAL_DIR *dir;struct EXTRNL *extrnl;struct MODEM *modem;struct PARAM *param;struct STATUS *status;int fd = -1; /* file descriptor for port */int xmc; /* magic cookie terminal */int msg_status; /* read/write permissions on TTY */char *null_ptr = ""; /* generic char pointer to a null */static int quit(), ci_match();static void print_usage();main(argc, argv)int argc;char *argv[];{ extern char *optarg; int c, i, data_bits; unsigned baud; char *mytty, *ttyname(), *term, *getenv(), *sys_name, parity; char *extra_dir, buf[80], message[80], *str_dup(), *number; char *aux; struct DIAL_DIR *read_dir(); struct EXTRNL *read_extrnl(); struct MODEM *read_modem(); struct PARAM *read_param(); struct STATUS *init(); struct stat stbuf; void exit(), error_win(), vcs_table(), terminal(), free_ptr(); void info();#ifdef OLDCURSES char *tgetstr(), *t, tb[1024]; t = tcbuf;#endif /* OLDCURSES */ signal(SIGINT, SIG_IGN); signal(SIGQUIT, SIG_IGN); signal(SIGTERM, (SIG_TYPE(*) ()) quit); signal(SIGHUP, (SIG_TYPE(*) ()) quit); extra_dir = NULL; sys_name = NULL; aux = NULL; parity = '\0'; baud = 0; data_bits = 0; number = NULL; /* the command line */ while ((c = getopt(argc, argv, "d:f:a:eonw:b:p:")) != EOF) { switch (c) { case 'd': /* the extra directory to search */ extra_dir = str_dup(optarg); break; case 'f': /* the short cut into the dialing dir */ sys_name = str_dup(optarg); break; case 'a': /* auxiliary (script, TTY, or modem) */ aux = str_dup(optarg); break; case 'e': if (parity != '\0') print_usage("Parity values are mutually exclusive"); parity = 'E'; break; case 'o': if (parity != '\0') print_usage("Parity values are mutually exclusive"); parity = 'O'; break; case 'n': if (parity != '\0') print_usage("Parity values are mutually exclusive"); parity = 'N'; break; case 'w': data_bits = atoi(optarg); if (data_bits != 7 && data_bits != 8) print_usage("Unsupported number of word length (data bits)"); break; case 'b': baud = (unsigned int) atoi(optarg); switch (baud) { case 300: case 1200: case 2400: case 4800: case 9600: case 19200: case 38400: break; default: print_usage("Unsupported baud rate"); break; } break; case 'p': number = str_dup(optarg); break; case '?': /* default */ print_usage(""); break; } } /* get terminal type */ term = getenv("TERM"); if (term == NULL || *term == '\0') { fprintf(stderr, "Windows not supported (TERM not defined)\n"); exit(1); } /* see if terminfo entry exists */#ifdef OLDCURSES i = tgetent(tb, term);#else /* OLDCURSES */ setupterm(term, 1, &i);#endif /* OLDCURSES */ if (i != 1) { fprintf(stderr, "Windows not supported (no terminfo data for \"%s\")\n", term); exit(1); } /* minimum screen size */#ifdef OLDCURSES if (tgetnum("co") < 80 || tgetnum("li") < 24) {#else /* OLDCURSES */ if (columns < 80 || lines < 24) {#endif /* OLDCURSES */ fprintf(stderr, "Windows not supported (minimum 80x24 screen required)\n"); exit(1); } /* must have cursor movement */#ifdef OLDCURSES if (tgetstr("cm", &t) == NULL) {#else /* OLDCURSES */ if (cursor_address == NULL) {#endif /* OLDCURSES */ fprintf(stderr, "Windows not supported (terminal too dumb)\n"); exit(1); } /* load magic cookie variable */#ifdef OLDCURSES xmc = tgetnum("sg");#else /* OLDCURSES */ xmc = magic_cookie_glitch;#endif /* OLDCURSES */ /* ok... now let's go! */#ifdef OLDCURSES ioctl(0, TIOCGETP, &t_mode);#endif /* OLDCURSES */ initscr(); nonl(); cbreak(); noecho();#ifdef OLDCURSES ioctl(0, TIOCGETP, &c_mode);#endif /* OLDCURSES */ dir = (struct DIAL_DIR *) NULL; extrnl = (struct EXTRNL *) NULL; param = (struct PARAM *) NULL; modem = (struct MODEM *) NULL; /* display herald if no arguments */ if (argc == 1) { info(AUTO_CLEAR); erase(); refresh(); } /* get "msgs" status */ if (mytty = ttyname(0)) { stat(mytty, &stbuf); msg_status = stbuf.st_mode & 0777; chmod(mytty, 0600); } mvaddstr(12, 31, "Initializing..."); refresh(); /* create the VCS table */ vcs_table(); /* create the status structure */ status = init(extra_dir); /* read the support files */ param = read_param(); dir = read_dir(); extrnl = read_extrnl(); modem = read_modem(); /* warning about screen size */ if (LINES > MAX_ROW || COLS > MAX_COL-1) error_win(0, "Your screen size exceeds an internal Pcomm limit", "The edges of the screen may contain garbage"); /* short-cut to dialing window? */ if (sys_name != NULL) { for (i=1; i<dir->d_entries+1; i++) { if (ci_match(dir->name[i], sys_name)) { dir->q_num[0] = i; dir->d_cur = i; if (!dial_win(25)) aux = dir->aux[dir->d_cur]; break; } } /* if match not found */ if (dir->q_num[0] == -1) { sprintf(buf, "Can't match \"%s\" in dialing directory", sys_name); sprintf(message, "file \"%s\"", dir->d_path); error_win(0, buf, message); } free_ptr(sys_name); } /* phone number on the command line */ else if (number != NULL) { dir->name[0] = str_dup(number); dir->number[0] = str_dup(number); if (baud) dir->baud[0] = baud; if (parity) dir->parity[0] = parity; if (data_bits) dir->data_bits[0] = data_bits; dir->q_num[0] = 0; dir->d_cur = 0; dial_win(25); free_ptr(number); } /* start terminal dialogue */ terminal(aux); exit(0);}/* * Something dreadful happened... Clean up the mess we made with the * TTY driver and release the phone line. */static intquit(){ void cleanup(); cleanup(1); /* never returns... */ return(0);}/* * Check write permission with the real UID and GID. Returns a 0 on * permission denied, 1 on OK, and 2 on OK-but the file already exists. */intcan_write(file)char *file;{ char *p, path[256], *strcpy(), *strrchr(); strcpy(path, file); /* dissect the path component */ if (p = strrchr(path, '/')) *p = '\0'; else strcpy(path, "."); /* if it already exists */ if (!access(file, 0)) { if (!access(file, 2)) return(OK_BUT_EXISTS); return(DENIED); } /* if path is writable */ if (!access(path, 2)) return(WRITE_OK); return(DENIED);}/* * Check the read and write permissions before opening a file. This * is a horrible kludge to work around the fact that a lot of systems * that claim to be SVID compatible don't treat setuid(2) and setgid(2) * properly. For example, on a Masscomp, you can't flip-flop back and * forth between the real and effective UID/GID. */FILE *uid_fopen(file, mode)char *file, *mode;{ FILE *fp;#ifdef SETUID_BROKE switch (*mode) { case 'a': case 'w': switch(can_write(file)) { case DENIED: fp = (FILE *) NULL; break; case OK_BUT_EXISTS: fp = fopen(file, mode); break; case WRITE_OK: fp = fopen(file, mode); chown(file, getuid(), getgid()); break; } break; case 'r': if (access(file, 4)) fp = (FILE *) NULL; else fp = fopen(file, mode); break; }#else /* SETUID_BROKE */ int euid, egid; euid = geteuid(); egid = getegid(); /* abdicate the throne */ setuid(getuid()); setgid(getgid()); fp = fopen(file, mode); /* put things back */ setuid(euid); setgid(egid);#endif /* SETUID_BROKE */ return(fp);}/* * See if s2 in contained in s1 (case insensitive). Returns a 1 on yes, * and a 0 on no. */static intci_match(s1, s2)char *s1, *s2;{ int i; char str1[128], str2[128], *strstr(); /* copy the strings to lower case */ i = 0; while(*s1) { if (isupper(*s1)) str1[i++] = tolower(*s1); else str1[i++] = *s1; if (i >= 127) break; s1++; } str1[i] = '\0'; i = 0; while(*s2) { if (isupper(*s2)) str2[i++] = tolower(*s2); else str2[i++] = *s2; if (i >= 127) break; s2++; } str2[i] = '\0'; /* do they match? */ if (strstr(str1, str2)) return(1); return(0);}static voidprint_usage(err_message)char *err_message;{ void exit(); if (*err_message != '\0') fprintf(stderr, "Error: %s\n", err_message); fprintf(stderr, "\nUsage: pcomm [-d directory] [-f system name] [-a auxiliary file]\n"); fprintf(stderr, " [-e|o|n] [-w word length] [-b baud] [-p phone number]\n\n"); fprintf(stderr, "Command line options:\n"); fprintf(stderr, "\t-d use this directory to find Pcomm support files\n"); fprintf(stderr, "\t-f dial the entry that matches this system name\n"); fprintf(stderr, "\t-a auxiliary file (script, TTY, or modem)\n\n"); fprintf(stderr, "The following are used for manual dialing:\n"); fprintf(stderr, "\t-e use even parity\n"); fprintf(stderr, "\t-o use odd parity\n"); fprintf(stderr, "\t-n use no parity\n"); fprintf(stderr, "\t-w word length (number of data bits 7 or 8)\n"); fprintf(stderr, "\t-b baud rate (300, 1200, 2400, 4800, 9600, 19200, 38400)\n"); fprintf(stderr, "\t-p phone number to dial\n"); exit(1);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -