Subject: v20i071: Pcomm telecommunication package, Part05/08 Newsgroups: comp.sources.unix Sender: sources Approved: rsalz@uunet.UU.NET Submitted-by: fthood!egray Posting-number: Volume 20, Issue 71 Archive-name: pcomm1.2/part05 #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # m_lib.c # macro.c # main.c # matches.c # misc.h # modem.h # modem_break.c # n_shell.c # p_lib.c # param.h # passthru.c # pexit.c # port.c export PATH; PATH=/bin:/usr/bin:$PATH echo shar: "extracting 'm_lib.c'" '(9951 characters)' if test -f 'm_lib.c' then echo shar: "will not over-write existing file 'm_lib.c'" else sed 's/^X//' << \SHAR_EOF > 'm_lib.c' X/* X * Routines to manipulate the pcomm.modem file X */ X X#include X#include "modem.h" X X/* X * Read the modem/TTY database file. Returns a pointer to a static area X * containing the MODEM structure. All modem entries and all TTY entries X * are created regardless of the number of physical entries in the file. X */ X Xstruct MODEM * Xread_modem(extra) Xchar *extra; X{ X extern char *null_ptr; X FILE *fp, *my_fopen(); X int i, tty, mod, line, oops, m_line, start, stop; X char *str_dup(), buf[200], message[80], token[40], *str_tok(), *str; X char *temp_token, *t_sep, *m_sep, *m_letter, *findfile(); X static struct MODEM m; X void error_win(); X X if ((m.m_path = findfile(extra, "pcomm.modem")) == NULL) X error_win(1, "Support file \"pcomm.modem\" is missing", "or no read permission"); X X if (!(fp = my_fopen(m.m_path, "r"))) { X sprintf(buf, "\"%s\" for read", m.m_path); X error_win(1, "Can't open modem/TTY file", buf); X } X X t_sep = ";;\n"; X m_sep = ";;;;\n;;;;;;\n;;;\n"; X m_letter = "abc"; X oops = 0; X tty = 0; X mod = 0; X line = 0; X m_line = 0; X while (fgets(buf, 200, fp) != NULL) { X line++; X if (tty >= NUM_TTY || mod >= NUM_MODEM) X break; X /* get the token */ X if (!(temp_token = str_tok(buf, '='))) { X sprintf(message, "is missing a token at line %d", line); X oops++; X break; X } X if (*temp_token != 'T' && *temp_token != 'M') { X sprintf(message, "is corrupted at line %d", line); X oops++; X break; X } X /* the TTY database */ X if (*temp_token == 'T') { X /* X * This is similar to the "real" strtok() command X * but this one returns a pointer to NULL on a missing X * token. Note the use of the field separator X * array. X */ X for (i=0; i<3; i++) { X if (!(str = str_tok((char *) NULL, t_sep[i]))) { X sprintf(message, "is missing a parameter at line %d", line); X oops++; X break; X } X switch (i) { X case 0: X m.tty[tty] = str_dup(str); X break; X case 1: X m.tname[tty] = str_dup(str); X break; X case 2: X m.init_sp[tty] = atoi(str); X break; X } X } X if (oops) X break; X /* sanity checking */ X sprintf(token, "TTY_%d", tty+1); X if (strcmp(token, temp_token)) { X sprintf(message, "is corrupted at line %d", line); X oops++; X break; X } X tty++; X continue; X } X /* the modem database */ X else { X sprintf(token, "MODEM_%d%c", mod+1, m_letter[m_line]); X if (strcmp(token, temp_token)) { X sprintf(message, "is corrupted at line %d", line); X oops++; X break; X } X /* X * There are three lines to the modem database. They X * are distinguished by the letters a, b, and, c X * appended to the entry number. X */ X switch (m_line) { X case 0: X start = 0; X stop = 5; X break; X case 1: X start = 5; X stop = 12; X break; X case 2: X start = 12; X stop = 16; X break; X } X for (i=start; i= 3) { X m_line = 0; X mod++; X } X } X } X fclose(fp); X X if (oops) { X sprintf(buf, "Modem/TTY database file \"%s\"", m.m_path); X error_win(1, buf, message); X } X m.t_entries = tty; X m.m_entries = mod; X m.t_cur = -1; X m.m_cur = -1; X /* if empty database */ X if (!tty) { X sprintf(buf, "Modem/TTY database file \"%s\"", m.m_path); X error_win(0, buf, "has no TTY data"); X } X if (!mod) { X sprintf(buf, "Modem/TTY database file \"%s\"", m.m_path); X error_win(0, buf, "has no modem data"); X } X /* fill in the rest */ X for (; ttym_path, "w"))) { X sprintf(buf, "\"%s\"", modem->m_path); X error_win(0, "No write permission on modem/TTY database file", buf); X return(1); X } X /* put back the TTY entries */ X for (i=0; it_entries; i++) X fprintf(fp, "TTY_%d=%s;%s;%d\n", i+1, modem->tty[i], X modem->tname[i], modem->init_sp[i]); X X /* put back the modem entries */ X for (i=0; im_entries; i++) { X fprintf(fp, "MODEM_%da=%s;%s;%s;%s;%s\n", i+1, modem->mname[i], X modem->init[i], modem->dial[i], modem->suffix[i], X modem->hang_up[i]); X X fprintf(fp, "MODEM_%db=%c;%s;%s;%s;%s;%s;%s\n", i+1, X modem->auto_baud[i], modem->con_3[i], modem->con_12[i], X modem->con_24[i], modem->con_48[i], modem->con_96[i], X modem->con_192[i]); X X fprintf(fp, "MODEM_%dc=%s;%s;%s;%s\n", i+1, modem->no_con1[i], X modem->no_con2[i], modem->no_con3[i], modem->no_con4[i]); X } X X fclose(fp); X return(0); X} X X/* X * See if the new modem is already in the database. If it's not, create X * a slot for it and update the modem->m_cur variable. X */ X Xvoid Xcreate_modem(str) Xchar *str; X{ X int i; X char *str_rep(), buf[80]; X void error_win(); X /* modem entry already exists? */ X for (i=0; im_entries; i++) { X if (!strcmp(str, modem->mname[i])) X return; X } X /* empty slot available? */ X if (modem->m_entries == NUM_MODEM) { X sprintf(buf, "\"%s\"", modem->m_path); X error_win(0, "No empty modem slots in", buf); X return; X } X /* create a new entry */ X i = modem->m_entries; X modem->mname[i] = str_rep(modem->mname[i], str); X X /* update number of entries */ X modem->m_entries++; X return; X} X X/* X * See if the modem names in the list still need to be in the database. X * If you find a "lost" entry, delete it and collapse the list. X */ X Xvoid Xdel_modem() X{ X extern char *null_ptr; X int i, j, match; X char *str_rep(); X void free_ptr(); X X for (i=0; im_entries; i++) { X match = 0; X for (j=0; jt_entries; j++) { X if (!strcmp(modem->mname[i], modem->tname[j])) { X match++; X break; X } X } X /* found a "lost" modem name */ X if (!match) { X for (j=i; jm_entries-1; j++) { X /* copy the info */ X modem->mname[j] = str_rep(modem->mname[j], modem->mname[j+1]); X modem->init[j] = str_rep(modem->init[j], modem->init[j+1]); X modem->dial[j] = str_rep(modem->dial[j], modem->dial[j+1]); X modem->suffix[j] = str_rep(modem->suffix[j], modem->suffix[j+1]); X modem->hang_up[j] = str_rep(modem->hang_up[j], modem->hang_up[j+1]); X X modem->auto_baud[j] = modem->auto_baud[j+1]; X modem->con_3[j] = str_rep(modem->con_3[j], modem->con_3[j+1]); X modem->con_12[j] = str_rep(modem->con_12[j], modem->con_12[j+1]); X modem->con_24[j] = str_rep(modem->con_24[j], modem->con_24[j+1]); X modem->con_48[j] = str_rep(modem->con_48[j], modem->con_48[j+1]); X modem->con_96[j] = str_rep(modem->con_96[j], modem->con_96[j+1]); X modem->con_192[j] = str_rep(modem->con_192[j], modem->con_192[j+1]); X X modem->no_con1[j] = str_rep(modem->no_con1[j], modem->no_con1[j+1]); X modem->no_con2[j] = str_rep(modem->no_con2[j], modem->no_con2[j+1]); X modem->no_con3[j] = str_rep(modem->no_con3[j], modem->no_con3[j+1]); X modem->no_con4[j] = str_rep(modem->no_con4[j], modem->no_con4[j+1]); X } X j = modem->m_entries -1; X X free_ptr(modem->mname[j]); X free_ptr(modem->init[j]); X free_ptr(modem->dial[j]); X free_ptr(modem->suffix[j]); X free_ptr(modem->hang_up[j]); X X free_ptr(modem->con_3[j]); X free_ptr(modem->con_12[j]); X free_ptr(modem->con_24[j]); X free_ptr(modem->con_48[j]); X free_ptr(modem->con_96[j]); X free_ptr(modem->con_192[j]); X X free_ptr(modem->no_con1[j]); X free_ptr(modem->no_con2[j]); X free_ptr(modem->no_con3[j]); X free_ptr(modem->no_con4[j]); X X /* create an empty entry */ X modem->mname[j] = null_ptr; X modem->init[j] = null_ptr; X modem->dial[j] = null_ptr; X modem->suffix[j] = null_ptr; X modem->hang_up[j] = null_ptr; X X modem->auto_baud[j] = 'Y'; X modem->con_3[j] = null_ptr; X modem->con_12[j] = null_ptr; X modem->con_24[j] = null_ptr; X modem->con_48[j] = null_ptr; X modem->con_96[j] = null_ptr; X modem->con_192[j] = null_ptr; X X modem->no_con1[j] = null_ptr; X modem->no_con2[j] = null_ptr; X modem->no_con3[j] = null_ptr; X modem->no_con4[j] = null_ptr; X X /* update the counts */ X modem->m_entries--; X if (modem->m_cur >= modem->m_entries) X modem->m_cur = -1; X return; X } X } X return; X} SHAR_EOF if test 9951 -ne "`wc -c < 'm_lib.c'`" then echo shar: "error transmitting 'm_lib.c'" '(should have been 9951 characters)' fi fi echo shar: "extracting 'macro.c'" '(5246 characters)' if test -f 'macro.c' then echo shar: "will not over-write existing file 'macro.c'" else sed 's/^X//' << \SHAR_EOF > 'macro.c' X/* X * The keyboard macro feature. Displays (and prompts for editing) the X * macros assigned to the shifted number keys. Prompts for saving X * changes to disk. X */ X X#include X#include X#include "config.h" X#include "misc.h" X#include "param.h" X Xvoid Xmacro() X{ X extern int fd; X WINDOW *ma_win, *newwin(); X int ans, changed; X char *mac, *str_rep(), *mac_prompt(); X X ma_win = newwin(18, 65, 2, 15); X mvwattrstr(ma_win, 1, 25, A_BOLD, "Keyboard Macros"); X horizontal(ma_win, 2, 0, 65); X mvwprintw(ma_win, 4, 0, " %4.4s-! %-50.50s\n", param->ascii_hot, param->mac_1); X wprintw(ma_win, " %4.4s-@ %-50.50s\n", param->ascii_hot, param->mac_2); X wprintw(ma_win, " %4.4s-# %-50.50s\n", param->ascii_hot, param->mac_3); X wprintw(ma_win, " %4.4s-$ %-50.50s\n", param->ascii_hot, param->mac_4); X wprintw(ma_win, " %4.4s-%% %-50.50s\n", param->ascii_hot, param->mac_5); X wprintw(ma_win, " %4.4s-^ %-50.50s\n", param->ascii_hot, param->mac_6); X wprintw(ma_win, " %4.4s-& %-50.50s\n", param->ascii_hot, param->mac_7); X wprintw(ma_win, " %4.4s-* %-50.50s\n", param->ascii_hot, param->mac_8); X wprintw(ma_win, " %4.4s-( %-50.50s\n", param->ascii_hot, param->mac_9); X wprintw(ma_win, " %4.4s-) %-50.50s\n", param->ascii_hot, param->mac_0); X mvwaddstr(ma_win, 15, 5, "Macro key to revise:"); X box(ma_win, VERT, HORZ); X /* on the bottom line */ X mvwaddstr(ma_win, 17, 21, " Press to continue "); X wmove(ma_win, 15, 26); X wrefresh(ma_win); X X changed = 0; X X while ((ans = wgetch(ma_win)) != ESC) { X switch (ans) { X case '!': /* shifted 1 */ X if ((mac = mac_prompt(ans, param->mac_1)) != NULL) { X param->mac_1 = str_rep(param->mac_1, mac); X clear_line(ma_win, 4, 9, TRUE); X mvwattrstr(ma_win, 4, 9, A_BOLD, mac); X changed++; X } X break; X case '@': /* shifted 2 */ X if ((mac = mac_prompt(ans, param->mac_2)) != NULL) { X param->mac_2 = str_rep(param->mac_2, mac); X clear_line(ma_win, 5, 9, TRUE); X mvwattrstr(ma_win, 5, 9, A_BOLD, mac); X changed++; X } X break; X case '#': /* shifted 3 */ X if ((mac = mac_prompt(ans, param->mac_3)) != NULL) { X param->mac_3 = str_rep(param->mac_3, mac); X clear_line(ma_win, 6, 9, TRUE); X mvwattrstr(ma_win, 6, 9, A_BOLD, mac); X changed++; X } X break; X case '$': /* shifted 4 */ X if ((mac = mac_prompt(ans, param->mac_4)) != NULL) { X param->mac_4 = str_rep(param->mac_4, mac); X clear_line(ma_win, 7, 9, TRUE); X mvwattrstr(ma_win, 7, 9, A_BOLD, mac); X changed++; X } X break; X case '%': /* shifted 5 */ X if ((mac = mac_prompt(ans, param->mac_5)) != NULL) { X param->mac_5 = str_rep(param->mac_5, mac); X clear_line(ma_win, 8, 9, TRUE); X mvwattrstr(ma_win, 8, 9, A_BOLD, mac); X changed++; X } X break; X case '^': /* shifted 6 */ X if ((mac = mac_prompt(ans, param->mac_6)) != NULL) { X param->mac_6 = str_rep(param->mac_6, mac); X clear_line(ma_win, 9, 9, TRUE); X mvwattrstr(ma_win, 9, 9, A_BOLD, mac); X changed++; X } X break; X case '&': /* shifted 7 */ X if ((mac = mac_prompt(ans, param->mac_7)) != NULL) { X param->mac_7 = str_rep(param->mac_7, mac); X clear_line(ma_win, 10, 9, TRUE); X mvwattrstr(ma_win, 10, 9, A_BOLD, mac); X changed++; X } X break; X case '*': /* shifted 8 */ X if ((mac = mac_prompt(ans, param->mac_8)) != NULL) { X param->mac_8 = str_rep(param->mac_8, mac); X clear_line(ma_win, 11, 9, TRUE); X mvwattrstr(ma_win, 11, 9, A_BOLD, mac); X changed++; X } X break; X case '(': /* shifted 9 */ X if ((mac = mac_prompt(ans, param->mac_9)) != NULL) { X param->mac_9 = str_rep(param->mac_9, mac); X clear_line(ma_win, 12, 9, TRUE); X mvwattrstr(ma_win, 12, 9, A_BOLD, mac); X changed++; X } X break; X case ')': /* shifted 0 */ X if ((mac = mac_prompt(ans, param->mac_0)) != NULL) { X param->mac_0 = str_rep(param->mac_0, mac); X clear_line(ma_win, 13, 9, TRUE); X mvwattrstr(ma_win, 13, 9, A_BOLD, mac); X changed++; X } X break; X default: X beep(); X break; X } X touchwin(ma_win); X wmove(ma_win, 15, 26); X wrefresh(ma_win); X } X /* if something changed */ X if (changed) { X /* save to disk? */ X if (yes_prompt(ma_win, 15, 30, A_BOLD, "Save to disk")) { X if (up_param()) { X touchwin(ma_win); X wrefresh(ma_win); X } X } X } X if (fd == -1) { X werase(ma_win); X wrefresh(ma_win); X } X delwin(ma_win); X return; X} X X/* X * Sounds like McDonalds doesn't it? Actually, it opens a new window X * and prompts for the new macro. Returns a pointer to the new string. X * Since it uses get_str(), the return value points to a static area. X */ X Xstatic char * Xmac_prompt(key, string) Xchar key, *string; X{ X extern char *null_ptr; X WINDOW *mp_win, *newwin(); X char *new, *get_str(); X X mp_win = newwin(6, 65, 8, 0); X mvwprintw(mp_win, 2, 3, "%4.4s-%c %-50.50s", param->ascii_hot, key, string); X mvwaddstr(mp_win, 3, 5, "New : "); X box(mp_win, VERT, HORZ); X wrefresh(mp_win); X X if ((new = get_str(mp_win, 50, "", "\n")) != NULL) { X /* if CR, return NULL */ X if (*new == '\0') X new = NULL; X /* if space, change to null_ptr */ X if (!strcmp(new, " ")) X new = null_ptr; X } X X werase(mp_win); X wrefresh(mp_win); X delwin(mp_win); X return(new); X} SHAR_EOF if test 5246 -ne "`wc -c < 'macro.c'`" then echo shar: "error transmitting 'macro.c'" '(should have been 5246 characters)' fi fi echo shar: "extracting 'main.c'" '(7580 characters)' if test -f 'main.c' then echo shar: "will not over-write existing file 'main.c'" else sed 's/^X//' << \SHAR_EOF > 'main.c' X/* X * Pcomm is a public domain telecommunication program for Unix that X * is designed to operate similar to the MSDOS program, ProComm. X * ProComm (TM) is copyrighted by Datastorm Technologies, Inc. X * X * Emmet P. Gray US Army, HQ III Corps & Fort Hood X * ...!uunet!uiucuxc!fthood!egray Attn: AFZF-DE-ENV X * Directorate of Engineering & Housing X * Environmental Management Office X * Fort Hood, TX 76544-5057 X * X * Release v1.0 12 Mar 88 X * Release v1.1 21 Aug 88 X * Release v1.2.0 4 Feb 89 X */ X X#include X#include X#include X#include X#include X#include X#define MAIN X#include "config.h" X#include "dial_dir.h" X#include "extrnl.h" X#include "misc.h" X#include "modem.h" X#include "param.h" X#include "status.h" X X#ifndef OLDCURSES X#include X#else /* OLDCURSES */ X#ifdef UNIXPC X#include X#endif /* UNIXPC */ Xchar tcbuf[1024]; Xstruct sgttyb t_mode, c_mode; X#define cbreak crmode X#endif /* OLDCURSES */ X X#ifdef SHAREDMEM Xint shm_id; X#endif /* SHAREDMEM */ X Xstruct DIAL_DIR *dir; Xstruct EXTRNL *extrnl; Xstruct MODEM *modem; Xstruct PARAM *param; Xstruct STATUS *status; X Xint fd = -1; /* file descriptor for port */ Xint xmc; /* magic cookie terminal */ Xint msg_status; /* read/write permissions on TTY */ Xchar *null_ptr = ""; /* generic null pointer */ X Xmain(argc, argv) Xint argc; Xchar *argv[]; X{ X extern char *optarg; X int c, i, code, quit(); X char *mytty, *ttyname(), *term, *getenv(), *sys_name, *str_dup(); X char *extra_dir, buf[80], message[80]; X struct DIAL_DIR *read_dir(); X struct EXTRNL *read_extrnl(); X struct MODEM *read_modem(); X struct PARAM *read_param(); X struct STATUS *init(); X struct stat stbuf; X void exit(), error_win(), free_ptr(); X#ifdef OLDCURSES X char *tgetstr(), *t, tb[1024]; X t = tcbuf; X#endif /* OLDCURSES */ X X signal(SIGINT, SIG_IGN); X signal(SIGQUIT, SIG_IGN); X signal(SIGTERM, quit); X signal(SIGHUP, quit); X X sys_name = NULL; X extra_dir = NULL; X /* the command line */ X while ((c = getopt(argc, argv, "d:f:")) != EOF) { X switch (c) { X case 'd': /* the extra directory to search */ X extra_dir = str_dup(optarg); X break; X case 'f': /* the short cut into the dialing dir */ X sys_name = str_dup(optarg); X break; X case '?': /* default */ X fprintf(stderr, "Usage: pcomm [-d directory] [-f system name]\n"); X exit(1); X break; X } X } X /* get terminal type */ X term = getenv("TERM"); X if (term == NULL || *term == '\0') { X fprintf(stderr, "Windows not supported (TERM not defined)\n"); X exit(1); X } X /* see if terminfo entry exists */ X#ifdef OLDCURSES X i = tgetent(tb, term); X#else /* OLDCURSES */ X setupterm(term, 1, &i); X#endif /* OLDCURSES */ X X if (i != 1) { X fprintf(stderr, "Windows not supported (no terminfo data for \"%s\")\n", term); X exit(1); X } X /* minimum screen size */ X#ifdef OLDCURSES X if (tgetnum("co") < 80 || tgetnum("li") < 24) { X#else /* OLDCURSES */ X if (columns < 80 || lines < 24) { X#endif /* OLDCURSES */ X fprintf(stderr, "Windows not supported (minimum 80x24 screen required)\n"); X exit(1); X } X /* must have cursor movement */ X#ifdef OLDCURSES X if (tgetstr("cm", &t) == NULL) { X#else /* OLDCURSES */ X if (cursor_address == NULL) { X#endif /* OLDCURSES */ X fprintf(stderr, "Windows not supported (terminal too dumb)\n"); X exit(1); X } X /* load magic cookie variable */ X#ifdef OLDCURSES X xmc = tgetnum("sg"); X#else /* OLDCURSES */ X xmc = magic_cookie_glitch; X#endif /* OLDCURSES */ X /* ok... now let's go! */ X#ifdef OLDCURSES X ioctl(0, TIOCGETP, &t_mode); X#endif /* OLDCURSES */ X X initscr(); X nonl(); X cbreak(); X noecho(); X X#ifdef OLDCURSES X ioctl(0, TIOCGETP, &c_mode); X#endif /* OLDCURSES */ X X dir = (struct DIAL_DIR *) NULL; X extrnl = (struct EXTRNL *) NULL; X param = (struct PARAM *) NULL; X modem = (struct MODEM *) NULL; X /* show the herald, return status */ X status = init(sys_name); X /* get "msgs" status */ X mytty = ttyname(0); X stat(mytty, &stbuf); X msg_status = stbuf.st_mode & 0777; X chmod(mytty, 0600); X X mvaddstr(12, 31, "Initializing..."); X refresh(); X /* read the support files */ X param = read_param(extra_dir); X dir = read_dir(extra_dir); X extrnl = read_extrnl(extra_dir); X modem = read_modem(extra_dir); X X /* warning about screen size */ X if (LINES > MAX_ROW || COLS > MAX_COL-1) X error_win(0, "Your screen size exceeds an internal Pcomm limit", X "The edges of the screen may contain garbage"); X X /* short-cut to dialing window? */ X code = 0; X if (sys_name != NULL) { X for (i=1; id_entries+1; i++) { X if (match_ci(dir->name[i], sys_name)) { X dir->q_num[0] = i; X dir->d_cur = i; X break; X } X } X /* if match is found */ X if (dir->q_num[0] != -1) X code = dial_win(); X else { X sprintf(buf, "Can't match \"%s\" in dialing directory", sys_name); X sprintf(message, "file \"%s\"", dir->d_path); X error_win(0, buf, message); X } X free_ptr(sys_name); X } X /* start terminal dialogue */ X terminal(extra_dir, code); X exit(0); X} X X/* X * Something dreadful happened... Clean up the mess we made with the X * TTY driver and release the phone line. X */ X Xint Xquit() X{ X void cleanup(); X X cleanup(1); X /* never returns... */ X return(0); X} X X/* X * Check write permission with the real UID and GID. Returns a 0 on X * permission denied, 1 on OK, and 2 on OK-but the file already exists. X */ X Xint Xcan_write(file) Xchar *file; X{ X char *p, path[256], *strcpy(), *strrchr(); X X strcpy(path, file); X /* dissect the path component */ X if (p = strrchr(path, '/')) X *p = '\0'; X else X strcpy(path, "."); X /* if it already exists */ X if (!access(file, 0)) { X if (!access(file, 2)) X return(OK_BUT_EXISTS); X return(DENIED); X } X /* if path is writable */ X if (!access(path, 2)) X return(WRITE_OK); X return(DENIED); X} X X/* X * Check the read and write permissions before opening a file. This X * is a horrible kludge to work around the fact that a lot of systems X * that claim to be SVID compatible don't treat setuid(2) and setgid(2) X * properly. For example, on a Masscomp, you can't flip-flop back and X * forth between the real and effective UID/GID. X */ X XFILE * Xmy_fopen(file, mode) Xchar *file, *mode; X{ X FILE *fp; X X#ifdef SETUGID X#ifdef SETUID_BROKE X switch (*mode) { X case 'a': X case 'w': X switch(can_write(file)) { X case DENIED: X fp = (FILE *) NULL; X break; X case OK_BUT_EXISTS: X fp = fopen(file, mode); X break; X case WRITE_OK: X fp = fopen(file, mode); X chown(file, getuid(), getgid()); X break; X } X break; X case 'r': X if (access(file, 4)) X fp = (FILE *) NULL; X else X fp = fopen(file, mode); X break; X } X#else /* SETUID_BROKE */ X int euid, egid; X X euid = geteuid(); X egid = getegid(); X /* abdicate the throne */ X setuid(getuid()); X setgid(getgid()); X X fp = fopen(file, mode); X /* put things back */ X setuid(euid); X setgid(egid); X#endif /* SETUID_BROKE */ X return(fp); X#else /* SETUGID */ X return(fopen(file, mode)); X#endif /* SETUGID */ X} X X/* X * See if s2 in contained in s1 (case insensitive). Returns a 1 on yes, X * and a 0 on no. X */ X Xmatch_ci(s1, s2) Xchar *s1, *s2; X{ X int i; X char str1[128], str2[128], *strstr(); X X /* copy the strings to lower case */ X i = 0; X while(*s1) { X if (isupper(*s1)) X str1[i++] = tolower(*s1); X else X str1[i++] = *s1; X X if (i >= 127) X break; X s1++; X } X str1[i] = '\0'; X X i = 0; X while(*s2) { X if (isupper(*s2)) X str2[i++] = tolower(*s2); X else X str2[i++] = *s2; X X if (i >= 127) X break; X s2++; X } X str2[i] = '\0'; X /* do they match? */ X if (strstr(str1, str2)) X return(1); X return(0); X} SHAR_EOF if test 7580 -ne "`wc -c < 'main.c'`" then echo shar: "error transmitting 'main.c'" '(should have been 7580 characters)' fi fi echo shar: "extracting 'matches.c'" '(754 characters)' if test -f 'matches.c' then echo shar: "will not over-write existing file 'matches.c'" else sed 's/^X//' << \SHAR_EOF > 'matches.c' X/* X * See if two strings match. Returns a 0 on success, and a 1 on failure. X * This is an external program to be used in shell scripts. X */ X X#define STRSTR X X#include X Xmain(argc, argv) Xint argc; Xchar *argv[]; X{ X char *strstr(); X void exit(); X X if (argc != 3) { X fprintf(stderr, "Usage: matches string1 string2\n"); X exit(-1); X } X X if (strstr(argv[1], argv[2])) X exit(0); X exit(1); X} X X#ifdef STRSTR X/* X * Return a pointer to the first occurance of string str2 in str1. X * Returns a NULL if str2 is not in str1. X */ X Xchar * Xstrstr(str1, str2) Xchar *str1, *str2; X{ X int len; X X len = strlen(str2); X while (*str1) { X if (*str2 == *str1) { X if (!strncmp(str2, str1, len)) X return(str1); X } X str1++; X } X return(NULL); X} X#endif /* STRSTR */ SHAR_EOF if test 754 -ne "`wc -c < 'matches.c'`" then echo shar: "error transmitting 'matches.c'" '(should have been 754 characters)' fi fi echo shar: "extracting 'misc.h'" '(1549 characters)' if test -f 'misc.h' then echo shar: "will not over-write existing file 'misc.h'" else sed 's/^X//' << \SHAR_EOF > 'misc.h' X/* X * Definitions to support the home-grown curses(3) functions and to make X * the old curses(3) routines happy. ("config.h" must be included first). X */ X X#define mvwattrstr(w,y,x,a,s) (wmove(w,y,x)==ERR?ERR:wattrstr(w,a,s)) X#define mvwattrch(w,y,x,a,c) (wmove(w,y,x)==ERR?ERR:wattrch(w,a,c)) X#define mvwattrnum(w,y,x,a,n) (wmove(w,y,x)==ERR?ERR:wattrnum(w,a,n)) X#define mvattrstr(y,x,a,s) (wmove(stdscr,y,x)==ERR?ERR:wattrstr(stdscr,a,s)) X#define mvattrch(y,x,a,c) (wmove(stdscr,y,x)==ERR?ERR:wattrch(stdscr,a,c)) X#define mvattrnum(y,x,a,n) (wmove(stdscr,y,x)==ERR?ERR:wattrnum(stdscr,a,n)) X#define attrstr(a,s) wattrstr(stdscr,a,s) X#define attrch(a,c) wattrch(stdscr,a,c) X#define attrnum(a,n) wattrnum(stdscr,a,n) X X#ifdef OLDCURSES X#ifdef NOPROMOTE X#define A_BOLD 0 X#define A_BLINK 0 X#define A_REVERSE 1 X#define A_DIM 0 X#define A_STANDOUT 1 X#define A_UNDERLINE 0 X#else /* NOPROMOTE */ X#define A_BOLD 1 X#define A_BLINK 1 X#define A_REVERSE 1 X#define A_DIM 1 X#define A_STANDOUT 1 X#define A_UNDERLINE 1 X#endif /* NOPROMOTE */ X#endif /* OLDCURSES */ X X#ifdef OLDCURSES Xtypedef char chtype; X#endif /* OLDCURSES */ X X#ifdef ACS_HLINE X#define VERT (chtype)0 X#define HORZ (chtype)0 X#else /* ACS_HLINE */ X#define VERT (chtype)'|' X#define HORZ (chtype)'-' X#define ACS_VLINE (chtype)'|' X#define ACS_HLINE (chtype)'-' X#endif /* ACS_HLINE */ X X/* X * Other miscellaneous stuff X */ X X#define BEL 7 X#define BS 8 X#define ESC 27 X#define DEL 127 X X#define MANUAL_CLEAR 0 X#define AUTO_CLEAR 1 X X#define DENIED 0 X#define WRITE_OK 1 X#define OK_BUT_EXISTS 2 SHAR_EOF if test 1549 -ne "`wc -c < 'misc.h'`" then echo shar: "error transmitting 'misc.h'" '(should have been 1549 characters)' fi fi echo shar: "extracting 'modem.h'" '(1538 characters)' if test -f 'modem.h' then echo shar: "will not over-write existing file 'modem.h'" else sed 's/^X//' << \SHAR_EOF > 'modem.h' X/* X * The modem and TTY databases. The first 3 elements make up the TTY X * database, the next 16 make up the modem database. A "tname" in common X * with a "mname" link the two together. X */ X X#define NUM_TTY 10 X#define NUM_MODEM 10 X Xstruct MODEM { X char *tty[NUM_TTY]; /* TTY names */ X char *tname[NUM_TTY]; /* modem name */ X int init_sp[NUM_TTY]; /* initialization baud rate */ X X char *mname[NUM_MODEM]; /* modem name (matches tname above) */ X char *init[NUM_MODEM]; /* initialization */ X char *dial[NUM_MODEM]; /* dial command */ X char *suffix[NUM_MODEM]; /* dialing command suffix */ X char *hang_up[NUM_MODEM]; /* hang up the modem */ X char auto_baud[NUM_MODEM]; /* should we sync baud rates? */ X char *con_3[NUM_MODEM]; /* 300 baud connect message */ X char *con_12[NUM_MODEM]; /* 1200 baud connect message */ X char *con_24[NUM_MODEM]; /* 2400 baud connect message */ X char *con_48[NUM_MODEM]; /* 4800 baud connect message */ X char *con_96[NUM_MODEM]; /* 9600 baud connect message */ X char *con_192[NUM_MODEM]; /* 19200 baud connect message */ X char *no_con1[NUM_MODEM]; /* no connect #1 */ X char *no_con2[NUM_MODEM]; /* no connect #2 */ X char *no_con3[NUM_MODEM]; /* no connect #3 */ X char *no_con4[NUM_MODEM]; /* no connect #4 */ X X int t_entries; /* number of TTY entries */ X int m_entries; /* number of modem entries */ X int t_cur; /* current TTY entry number */ X int m_cur; /* current modem entry number */ X X char *m_path; /* path to the pcomm.modem file */ X}; X X#ifndef MAIN Xextern struct MODEM *modem; X#endif /* MAIN */ SHAR_EOF if test 1538 -ne "`wc -c < 'modem.h'`" then echo shar: "error transmitting 'modem.h'" '(should have been 1538 characters)' fi fi echo shar: "extracting 'modem_break.c'" '(407 characters)' if test -f 'modem_break.c' then echo shar: "will not over-write existing file 'modem_break.c'" else sed 's/^X//' << \SHAR_EOF > 'modem_break.c' X/* X * Send a modem break. This is an external program to be used in shell X * scripts. X */ X X#include X#ifdef BSD X#include X#else /* BSD */ X#include X#endif /* BSD */ X Xmain() X{ X unsigned int sleep(); X X#ifdef BSD X ioctl(1, TIOCSBRK, (struct sgttyb *) 0); X sleep(1); X return(ioctl(1, TIOCCBRK, (struct sgttyb *) 0)); X#else /* BSD */ X return(ioctl(1, TCSBRK, 0)); X#endif /* BSD */ X} SHAR_EOF if test 407 -ne "`wc -c < 'modem_break.c'`" then echo shar: "error transmitting 'modem_break.c'" '(should have been 407 characters)' fi fi echo shar: "extracting 'n_shell.c'" '(1336 characters)' if test -f 'n_shell.c' then echo shar: "will not over-write existing file 'n_shell.c'" else sed 's/^X//' << \SHAR_EOF > 'n_shell.c' X/* X * Spawn a "native" shell. Native means the shell found in the SHELL X * environmental variable. X */ X X#include X#include X#include X#include "config.h" X Xvoid Xn_shell() X{ X WINDOW *sh_win, *newwin(); X SIG_TYPE (*istat)(), (*qstat)(); X int sig_status, spid, w; X char *shell, *shellpath, *getenv(), *strrchr(); X unsigned int sleep(); X void _exit(); X /* a full window */ X sh_win = newwin(LINES, COLS, 0, 0); X X touchwin(sh_win); X waddstr(sh_win, "Pcomm <=> Unix gateway, use ^D or 'exit' to return\n"); X wrefresh(sh_win); X /* out of curses mode */ X resetterm(); X X shellpath = getenv("SHELL"); X if (shellpath == NULL || *shellpath == '\0') X shellpath = "/bin/sh"; X X if (shell = strrchr(shellpath, '/')) X shell++; X else { X shellpath = "/bin/sh"; X shell = "sh"; X } X X if (!(spid = fork())) { X signal(SIGINT, SIG_DFL); X signal(SIGQUIT, SIG_DFL); X#ifdef SETUGID X setgid(getgid()); X setuid(getuid()); X#endif /* SETUGID */ X execl(shellpath, shell, "-i", (char *) 0); X _exit(1); X } X istat = signal(SIGINT, SIG_IGN); X qstat = signal(SIGQUIT, SIG_IGN); X X while ((w = wait(&sig_status)) != spid && w != -1) X ; X X signal(SIGINT, istat); X signal(SIGQUIT, qstat); X /* back to curses mode */ X sleep(1); X fixterm(); X X clearok(curscr, TRUE); X werase(sh_win); X wrefresh(sh_win); X delwin(sh_win); X return; X} SHAR_EOF if test 1336 -ne "`wc -c < 'n_shell.c'`" then echo shar: "error transmitting 'n_shell.c'" '(should have been 1336 characters)' fi fi echo shar: "extracting 'p_lib.c'" '(7337 characters)' if test -f 'p_lib.c' then echo shar: "will not over-write existing file 'p_lib.c'" else sed 's/^X//' << \SHAR_EOF > 'p_lib.c' X/* X * Routines to manipulate the pcomm.param file. X */ X X#include X#include "param.h" X X/* X * Read the parameter structure from the pcomm.param file. Returns a X * pointer to a static area containing the PARAM structure. All errors X * are fatal. X */ X Xstruct PARAM * Xread_param(extra) Xchar *extra; X{ X FILE *fp, *my_fopen(); X int i, line, oops; X char buf[200], *temp_token, *str, *str_dup(), *findfile(); X char message[80], *str_tok(); X static char *token[NUM_PARAM] = {"D_BAUD", "D_PARITY", "D_DBITS", X "D_SBITS", "HOT", "ASCII_HOT", "D_DUPLEX", "FLOW", "CR_IN", "CR_OUT", X "LOGFILE", "DUMPFILE", "STRIP", "PAUSE_CHAR", "CR_CHAR", "CTRL_CHAR", X "ESC_CHAR", "BRK_CHAR", "ABORT", "C_DELAY", "R_DELAY", "LECHO", X "EXPAND", "CR_DELAY", "PACE", "CR_UP", "LF_UP", "TIMER", "CR_DN", X "LF_DN", "LD_PLUS", "LD_MINUS", "LD_AT", "LD_POUND", "MAC_1", X "MAC_2", "MAC_3", "MAC_4", "MAC_5", "MAC_6", "MAC_7", "MAC_8", X "MAC_9", "MAC_0"}; X static struct PARAM p; X void error_win(); X X if ((p.p_path = findfile(extra, "pcomm.param")) == NULL) X error_win(1, "Support file \"pcomm.param\" is missing", "or no read permission"); X X if (!(fp = my_fopen(p.p_path, "r"))) { X sprintf(buf, "\"%s\" for read", p.p_path); X error_win(1, "Can't open parameter file", buf); X } X X oops = 0; X line = 0; X for (i=0; ip_path, "w"))) { X sprintf(buf, "\"%s\"", param->p_path); X error_win(0, "No write permission on parameter file", buf); X return(1); X } X X fprintf(fp, "D_BAUD=%d\n", param->d_baud); X fprintf(fp, "D_PARITY=%c\n", param->d_parity); X fprintf(fp, "D_DBITS=%d\n", param->d_dbits); X fprintf(fp, "D_SBITS=%d\n", param->d_sbits); X fprintf(fp, "HOT=%d\n", param->hot); X fprintf(fp, "ASCII_HOT=%s\n", param->ascii_hot); X fprintf(fp, "D_DUPLEX=%s\n", param->d_duplex); X fprintf(fp, "FLOW=%s\n", param->flow); X fprintf(fp, "CR_IN=%s\n", param->cr_in); X fprintf(fp, "CR_OUT=%s\n", param->cr_out); X fprintf(fp, "LOGFILE=%s\n", param->logfile); X fprintf(fp, "DUMPFILE=%s\n", param->dumpfile); X fprintf(fp, "STRIP=%s\n", param->strip); X fprintf(fp, "PAUSE_CHAR=%c\n", param->pause_char); X fprintf(fp, "CR_CHAR=%c\n", param->cr_char); X fprintf(fp, "CTRL_CHAR=%c\n", param->ctrl_char); X fprintf(fp, "ESC_CHAR=%c\n", param->esc_char); X fprintf(fp, "BRK_CHAR=%c\n", param->brk_char); X fprintf(fp, "ABORT=%s\n", param->abort); X fprintf(fp, "C_DELAY=%d\n", param->c_delay); X fprintf(fp, "R_DELAY=%d\n", param->r_delay); X fprintf(fp, "LECHO=%s\n", param->lecho); X fprintf(fp, "EXPAND=%s\n", param->expand); X fprintf(fp, "CR_DELAY=%d\n", param->cr_delay); X fprintf(fp, "PACE=%s\n", param->pace); X fprintf(fp, "CR_UP=%s\n", param->cr_up); X fprintf(fp, "LF_UP=%s\n", param->lf_up); X fprintf(fp, "TIMER=%d\n", param->timer); X fprintf(fp, "CR_DN=%s\n", param->cr_dn); X fprintf(fp, "LF_DN=%s\n", param->lf_dn); X fprintf(fp, "LD_PLUS=%s\n", param->ld_plus); X fprintf(fp, "LD_MINUS=%s\n", param->ld_minus); X fprintf(fp, "LD_AT=%s\n", param->ld_at); X fprintf(fp, "LD_POUND=%s\n", param->ld_pound); X fprintf(fp, "MAC_1=%s\n", param->mac_1); X fprintf(fp, "MAC_2=%s\n", param->mac_2); X fprintf(fp, "MAC_3=%s\n", param->mac_3); X fprintf(fp, "MAC_4=%s\n", param->mac_4); X fprintf(fp, "MAC_5=%s\n", param->mac_5); X fprintf(fp, "MAC_6=%s\n", param->mac_6); X fprintf(fp, "MAC_7=%s\n", param->mac_7); X fprintf(fp, "MAC_8=%s\n", param->mac_8); X fprintf(fp, "MAC_9=%s\n", param->mac_9); X fprintf(fp, "MAC_0=%s\n", param->mac_0); X X fclose(fp); X return(0); X} SHAR_EOF if test 7337 -ne "`wc -c < 'p_lib.c'`" then echo shar: "error transmitting 'p_lib.c'" '(should have been 7337 characters)' fi fi echo shar: "extracting 'param.h'" '(2757 characters)' if test -f 'param.h' then echo shar: "will not over-write existing file 'param.h'" else sed 's/^X//' << \SHAR_EOF > 'param.h' X/* X * The standard Pcomm parameters. Everything can be altered by using one X * of Pcomm's menus. Although editing by hand is not encouraged, the X * pcomm.param file is just an ASCII file. X */ X X#define MAX_CDELAY 120 X#define MIN_CDELAY 10 X#define MAX_PAUSE 120 X#define MIN_PAUSE 1 X#define MAX_TIMER 20 X#define MIN_TIMER 2 X X#define NUM_PARAM 44 X#define LINE_SET 0 X#define TERM_SETUP 4 X#define GEN_SETUP 10 X#define DELAY_TIMES 19 X#define ASCII_SETUP 21 X#define LD_CODES 30 X#define MACROS 34 X Xstruct PARAM { X /* 0-3 used in ls_menu() */ X int d_baud; /* default baud rate */ X char d_parity; /* default parity */ X int d_dbits; /* default data bits */ X int d_sbits; /* default stop bits */ X X /* 4-9 used in term_setup() */ X int hot; /* the decimal code for the hot key */ X char *ascii_hot; /* ascii representation of hot key */ X char *d_duplex; /* default duplex */ X char *flow; /* flow control */ X char *cr_in; /* send as carriage return */ X char *cr_out; /* receive carriage return as */ X X /* 10-18 used in gen_setup() */ X char *logfile; /* default log file */ X char *dumpfile; /* default screen dump file */ X char *strip; /* strip high bit (translate table) */ X char pause_char; /* pause char synonym */ X char cr_char; /* carriage return char synonym */ X char ctrl_char; /* ctrl char synonym */ X char esc_char; /* escape char synonym */ X char brk_char; /* modem break synonym */ X char *abort; /* destination of aborted downloads */ X X /* 19-20 used in gen_setup() & delay_times() */ X int c_delay; /* connect delay time */ X int r_delay; /* redial delay time */ X X /* 21-29 used in axfer_setup() */ X char *lecho; /* echo locally? */ X char *expand; /* expand blank lines? */ X int cr_delay; /* carriage return delay (ms) */ X char *pace; /* pace the output? */ X char *cr_up; /* send carriage return as */ X char *lf_up; /* send line feed as */ X int timer; /* transfer timeout */ X char *cr_dn; /* receive carriage return as */ X char *lf_dn; /* receive line feed as */ X X /* 30-33 used in d_revise() */ X char *ld_plus; /* + long distance code */ X char *ld_minus; /* - long distance code */ X char *ld_at; /* @ long distance code */ X char *ld_pound; /* # long distance code */ X X /* 34-43 used in macro() */ X char *mac_1; /* shifted 1 macro */ X char *mac_2; /* shifted 2 macro */ X char *mac_3; /* shifted 3 macro */ X char *mac_4; /* shifted 4 macro */ X char *mac_5; /* shifted 5 macro */ X char *mac_6; /* shifted 6 macro */ X char *mac_7; /* shifted 7 macro */ X char *mac_8; /* shifted 8 macro */ X char *mac_9; /* shifted 9 macro */ X char *mac_0; /* shifted 0 macro */ X X char *p_path; /* path to the pcomm.param file */ X}; X X#ifndef MAIN Xextern struct PARAM *param; X#endif /* MAIN */ SHAR_EOF if test 2757 -ne "`wc -c < 'param.h'`" then echo shar: "error transmitting 'param.h'" '(should have been 2757 characters)' fi fi echo shar: "extracting 'passthru.c'" '(2489 characters)' if test -f 'passthru.c' then echo shar: "will not over-write existing file 'passthru.c'" else sed 's/^X//' << \SHAR_EOF > 'passthru.c' X/* X * A transparent "pass-thru" mode, designed to allow binary transfers X * between 3 machines (with the middle machine in the pass-thru mode). X * A non-zero return code means the input routine should be restarted. X */ X X#include X#include X#include X#include "config.h" X#include "misc.h" X X#ifdef BSD X#include Xjmp_buf cp_buf; X#endif /* BSD */ X Xint Xpass_thru() X{ X extern int fd; X WINDOW *pt_win, *newwin(); X int num; X void cpio(), error_win(); X X pt_win = newwin(5, 70, 5, 5); X X mvwaddstr(pt_win, 2, 4, "Enter the expiration time (5-60 sec): "); X box(pt_win, VERT, HORZ); X X mvwattrstr(pt_win, 0, 3, A_BOLD, " Pass Through Mode "); X wmove(pt_win, 2, 43); X wrefresh(pt_win); X /* get the answer */ X while ((num = get_num(pt_win, 2)) != -1) { X /* out of bounds */ X if (num < 5 || num > 60) { X beep(); X clear_line(pt_win, 2, 43, TRUE); X wmove(pt_win, 2, 43); X wrefresh(pt_win); X } X else { X werase(pt_win); X wrefresh(pt_win); X delwin(pt_win); X X if (fd == -1) { X error_win(0, "Not currently connected to any host", ""); X return(0); X } X X touchwin(stdscr); X refresh(); X X cpio((unsigned int) num); X return(1); X } X } X if (fd == -1) { X werase(pt_win); X wrefresh(pt_win); X } X delwin(pt_win); X return(0); X} X X/* X * Copy the stdin to the TTYout and copy the TTYin to the stdout. Uses X * multi character reads. I'm not too concerned about the excess baggage X * caused by the entire image being forked... this feature won't be used X * that often. X */ X Xstatic int cp_flag; X Xstatic void Xcpio(num) Xunsigned int num; X{ X extern int fd; X int cpid, n, cp_force(); X char buf[CLIST_SIZ]; X unsigned int alarm(), sleep(); X void line_set(), xmodem_mode(), input_off(); X X /* out of curses mode */ X resetterm(); X X input_off(); X xmodem_mode(0); X xmodem_mode(fd); X X /* copy the TTYin to stdout */ X if (!(cpid = fork())) { X while (1) { X n = read(fd, buf, CLIST_SIZ); X write(1, buf, n); X } X } X X cp_flag = 0; X signal(SIGALRM, cp_force); X /* copy the stdin to TTYout */ X while (1) { X alarm(num); X#ifdef BSD X if (setjmp(cp_buf)) X break; X#endif /* BSD */ X n = read(0, buf, CLIST_SIZ); X if (cp_flag) X break; X write(fd, buf, n); X } X kill(cpid, SIGKILL); X /* back to curses mode */ X sleep(1); X fixterm(); X beep(); X line_set(); X clearok(curscr, TRUE); X return; X} X X/* ARGSUSED */ Xstatic int Xcp_force(dummy) X{ X#ifdef BSD X longjmp(cp_buf, 1); X#else /* BSD */ X signal(SIGALRM, cp_force); X cp_flag = 1; X#endif /* BSD */ X} SHAR_EOF if test 2489 -ne "`wc -c < 'passthru.c'`" then echo shar: "error transmitting 'passthru.c'" '(should have been 2489 characters)' fi fi echo shar: "extracting 'pexit.c'" '(2579 characters)' if test -f 'pexit.c' then echo shar: "will not over-write existing file 'pexit.c'" else sed 's/^X//' << \SHAR_EOF > 'pexit.c' X/* X * Exit Pcomm. A user requested abort. There are a lot of things to do X * before we exit! X */ X X#include X#include X#include "config.h" X#include "dial_dir.h" X#include "misc.h" X#include "param.h" X#include "status.h" X X#ifdef SHAREDMEM X#include X#include X#include X#endif /* SHAREDMEM */ X Xvoid Xpexit() X{ X extern int fd; X WINDOW *ex_win, *newwin(); X void cleanup(), st_line(); X X ex_win = newwin(5, 33, 3, 7); X X box(ex_win, VERT, HORZ); X mvwattrstr(ex_win, 0, 3, A_BOLD, " Exit "); X if (yes_prompt(ex_win, 2, 4, A_BLINK, "Exit to Unix")) { X st_line(" exiting"); X cleanup(0); X } X if (fd == -1) { X werase(ex_win); X wrefresh(ex_win); X } X delwin(ex_win); X return; X} X X/* X * Do the clean up detail before we exit. Only the status structure X * is guaranteed to exit. X */ X Xvoid Xcleanup(val) Xint val; X{ X extern int msg_status; X void release_port(), input_off(), exit(); X char *ttyname(); X#ifdef SHAREDMEM X extern int shm_id; X void perror(); X#endif /* SHAREDMEM */ X /* kill the input routine */ X input_off(); X /* release the port */ X release_port(QUIET); X /* zap the virtual screen */ X#ifdef SHAREDMEM X if (shmdt((char *) status) < 0) X perror("shmdt"); X if (shmctl(shm_id, IPC_RMID, (struct shmid_ds *) NULL) < 0) X perror("shmctl"); X#else /* SHAREDMEM */ X unlink(status->vs_path); X#endif /* SHAREDMEM */ X X /* X * If we die an un-natural death (such as a SIGHUP on the loss of X * the controlling terminal) we won't have a terminal to mess with. X */ X if (isatty(0)) { X touchwin(stdscr); X clear(); X refresh(); X endwin(); X /* return the TTY chmod */ X chmod(ttyname(0), msg_status); X } X exit(val); X} X X/* X * Open a window to display an error message. Handles both fatal and X * non-fatal errors X */ X Xvoid Xerror_win(code, line_one, line_two) Xint code; Xchar *line_one, *line_two; X{ X WINDOW *e_win, *newwin(); X void cleanup(), st_line(); X X /* make sure we're in curses mode */ X fixterm(); X e_win = newwin(7, 70, 9, 5); X /* display the nasty note */ X mvwaddstr(e_win, 2, 4, line_one); X mvwaddstr(e_win, 3, 4, line_two); X box(e_win, VERT, HORZ); X X if (code) { X mvwattrstr(e_win, 0, 4, A_BOLD, " Error "); X mvwattrstr(e_win, 5, 24, A_BLINK, "Press any key to exit"); X wmove(e_win, 5, 46); X } X else { X mvwattrstr(e_win, 0, 4, A_BOLD, " Warning "); X mvwattrstr(e_win, 5, 22, A_BLINK, "Press any key to continue"); X wmove(e_win, 5, 48); X } X beep(); X wrefresh(e_win); X X wgetch(e_win); X werase(e_win); X wrefresh(e_win); X delwin(e_win); X X if (code) { X st_line(" exiting"); X cleanup(code); X } X return; X} SHAR_EOF if test 2579 -ne "`wc -c < 'pexit.c'`" then echo shar: "error transmitting 'pexit.c'" '(should have been 2579 characters)' fi fi echo shar: "extracting 'port.c'" '(10197 characters)' if test -f 'port.c' then echo shar: "will not over-write existing file 'port.c'" else sed 's/^X//' << \SHAR_EOF > 'port.c' X/* X * Routines to get or release a TTY port. X */ X X#define MAX_PID 30000 X#define TRUE 1 X#define FALSE 0 X X#include X#include X#include X#include "config.h" X#include "dial_dir.h" X#include "modem.h" X X#ifdef BSD X#include X#endif /* BSD */ X X#ifdef UNIXPC X#include X#endif /* UNIXPC */ X X#ifdef XENIX_LOCKS X#include X#endif /* XENIX_LOCKS */ X Xstatic int getty_status = 0; Xstatic char *lock_path = NULL; X/* X * Finds a free (or requested) serial port. Creates a lock file to hold X * for our use. Loads the modem database. A non-zero return code means X * all ports (or the requested port) are busy. X */ X Xint Xget_port() X{ X extern int fd; X register int i; X int j, k, lfd, list[NUM_TTY], cmask, tbaud, is_dev, progpid; X char file[80], buf[80], message[80], *str_rep(), *last_c; X unsigned int sleep(); X void error_win(), line_set(), release_port(), send_str(); X X is_dev = chk_script(dir->script[dir->d_cur]); X /* X * If you already have a port, see if it is good enough for the X * current request. X */ X#ifdef KEEP_PORT X if (fd != -1) { X if (!strcmp(dir->script[dir->d_cur], modem->tty[modem->t_cur]) X || (!is_dev && ck_speed(modem->t_cur, dir->baud[dir->d_cur]))){ X /* X * Reset the line because the baud rate (or other X * parameters) may have changed. X */ X line_set(); X return(0); X } X } X#endif /* KEEP_PORT */ X X release_port(VERBOSE); X X list[0] = -1; X /* X * See if you want a specific TTY port. If the script field in the X * dialing directory is a valid device name, then use that TTY. X */ X if (is_dev) { X for (i=0; it_entries; i++) { X /* and it exists in modem database */ X if (!strcmp(dir->script[dir->d_cur], modem->tty[i])) { X list[0] = i; X list[1] = -1; X break; X } X } X /* oops... we don't know that port */ X if (list[0] == -1) { X sprintf(message, "Device \"%s\" in the script field doesn't exist in", dir->script[dir->d_cur]); X sprintf(buf, "modem/TTY database \"%s\"", modem->m_path); X error_win(0, message, buf); X } X } X X /* X * Create a list of acceptable TTYs. It searches the modem database X * for the requested baud rate. X */ X k = 0; X if (list[0] == -1) { X for (i=0; it_entries; i++) { X /* skip ports with no modems */ X if (!strcmp(modem->tname[i], "DIRECT")) X continue; X X /* can handle requested baud rate? */ X if (ck_speed(i, dir->baud[dir->d_cur])) X list[k++] = i; X } X /* the end of list marker */ X list[k] = -1; X } X /* empty list? */ X if (list[0] == -1) { X sprintf(message, "No modem at a %d baud rating exists in the", dir->baud[dir->d_cur]); X sprintf(buf, "modem database \"%s\"", modem->m_path); X error_win(0, message, buf); X return(1); X } X /* check the list for a free port */ X i = 0; X while (list[i] != -1) { X /* create a lock file name */ X sprintf(file, "%s/LCK..%s", LOCK_DIR, modem->tty[list[i]]); X X#ifdef XENIX_LOCKS X last_c = file + strlen(file)-1; X if (isuuper(*last_c)) X *last_c = tolower(*last_c); X#endif /* XENIX_LOCKS */ X X#ifdef DEBUG X fprintf(stderr, "get_port: checking '/dev/%s'\n", modem->tty[list[i]]); X#endif /* DEBUG */ X X /* no lock exists or it is dead */ X if (checklock(file)) { X getty_status = set_getty(modem->tty[list[i]], FALSE); X X cmask = umask(0); X if ((lfd = open(file, O_CREAT|O_EXCL|O_WRONLY, 0666)) < 0) { X if (getty_status) X set_getty(modem->tty[list[i]], TRUE); X sprintf(buf, "\"%s\"", file); X error_win(1, "Can't create the lockfile", buf); X } X umask(cmask); X#ifdef ASCII_PID X sprintf(buf, "%10d\n", getpid()); X write(lfd, buf, 11); X#else /* ASCII_PID */ X progpid = getpid(); X write(lfd, (char *) &progpid, sizeof(int)); X#endif /* ASCII_PID */ X close(lfd); X /* store the new values */ X lock_path = str_rep(lock_path, file); X modem->t_cur = list[i]; X X /* open the device (ignore DCD) */ X sprintf(buf, "/dev/%s", modem->tty[modem->t_cur]); X if ((fd = open(buf, O_RDWR|O_NDELAY)) < 0) { X if (getty_status) X set_getty(modem->tty[modem->t_cur], TRUE); X sprintf(file, "Can't open port \"%s\" for read and write", buf); X error_win(1, file, ""); X } X /* change line settings */ X line_set(); X /* ...just to be sure */ X close(open(buf, O_RDWR)); X X /* turn off the O_NDELAY setting */ X tty_noblock(fd, FALSE); X X /* load the modem data base */ X modem->m_cur = -1; X for (j=0; jm_entries; j++) { X if (!strcmp(modem->tname[modem->t_cur], modem->mname[j])) { X modem->m_cur = j; X break; X } X } X if (modem->m_cur == -1) { X sprintf(buf, "Modem name \"%s\" in TTY database", X modem->tname[modem->t_cur]); X error_win(1, buf, "does not exist in modem database"); X } X /* initialize the modem */ X if (modem->init_sp[modem->t_cur]) { X tbaud = dir->baud[dir->d_cur]; X dir->baud[dir->d_cur] = modem->init_sp[modem->t_cur]; X line_set(); X send_str(modem->init[modem->m_cur], SLOW); X dir->baud[dir->d_cur] = tbaud; X } X else X send_str(modem->init[modem->m_cur], SLOW); X sleep(1); X return(0); X } X i++; X } X error_win(0, "All ports are busy now, try again later", ""); X return(1); X} X X/* X * Release the port. Closes the file descriptor and removes the X * lock file X */ X Xvoid Xrelease_port(verbose) Xint verbose; X{ X extern int fd; X extern char *null_ptr; X char buf[80]; X void free_ptr(), hang_up(); X X /* X * The modem structure can't be guaranteed to exist yet. For example, X * an error in reading one of the other support files would cause X * this routine to be used before the MODEM structure gets allocated. X */ X if (modem == NULL) X return; X /* close the port */ X if (fd != -1) { X tty_flush(fd, 2); X /* X * Since HUPCL is set, the close() should drop the DTR and X * hang up the modem (provided you've got the modem to X * respond to DTR). Since this is not guaranteed, we send X * the hang_up string first. X */ X hang_up(verbose); X close(fd); X } X /* remove the lock */ X if (lock_path != NULL && *lock_path != '\0') { X if (unlink(lock_path)) { X sprintf(buf, "\"%s\"", lock_path); X error_win(0, "Can't remove the lock file", buf); X } X free_ptr(lock_path); X lock_path = null_ptr; X } X /* turn the getty back on? */ X if (getty_status && modem->t_cur != -1) X set_getty(modem->tty[modem->t_cur], TRUE); X /* clean up the structure */ X fd = -1; X modem->m_cur = -1; X modem->t_cur = -1; X return; X} X X/* X * Turn the /etc/getty on or off for the specified port. A non-zero return X * code means that the getty was on. Systems with uugetty() or dedicated X * dialout ports won't need this routine. X */ X X/* ARGSUSED */ Xstatic int Xset_getty(tty, on) Xchar *tty; Xint on; X{ X#ifdef UNIXPC X int i, ret_code; X char buf[40]; X unsigned int sleep(); X /* the last three characters */ X i = strlen(tty) -3; X X ret_code = 0; X if (on) { X sprintf(buf, "setgetty %s 1", tty+i); X system(buf); X } X else { X sprintf(buf, "setgetty %s 0", tty+i); X if (system(buf) == 512) X ret_code++; X sleep(1); X } X return(ret_code); X#else /* UNIXPC */ X /* X * If you don't have one of these cute little routines, you X * might wanna write one. It should check for an existing lock X * file, edit the /etc/inittab file, and issue an init -q. X * The return code should tell if there was a getty or not. X * Obviously the program would be suid to root. X */ X return(0); X#endif /* UNIXPC */ X} X X/* X * Check the lock file for a valid pid value. Error conditions such X * as not being able to open the lock file or not being able to interpret X * the contents of the lock file cause the code to assume that the lock X * file is valid. Let the user worry about weird special cases. A X * non-zero return code means the lock is dead or doesn't exist. X */ X Xstatic int Xchecklock(lockfile) Xchar *lockfile; X{ X extern int errno; X int lfd, lckpid, n; X char buf[40]; X /* doesn't exist */ X if (access(lockfile, 0)) X return(1); X /* can't open the lock file */ X if ((lfd = open(lockfile, 0)) < 0) X return(0); X X#ifdef ASCII_PID X if ((n = read(lfd, buf, 40)) <= 0) { X close(lfd); X return(0); X } X close(lfd); X buf[n--] = '\0'; X lckpid = atoi(buf); X#else /* ASCII_PID */ X if (read(lfd, (char *) &lckpid, sizeof(int)) != sizeof(int)) { X close(lfd); X return(0); X } X close(lfd); X#endif /* ASCII_PID */ X /* invalid pid? */ X if (lckpid <= 0 || lckpid > MAX_PID) X return(0); X X if ((kill(lckpid, 0) == -1) && (errno == ESRCH)) { X /* X * If the kill was unsuccessful due to an ESRCH error, X * that means the process is no longer active and the X * lock file can be safely removed. X */ X unlink(lockfile); X sleep(1); X return(1); X } X /* X * If the kill() was successful, that means the process must X * still be active. X */ X return(0); X} X X/* X * Check to see if the desired baud rate can be handled by the modem. X * Uses the connect strings to make this determination. The first X * argument is the index into the TTY database. A non-zero return code X * means "yes it can". X */ X Xstatic int Xck_speed(tty, baud) Xint tty, baud; X{ X int i, mod; X char buf[60]; X /* find the modem database */ X mod = -1; X for (i=0; im_entries; i++) { X if (!strcmp(modem->mname[i], modem->tname[tty])) { X mod = i; X break; X } X } X if (mod == -1) { X sprintf(buf, "Modem name \"%s\" in TTY database", modem->tname[tty]); X error_win(1, buf, "does not exist in modem database"); X } X X#ifdef DEBUG X fprintf(stderr, "ck_speed: checking modem \"%s\" for %d baud\n", modem->mname[mod], baud); X#endif /* DEBUG */ X X switch (baud) { X case 300: X if (*modem->con_3[mod] != '\0') X return(1); X break; X case 1200: X if (*modem->con_12[mod] != '\0') X return(1); X break; X case 2400: X if (*modem->con_24[mod] != '\0') X return(1); X break; X case 4800: X if (*modem->con_48[mod] != '\0') X return(1); X break; X case 9600: X if (*modem->con_96[mod] != '\0') X return(1); X break; X case 19200: X if (*modem->con_192[mod] != '\0') X return(1); X break; X } X return(0); X} X X/* X * Check to see if the script field is a valid device name. X */ X Xchk_script(script) Xchar *script; X{ X char buf[80], *strcpy(), *strcat(); X X if (*script == '\0') X return(0); X X strcpy(buf, "/dev/"); X strcat(buf, script); X X if (!access(buf, 0)) X return(1); X return(0); X} SHAR_EOF if test 10197 -ne "`wc -c < 'port.c'`" then echo shar: "error transmitting 'port.c'" '(should have been 10197 characters)' fi fi exit 0 # End of shell archive