Pcomm v1.1 (5 of 8)
Emmet Gray
egray at killer.DALLAS.TX.US
Mon Sep 5 04:03:21 AEST 1988
This is part 5 (of 8) to the Pcomm v1.1 release package.
Emmet P. Gray US Army, HQ III Corps & Fort Hood
..!uunet!uiucuxc!fthood!egray Attn: AFZF-DE-ENV
DEH, Environmental Management Office
Fort Hood, TX 76544-5057
------------------------------------------------------------------------------
#! /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
# This archive created: Sat Sep 3 15:35:00 1988
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
More information about the Unix-pc.sources
mailing list