[comp.sources.unix] v14i101: Dial out and terminal emulator, Part03/06

rsalz@bbn.com (Rich Salz) (05/19/88)

Submitted-by: fthood!egray
Posting-number: Volume 14, Issue 101
Archive-name: pcomm/part03

#! /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:
#	d_print.c
#	d_prompt.c
#	d_revise.c
#	data_log.c
#	di_delay.c
#	di_win.c
#	dial.c
#	expand.c
#	getcwd.c
#	getopt.c
#	help.c
#	info.c
#	init.c
export PATH; PATH=/bin:/usr/bin:$PATH
echo shar: "extracting 'd_print.c'" '(3497 characters)'
if test -f 'd_print.c'
then
	echo shar: "will not over-write existing file 'd_print.c'"
else
sed 's/^X//' << \SHAR_EOF > 'd_print.c'
X/*
X * The print option of the dialing directory.  A carriage return will
X * send the dialing directory to the print spool program, otherwise the
X * selected file will be used.
X */
X
X#define LPRINT "/usr/bin/lprint"
X
X#include <stdio.h>
X#include <curses.h>
X#include "dial_dir.h"
X#include "misc.h"
X
Xvoid
Xprint_dir()
X{
X	FILE *fp, *popen();
X	WINDOW *p_win, *newwin();
X	char *file, *get_str_erase(), buf[80];
X	int is_printer, i, can;
X	void error_win();
X	unsigned int sleep();
X	
X	p_win = newwin(5, 54, 0, 26);
X
X	mvwaddstr(p_win, 2, 3, "Print to: (printer)");
X	box(p_win, '|', '-');
X	wmove(p_win, 2, 13);
X	wrefresh(p_win);
X
X	/*
X	 * This is a special version of get_str() that looks at the
X	 * first character to see if it should erase the default answer
X	 * already on the screen.
X	 */
X	if ((file = get_str_erase(p_win, 40)) == NULL) {
X					/* erase because it overlaps dm_win */
X		werase(p_win);
X		wrefresh(p_win);
X		delwin(p_win);
X		return;
X	}
X	is_printer = 0;
X					/* the default (printer) */
X	if (*file == NULL) {
X		if (!(fp = popen(LPRINT, "w"))) {
X			sprintf(buf, "'%s'", LPRINT);
X			error_win(0, "Can't open printer device", buf);
X			werase(p_win);
X			wrefresh(p_win);
X			delwin(p_win);
X			return;
X		}
X		is_printer = 1;
X	}
X					/* the requested file */
X	else {
X		/*
X		 * Check to see if the file already exists (and if we
X		 * have write permission too).  Currently only allows
X		 * you to bail out or overwrite the file.
X		 */
X		if (!(can = can_write(file))) {
X			sprintf(buf, "'%s'", file);
X			error_win(0, "No write permission on file", buf);
X			werase(p_win);
X			wrefresh(p_win);
X			delwin(p_win);
X			return;
X		}
X		if (can == 2) {
X			werase(p_win);
X			mvwprintw(p_win, 2, 3, "File '%s' already exists!", file);
X			beep();
X			box(p_win, '|', '-');
X			if (!yes_prompt(p_win, 3, 3, A_BOLD, "Overwrite")) {
X				werase(p_win);
X				wrefresh(p_win);
X				delwin(p_win);
X				return;
X			}
X		}
X			
X		fp = fopen(file, "w");
X	}
X	
X	werase(p_win);
X	mvwaddstr(p_win, 2, 13, "Printing pcomm directory");
X	box(p_win, '|', '-');
X	wrefresh(p_win);
X
X	/*
X	 * Only prints up to the end of the physical file, not the entire
X	 * structure.  I gave some thought about not printing empty entries,
X	 * but...
X	 */
X	for (i=1; i<=dir->d_entries; i++)
X		fprintf(fp, "%4d- %-20.20s %18.18s  %5d-%c-%d-%d  %c  %-14.14s\n",
X		 i, dir->name[i], dir->number[i], dir->baud[i], dir->parity[i],
X		 dir->dbits[i], dir->sbits[i], dir->duplex[i], dir->index[i]);
X
X	if (is_printer)
X		pclose(fp);
X	else {
X					/* a dramatic delay... */
X		sleep(1);
X		fclose(fp);
X	}
X
X	werase(p_win);
X	wrefresh(p_win);
X	delwin(p_win);
X	return;
X}
X
X/*
X * Get a string from a window but erase the line first.
X */
X
Xchar *
Xget_str_erase(win, num)
XWINDOW *win;
Xint num;
X{
X	int count, x, y, done_it;
X	char ans;
X	static char buf[80];
X
X	done_it = 0;
X	count = 0;
X	while ((ans = wgetch(win)) != '\r') {
X					/* do our own backspace */
X		if (ans == 8) {
X			if (!count) {
X				beep();
X				continue;
X			}
X			count--;
X			buf[count] = NULL;
X			getyx(win, y, x);
X			x--;
X			wmove(win, y, x);
X			waddch(win, ' ');
X			wmove(win, y, x);
X			wrefresh(win);
X			continue;
X		}
X					/* exceeded the max ? */
X		if (count == num) {
X			beep();
X			continue;
X		}
X					/* an ESC anywhere in the string */
X		if (ans == 27)
X			return(NULL);
X					/* erase the default answer */
X		if (!done_it) {
X			waddstr(win, "         ");
X			wmove(win, 2, 13);
X			wrefresh(win);
X			done_it = 1;
X		}
X
X		buf[count] = ans;
X		waddch(win, ans);
X		wrefresh(win);
X		count++;
X	}
X	buf[count] = NULL;
X	return(buf);
X}
SHAR_EOF
if test 3497 -ne "`wc -c < 'd_print.c'`"
then
	echo shar: "error transmitting 'd_print.c'" '(should have been 3497 characters)'
fi
fi
echo shar: "extracting 'd_prompt.c'" '(5941 characters)'
if test -f 'd_prompt.c'
then
	echo shar: "will not over-write existing file 'd_prompt.c'"
else
sed 's/^X//' << \SHAR_EOF > 'd_prompt.c'
X/*
X * Prompt for directory entry changes.  Copies the original values in
X * case you change your mind half way thru.  A return code of 1 means
X * the entry was changed.
X */
X
X#include <stdio.h>
X#include <curses.h>
X#include "dial_dir.h"
X#include "misc.h"
X
Xint
Xprompt_lib(win, i)
XWINDOW *win;
Xint i;
X{
X	int n, baud, dbits, sbits, spot;
X	static int valid_baud[6] = {300, 1200, 2400, 4800, 9600, 19200};
X	static char *valid_parity[3] = {"Even", "Odd", "None"};
X	char *ans, *get_str(), c, temp, *name, *number, *index, parity;
X	char duplex, *strdup(), buf[40];
X	void free_ptr();
X	extern int xmc;
X	extern char *null_ptr;
X					/* make copies */
X	name = strdup(dir->name[i]);
X	number = strdup(dir->number[i]);
X	baud = dir->baud[i];
X	parity = dir->parity[i];
X	dbits = dir->dbits[i];
X	sbits = dir->sbits[i];
X	duplex = dir->duplex[i];
X	index = strdup(dir->index[i]);
X					/* display original values */
X	werase(win);
X	mvwprintw(win, 2, 5, "%-20.20s %18.18s  %5d-%c-%d-%d  %c  %-14.14s\n",
X	 dir->name[i], dir->number[i], dir->baud[i], dir->parity[i],
X	 dir->dbits[i], dir->sbits[i], dir->duplex[i], dir->index[i]);
X	box(win, '|', '-');
X
X					/* prompt for name */
X	mvwaddstr(win, 4, 4, "Name: ");
X	wrefresh(win);
X
X	if ((ans = get_str(win, 20, NULL, ";")) == NULL)
X		return(0);
X	if (*ans != NULL) {
X		if (!strcmp(ans, " "))
X			name = null_ptr;
X		else
X			name = strdup(ans);
X		mvwaddstr(win, 2, 5, "                    ");
X		wrefresh(win);
X		mvwattrstr(win, 2, 5, A_BOLD, name);
X	}
X					/* prompt for number */
X	clear_line(win, 4, 4, 1);
X	waddstr(win, "Number: ");
X	wrefresh(win);
X
X	if ((ans = get_str(win, 18, NULL, ";")) == NULL)
X		return(0);
X	if (*ans != NULL) {
X		if (!strcmp(ans, " "))
X			number = null_ptr;
X		else
X			number = strdup(ans);
X		mvwaddstr(win, 2, 26, "                  ");
X		wrefresh(win);
X		/*
X		 * Should be right justified, but we don't wanna to have
X		 * the attribute turned on for blanks.
X		 */
X		spot = 26 + 18 - strlen(number);
X		mvwattrstr(win, 2, spot, A_BOLD, number);
X	}
X					/* template for next few */
X	clear_line(win, 4, 4, 1);
X	mvwaddstr(win, 4, 31, "(Any key to change, <CR> to accept)");
X
X	/*
X	 * These next few prompts display a series of choices and allow
X	 * the user to hit a return to accept the currently showing
X	 * value.  The first value displayed is always the current value.
X	 */
X					/* choose from baud menu */
X	for (n=0; n<6; n++) {
X		if (valid_baud[n] == baud)
X			break;
X	}
X	mvwprintw(win, 4, 4, "Baud: %-5d", valid_baud[n]);
X	wmove(win, 4, 10);
X	wrefresh(win);
X
X	while ((c = wgetch(win)) != '\r') {
X		if (c == 27)
X			return(0);
X		n = (n == 5) ? 0 : n+1;
X		mvwprintw(win, 4, 4, "Baud: %-5d", valid_baud[n]);
X		wmove(win, 4, 10);
X		wrefresh(win);
X	}
X	if (baud != valid_baud[n]) {
X		baud = valid_baud[n];
X		sprintf(buf, "%5d", baud);
X		if (xmc > 0) {
X			sprintf(buf, "%5d-%c-%d-%d", baud, parity, dbits, sbits);
X			mvwaddstr(win, 2, 46, "           ");
X			wrefresh(win);
X		}
X		mvwattrstr(win, 2, 46, A_BOLD, buf);
X	}
X					/* choose from parity menu */
X	for (n=0; n<3; n++) {
X		if (*valid_parity[n] == parity)
X			break;
X	}
X	mvwprintw(win, 4, 4, "Parity: %-5.5s", valid_parity[n]);
X	wmove(win, 4, 12);
X	wrefresh(win);
X
X	while ((c = wgetch(win)) != '\r') {
X		if (c == 27)
X			return(0);
X		n = (n == 2) ? 0 : n+1;
X		mvwprintw(win, 4, 4, "Parity: %-5.5s", valid_parity[n]);
X		wmove(win, 4, 12);
X		wrefresh(win);
X	}
X	if (parity != *valid_parity[n]) {
X		parity = *valid_parity[n];
X		if (xmc > 0) {
X			sprintf(buf, "%5d-%c-%d-%d", baud, parity, dbits, sbits);
X			mvwaddstr(win, 2, 46, "           ");
X			wrefresh(win);
X			mvwattrstr(win, 2, 46, A_BOLD, buf);
X		}
X		else
X			mvwattrch(win, 2, 52, A_BOLD, parity);
X	}
X					/* choose from data bits menu */
X	n = dbits;
X	mvwprintw(win, 4, 4, "Data Bits: %d    ", n);
X	wmove(win, 4, 15);
X	wrefresh(win);
X
X	while ((c = wgetch(win)) != '\r') {
X		if (c == 27)
X			return(0);
X		n = (n == 8) ? 7 : 8;
X		mvwprintw(win, 4, 4, "Data Bits: %d    ", n);
X		wmove(win, 4, 15);
X		wrefresh(win);
X	}
X	if (dbits != n) {
X		dbits = n;
X		if (xmc > 0) {
X			sprintf(buf, "%5d-%c-%d-%d", baud, parity, dbits, sbits);
X			mvwaddstr(win, 2, 46, "           ");
X			wrefresh(win);
X			mvwattrstr(win, 2, 46, A_BOLD, buf);
X		}
X		else
X			mvwattrnum(win, 2, 54, A_BOLD, dbits);
X	}
X					/* choose from stop bits menu */
X	n = sbits;
X	mvwprintw(win, 4, 4, "Stop Bits: %d    ", n);
X	wmove(win, 4, 15);
X	wrefresh(win);
X
X	while ((c = wgetch(win)) != '\r') {
X		if (c == 27)
X			return(0);
X		n = (n == 2) ? 1 : 2;
X		mvwprintw(win, 4, 4, "Stop Bits: %d    ", n);
X		wmove(win, 4, 15);
X		wrefresh(win);
X	}
X	if (sbits != n) {
X		sbits = n;
X		if (xmc > 0) {
X			sprintf(buf, "%5d-%c-%d-%d", baud, parity, dbits, sbits);
X			mvwaddstr(win, 2, 46, "           ");
X			wrefresh(win);
X			mvwattrstr(win, 2, 46, A_BOLD, buf);
X		}
X		else
X			mvwattrnum(win, 2, 56, A_BOLD, sbits);
X	}
X					/* choose from duplex menu */
X	temp = duplex;
X	mvwprintw(win, 4, 4, "Duplex: %c    ", temp);
X	wmove(win, 4, 12);
X	wrefresh(win);
X
X	while ((c = wgetch(win)) != '\r') {
X		if (c == 27)
X			return(0);
X		temp = (temp == 'F') ? 'H' : 'F';
X		mvwprintw(win, 4, 4, "Duplex: %c    ", temp);
X		wmove(win, 4, 12);
X		wrefresh(win);
X	}
X	if (duplex != temp) {
X		duplex = temp;
X		mvwattrch(win, 2, 59, A_BOLD, duplex);
X	}
X					/* prompt for command line index */
X	clear_line(win, 4, 4, 1);
X	waddstr(win, "Command line index (or tty): ");
X	wrefresh(win);
X
X	if ((ans = get_str(win, 14, NULL, ";")) == NULL)
X		return(0);
X	if (*ans != NULL) {
X		if (!strcmp(ans, " "))
X			index = null_ptr;
X		else
X			index = strdup(ans);
X		mvwattrstr(win, 2, 62, A_BOLD, index);
X	}
X					/* store 'em for real */
X	free_ptr(dir->name[i]);
X	free_ptr(dir->number[i]);
X	free_ptr(dir->index[i]);
X
X	dir->name[i] = strdup(name);
X	dir->number[i] = strdup(number);
X	dir->baud[i] = baud;
X	dir->parity[i] = parity;
X	dir->dbits[i] = dbits;
X	dir->sbits[i] = sbits;
X	dir->duplex[i] = duplex;
X	dir->index[i] = strdup(index);
X
X	free_ptr(name);
X	free_ptr(number);
X	free_ptr(index);
X	return(1);
X}
SHAR_EOF
if test 5941 -ne "`wc -c < 'd_prompt.c'`"
then
	echo shar: "error transmitting 'd_prompt.c'" '(should have been 5941 characters)'
fi
fi
echo shar: "extracting 'd_revise.c'" '(3971 characters)'
if test -f 'd_revise.c'
then
	echo shar: "will not over-write existing file 'd_revise.c'"
else
sed 's/^X//' << \SHAR_EOF > 'd_revise.c'
X/*
X * The revise option of the dialing directory.  A return code of 1 means
X * that something was updated.  Prompts for saving changes to disk.
X */
X
X#include <stdio.h>
X#include <curses.h>
X#include "dial_dir.h"
X#include "misc.h"
X#include "param.h"
X
Xint
Xrevise()
X{
X	WINDOW *r_win, *newwin();
X	int count, dir_flag, param_flag, num, x, y, save;
X	char ans, buf[40], *ld, *prompt_ld(), *strdup();
X	void free_ptr();
X	
X	r_win = newwin(7, 77, 7, 2);
X
X	mvwaddstr(r_win, 3, 6, "Entry to revise?");
X	mvwaddstr(r_win, 3, 35, "(Entry Number, +, -, @, #)");
X	box(r_win, '|', '-');
X	wmove(r_win, 3, 23);
X	wrefresh(r_win);
X
X	dir_flag = 0;
X	param_flag = 0;
X	count = 0;
X
X	/*
X	 * Can't use my home-grown get_str() and get_num() functions
X	 * here, because we are prompting for an entry number or a
X	 * long distance code.  This routine echoes numbers only.
X	 */
X	while ((ans = wgetch(r_win)) != 27) {
X		if (ans >= '0' && ans <= '9') {
X			if (count == 3) {
X				beep();
X				continue;
X			}
X			buf[count] = ans;
X			waddch(r_win, ans);
X			wrefresh(r_win);
X			count++;
X			continue;
X		}
X					/* terminating <CR> */
X		if (ans == '\r') {
X			if (!count) {
X				beep();
X				continue;
X			}
X			buf[count] = NULL;
X			num = atoi(buf);
X					/* valid range of numbers? */
X			if (num == 0 || num > NUM_DIR) {
X				beep();
X				mvwaddstr(r_win, 3, 23, "   ");
X				wmove(r_win, 3, 23);
X				wrefresh(r_win);
X				count = 0;
X				continue;
X			}
X					/* prompt for that entry */
X			if (prompt_lib(r_win, num)) {
X				dir_flag++;
X				break;
X			}
X			delwin(r_win);
X			return(0);
X		}
X					/* do our own backspace */
X		if (ans == 8) {
X			if (!count) {
X				beep();
X				continue;
X			}
X			count--;
X			buf[count] = NULL;
X			getyx(r_win, y, x);
X			x--;
X			wmove(r_win, y, x);
X			waddch(r_win, ' ');
X			wmove(r_win, y, x);
X			wrefresh(r_win);
X			continue;
X		}
X					/* non-number after number is error */
X		if (count) {
X			beep();
X			continue;
X		}
X					/* prompt for LD codes */
X		switch (ans) {
X			case '+':
X				if ((ld = prompt_ld(r_win, param->ld_plus, ans)) != NULL) {
X					free_ptr(param->ld_plus);
X					param->ld_plus = strdup(ld);
X					param_flag++;
X				}
X				break;
X			case '-':
X				if ((ld = prompt_ld(r_win, param->ld_minus, ans)) != NULL) {
X					free_ptr(param->ld_minus);
X					param->ld_minus = strdup(ld);
X					param_flag++;
X				}
X				break;
X			case '@':
X				if ((ld = prompt_ld(r_win, param->ld_at, ans)) != NULL) {
X					free_ptr(param->ld_at);
X					param->ld_at = strdup(ld);
X					param_flag++;
X				}
X				break;
X			case '#':
X				if ((ld = prompt_ld(r_win, param->ld_pound, ans)) != NULL) {
X					free_ptr(param->ld_pound);
X					param->ld_pound = strdup(ld);
X					param_flag++;
X				}
X				break;
X			default:
X				beep();
X				continue;
X		}
X		break;
X	}
X					/* if nothing changed */
X	if (!param_flag && !dir_flag) {
X		delwin(r_win);
X		return(0);
X	}
X					/* save to disk ? */
X	clear_line(r_win, 4, 4, 1);
X	if (dir_flag) {
X		sprintf(buf, "Save entry %d to disk", num);
X		save = yes_prompt(r_win, 4, 4, A_BOLD, buf);
X	}
X	else
X		save = yes_prompt(r_win, 4, 4, A_BOLD, "Save to disk");
X
X					/* update the files */
X	if (save && dir_flag) {
X		if (update_dir(num)) {
X			touchwin(r_win);
X			wrefresh(r_win);
X		}
X	}
X	if (save && param_flag) {
X		if (update_param()) {
X			touchwin(r_win);
X			wrefresh(r_win);
X		}
X	}
X	delwin(r_win);
X	return(1);
X}
X
X/*
X * Prompt for long distance code changes.  If new string is a space,
X * change it to a null pointer.  Returns the new value or NULL on escape.
X */
X
Xchar *
Xprompt_ld(win, current_ld, name)
XWINDOW *win;
Xchar *current_ld, name;
X{
X	char *ans, *get_str();
X	extern char *null_ptr;
X
X	werase(win);
X	mvwprintw(win, 2, 4, "%-20.20s", current_ld);
X	mvwprintw(win, 4, 4, "New LD code for %c: ", name);
X	box(win, '|', '-');
X	wrefresh(win);
X
X	if ((ans = get_str(win, 20, NULL, NULL)) == NULL)
X		return(NULL);
X					/* if space, change to NULL pointer */
X	if (!strcmp(ans, " "))
X		ans = null_ptr;
X					/* display new value */
X	clear_line(win, 2, 4, 1);
X	wattrstr(win, A_BOLD, ans);
X
X	return(ans);
X}
SHAR_EOF
if test 3971 -ne "`wc -c < 'd_revise.c'`"
then
	echo shar: "error transmitting 'd_revise.c'" '(should have been 3971 characters)'
fi
fi
echo shar: "extracting 'data_log.c'" '(1840 characters)'
if test -f 'data_log.c'
then
	echo shar: "will not over-write existing file 'data_log.c'"
else
sed 's/^X//' << \SHAR_EOF > 'data_log.c'
X/*
X * Open a window to prompt for a path name to be used for the data logging
X * feature.  Turns on the data logging by killing the input routine and
X * restarting it.  A return code of 1 means we need to restart the input
X * routine.
X */
X
X#include <stdio.h>
X#include <curses.h>
X#include "misc.h"
X#include "param.h"
X#include "status.h"
X
Xint
Xdata_logging(fd)
Xint fd;
X{
X	int ret_code;
X	WINDOW *dl_win, *newwin();
X	char *ans, *path, *expand(), *get_str(), *strdup();
X	void input_off(), free_ptr();
X	extern char *null_ptr;
X
X	dl_win = newwin(6, 70, 5, 5);
X
X	mvwprintw(dl_win, 2, 4, "Default log file: %s", param->logfile);
X	mvwaddstr(dl_win, 3, 4, "New log file: ");
X	box(dl_win, '|', '-');
X
X	mvwattrstr(dl_win, 0, 3, A_BOLD, " Start Data Logging ");
X	wmove(dl_win, 3, 18);
X	wrefresh(dl_win);
X					/* get the path */
X	ret_code = 0;
X	path = null_ptr;
X	while ((ans = get_str(dl_win, 60, NULL, " 	")) != NULL) {
X					/* give 'em the default */
X		if (*ans == NULL)
X			path = strdup(param->logfile);
X		else
X			path = expand(ans);
X
X					/* test write permission */
X		if (can_write(path)) {
X			ret_code++;
X			break;
X		}
X
X		beep();
X		mvwattrstr(dl_win, 4, 24, A_BOLD, "No write permission");
X		wrefresh(dl_win);
X		wait_key(dl_win, 3);
X					/* cleanup the mess */
X		clear_line(dl_win, 3, 18, 1);
X		clear_line(dl_win, 4, 24, 1);
X		wmove(dl_win, 3, 18);
X		wrefresh(dl_win);
X	}
X	if (ret_code) {
X		/*
X		 * Killing and then restarting the input routine is the
X		 * only way to change the name of the file that the input
X		 * routines uses.  It also assures that the 'status->log'
X		 * flag is in sync with the flag in the input routine.
X		 */
X		input_off();
X		status->log = 1;
X		free_ptr(status->log_path);
X		status->log_path = strdup(path);
X	}
X	if (fd == -1) {
X		werase(dl_win);
X		wrefresh(dl_win);
X	}
X	delwin(dl_win);
X
X	free_ptr(path);
X	return(ret_code);
X}
SHAR_EOF
if test 1840 -ne "`wc -c < 'data_log.c'`"
then
	echo shar: "error transmitting 'data_log.c'" '(should have been 1840 characters)'
fi
fi
echo shar: "extracting 'di_delay.c'" '(1941 characters)'
if test -f 'di_delay.c'
then
	echo shar: "will not over-write existing file 'di_delay.c'"
else
sed 's/^X//' << \SHAR_EOF > 'di_delay.c'
X/*
X * Prompt for new delay times during a dialing session.  Also, prompts
X * if changes should be saved to disk.  Dialing is suspended during
X * this routine.
X */
X
X#include <stdio.h>
X#include <curses.h>
X#include "misc.h"
X#include "param.h"
X
Xvoid
Xdelay_times()
X{
X	WINDOW *dt_win, *newwin();
X	int cdelay, pause;
X
X	dt_win = newwin(9, 45, 7, 15);
X
X	mvwprintw(dt_win, 2, 4, "Current carrier delay time: %d", param->cdelay);
X	mvwprintw(dt_win, 3, 4, "Current pause between redials: %d", param->pause);
X	mvwaddstr(dt_win, 5, 4, "New carrier delay: ");
X	mvwaddstr(dt_win, 6, 4, "New pause time: ");
X	box(dt_win, '|', '-');
X
X	mvwattrstr(dt_win, 0, 3, A_BOLD, " Change delay times ");
X	wmove(dt_win, 5, 23);
X	wrefresh(dt_win);
X					/* get the cdelay number */
X	if ((cdelay = get_num(dt_win, 3)) == -1) {
X		delwin(dt_win);
X		return;
X	}
X					/* give 'em the current settings */
X	if (!cdelay) {
X		cdelay = param->cdelay;
X		wprintw(dt_win, "%-3d", cdelay);
X	}
X	else {
X					/* some reasonable limit */
X		if (cdelay > MAX_CDELAY || cdelay < MIN_CDELAY) {
X			beep();
X			if (cdelay > MAX_CDELAY)
X				cdelay = MAX_CDELAY;
X			else
X				cdelay = MIN_CDELAY;
X			mvwprintw(dt_win, 5, 23, "%-3d", cdelay);
X		}
X	}
X					/* get the pause number */
X	wmove(dt_win, 6, 20);
X	wrefresh(dt_win);
X	if ((pause = get_num(dt_win, 3)) == -1) {
X		delwin(dt_win);
X		return;
X	}
X					/* give 'em the current settings */
X	if (!pause) {
X		pause = param->pause;
X		wprintw(dt_win, "%-3d", pause);
X	}
X	else {
X					/* some reasonable limit */
X		if (pause > MAX_PAUSE || pause < MIN_PAUSE) {
X			beep();
X			if (pause > MAX_PAUSE)
X				pause = MAX_PAUSE;
X			else
X				pause = MIN_PAUSE;
X			mvwprintw(dt_win, 6, 20, "%-3d", pause);
X		}
X	}
X					/* set 'em */
X	param->cdelay = cdelay;
X	param->pause = pause;
X					/* save 'em to disk ? */
X	if (yes_prompt(dt_win, 7, 12, A_BOLD, "Save to disk")) {
X		if (update_param()) {
X			touchwin(dt_win);
X			wrefresh(dt_win);
X		}
X	}
X
X	delwin(dt_win);
X	return;
X}
SHAR_EOF
if test 1941 -ne "`wc -c < 'di_delay.c'`"
then
	echo shar: "error transmitting 'di_delay.c'" '(should have been 1941 characters)'
fi
fi
echo shar: "extracting 'di_win.c'" '(9254 characters)'
if test -f 'di_win.c'
then
	echo shar: "will not over-write existing file 'di_win.c'"
else
sed 's/^X//' << \SHAR_EOF > 'di_win.c'
X/*
X * The dialing window routines.
X */
X
X#define MAX_PASS 25
X
X#include <stdio.h>
X#include <curses.h>
X#include <signal.h>
X#include <setjmp.h>
X#include "dial_dir.h"
X#include "misc.h"
X#include "modem.h"
X#include "param.h"
X#include "status.h"
X
X/*
X * The dialing window.  Its job is to kill the input routine, get a port,
X * cycle thru the entries in the queue, while interpreting both the
X * user's requests and the modem's responses.  A return code of 1 means
X * we're ready to fire up the input mode.
X */
X
Xint
Xdial_win()
X{
X	WINDOW *di_win, *newwin();
X	int i, j, ans, want_out, pass, tic, baud, modem_sync;
X	long now, time();
X	char *tbuf, *ctime(), *str, cr=13, *monitor_dial();
X	void disp_queue(), send_str(), dial_it(), delay_times(), input_off();
X	void error_win(), status_line(), line_set(), hang_up();
X	extern int rc_index;
X	unsigned int sleep();
X					/* are we already talking? */
X	input_off();
X	hang_up(1);
X
X	if (get_port())
X		return(0);
X	/*
X	 * If the phone number is a NULL, then either we are on a
X	 * direct line, or you want to do the dialing yourself.
X	 */
X	if (*dir->number[dir->q_num[0]] == NULL) {
X					/* check LD permission */
X		if (limit_ld(0))
X			return(0);
X					/* can't talk directly to OBM */
X		if (!strcmp(modem->mname[modem->m_cur], "OBM")) {
X			error_win(0, "Can't access the line directly.", "Use the automatic dialing feature");
X			return(0);
X		}
X		unlink(status->vs_path);
X		touchwin(stdscr);
X		clear();
X		printw("Connected to %s at %d baud...\n", modem->tty[modem->t_cur], dir->baud[dir->d_cur]);
X		refresh();
X		return(1);
X	}
X
X	di_win = newwin(17, 70, 3, 5);
X					/* the basic window */
X	mvwattrstr(di_win, 1, 20, A_BOLD, "D I A L I N G       W I N D O W");
X	mvwaddstr(di_win, 2, 0, "---------------------------------------------------------------------");
X	mvwaddstr(di_win, 4, 23, "System name:");
X	mvwaddstr(di_win, 5, 23, "Pass number:");
X	mvwaddstr(di_win, 6, 14, "Elapse time this try:");
X	mvwaddstr(di_win, 7, 13, "Time at start of dial:");
X	mvwaddstr(di_win, 8, 9, "Time at start of this try:");
X	mvwaddstr(di_win, 9, 16, "Connect delay time:");
X	mvwaddstr(di_win, 10, 15, "Pause between tries:");
X	mvwaddstr(di_win, 11, 25, "Index/tty:");
X	mvwaddstr(di_win, 12, 16, "Result of last try:");
X
X	mvwaddstr(di_win, 14, 3, "SPACE: Recycle");
X	mvwaddstr(di_win, 14, 21, "DEL: Remove from queue");
X	mvwaddstr(di_win, 14, 46, "E: Change delay times");
X
X					/* the start time */
X	time(&now);
X	tbuf = ctime(&now);
X	tbuf[19] = NULL;
X	mvwaddstr(di_win, 7, 36, &tbuf[11]);
X
X	mvwprintw(di_win, 9, 36, "%-4d", param->cdelay);
X	mvwprintw(di_win, 10, 36, "%-4d", param->pause);
X
X	box(di_win, '|', '-');
X	mvwaddstr(di_win, 16, 25, " Press ESC to abort ");
X
X	pass = 0;
X	i = 0;
X	want_out = 0;
X	while (!want_out && pass <= MAX_PASS) {
X		ans = -1;
X		pass++;
X					/* update the d_cur variable */
X		dir->d_cur = dir->q_num[i];
X					/* check LD permission */
X		if (limit_ld(i))
X			return(0);
X					/* get a port */
X		if (get_port())
X			return(0);
X					/* can the modem sync baud rates ? */
X		modem_sync = can_sync();
X					/* fill in the window */
X		disp_queue(di_win, dir->d_cur, pass);
X
X		/*
X		 * The actual dial routine. The 'i' is the index into the
X		 * queue, not the entry number.  Returns immediately without
X		 * waiting for a carrier.
X		 */
X		dial_it(i);
X		ioctl(status->fd, TCFLSH, 0);
X
X		/*
X		 * Here we do a time-slice between reading the result codes
X		 * from the modem and reading the keyboard.  The one second
X		 * granularity won't be too accurate, but who cares?
X		 */
X		tic = 0;
X		rc_index = 0;
X		while (tic < param->cdelay) {
X			if (!(str = monitor_dial())) {
X				mvwprintw(di_win, 6, 36, "%-4d", ++tic);
X				wrefresh(di_win);
X			}
X			else {
X				/*
X				 * A return code that converts to an number
X				 * that is less than 300 is probably an error
X				 * message.
X				 */
X				baud = atoi(str);
X				if (baud < 300) {
X					mvwprintw(di_win, 12, 36, "%-20.20s", str);
X					wmove(di_win, 12, 36);
X					wrefresh(di_win);
X					break;
X				}
X					/* we're connected */
X				beep();
X				clear_line(di_win, 12, 36, 1);
X				wattrstr(di_win, A_BLINK, "CONNECTED");
X				wmove(di_win, 12, 36);
X				wrefresh(di_win);
X				wait_key(di_win, 2);
X				delwin(di_win);
X
X				/*
X				 * Did the modem sync at a different baud
X				 * rate than what we expected?
X				 */
X				if (modem_sync) {
X					if (dir->baud[dir->d_cur] != baud) {
X						dir->baud[dir->d_cur] = baud;
X						line_set();
X					}
X				}
X
X				unlink(status->vs_path);
X				touchwin(stdscr);
X				clear();
X				printw("Connected to %s at %d baud...\n",
X				 dir->name[dir->d_cur], dir->baud[dir->d_cur]);
X				refresh();
X
X					/* log the call */
X				log_calls(i);
X				return(1);
X			}
X			if (tic == param->cdelay)
X				break;
X					/* ok... try the keyboard */
X			if ((ans = wait_key(di_win, 1)) != -1)
X				break;
X
X			mvwprintw(di_win, 6, 36, "%-4d", ++tic);
X			wrefresh(di_win);
X		}
X		/*
X		 * If the modem did not return a code, then we need to
X		 * stop it.  Sending a CR will stop most modems cold,
X		 * except of course for the OBM...
X		 */
X		if (str == NULL) {
X			if (!strcmp(modem->mname[modem->m_cur], "OBM"))
X				hang_up(0);
X			else
X				write(status->fd, &cr, 1);
X			sleep(1);
X		}
X					/* if we get here, no key was pressed */
X		if (ans == -1) {
X			clear_line(di_win, 6, 14, 1);
X			mvwaddstr(di_win, 6, 27, "Pausing:");
X					/* no return code ? */
X			if (str == NULL) {
X				clear_line(di_win, 12, 36, 1);
X				waddstr(di_win, "TIMED OUT");
X				wmove(di_win, 12, 36);
X			}
X					/* do the pause */
X			tic = 0;
X			while (tic < param->pause) {
X				if ((ans = wait_key(di_win, 1)) != -1)
X					break;
X				mvwprintw(di_win, 6, 36, "%-4d", ++tic);
X				wrefresh(di_win);
X			}
X			clear_line(di_win, 6, 14, 1);
X			waddstr(di_win, "Elapse time this try:");
X		}
X					/* Process the keystroke */
X		switch(ans) {
X			case ' ':	/* next in the queue */
X				clear_line(di_win, 12, 36, 1);
X				waddstr(di_win, "RECYCLED");
X				wmove(di_win, 12, 36);
X				wrefresh(di_win);
X				/* fall thru... */
X			case -1:	/* no key was pressed */
X				i++;
X				if (i > NUM_QUEUE)
X					i = 0;
X				if (dir->q_num[i] == -1)
X					i = 0;
X				break;
X			case 127:	/* DEL key, remove from queue */
X				if (dir->q_num[1] == -1) {
X					beep();
X					clear_line(di_win, 12, 36, 1);
X					waddstr(di_win, "NO MORE ENTRIES");
X					wmove(di_win, 12, 36);
X					wrefresh(di_win);
X					wait_key(di_win, 3);
X					break;
X				}
X				clear_line(di_win, 12, 36, 1);
X				waddstr(di_win, "ENTRY DELETED");
X				wmove(di_win, 12, 36);
X				wrefresh(di_win);
X				wait_key(di_win, 3);
X
X					/* compact the queue */
X				for (j=i; j<NUM_QUEUE-1; j++)
X					dir->q_num[j] = dir->q_num[j+1];
X				dir->q_num[NUM_QUEUE-1] = -1;
X				break;
X			case 'e':
X			case 'E':	/* change delay time */
X				delay_times();
X				touchwin(di_win);
X				mvwprintw(di_win, 9, 36, "%-4d", param->cdelay);
X				mvwprintw(di_win, 10, 36, "%-4d", param->pause);
X				break;
X			case 27:	/* ESC key */
X				beep();
X				clear_line(di_win, 12, 36, 1);
X				wattrstr(di_win, A_BLINK, "DIAL ABORTED");
X				wmove(di_win, 12, 36);
X				wrefresh(di_win);
X				wait_key(di_win, 3);
X				want_out++;
X				break;
X			default:
X				beep();
X				break;
X		}
X	}
X					/* clean up and go home */
X	werase(di_win);
X	wrefresh(di_win);
X	delwin(di_win);
X	if (!want_out)
X		error_win(0, "Exceeded the maximum number number of dialing attempts", NULL);
X	return(0);
X}
X
X/*
X * Display what info we know at this time.
X */
X
Xvoid
Xdisp_queue(win, entry, pass)
XWINDOW *win;
Xint entry, pass;
X{
X	long now, time();
X	char *tbuf, *ctime();
X	void status_line();
X					/* redo the status line */
X	status_line(NULL);
X					/* system name */
X	clear_line(win, 4, 36, 1);
X	waddstr(win, dir->name[entry]);
X					/* pass number */
X	mvwprintw(win, 5, 36, "%-4d", pass);
X					/* time of this call */
X	time(&now);
X	tbuf = ctime(&now);
X	tbuf[19] = NULL;
X	mvwaddstr(win, 8, 36, &tbuf[11]);
X					/* the index field */	
X	clear_line(win, 11, 36, 1);
X	waddstr(win, dir->index[entry]);
X
X	wmove(win, 12, 36);
X	wrefresh(win);
X	return;
X}
X
X/*
X * Monitor the progress of the dialing, but returns a NULL after one
X * second of inactivity.
X */
X
Xjmp_buf md_jmp;
X
Xchar *
Xmonitor_dial()
X{
X	int force_md();
X	char *ans, *read_codes();
X	unsigned int alarm();
X
X	if (setjmp(md_jmp))
X		return(NULL);
X	signal(SIGALRM, force_md);
X	alarm(1);
X	ans = read_codes();
X	alarm(0);
X	return(ans);
X}
Xint
Xforce_md(dummy)
Xint dummy;
X{
X	void longjmp();
X
X	longjmp(md_jmp, 1);
X}
X
X/*
X * Determine if the modem can detect the synchronization of the baud
X * rate if it's different that what it expects.  To do this, we check
X * to see if any two connect strings are the same.  A return code of
X * 1 means the modem can sync.
X */
X
Xint
Xcan_sync()
X{
X	int i;
X
X	i = modem->m_cur;
X					/* not both null (sneaky trick) */
X	if (*modem->con_3[i] + *modem->con_12[i]) {
X		if (!strcmp(modem->con_3[i], modem->con_12[i]))
X			return(0);
X	}
X	if (*modem->con_12[i] + *modem->con_24[i]) {
X		if (!strcmp(modem->con_12[i], modem->con_24[i]))
X			return(0);
X	}
X	if (*modem->con_24[i] + *modem->con_48[i]) {
X		if (!strcmp(modem->con_24[i], modem->con_48[i]))
X			return(0);
X	}
X	if (*modem->con_48[i] + *modem->con_96[i]) {
X		if (!strcmp(modem->con_48[i], modem->con_96[i]))
X			return(0);
X	}
X	if (*modem->con_96[i] + *modem->con_192[i]) {
X		if (!strcmp(modem->con_96[i], modem->con_192[i]))
X			return(0);
X	}
X	return(1);
X}
SHAR_EOF
if test 9254 -ne "`wc -c < 'di_win.c'`"
then
	echo shar: "error transmitting 'di_win.c'" '(should have been 9254 characters)'
fi
fi
echo shar: "extracting 'dial.c'" '(6478 characters)'
if test -f 'dial.c'
then
	echo shar: "will not over-write existing file 'dial.c'"
else
sed 's/^X//' << \SHAR_EOF > 'dial.c'
X/*
X * The routines that dial the modem and listen for the return codes.
X */
X
X#include <stdio.h>
X#include <termio.h>
X#ifdef UNIXPC
X#include <sys/phone.h>
X#endif /* UNIXPC */
X#include "dial_dir.h"
X#include "modem.h"
X#include "param.h"
X#include "status.h"
X
X/*
X * Get the dial string ready, send it to the modem.  The parameter is not
X * the actual entry number, it is an index into the queue.
X */
X
Xvoid
Xdial_it(num)
Xint num;
X{
X	int i;
X	char s[100], number[40], *strcpy(), *strcat(), *n, *strchr();
X	void send_str();
X#ifdef UNIXPC
X	struct updata pbuf;
X	unsigned int sleep();
X#endif /* UNIXPC */
X
X	/*
X	 * Create the string to be sent to the modem.  The long distance
X	 * codes are added if they are requested.
X	 */
X	s[0] = NULL;
X	strcpy(s, modem->dial[modem->m_cur]);
X
X	switch (dir->q_ld[num]) {
X		case 0:			/* no ld code requested */
X			break;
X		case '+':
X			strcat(s, param->ld_plus);
X			break;
X		case '-':
X			strcat(s, param->ld_minus);
X			break;
X		case '@':
X			strcat(s, param->ld_at);
X			break;
X		case '#':
X			strcat(s, param->ld_pound);
X			break;
X	}
X	/*
X	 * Purify the phone number by removing all the pretty characters
X	 * that don't need to be sent to the modem.  Typically the '-',
X	 * '(', ')', and space characters are just for looks.
X	 */
X	i = 0;
X	n = dir->number[dir->q_num[num]];
X	while (*n) {
X		if (!strchr("-() ", *n))
X			number[i++] = *n;
X		n++;
X	}
X	number[i] = NULL;
X					/* add it to the string */
X	strcat(s, number);
X	strcat(s, modem->suffix[modem->m_cur]);
X
X#ifdef UNIXPC
X					/* special case for OBM */
X	if (!strcmp(modem->mname[modem->m_cur], "OBM")) {
X					/* prepare the modem */
X		pbuf.c_lineparam = DATA|DTMF;
X		pbuf.c_waitdialtone = 5;
X		pbuf.c_linestatus = 0;
X		pbuf.c_feedback = SPEAKERON|NORMSPK;
X		pbuf.c_waitflash = 500;
X		ioctl(status->fd, PIOCSETP, &pbuf);
X
X					/* connect the dialer */
X		ioctl(status->fd, PIOCRECONN);
X		sleep(1);
X					/* dial each digit */
X		n = s;
X		while(*n) {
X					/* switch tone/pulse dialing ? */
X			switch(*n) {
X				case '^':
X					pbuf.c_lineparam = DATA|PULSE;
X					ioctl(status->fd, PIOCSETP, &pbuf);
X					break;
X				case '%':
X					pbuf.c_lineparam = DATA|DTMF;
X					ioctl(status->fd, PIOCSETP, &pbuf);
X					break;
X				default:
X					ioctl(status->fd, PIOCDIAL, n);
X					break;
X			}
X			n++;
X		}
X	}
X
X#else /* UNIXPC */
X	send_str(s);
X#endif /* UNIXPC */
X	return;
X}
X
X/*
X * Send a string to the modem.  Performs all the character synonym
X * translations.  No sanity checking on the "m_cur" value.
X */
X
Xvoid
Xsend_str(s)
Xchar *s;
X{
X	int skip;
X	char c;
X	unsigned int sleep();
X					/* empty string ?? */
X	if (s == NULL || *s == NULL)
X		return;
X
X	ioctl(status->fd, TCFLSH, 1);	
X	/*
X	 * Change the character synonyms to their real values.  Writes
X	 * the characters to the modem.  To remove the special meaning
X	 * of one of the characters, prepend a '\' to it.
X	 */
X	skip = 0;
X	while (*s) {
X		c = *s;
X					/* send the literal character */
X		if (skip) {
X			skip = 0;
X			write(status->fd, &c, 1);
X			ioctl(status->fd, TCSBRK, 1);
X			s++;
X			continue;
X		}
X					/* turn off the special meaning */
X		if (c == '\\') {
X			skip = 1;
X			s++;
X			continue;
X		}
X					/* carriage return synonym */
X		if (c == param->cr_char)
X			c = '\r';
X					/* 2 character control sequence */
X		if (c == param->ctrl_char) {
X			s++;
X			c = *s;
X					/* premature EOF? */
X			if (c == NULL)
X				break;
X			if (c > '_')
X				c -= 96;
X			else
X				c -= 64;
X		}
X					/* escape synonym */
X		if (c == param->esc_char)
X			c = 27;
X					/* pause synonym */
X		if (c == param->pause_char) {
X			sleep(1);
X			s++;
X			continue;
X		}
X		write(status->fd, &c, 1);
X		/*
X		 * Because the pause char makes the timing critical, we
X		 * wait until the buffer is clear before we continue.
X		 */
X		ioctl(status->fd, TCSBRK, 1);
X		s++;
X	}
X	return;
X}
X
X/*
X * Read the result codes coming back from the modem.  Test for the 6
X * "connect" strings and the 4 "no connect" strings.  Return the connected
X * baud rate (as a string) or the error message.
X */
X
Xchar rc_buf[512];
Xint rc_index;
X
Xchar *
Xread_codes()
X{
X	char c;
X#ifdef UNIXPC
X	unsigned int sleep();
X	struct updata pbuf;
X					/* special case for OBM */
X	if (!strcmp(modem->mname[modem->m_cur], "OBM")) {
X		ioctl(status->fd, PIOCGETP, &pbuf);
X
X					/* fake the return code */
X		if (pbuf.c_linestatus & MODEMCONNECTED)
X			return("1200");
X
X		sleep(1);
X		return(NULL);
X	}
X#endif /* UNIXPC */
X					/* search for key words */
X	for (; rc_index<511; rc_index++) {
X		if (read(status->fd, &c, 1) <= 0)
X			return(NULL);
X
X		rc_buf[rc_index] = c;
X		rc_buf[rc_index+1] = NULL;
X					/* the connect strings */
X		if (match(rc_buf, modem->con_3[modem->m_cur]))
X			return("300");
X
X		if (match(rc_buf, modem->con_12[modem->m_cur]))
X			return("1200");
X
X		if (match(rc_buf, modem->con_24[modem->m_cur]))
X			return("2400");
X
X		if (match(rc_buf, modem->con_48[modem->m_cur]))
X			return("4800");
X
X		if (match(rc_buf, modem->con_96[modem->m_cur]))
X			return("9600");
X
X		if (match(rc_buf, modem->con_192[modem->m_cur]))
X			return("19200");
X
X					/* the no connect strings */
X		if (match(rc_buf, modem->no_con1[modem->m_cur]))
X			return(modem->no_con1[modem->m_cur]);
X
X		if (match(rc_buf, modem->no_con2[modem->m_cur]))
X			return(modem->no_con2[modem->m_cur]);
X
X		if (match(rc_buf, modem->no_con3[modem->m_cur]))
X			return(modem->no_con3[modem->m_cur]);
X
X		if (match(rc_buf, modem->no_con4[modem->m_cur]))
X			return(modem->no_con4[modem->m_cur]);
X	}
X					/* ran out of buffer ? */
X	return("ERROR");
X}
X
X/*
X * Test for a match between two character strings.  A return code of 1
X * means that s2 was found at the end of s1
X */
X
Xint
Xmatch(s1, s2)
Xchar *s1, *s2;
X{
X	int i, skip, diff;
X	char c, new[40];
X					/* if no string to match */
X	if (*s2 == NULL)
X		return(0);
X					/* translate synonyms */
X	i = 0;
X	skip = 0;
X	while (*s2) {
X		c = *s2;
X					/* literal character */
X		if (skip) {
X			skip = 0;
X			new[i++] = c;
X			s2++;
X			continue;
X		}
X					/* turn off the special meaning */
X		if (c == '\\') {
X			skip = 1;
X			s2++;
X			continue;
X		}
X					/* carriage return synonym */
X		if (c == param->cr_char)
X			c = '\r';
X
X					/* 2 character control sequence */
X		if (c == param->ctrl_char) {
X			s2++;
X			c = *s2;
X			if (c == NULL)
X				break;
X			if (c > '_')
X				c -= 96;
X			else
X				c -= 64;
X		}
X					/* escape synonym */
X		if (c == param->esc_char)
X			c = 27;
X
X		new[i++] = c;
X		s2++;
X	}
X	new[i] = NULL;
X
X	diff = strlen(s1) - strlen(new);
X					/* is it possible ? */
X	if (diff < 0)
X		return(0);
X					/* test it out */
X	if (!strcmp(&s1[diff], new))
X		return(1);
X	return(0);
X}
SHAR_EOF
if test 6478 -ne "`wc -c < 'dial.c'`"
then
	echo shar: "error transmitting 'dial.c'" '(should have been 6478 characters)'
fi
fi
echo shar: "extracting 'expand.c'" '(2396 characters)'
if test -f 'expand.c'
then
	echo shar: "will not over-write existing file 'expand.c'"
else
sed 's/^X//' << \SHAR_EOF > 'expand.c'
X/*
X * Do file name expansion with 'native' shell.  Using the native shell
X * (as described in the SHELL environmental variable) allows for csh or
X * ksh abbreviations that sh doesn't recognize.
X */
X
X#include <stdio.h>
X#include <signal.h>
X
Xchar *
Xexpand(input)
Xchar *input;
X{
X	FILE *pfp, *native_popen();
X	char *ans, buf[1024], *strpbrk(), *strdup();
X	extern char *null_ptr;
X	void free_ptr();
X
X					/* same rules as strdup() */
X	if (input == NULL)
X		return(NULL);
X	if (*input == NULL)
X		return(null_ptr);
X					/* any thing to expand ? */
X	ans = strdup(input);
X	if (!strpbrk(input, "$*{}[]\\?~"))
X		return(ans);
X					/* popen an echo */
X	sprintf(buf, "echo %s", input);
X
X	pfp = native_popen(buf, "r");
X	fgets(buf, 1024, pfp);
X	native_pclose(pfp);
X
X	if (!strlen(buf))
X		return(ans);
X					/* zap the line feed */
X	buf[strlen(buf)-1] = NULL;
X
X	free_ptr(ans);
X	ans = strdup(buf);
X	return(ans);
X}
X
X#define	tst(a,b) (*mode == 'r'? (b) : (a))
X#define	RDR	0
X#define	WTR	1
Xstatic int popen_pid[20];
X
XFILE *
Xnative_popen(cmd, mode)
Xchar *cmd, *mode;
X{
X	int myside, hisside, pid, p[2];
X	char *shellpath, *shell, *flags, *getenv(), *strrchr();
X	void _exit();
X
X	if (pipe(p) < 0)
X		return NULL;
X
X	myside = tst(p[WTR], p[RDR]);
X	hisside = tst(p[RDR], p[WTR]);
X					/* get the environmental variable */
X	shellpath = getenv("SHELL");
X	if (shellpath == NULL || strlen(shellpath) == 0)
X		shellpath = "/bin/sh";
X
X	shell = strrchr(shellpath, '/') + 1;
X					/* fix up the flags */
X	if (!strcmp(shell, "csh"))
X		flags = "-fc";
X	else
X		flags = "-c";		/* Korn shell too */
X
X	if (!(pid = fork())) {
X		int stdio;
X					/* no error messages please */
X		close(2);
X#ifdef SGID
X		setgid(getgid());
X#endif /* SGID */
X		stdio = tst(0, 1);
X		close(myside);
X		close(stdio);
X		fcntl(hisside, 0, stdio);
X		close(hisside);
X		execl(shellpath, shell, flags, cmd, 0);
X		_exit(1);
X	}
X	if (pid == -1) {
X		close(myside);
X		close(hisside);
X		return NULL;
X	}
X
X	popen_pid[myside] = pid;
X
X	close(hisside);
X	return(fdopen(myside, mode));
X}
X
Xnative_pclose(ptr)
XFILE *ptr;
X{
X	int f, r, (*hstat)(), (*istat)(), (*qstat)(), status;
X
X	f = fileno(ptr);
X	fclose(ptr);
X	istat = signal(SIGINT, SIG_IGN);
X	qstat = signal(SIGQUIT, SIG_IGN);
X	hstat = signal(SIGHUP, SIG_IGN);
X
X	while ((r = wait(&status)) != popen_pid[f] && r != -1)
X		;
X
X	if (r == -1)
X		status = -1;
X
X	signal(SIGINT, istat);
X	signal(SIGQUIT, qstat);
X	signal(SIGHUP, hstat);
X	return(status);
X}
SHAR_EOF
if test 2396 -ne "`wc -c < 'expand.c'`"
then
	echo shar: "error transmitting 'expand.c'" '(should have been 2396 characters)'
fi
fi
echo shar: "extracting 'getcwd.c'" '(382 characters)'
if test -f 'getcwd.c'
then
	echo shar: "will not over-write existing file 'getcwd.c'"
else
sed 's/^X//' << \SHAR_EOF > 'getcwd.c'
X/*
X * Can you believe it???  Masscomps don't have a function to return the
X * current working directory while in the AT&T universe!
X */
X
X#include <stdio.h>
X
Xchar *
Xgetcwd(buf, size)
Xchar *buf;
Xint size;
X{
X	FILE *pfp, *popen();
X
X	if (!(pfp = popen("pwd", "r")))
X		return(".");
X	
X	fgets(buf, size, pfp);
X	pclose(pfp);
X					/* zap the NL */
X	buf[strlen(buf)-1] = NULL;
X	return(buf);
X}
SHAR_EOF
if test 382 -ne "`wc -c < 'getcwd.c'`"
then
	echo shar: "error transmitting 'getcwd.c'" '(should have been 382 characters)'
fi
fi
echo shar: "extracting 'getopt.c'" '(1034 characters)'
if test -f 'getopt.c'
then
	echo shar: "will not over-write existing file 'getopt.c'"
else
sed 's/^X//' << \SHAR_EOF > 'getopt.c'
X/*
X * Parse the command line and return option flags and arguments
X */
X
X#include <stdio.h>
X
Xint optind = 1;
Xchar *optarg;
X
Xint
Xgetopt(argc, argv, opts)
Xint argc;
Xchar *argv[];
Xchar *opts;
X{
X	static int sp = 1;
X	int c, strcmp();
X	char *cp, *strchr();
X
X	if (sp == 1) {
X		if (optind >= argc || argv[optind][0] != '-' || argv[optind][1] == '\0')
X			return(EOF);
X		else if (strcmp(argv[optind], "--") == NULL) {
X			optind++;
X			return(EOF);
X		}
X	}
X	c = argv[optind][sp];
X	if (c == ':' || (cp=strchr(opts, c)) == NULL) {
X		fprintf(stderr, "%s: illegal option '%c'\n", argv[0], c);
X		if (argv[optind][++sp] == '\0') {
X			optind++;
X			sp = 1;
X		}
X		return('?');
X	}
X	if (*++cp == ':') {
X		if (argv[optind][sp+1] != '\0')
X			optarg = &argv[optind++][sp+1];
X		else if (++optind >= argc) {
X			fprintf(stderr, "%s: option '%c' requires an argument\n", argv[0], c);
X			sp = 1;
X			return('?');
X		} else
X			optarg = argv[optind++];
X		sp = 1;
X	} else {
X		if (argv[optind][++sp] == '\0') {
X			sp = 1;
X			optind++;
X		}
X		optarg = NULL;
X	}
X	return(c);
X}
SHAR_EOF
if test 1034 -ne "`wc -c < 'getopt.c'`"
then
	echo shar: "error transmitting 'getopt.c'" '(should have been 1034 characters)'
fi
fi
echo shar: "extracting 'help.c'" '(1786 characters)'
if test -f 'help.c'
then
	echo shar: "will not over-write existing file 'help.c'"
else
sed 's/^X//' << \SHAR_EOF > 'help.c'
X/*
X * Display the help screen.  Press any key to continue.  If the ascii_hot
X * string is more than 4 characters wide, this screen will look silly.
X * Maybe one day, this will also contain page-full descriptions of each
X * command.
X */
X
X#include <stdio.h>
X#include <curses.h>
X#include "misc.h"
X
Xvoid
Xhelp_screen(hot, fd)
Xchar *hot;
Xint fd;
X{
X	WINDOW *h_win, *newwin();
X
X	h_win = newwin(17, 80, 0, 0);
X
X	mvwattrstr(h_win, 1, 29, A_BOLD, "P C O M M       H E L P\n");
X	waddstr(h_win, "-------------------------------------------------------------------------------\n\n");
X	wattrstr(h_win, A_BOLD, "        Major Functions         Utility Functions         File Functions\n\n");
X	wprintw(h_win, "  Dialing Directory .%4.4s-D  Program Info .....%4.4s-I  Send files ....%4.4s-up\n", hot, hot, hot);
X	wprintw(h_win, "  Auto Redial .......%4.4s-R  Setup Screen .....%4.4s-S  Receive files .%4.4s-dn\n", hot, hot, hot);
X	wprintw(h_win, "  Keyboard Macros ...%4.4s-M  Change Directory .%4.4s-B  Directory .....%4.4s-F\n", hot, hot, hot);
X	wprintw(h_win, "  Line Settings .....%4.4s-P  Clear Screen .....%4.4s-C  Screen Dump ...%4.4s-G\n", hot, hot, hot);
X	wprintw(h_win, "  Exit Pcomm ........%4.4s-X  Toggle Duplex ....%4.4s-E  Data Logging ..%4.4s-1\n", hot, hot, hot);
X	wprintw(h_win, "  Unix Gateway ......%4.4s-4  Hangup Phone .....%4.4s-H  Toggle Log ....%4.4s-2\n", hot, hot, hot);
X	mvwprintw(h_win, 12, 29, "Printer On/Off ...%4.4s-L", hot);
X	mvwprintw(h_win, 13, 29, "Toggle CR/CR-LF ..%4.4s-3", hot);
X	mvwprintw(h_win, 14, 29, "Break Key ........%4.4s-7", hot);
X
X	box(h_win, '|', '-');
X	mvwaddstr(h_win, 16, 27, " Press any key to continue ");
X	wmove(h_win, 16, 79);
X	wrefresh(h_win);
X
X	wgetch(h_win);
X	if (fd == -1) {
X		werase(h_win);
X		wrefresh(h_win);
X	}
X	delwin(h_win);
X	return;
X}
SHAR_EOF
if test 1786 -ne "`wc -c < 'help.c'`"
then
	echo shar: "error transmitting 'help.c'" '(should have been 1786 characters)'
fi
fi
echo shar: "extracting 'info.c'" '(1269 characters)'
if test -f 'info.c'
then
	echo shar: "will not over-write existing file 'info.c'"
else
sed 's/^X//' << \SHAR_EOF > 'info.c'
X/*
X * Display the initial welcome screen (to include all of the proper
X * acknowledgements).  Press any key to continue.
X */
X
X#include <stdio.h>
X#include <curses.h>
X
Xinfo(fd)
Xint fd;
X{
X	WINDOW *w_win, *newwin();
X					/* display the welcome screen */
X	w_win = newwin(23, 80, 0, 0);
X
X	mvwaddstr(w_win, 2, 18, "PPPPPP    CCCC    OOOO    MM   MM   MM   MM");
X	mvwaddstr(w_win, 3, 18, "P    P   C       O    O   M M M M   M M M M");
X	mvwaddstr(w_win, 4, 18, "PPPPPP   C       O    O   M  M  M   M  M  M");
X	mvwaddstr(w_win, 5, 18, "P        C       O    O   M     M   M     M");
X	mvwaddstr(w_win, 6, 18, "P         CCCC    OOOO    M     M   M     M");
X
X	mvwaddstr(w_win, 10, 5, "Pcomm is a public domain telecommunication program for Unix designed");
X	mvwaddstr(w_win, 11, 5, "to operate similar to the popular MSDOS program, ProComm.  ProComm (TM)");
X	mvwaddstr(w_win, 12, 5, "is copyrighted by Datastorm Technologies, Inc.  This is a completely");
X	mvwaddstr(w_win, 13, 5, "new program and contains no ProComm source code.");
X	mvwaddstr(w_win, 19, 45, "Emmet P Gray");
X	mvwaddstr(w_win, 20, 45, "...ihnp4!uiucuxc!fthood!egray");
X
X	wmove(w_win, 22, 79);
X	wrefresh(w_win);
X	
X	wgetch(w_win);
X	if (fd == -1) {
X		werase(w_win);
X		wrefresh(w_win);
X	}
X	delwin(w_win);
X	return;
X}
SHAR_EOF
if test 1269 -ne "`wc -c < 'info.c'`"
then
	echo shar: "error transmitting 'info.c'" '(should have been 1269 characters)'
fi
fi
echo shar: "extracting 'init.c'" '(3537 characters)'
if test -f 'init.c'
then
	echo shar: "will not over-write existing file 'init.c'"
else
sed 's/^X//' << \SHAR_EOF > 'init.c'
X/*
X * Display the welcome screen and find the pcomm files.  Returns a
X * pointer to the STATUS structure.  All errors are fatal.
X */
X
X#define DEFAULT "/usr/local/lib/pcomm"
X#define VERSION "1.0"
X
X#include <stdio.h>
X#include <curses.h>
X#include "misc.h"
X#include "status.h"
X
Xstruct STATUS *
Xinit(extra, file)
Xchar *extra, *file;
X{
X	char *ans, *findfile(), *strdup(), *mktemp();
X	static struct STATUS s;
X	void s_error_win(), free_ptr();
X	extern char *null_ptr;
X					/* find the support files */
X	if ((ans = findfile(extra, "pcomm.param")) == NULL)
X		s_error_win("Can't find pcomm.param file");
X	s.p_path = strdup(ans);
X
X	if ((ans = findfile(extra, "pcomm.dial_dir")) == NULL)
X		s_error_win("Can't find pcomm.dial_dir file");
X	s.d_path = strdup(ans);
X
X	if ((ans = findfile(extra, "pcomm.modem")) == NULL)
X		s_error_win("Can't find pcomm.modem file");
X	s.m_path = strdup(ans);
X					/* some defaults */
X	s.lock_path = null_ptr;
X	s.vs_path = mktemp("/tmp/pcommXXXXXX");
X	s.log_path = strdup("NOT_DEFINED");
X	s.fd = -1;
X	s.log = 0;
X	s.print = 0;
X	s.msg = 0;
X	s.pid = -1;
X					/* display herald if no short-cut */
X	if (file == NULL) {
X
X		mvaddstr(2, 18, "PPPPPP    CCCC    OOOO    MM   MM   MM   MM");
X		mvaddstr(3, 18, "P    P   C       O    O   M M M M   M M M M");
X		mvaddstr(4, 18, "PPPPPP   C       O    O   M  M  M   M  M  M");
X		mvaddstr(5, 18, "P        C       O    O   M     M   M     M");
X		mvaddstr(6, 18, "P         CCCC    OOOO    M     M   M     M");
X
X		mvprintw(10, 26, ">>> Pcomm Version %s <<<", VERSION);
X		mvaddstr(13, 14, "A public domain telecommunication program for Unix");
X		mvaddstr(14, 8, "designed to operate similar to the popular MSDOS program, ProComm.");
X		mvaddstr(15, 11, "ProComm (TM) is copyrighted by Datastorm Technologies, Inc.");
X		mvaddstr(19, 45, "Emmet P. Gray");
X		mvaddstr(20, 45, "...!ihnp4!uiucuxc!fthood!egray");
X		move(LINES-1, COLS-1);
X		refresh();
X					/* Delay so you can read the herald */
X		wait_key(stdscr, 5);
X	}
X	erase();
X	refresh();
X	free_ptr(extra);
X	return(&s);
X}
X
X/*
X * Search the extra directory (supplied on the command line), then the
X * directory in the PCOMM environmental variable, then the current directory,
X * and lastly, the default directory.
X */
X
Xchar *
Xfindfile(extra, name)
Xchar *extra, *name;
X{
X	int i;
X	static char temp[200];
X	char *pcomm, *getenv(), *path, pbuf[200], *getcwd();
X	
X					/* see if PCOMM variable is set */	
X	pcomm = getenv("PCOMM");
X	if (pcomm == NULL || *pcomm == NULL)
X		pcomm = NULL;
X	else {
X					/* zap the trailing separator */
X		if (pcomm[strlen(pcomm)-1] == '/')
X			pcomm[strlen(pcomm)-1] = NULL;
X	}
X
X	for (i=0; i<4; i++) {
X					/* directory search order */
X		switch(i) {
X			case 0:
X				path = extra;
X				break;
X			case 1:
X				path = pcomm;
X				break;
X			case 2:
X				path = getcwd(pbuf, 200);
X				break;
X			case 3:
X				path = DEFAULT;
X				break;
X		}
X		sprintf(temp, "%s/%s", path, name);
X					/* read permission checked */
X		if (!access(temp, 4))
X			return(temp);
X	}
X	return(NULL);
X}
X
X/*
X * Handle fatal errors, similar to error_win() but we can't rely on
X * the status structure (since it hasn't been created yet!).
X */
X
Xvoid
Xs_error_win(str)
Xchar *str;
X{
X	WINDOW *se_win, *newwin();
X	void exit();
X
X	se_win = newwin(7, 70, 9, 5);
X					/* display the nasty note */
X	mvwaddstr(se_win, 2, 4, str);
X	mvwattrstr(se_win, 5, 24, A_BLINK, "Press any key to exit");
X	box(se_win, '|', '-');
X	beep();
X	wrefresh(se_win);
X
X	wgetch(se_win);
X	delwin(se_win);
X					/* erase the window we made */
X	touchwin(stdscr);
X	erase();
X	refresh();
X	endwin();
X	exit(1);
X}
SHAR_EOF
if test 3537 -ne "`wc -c < 'init.c'`"
then
	echo shar: "error transmitting 'init.c'" '(should have been 3537 characters)'
fi
fi
exit 0
#	End of shell archive


-- 
Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.