rsalz@uunet.uu.net (Rich Salz) (09/13/88)
Submitted-by: Emmet P Gray <fthood!egray> Posting-number: Volume 16, Issue 10 Archive-name: pcomm2/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 # n_shell.c # p_lib.c # passthru.c # pexit.c # port.c # redial.c export PATH; PATH=/bin:/usr/bin:$PATH echo shar: "extracting 'm_lib.c'" '(10070 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 <stdio.h> 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 *strdup(), 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 /* read permission checked */ X fp = my_fopen(m.m_path, "r"); 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 null pointer on a missing X * attribute. 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] = strdup(str); X break; X case 1: X m.tname[tty] = strdup(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<stop; i++) { X if (!(str = str_tok((char *) NULL, m_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.mname[mod] = strdup(str); X break; X case 1: X m.init[mod] = strdup(str); X break; X case 2: X m.dial[mod] = strdup(str); X break; X case 3: X m.suffix[mod] = strdup(str); X break; X case 4: X m.hang_up[mod] = strdup(str); X break; X case 5: X m.auto_baud[mod] = *str; X break; X case 6: X m.con_3[mod] = strdup(str); X break; X case 7: X m.con_12[mod] = strdup(str); X break; X case 8: X m.con_24[mod] = strdup(str); X break; X case 9: X m.con_48[mod] = strdup(str); X break; X case 10: X m.con_96[mod] = strdup(str); X break; X case 11: X m.con_192[mod] = strdup(str); X break; X case 12: X m.no_con1[mod] = strdup(str); X break; X case 13: X m.no_con2[mod] = strdup(str); X break; X case 14: X m.no_con3[mod] = strdup(str); X break; X case 15: X m.no_con4[mod] = strdup(str); X break; X } X } X if (oops) X break; X m_line++; X if (m_line >= 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 (; tty<NUM_TTY; tty++) { X m.tty[tty] = null_ptr; X m.tname[tty] = null_ptr; X m.init_sp[tty] = 0; X } X for (; mod<NUM_MODEM; mod++) { X m.mname[mod] = null_ptr; X m.init[mod] = null_ptr; X m.dial[mod] = null_ptr; X m.suffix[mod] = null_ptr; X m.hang_up[mod] = null_ptr; X X m.auto_baud[mod] = 'Y'; X m.con_3[mod] = null_ptr; X m.con_12[mod] = null_ptr; X m.con_24[mod] = null_ptr; X m.con_48[mod] = null_ptr; X m.con_96[mod] = null_ptr; X m.con_192[mod] = null_ptr; X X m.no_con1[mod] = null_ptr; X m.no_con2[mod] = null_ptr; X m.no_con3[mod] = null_ptr; X m.no_con4[mod] = null_ptr; X } X return(&m); X} X X/* X * Update the modem database. Other routines actually do the changes X * or deletions in memory. A return code of 1 means non-fatal error. X */ X Xint Xup_modem() X{ X FILE *fp, *my_fopen(); X char buf[80]; X int i; X void error_win(); X X /* open for write */ X if (!(fp = my_fopen(modem->m_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; i<modem->t_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; i<modem->m_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 *strdup(), buf[80]; X void error_win(), free_ptr(); X /* modem entry already exists? */ X for (i=0; i<modem->m_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 free_ptr(modem->mname[modem->m_entries]); X modem->mname[modem->m_entries] = strdup(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 *strdup(); X void free_ptr(); X X for (i=0; i<modem->m_entries; i++) { X match = 0; X for (j=0; j<modem->t_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; j<modem->m_entries-1; j++) { 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 /* copy the info */ X modem->mname[j] = strdup(modem->mname[j+1]); X modem->init[j] = strdup(modem->init[j+1]); X modem->dial[j] = strdup(modem->dial[j+1]); X modem->suffix[j] = strdup(modem->suffix[j+1]); X modem->hang_up[j] = strdup(modem->hang_up[j+1]); X X modem->auto_baud[j] = modem->auto_baud[j+1]; X modem->con_3[j] = strdup(modem->con_3[j+1]); X modem->con_12[j] = strdup(modem->con_12[j+1]); X modem->con_24[j] = strdup(modem->con_24[j+1]); X modem->con_48[j] = strdup(modem->con_48[j+1]); X modem->con_96[j] = strdup(modem->con_96[j+1]); X modem->con_192[j] = strdup(modem->con_192[j+1]); X X modem->no_con1[j] = strdup(modem->no_con1[j+1]); X modem->no_con2[j] = strdup(modem->no_con2[j+1]); X modem->no_con3[j] = strdup(modem->no_con3[j+1]); X modem->no_con4[j] = strdup(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 10070 -ne "`wc -c < 'm_lib.c'`" then echo shar: "error transmitting 'm_lib.c'" '(should have been 10070 characters)' fi fi echo shar: "extracting 'macro.c'" '(5243 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 <stdio.h> X#include <curses.h> X#include "config.h" X#include "misc.h" X#include "param.h" X Xint Xmacro() X{ X extern int fd; X WINDOW *ma_win, *newwin(); X int ans, ret_code; X char *mac, *strdup(), *mac_prompt(); X void free_ptr(); 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 <ESC> to continue "); X wmove(ma_win, 15, 26); X wrefresh(ma_win); X X ret_code = 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 free_ptr(param->mac_1); X param->mac_1 = strdup(mac); X clear_line(ma_win, 4, 9, 1); X mvwattrstr(ma_win, 4, 9, A_BOLD, mac); X ret_code++; X } X break; X case '@': /* shifted 2 */ X if ((mac = mac_prompt(ans, param->mac_2)) != NULL) { X free_ptr(param->mac_2); X param->mac_2 = strdup(mac); X clear_line(ma_win, 5, 9, 1); X mvwattrstr(ma_win, 5, 9, A_BOLD, mac); X ret_code++; X } X break; X case '#': /* shifted 3 */ X if ((mac = mac_prompt(ans, param->mac_3)) != NULL) { X free_ptr(param->mac_3); X param->mac_3 = strdup(mac); X clear_line(ma_win, 6, 9, 1); X mvwattrstr(ma_win, 6, 9, A_BOLD, mac); X ret_code++; X } X break; X case '$': /* shifted 4 */ X if ((mac = mac_prompt(ans, param->mac_4)) != NULL) { X free_ptr(param->mac_4); X param->mac_4 = strdup(mac); X clear_line(ma_win, 7, 9, 1); X mvwattrstr(ma_win, 7, 9, A_BOLD, mac); X ret_code++; X } X break; X case '%': /* shifted 5 */ X if ((mac = mac_prompt(ans, param->mac_5)) != NULL) { X free_ptr(param->mac_5); X param->mac_5 = strdup(mac); X clear_line(ma_win, 8, 9, 1); X mvwattrstr(ma_win, 8, 9, A_BOLD, mac); X ret_code++; X } X break; X case '^': /* shifted 6 */ X if ((mac = mac_prompt(ans, param->mac_6)) != NULL) { X free_ptr(param->mac_6); X param->mac_6 = strdup(mac); X clear_line(ma_win, 9, 9, 1); X mvwattrstr(ma_win, 9, 9, A_BOLD, mac); X ret_code++; X } X break; X case '&': /* shifted 7 */ X if ((mac = mac_prompt(ans, param->mac_7)) != NULL) { X free_ptr(param->mac_7); X param->mac_7 = strdup(mac); X clear_line(ma_win, 10, 9, 1); X mvwattrstr(ma_win, 10, 9, A_BOLD, mac); X ret_code++; X } X break; X case '*': /* shifted 8 */ X if ((mac = mac_prompt(ans, param->mac_8)) != NULL) { X free_ptr(param->mac_8); X param->mac_8 = strdup(mac); X clear_line(ma_win, 11, 9, 1); X mvwattrstr(ma_win, 11, 9, A_BOLD, mac); X ret_code++; X } X break; X case '(': /* shifted 9 */ X if ((mac = mac_prompt(ans, param->mac_9)) != NULL) { X free_ptr(param->mac_9); X param->mac_9 = strdup(mac); X clear_line(ma_win, 12, 9, 1); X mvwattrstr(ma_win, 12, 9, A_BOLD, mac); X ret_code++; X } X break; X case ')': /* shifted 0 */ X if ((mac = mac_prompt(ans, param->mac_0)) != NULL) { X free_ptr(param->mac_0); X param->mac_0 = strdup(mac); X clear_line(ma_win, 13, 9, 1); X mvwattrstr(ma_win, 13, 9, A_BOLD, mac); X ret_code++; 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 (ret_code) { 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(ret_code); X} X X/* X * Sounds like Mac Donalds doesn't it? Actually, it opens a new window X * and prompts for the new macro. Returns a pointer to the new string. 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 new = get_str(mp_win, 50, "", ""); X /* if space, change to NULL pointer */ X if (!strcmp(new, " ")) X new = null_ptr; X X werase(mp_win); X wrefresh(mp_win); X delwin(mp_win); X return(new); X} SHAR_EOF if test 5243 -ne "`wc -c < 'macro.c'`" then echo shar: "error transmitting 'macro.c'" '(should have been 5243 characters)' fi fi echo shar: "extracting 'main.c'" '(6133 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 * patch #1 22 Mar 88 X * patch #2 26 Mar 88 X * patch #3 3 Apr 88 X * patch #4 14 Apr 88 X * patch #5 25 May 88 X * Release v1.1 21 Aug 88 X */ X X#include <stdio.h> X#include <signal.h> X#include <curses.h> X#include <sys/types.h> X#include <sys/stat.h> X#include "config.h" X#ifndef OLDCURSES X#include <term.h> X#endif /* OLDCURSES */ X#define MAIN X#include "dial_dir.h" X#include "modem.h" X#include "param.h" X#include "status.h" X X#ifdef OLDCURSES Xchar tcbuf[1024], *TI, *VS; X#define cbreak crmode X#endif /* OLDCURSES */ X X#ifdef SHAREDMEM Xint shm_id; X#endif /* SHAREDMEM */ X Xstruct PARAM *param; Xstruct DIAL_DIR *dir; Xstruct STATUS *status; Xstruct MODEM *modem; 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, ret_code, i, code, quit(); X char *mytty, *ttyname(), *term, *getenv(), *short_cut, *strdup(); X char *extra_dir, buf[80], message[80]; X struct PARAM *read_param(); X struct DIAL_DIR *read_dir(); X struct STATUS *init(); X struct MODEM *read_modem(); 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 short_cut = 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 = strdup(optarg); X break; X case 'f': /* the index into the dialing dir */ X short_cut = strdup(optarg); X break; X case '?': /* default */ X fprintf(stderr, "Usage: pcomm [-d directory] [-f index]\n"); X exit(1); X break; X } X } X /* get terminal type */ X term = getenv("TERM"); X if (term == NULL || *term == NULL) { X fprintf(stderr, "Windows not supported (TERM not defined)\n"); X exit(1); X } X /* see if terminfo entry exists */ X#ifdef OLDCURSES X ret_code = tgetent(tb, term); X#else /* OLDCURSES */ X setupterm(term, 1, &ret_code); X#endif /* OLDCURSES */ X if (ret_code != 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 TI = tgetstr("ti", &t); X VS = tgetstr("vs", &t); X#else /* OLDCURSES */ X xmc = magic_cookie_glitch; X#endif /* OLDCURSES */ X /* ok... now lets go! */ X initscr(); X nonl(); X cbreak(); X noecho(); X X param = (struct PARAM *) NULL; X modem = (struct MODEM *) NULL; X dir = (struct DIAL_DIR *) NULL; X /* show the herald, return status */ X status = init(short_cut); X /* get "msgs" status */ X mytty = ttyname(0); X stat(mytty, &stbuf); X chmod(mytty, 0600); X msg_status = stbuf.st_mode & 0777; X /* read the support files */ X param = read_param(extra_dir); X dir = read_dir(extra_dir); X modem = read_modem(extra_dir); X free_ptr(extra_dir); X /* warning about screen size */ X if (LINES > MAX_ROW || COLS > MAX_COL) 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 (short_cut != NULL) { X for (i=1; i<dir->d_entries+1; i++) { X if (!strcmp(dir->index[i], short_cut)) { 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 find index '%s' in dialing directory", short_cut); X sprintf(message, "file '%s'", dir->d_path); X error_win(0, buf, message); X } X free_ptr(short_cut); X } X /* start terminal dialogue */ X terminal(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[200], *strcpy(), *strrchr(); X X p = strcpy(path, file); X /* dissect the path component */ X if (p = strrchr(path, '/')) X *(p++) = NULL; X else X strcpy(path, "."); X /* if it already exists */ X if (!access(file, 0)) { X if (!access(file, 2)) X return(2); X return(0); X } X /* if path is writable */ X if (!access(path, 2)) X return(1); X return(0); X} X X/* X * Check the read and write permissions before opening a file. This X * is a horrible kludge to work around that 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#ifdef SETUGID X switch (*mode) { X case 'a': X case 'w': X if (!can_write(file)) X return(NULL); X break; X case 'r': X if (access(file, 4)) X return(NULL); X break; X } X#endif /* SETUGID */ X return ((FILE *) fopen(file, mode)); X} SHAR_EOF if test 6133 -ne "`wc -c < 'main.c'`" then echo shar: "error transmitting 'main.c'" '(should have been 6133 characters)' fi fi echo shar: "extracting 'n_shell.c'" '(1255 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 <stdio.h> X#include <signal.h> X#include <curses.h> X#include "config.h" X Xvoid Xn_shell() X{ X WINDOW *sh_win, *newwin(); X int (*istat)(), (*qstat)(), 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 == NULL) X shellpath = "/bin/sh"; X X shell = strrchr(shellpath, '/') + 1; 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(&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 1255 -ne "`wc -c < 'n_shell.c'`" then echo shar: "error transmitting 'n_shell.c'" '(should have been 1255 characters)' fi fi echo shar: "extracting 'p_lib.c'" '(7151 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 <stdio.h> X#include "param.h" X X/* X * Read the parameter structure from the pcomm.param file. Returns a X * pointer to the PARAM structure. All errors are fatal. X */ X Xstruct PARAM * Xread_param(extra) Xchar *extra; X{ X FILE *fp; X int i, oops; X char buf[80], *temp_token, *str, *strdup(), *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 /* read permission already checked */ X fp = fopen(p.p_path, "r"); X X oops = 0; X for (i=0; i<NUM_PARAM; i++) { X if (fgets(buf, 80, fp) == NULL) { X sprintf(message, "is truncated at line %d", i+1); X oops++; X break; X } X /* parse the input line */ X if (!(temp_token = str_tok(buf, '='))) { X sprintf(message, "is missing a token at line %d", i+1); X oops++; X break; X } X if (!(str = str_tok((char *) NULL, '\n'))) { X sprintf(message, "is missing a parameter at line %d", i+1); X oops++; X break; X } X /* sanity checking */ X if (strcmp(temp_token, token[i])) { X sprintf(message, "is corrupted at line %d", i+1); X oops++; X break; X } X X switch (i) { X /* used in ls_menu() */ X case LINE_SET: X p.d_baud = atoi(str); X break; X case LINE_SET+1: X p.d_parity = *str; X break; X case LINE_SET+2: X p.d_dbits = atoi(str); X break; X case LINE_SET+3: X p.d_sbits = atoi(str); X break; X X /* used in term_setup() */ X case TERM_SETUP: X p.hot = atoi(str); X break; X case TERM_SETUP+1: X p.ascii_hot = strdup(str); X break; X case TERM_SETUP+2: X p.d_duplex = strdup(str); X break; X case TERM_SETUP+3: X p.flow = strdup(str); X break; X case TERM_SETUP+4: X p.cr_in = strdup(str); X break; X case TERM_SETUP+5: X p.cr_out = strdup(str); X break; X X /* used in gen_setup() */ X case GEN_SETUP: X p.logfile = strdup(str); X break; X case GEN_SETUP+1: X p.dumpfile = strdup(str); X break; X case GEN_SETUP+2: X p.strip = strdup(str); X break; X case GEN_SETUP+3: X p.pause_char = *str; X break; X case GEN_SETUP+4: X p.cr_char = *str; X break; X case GEN_SETUP+5: X p.ctrl_char = *str; X break; X case GEN_SETUP+6: X p.esc_char = *str; X break; X case GEN_SETUP+7: X p.brk_char = *str; X break; X case GEN_SETUP+8: X p.abort = strdup(str); X break; X X /* used in gen_setup() delay_times() */ X case DELAY_TIMES: X p.c_delay = atoi(str); X break; X case DELAY_TIMES+1: X p.r_delay = atoi(str); X break; X X /* used in axfer_setup() */ X case ASCII_SETUP: X p.lecho = strdup(str); X break; X case ASCII_SETUP+1: X p.expand = strdup(str); X break; X case ASCII_SETUP+2: X p.cr_delay = atoi(str); X break; X case ASCII_SETUP+3: X p.pace = strdup(str); X break; X case ASCII_SETUP+4: X p.cr_up = strdup(str); X break; X case ASCII_SETUP+5: X p.lf_up = strdup(str); X break; X case ASCII_SETUP+6: X p.timer = atoi(str); X break; X case ASCII_SETUP+7: X p.cr_dn = strdup(str); X break; X case ASCII_SETUP+8: X p.lf_dn = strdup(str); X break; X X /* used in d_revise() */ X case LD_CODES: X p.ld_plus = strdup(str); X break; X case LD_CODES+1: X p.ld_minus = strdup(str); X break; X case LD_CODES+2: X p.ld_at = strdup(str); X break; X case LD_CODES+3: X p.ld_pound = strdup(str); X break; X X /* used in macro() */ X case MACROS: X p.mac_1 = strdup(str); X break; X case MACROS+1: X p.mac_2 = strdup(str); X break; X case MACROS+2: X p.mac_3 = strdup(str); X break; X case MACROS+3: X p.mac_4 = strdup(str); X break; X case MACROS+4: X p.mac_5 = strdup(str); X break; X case MACROS+5: X p.mac_6 = strdup(str); X break; X case MACROS+6: X p.mac_7 = strdup(str); X break; X case MACROS+7: X p.mac_8 = strdup(str); X break; X case MACROS+8: X p.mac_9 = strdup(str); X break; X case MACROS+9: X p.mac_0 = strdup(str); X break; X } X } X fclose(fp); X if (oops) { X sprintf(buf, "Parameter file '%s'", p.p_path); X error_win(1, buf, message); X } X return(&p); X} X X/* X * Write the updated param structure to disk. The values in memory should X * have already been "purified". Later, we'll update only the entries that X * have been explicitly asked for. A return code of 1 means non-fatal error. X */ X Xint Xup_param() X{ X FILE *fp, *my_fopen(); X char buf[80]; X void error_win(); X /* open for write */ X if (!(fp = my_fopen(param->p_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 7151 -ne "`wc -c < 'p_lib.c'`" then echo shar: "error transmitting 'p_lib.c'" '(should have been 7151 characters)' fi fi echo shar: "extracting 'passthru.c'" '(2141 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 <stdio.h> X#include <signal.h> X#include <curses.h> X#include "config.h" X#include "misc.h" X Xint Xpass_thru() X{ X extern int fd; X WINDOW *pt_win, *newwin(); X int num; X void cpio(); 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, 1); 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 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 bagage 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[BUFSIZ]; 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, BUFSIZ); 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 n = read(0, buf, BUFSIZ); 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/*ARGSUSED*/ Xstatic int Xcp_force(dummy) X{ X cp_flag = 1; X} SHAR_EOF if test 2141 -ne "`wc -c < 'passthru.c'`" then echo shar: "error transmitting 'passthru.c'" '(should have been 2141 characters)' fi fi echo shar: "extracting 'pexit.c'" '(2504 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 <stdio.h> X#include <curses.h> X#include "config.h" X#ifdef SHAREDMEM X#include <sys/types.h> X#include <sys/ipc.h> X#include <sys/shm.h> X#endif /* SHAREDMEM */ X#include "dial_dir.h" X#include "misc.h" X#include "param.h" X#include "status.h" 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#endif /* SHAREDMEM */ X /* kill the input routine */ X input_off(); X /* release the port */ X release_port(0); 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 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 2504 -ne "`wc -c < 'pexit.c'`" then echo shar: "error transmitting 'pexit.c'" '(should have been 2504 characters)' fi fi echo shar: "extracting 'port.c'" '(9459 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 X#include <stdio.h> X#include <fcntl.h> X#include <termio.h> X#include <errno.h> X#include "config.h" X#ifdef UNIXPC X#include <sys/phone.h> X#endif /* UNIXPC */ X#include "dial_dir.h" X#include "modem.h" X Xstatic int getty_status; 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 return code of 1 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; X char file[80], buf[80], message[80], *strdup(); X unsigned int sleep(); X void error_win(), line_set(), release_port(), send_str(); X void free_ptr(); X#ifndef ASCII_PID X int progpid; X#endif /* ASCII_PID */ X X /* X * If we 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->index[dir->d_cur], modem->tty[modem->t_cur]) || X 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 release_port(1); X X list[0] = -1; X /* X * See if you want a specific TTY port. If the index field in the X * dialing directory is a valid device name, then use that TTY. X */ X if (*dir->index[dir->d_cur] != NULL) { X sprintf(buf, "/dev/%s", dir->index[dir->d_cur]); X /* if index is a valid device */ X if (!access(buf, 0)) { X for (i=0; i<modem->t_entries; i++) { X /* and it exists in modem database */ X if (!strcmp(dir->index[dir->d_cur], modem->tty[i])) { X list[0] = i; X list[1] = -1; X break; X } X } 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; i<modem->t_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#ifdef DEBUG X fprintf(stderr, "get_port: checking '/dev/%s'\n", modem->tty[list[i]]); X#endif /* DEBUG */ X X /* does it exist or is it dead? */ X if (checklock(file)) { X getty_status = set_getty(modem->tty[list[i]], 0); 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]], 1); 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 free_ptr(lock_path); X lock_path = strdup(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], 1); X sprintf(file, "Can't open port '%s' for read and write", buf); X error_win(1, file, ""); X } X /* turn off the "no delay" mode */ X fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NDELAY); X /* change line settings */ X line_set(); X /* load the modem data base */ X modem->m_cur = -1; X for (j=0; j<modem->m_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]); X dir->baud[dir->d_cur] = tbaud; X } X else X send_str(modem->init[modem->m_cur]); 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 ioctl(fd, TCFLSH, 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 != NULL) { 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) X set_getty(modem->tty[modem->t_cur], 1); 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 return code X * of 1 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 return X * code of 1 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; X#ifdef ASCII_PID X int n; X char buf[40]; X#endif /* ASCII_PID */ 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 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 return code of 1 X * means yes. 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; i<modem->m_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#ifdef DEBUG X fprintf(stderr, "ck_speed: checking modem '%s' for %d buad\n", modem->mname[mod], baud); X#endif /* DEBUG */ X X switch (baud) { X case 300: X if (*modem->con_3[mod] != NULL) X return(1); X break; X case 1200: X if (*modem->con_12[mod] != NULL) X return(1); X break; X case 2400: X if (*modem->con_24[mod] != NULL) X return(1); X break; X case 4800: X if (*modem->con_48[mod] != NULL) X return(1); X break; X case 9600: X if (*modem->con_96[mod] != NULL) X return(1); X break; X case 19200: X if (*modem->con_192[mod] != NULL) X return(1); X break; X } X return(0); X} SHAR_EOF if test 9459 -ne "`wc -c < 'port.c'`" then echo shar: "error transmitting 'port.c'" '(should have been 9459 characters)' fi fi echo shar: "extracting 'redial.c'" '(2242 characters)' if test -f 'redial.c' then echo shar: "will not over-write existing file 'redial.c'" else sed 's/^X//' << \SHAR_EOF > 'redial.c' X/* X * The redial option (actually a misnomer, it's really a queuing system). X * We expect a space-separated list of dialing directory entries (although X * new users always try to put in a phone number). A non-zero return code X * means we're ready to dial. X */ X X#include <stdio.h> X#include <curses.h> X#include "config.h" X#include "dial_dir.h" X#include "misc.h" X Xint Xredial() X{ X extern int fd; X WINDOW *rd_win, *newwin(); X char *ans, *entry, *get_str(), *strchr(), *strtok(); X int i, oops, number, ret_code; X X rd_win = newwin(6, 70, 5, 5); X X mvwaddstr(rd_win, 4, 23, "(<CR> for previous numbers)"); X mvwaddstr(rd_win, 2, 4, "Directory Entry Number(s): "); X box(rd_win, VERT, HORZ); X X mvwattrstr(rd_win, 0, 3, A_BOLD, " Redial Queue "); X wmove(rd_win, 2, 31); X wrefresh(rd_win); X /* get the string of numbers */ X ret_code = 0; X while ((ans = get_str(rd_win, 35, "0123456789+-@# ", "")) != NULL) { X oops = 0; X if (*ans == NULL) { X /* use previous queue */ X if (dir->q_num[0] != -1) { X ret_code++; X break; X } X /* there is no previous queue */ X beep(); X mvwattrstr(rd_win, 3, 4, A_BOLD, "No previous numbers"); X wrefresh(rd_win); X wait_key(rd_win, 3); X clear_line(rd_win, 3, 4, 1); X wmove(rd_win, 2, 31); X wrefresh(rd_win); X continue; X } X /* parse the queue values */ X entry = strtok(ans, " "); X for (i=0; i<NUM_QUEUE; i++) { X if (*entry == NULL) { X dir->q_num[i] = -1; X continue; X } X /* is there a LD code? */ X dir->q_ld[i] = NULL; X if (strchr("+-@#", *entry)) { X dir->q_ld[i] = *entry; X entry++; X } X X /* X * Zero is valid here, because it means use X * the current entry information. X */ X number = atoi(entry); X if (number < -1 || number > NUM_DIR) { X beep(); X mvwattrstr(rd_win, 3, 4, A_BOLD, "Invalid directory entry number"); X wrefresh(rd_win); X wait_key(rd_win, 3); X clear_line(rd_win, 3, 4, 1); X clear_line(rd_win, 2, 31, 1); X wrefresh(rd_win); X oops++; X break; X } X /* store the number in the queue */ X dir->q_num[i] = number; X entry = strtok((char *) NULL, " "); X } X if (oops) X continue; X ret_code++; X break; X } X if (fd == -1) { X werase(rd_win); X wrefresh(rd_win); X } X delwin(rd_win); X return(ret_code); X} SHAR_EOF if test 2242 -ne "`wc -c < 'redial.c'`" then echo shar: "error transmitting 'redial.c'" '(should have been 2242 characters)' fi fi exit 0 # End of shell archive -- Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.