Thread View: de.comp.sources.unix
1 messages
1 total messages
Started by Frank Kaefer
Wed, 22 Jul 1992 05:04
v01i004: Pcomm 2.0 - telecommunication program for Unix, Part04/08
Author: Frank Kaefer
Date: Wed, 22 Jul 1992 05:04
Date: Wed, 22 Jul 1992 05:04
3624 lines
89799 bytes
89799 bytes
Submitted-by: egray@osiris.cso.uiuc.edu (Emmet P. Gray)
Posting-number: Volume 1, Issue 4
Archive-name: pcomm/part04
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of archive 4 (of 8)."
# Contents: pcomm-2.0/Pcomm.1 pcomm-2.0/Pcomm_cmd.out
# pcomm-2.0/curses.c pcomm-2.0/dial.c pcomm-2.0/p_lib.c
# pcomm-2.0/terminal.c pcomm-2.0/x_batch.c pcomm-2.0/x_menu.c
# pcomm-2.0/xmodem.c
# Wrapped by fkk@stasys on Tue Jul 21 22:05:59 1992
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'pcomm-2.0/Pcomm.1' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'pcomm-2.0/Pcomm.1'\"
else
echo shar: Extracting \"'pcomm-2.0/Pcomm.1'\" \(9656 characters\)
sed "s/^X//" >'pcomm-2.0/Pcomm.1' <<'END_OF_FILE'
X.\" use tbl and the man macro package
X.if n .ds rq ""
X.el .ds rq ''
X.if n .ds lq ""
X.el .ds lq ``
X.TH PCOMM 1 local
X.SH NAME
Xpcomm \- a telecommunication program
X.SH SYNOPSIS
X.B pcomm
X[
X.B \-d
Xdirectory ] [
X.B \-f
Xsystem name ] [
X.B \-a
Xauxiliary file ] [
X.B \-e
X|
X.B o
X|
X.B n
X] [
X.B -w
Xword length ] [
X.B -b
Xbaud rate ] [
X.B -p
Xphone number ]
X.SH DESCRIPTION
X.I Pcomm
Xis a public domain telecommunication program for Unix that is designed
Xto operate similarly to the MSDOS program, ProComm. ProComm (TM) is
Xcopyrighted by Datastorm Technologies, Inc.
X.PP
XThe
X.I \-d
Xoption is used to specify an additional path to search for the Pcomm
Xsupport files.
X.PP
XThe
X.I \-f
Xoption is used to specify automatic dialing of an entry in the dialing
Xdirectory. The
X.I name
Xfield in the dialing directory is checked against the string given on
Xthe command line. If a match is found, that entry is automatically
Xdialed.
X.PP
XThe
X.I \-a
Xoption is used to specify a script file to be \*(lqplayed\*(rq, the TTY
Xto be used, or the modem to be used.
X.PP
XThe remaining options are used to set the parity, data bits, baud rate,
Xand telephone number from the command line. The normal method of
Xdialing is from the dialing directory.
X.RS 5
X.TP
X.B \-e
XSet the parity to even.
X.TP
X.B \-o
XSet the parity to odd.
X.TP
X.B \-n
XSet the parity to none.
X.TP
X.B \-w
XSet the word length (number of data bits).
X.TP
X.B \-b
XSet the baud rate.
X.TP
X.B \-p
XDial this phone number.
X.RE
X.PP
XWhenever
X.I Pcomm
Xis in the command mode, a status line is displayed at the bottom of the
Xscreen. The eight fields of the status line are:
X.PP
X.RS 5
X.nf
X\(bu help screen command (or a temporary message)
X\(bu name of the TTY device in use
X\(bu duplex mode (FDX = full duplex, HDX = half duplex)
X\(bu current line settings
X\(bu status of data logging option
X\(bu status of printer logging option
X\(bu incoming CR translation
X\(bu outgoing CR translation
X.fi
X.RE
X.SH COMMANDS
XThe following commands are accessible by pressing a user definable
X\*(lqhot key\*(rq followed by a letter, number, or arrow key. The
Xdefault \*(lqhot key\*(rq is control-A. The notation \*(lq^A-X\*(rq
Xmeans control-A followed by the letter X. The dash (\-) is for clarity,
Xand is not a part of the command sequence.
X.TP
X.B ^A-0
XHelp Screen. Display a brief review of the available commands. Uses
Xthe number zero \*(lq0\*(rq not the letter \*(lqO\*(rq.
X.TP
X.B ^A-D
XDialing Directory. The dialing directory screen is used to display and
Xmaintain the database of phone number entries, and to select an entry
Xfor dialing. To dial an entry, just enter the entry number at the
Xprompt. If the script field contains valid Unix shell script, that file
Xis \*(lqplayed\*(rq, after the connection is made, to typically log the
Xuser on to the remote system. See the Pcomm Reference Manual for the
Xformat and use of the script files. The following commands are
Xavailable from the dialing directory:
X.RS 5
X.TP
X.B R
XRevise (or add) a dialing directory entry or a long distance dialing
Xcode.
X.TP
X.B P
XPrint (display) the long distance dialing codes.
X.TP
X.B up/down
XScroll the dialing directory up or down 10 lines. Uses the up and down
Xarrow keys.
X.TP
X.B M
XManual dial. Prompts for a phone number rather than using a number
Xalready in the dialing directory.
X.TP
X.B D
XDelete an entry or a range of entries.
X.TP
X.B L
XPrint. Send the dialing directory to the printer or a file of your
Xchoice.
X.RE
X.TP
X.B ^A-R
XAutomatic redial of selected dialing directory entries. Prompts the
Xuser for a list of directory entries to be placed in the queue.
X.I Pcomm
Xwill dial the numbers in a cycle until one of them answers.
X.TP
X.B ^A-M
XAllows the user to maintain a list of keyboard macros assigned to the
Xshifted number keys. When pressed, the string assigned to that key is
Xsent to the remote system.
X.TP
X.B ^A-P
XAdjust the current communication line settings. Display a menu of baud
Xrate, parity, data bit, and stop bit choices. Allows the new choice to
Xbe saved and become the default. After dialing a remote, the line
Xsettings in the dialing directory entry are automatically used. The
Xcurrent line settings are shown in the status line.
X.TP
X.B ^A-X
XExit from
X.I Pcomm.
X.TP
X.B ^A-4
XSpawn a Unix shell while still communicating with the remote system.
XUses the \*(lqnative\*(rq shell as described in the SHELL environmental
Xvariable.
X.TP
X.B ^A-5
XSelect a script file to be used to automate common keyboard input and
Xto perform Pcomm command sequences.
X.TP
X.B ^A-I
XDisplay the program information screen.
X.TP
X.B ^A-S
XDisplay a choice of setup screens. The following sub-menus are
Xavailable:
X.RS 5
X.TP
X.B 1
XTTY Setup. This setup assigns the TTY ports that
X.I Pcomm
Xis allowed to use, and what is attached to each port.
X.TP
X.B 2
XModem Setup. The modem setup contains the commands to make the modem
Xdial, hang up the phone, etc.
X.TP
X.B 3
XTerminal Setup. The terminal setup contains the definition of the
X\*(lqhot key\*(rq and the mapping of the end-of-line characters.
X.TP
X.B 4
XGeneral Setup. The general setup contains the default log file name,
Xand the set of character synonyms.
X.TP
X.B 5
XASCII Transfer Setup. This setup screen contains additional character
Xtranslations allowed during ASCII file transfers.
X.TP
X.B 6
XExternal Protocol Setup. This setup screen allows the user to embed the
Xnames of external file transfer programs into the list of available
Xprotocols.
X.TP
X.B S
XSave the changes to disk.
X.RE
X.TP
X.B ^A-B
XChange the current working directory.
X.TP
X.B ^A-C
XClear the local screen and home the cursor.
X.TP
X.B ^A-E
XToggle the duplex mode from full to half, or from half to full. The
Xstatus line shows the current duplex mode.
X.TP
X.B ^A-H
XHang up the phone. Disconnect the phone, but remain in
X.I Pcomm.
X.TP
X.B ^A-L
XToggle the printer on and off. Since the printer is accessed through
Xthe normal Unix spool program, the output is not sent to the printer
Xuntil
X.B after
Xthis feature is turned off.
X.TP
X.B ^A-3
XToggle the incoming line termination characters between the carriage
Xreturn and the carriage return line feed pair. This affects the
Xterminal session only, not the file transfers. The current settings are
Xshown in the status line.
X.TP
X.B ^A-7
XSend a modem break. This is
X.B not
Xthe same as the break key on the keyboard.
X.TP
X.B ^A-up
XDisplay a menu of file transfer protocols to be used to send files to a
Xremote system. Uses the up arrow key.
X.TP
X.B ^A-down
XDisplay file transfer protocols to be used to receive files from a
Xremote system. Uses the down arrow key.
X.TP
X.B ^A-F
XDisplay the contents of a Unix directory.
X.TP
X.B ^A-G
XDump the contents of the screen to a specified file. Special graphics
Xcharacters may not be represented accurately in the file.
X.TP
X.B ^A-1
XBegin data logging. Prompts the user for the name of the file that will
Xbe used to collect a complete record of the terminal session.
X.TP
X.B ^A-2
XToggle the data logging option without prompting for a new file name.
XThe status line shows the current data logging mode.
X.SH "FILE TRANSFERS"
X.I Pcomm
Xunderstands the following file transfer protocols:
X.PP
X.RS 5
X.TS
Xl l l l
Xl l l l
X_ _ _ _
Xl l l l.
Xprotocol packet error multiple
Xname size method files?
Xxmodem 128 checksum/CRC no
Xxmodem-1k 128/1024 checksum/CRC no
Xmodem7 128 checksum yes
Xymodem 128/1024 CRC yes
Xymodem-g 128/1024 none yes
XASCII none none no
Xzmodem 128/1024 CRC yes
X(external) ? ? ?
X.TE
X.RE
X.PP
X.I Pcomm
Xcan use an external program, such as Kermit or a proprietary program, to
Xtransfer files. Commonly used external programs (such as zmodem in the
Xexample above) can have their names embedded into the list of available
Xprotocols.
X.PP
X.SH CONFIGURATION
X.I Pcomm
Xmust have access to the terminfo or termcap data for the terminal being
Xused. The minimum capabilities include a screen size of at least 80
Xcolumns by 24 lines and cursor movement capabilities. Running
X.I Pcomm
Xfrom terminals at relatively slow speeds (i.e. 1200 baud) will cause the
Xwindows to appear sluggish.
X.PP
XTerminals that don't have arrow keys or systems without the newer
Xversions of curses(3) will require the user to substitute the letter
X\*(lqU\*(rq for \*(lqup arrow\*(rq and \*(lqN\*(rq for \*(lqdown
Xarrow\*(rq.
X.PP
XThere are four Pcomm support files that contain the dialing directory,
Xthe external file transfer programs, the modem/TTY database, and the
Xstart-up default parameters. Users may maintain private versions of
Xthese files in a directory of their choice.
X.I Pcomm
Xalso uses normal Unix shell scripts to perform the \*(lqchat\*(rq
Xsequences necessary to automatically log a user onto a remote system.
XScripts that invoke Pcomm commands require the use of the
X.I Pcomm_cmd
Xcommand. See pcomm_cmd(1).
X.I Pcomm
Xuses the environmental variable PCOMM to search for the
X\*(lqprivate\*(rq support files and script files. The following
Xdirectories are searched to find the files:
X.PP
X.RS 5
X.nf
X\(bu directory given with the \fI\-d\fP option
X\(bu directory in the PCOMM environmental variable
X\(bu current directory
X\(bu default directory (compiled into Pcomm)
X.fi
X.RE
X.PP
XThe script field in the dialing directory serves two purposes. The
Xfirst use is to identify the shell script to use for automating command
Xkeyboard and command sequences. The second use is to specify a TTY name
Xfor a given entry. If the script is a valid device name, that device is
Xused instead of searching the TTY database for a free port.
X.SH FILES
X.TS
Xl l.
Xpcomm.dial_dir the dialing directory
Xpcomm.extrnl the external file transfer programs
Xpcomm.modem the modem/TTY database
Xpcomm.param the start-up default parameters
X.TE
X.SH "SEE ALSO"
XPcomm Reference Manual, pcomm_cmd(1), waitfor(1), matches(1)
END_OF_FILE
if test 9656 -ne `wc -c <'pcomm-2.0/Pcomm.1'`; then
echo shar: \"'pcomm-2.0/Pcomm.1'\" unpacked with wrong size!
fi
# end of 'pcomm-2.0/Pcomm.1'
fi
if test -f 'pcomm-2.0/Pcomm_cmd.out' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'pcomm-2.0/Pcomm_cmd.out'\"
else
echo shar: Extracting \"'pcomm-2.0/Pcomm_cmd.out'\" \(8659 characters\)
sed "s/^X//" >'pcomm-2.0/Pcomm_cmd.out' <<'END_OF_FILE'
X
X
X
X PCOMM_CMD(1) (local) PCOMM_CMD(1)
X
X
X
X NAME
X pcomm_cmd - send a command to Pcomm
X
X SYNOPSIS
X pcomm_cmd [ command ] [ options ] [ arguments ]
X
X DESCRIPTION
X Pcomm_cmd is a Pcomm support program. It is used from
X inside shell scripts to access Pcomm commands, such as
X "pcomm_cmd send xmodem junk" for sending the file "junk"
X to the remote using the xmodem file transfer protocol.
X
X The following command line options are supported.
X
X SET BAUD [ 300 | 1200 | 2400 | 4800 | 9600 | 19200 | 38400 ]
X Set the baud rate for the current connection. This
X feature is for use with the DIAL MANUAL command, since
X the baud rate information in the dialing directory
X entries overrides this value.
X
X SET PARITY [ EVEN | ODD | NONE ]
X Set the parity for the current connection. For use
X with the DIAL MANUAL command.
X
X SET DATA_BITS [ 7 | 8 ]
X The number of data bits (word length) used for the
X current connection. For use with the DIAL MANUAL
X command.
X
X SET STOP_BITS [ 1 | 2 ]
X The number of stop bits for the current connection.
X For use with the DIAL MANUAL command.
X
X SET DUPLEX [ HALF | FULL ]
X Set the duplex mode (local echo). The HALF option is
X used if the remote system does not echo characters as
X they are typed.
X
X SET AUX filename
X Use the argument as the auxiliary file associated with
X the current connection. Since chaining of scripts is not
X supported, this feature would only be used to set the TTY
X or modem.
X
X SET HOT_KEY [1-256]
X Change the decimal value of the "hot key" to this
X value.
X
X SET ASCII_HOT string
X Change the ASCII representation of the hot key to the
X
X
X
X
X
X Page 1
X
X
X
X
X
X
X PCOMM_CMD(1) (local) PCOMM_CMD(1)
X
X
X
X given argument. The length of the string must be no
X more than 4 characters wide.
X
X SET FLOW_CTRL [ XON/XOFF | NONE ]
X Set the flow control between the local and remote
X systems to either XON/XOFF or NONE.
X
X SET CR_IN [ CR | CR/LF ]
X Translate in-comming carriage returns carriage return
X followed by a line feed, or pass the carriage return
X through unchanged.
X
X SET CR_OUT [ CR | CR/LF ]
X Translate out-going carriage returns to CR or CR/LF.
X
X SET LOGFILE filename
X Change the name of the default log file. For use with
X the DATA_LOG command.
X
X SET DUMPFILE filename
X Change the name of the screen dump file. For use with
X the SCREEN_DUMP command.
X
X SET STRIP [ YES | NO ]
X Should the in-comming data be stripped to 7 bits?
X
X SET LOCAL_ECHO [ YES | NO ]
X Should data be shown on the screen during ASCII
X uploads?
X
X SET EXPAND [ YES | NO ]
X Should blank lines be "expanded" to a line with a
X single space? For use only during ASCII uploads.
X
X SET CR_DELAY [ 0 | 100 | 150 ]
X Set the delay for the carraige returns for ASCII
X uploads.
X
X SET PACE [ YES | NO ]
X Should the entire upload be artifically slowed down?
X For use during ASCII uploads.
X
X SET CR_UP [ NONE | ADD_LF | STRIP ]
X Controls the translation of carraige returns during
X ASCII uploads.
X
X SET LF_UP [ NONE | ADD_CR | STRIP ]
X Controls the translation of line feeds during ASCII
X uploads.
X
X SET TIMER [5-150]
X Controls the timer (in seconds) that detects the end of
X
X
X
X Page 2
X
X
X
X
X
X
X PCOMM_CMD(1) (local) PCOMM_CMD(1)
X
X
X
X an ASCII download.
X
X SET CR_DN [ NONE | ADD_LF | STRIP ]
X Controls the translation of carraige returns during
X ASCII downloads.
X
X SET LF_DN [ NONE | ADD_CR | STRIP ]
X Controls the translation of line feeds during ASCII
X downloads.
X
X QUERY TTY_NAME
X Returns the name of the current TTY in use or NONE.
X
X QUERY MODEM_NAME
X Returns the name of the current modem in use or NONE.
X
X IF CONNECTED
X Returns a 1 if Pcomm is currently connected to a
X remote, otherwise a 0.
X
X IF LOG_STATUS
X Returns a 1 if the data logging feature is turned on,
X otherwise 0.
X
X IF PRINTER_STATUS
X Returns a 1 if the printer is turned on, otherwise 0.
X
X DIAL [ MANUAL phone_number ] entry_number
X Dial an entry from the dialing directory. The MANUAL
X option is used to optionaly dial a phone number without
X the use of the dialing directory. DIAL returns after 1
X attempt. A return code of 1 means a connection was
X made. The dial function will not be allowed to switch
X TTY ports. If the current TTY is not suitable (i.e.
X not attached to the correct modem), the script will be
X terminated.
X
X REDIAL entry_number
X Similar to the DIAL command, but 10 attempts are made.
X
X EXIT Hang up the phone and exit from Pcomm.
X
X CLEAR_SCREEN
X Clear the screen.
X
X CHG_DIR directory
X Change the current working directory to the given
X directory.
X
X HANG_UP
X Hang up the phone, but remain in Pcomm.
X
X
X
X
X Page 3
X
X
X
X
X
X
X PCOMM_CMD(1) (local) PCOMM_CMD(1)
X
X
X
X PRINTER [ ON | OFF ]
X Control the logging of data to the printer.
X
X MODEM_BREAK
X Send a modem break to the remote system. This is
X typically used to tell the remote to switch to a
X different baud rate.
X
X SEND protocol filename
X Send a file to the remote. The valid protocols are
X XMODEM, XMODEM_1K, MODEM7, YMODEM, YMODEM_G, ASCII,
X EXT_1, EXT_2, and EXT_3.
X
X RECEIVE protocol filename
X Receive a file from the remote. The valid protocols
X are XMODEM, XMODEM_1K, MODEM7, YMODEM, YMODEM_G, ASCII,
X EXT_1, EXT_2, and EXT_3.
X
X SCREEN_DUMP
X Dump the current contents of the screen to the
X DUMPFILE. If the file already exists, the new contents
X are appended to the file.
X
X DATA_LOG [ ON | OFF ]
X Control logging of the terminal session to the LOGFILE.
X If the file already exists, the new contents are
X appended to the file.
X
X EXAMLES
X The following is an example of a shell script that will dial
X a system, log a user on, transfer a file called "junk" using
X xmodem, log out, and exit Pcomm.
X
X # dial entry number 23 in my dialing directory
X pcomm_cmd dial 23
X # wait for the login prompt
X waitfor ogin:
X # send my user id
X echo egray
X # wait for the password prompt
X waitfor assword:
X # send my passwd
X echo abcdefg
X # wait for terminal type prompt
X waitfor vt100
X # echo my type
X echo vt100
X # wait for a Unix prompt
X waitfor $
X # start up an xmodem file transfer
X echo sx junk
X # wait for the sx command to say its ready
X
X
X
X Page 4
X
X
X
X
X
X
X PCOMM_CMD(1) (local) PCOMM_CMD(1)
X
X
X
X waitfor now
X sleep 1
X # do a file transfer
X pcomm_cmd receive xmodem junk
X # wait for the prompt
X waitfor $
X # log me out
X echo "^D"
X sleep 1
X # exit pcomm
X pcomm_cmd exit
X
X SEE ALSO
X pcomm(1), waitfor(1), matches(1), Pcomm Reference Manual
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X Page 5
X
X
X
END_OF_FILE
if test 8659 -ne `wc -c <'pcomm-2.0/Pcomm_cmd.out'`; then
echo shar: \"'pcomm-2.0/Pcomm_cmd.out'\" unpacked with wrong size!
fi
# end of 'pcomm-2.0/Pcomm_cmd.out'
fi
if test -f 'pcomm-2.0/curses.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'pcomm-2.0/curses.c'\"
else
echo shar: Extracting \"'pcomm-2.0/curses.c'\" \(8961 characters\)
sed "s/^X//" >'pcomm-2.0/curses.c' <<'END_OF_FILE'
X/*
X * Miscellaneous curses(3) routines.
X */
X
X#define STR_WIDTH 256
X#define NUM_WIDTH 16
X
X#include <stdio.h>
X#include <curses.h>
X#include <signal.h>
X#include "config.h"
X#include "misc.h"
X#include "status.h"
X
X#ifdef BSD
X#include <setjmp.h>
Xjmp_buf wk_buf;
X#endif /* BSD */
X
X#ifndef OLDCURSES
X#include <term.h>
X#else /* OLDCURSES */
X#ifdef UNIXPC
X#include <sgtty.h>
X#endif /* UNIXPC */
X#endif /* OLDCURSES */
X
X/*
X * Get a string from a window. Similar to wgetstr(), except we limit
X * the length, return a NULL (not pointer to NULL) on <ESC> key, beep
X * at any character in "disallow" string, and beep at any character not
X * in "allow". (It doesn't make sense to use both "allow" and "disallow"
X * at the same time). Returns a pointer to a static area.
X */
X
Xchar *
Xget_str(win, num, allow, disallow)
XWINDOW *win;
Xint num;
Xchar *allow, *disallow;
X{
X int count, x, y;
X char ans, *strchr();
X static char buf[STR_WIDTH];
X
X count = 0;
X while ((ans = wgetch(win)) != '\r') {
X /* do our own backspace */
X if (ans == BS || ans == DEL) {
X if (!count) {
X beep();
X continue;
X }
X count--;
X buf[count] = '\0';
X getyx(win, y, x);
X x--;
X wmove(win, y, x);
X waddch(win, (chtype) ' ');
X wmove(win, y, x);
X wrefresh(win);
X continue;
X }
X /* an <ESC> anywhere in the string */
X if (ans == ESC)
X return(NULL);
X
X /* illegal character? */
X if (*disallow != '\0' && strchr(disallow, ans)) {
X beep();
X continue;
X }
X if (*allow != '\0' && !strchr(allow, ans)) {
X beep();
X continue;
X }
X /* exceeded the max? */
X if (count >= num || count >= STR_WIDTH) {
X beep();
X continue;
X }
X
X buf[count] = ans;
X waddch(win, (chtype) ans);
X wrefresh(win);
X count++;
X }
X buf[count] = '\0';
X return(buf);
X}
X
X/*
X * Get a number from a window. We limit the length and return a -1
X * on <ESC> key.
X */
X
Xint
Xget_num(win, num)
XWINDOW *win;
Xint num;
X{
X int count, x, y, number;
X char ans, buf[NUM_WIDTH];
X
X count = 0;
X while ((ans = wgetch(win)) != '\r') {
X /* do our own backspace */
X if (ans == BS || ans == DEL) {
X if (!count) {
X beep();
X continue;
X }
X count--;
X buf[count] = '\0';
X getyx(win, y, x);
X x--;
X wmove(win, y, x);
X waddch(win, (chtype) ' ');
X wmove(win, y, x);
X wrefresh(win);
X continue;
X }
X /* an <ESC> anywhere in the string */
X if (ans == ESC)
X return(-1);
X /* only digits are allowed */
X if (ans < '0' || ans > '9') {
X beep();
X continue;
X }
X /* exceeded the max? */
X if (count >= num || count >= NUM_WIDTH) {
X beep();
X continue;
X }
X
X buf[count] = ans;
X waddch(win, (chtype) ans);
X wrefresh(win);
X count++;
X }
X buf[count] = '\0';
X number = atoi(buf);
X return(number);
X}
X
X/*
X * Change video attributes while printing a string. The use of the
X * pre-processor definition NOPROMOTE (located in config.h) means that
X * strings will be printed without any special video attribute if the
X * requested capability doesn't exist.
X */
X
Xwattrstr(win, attr, str)
XWINDOW *win;
Xchtype attr;
Xchar *str;
X{
X int do_it;
X /* if nothing, do nothing */
X if (str == NULL || *str == '\0')
X return(0);
X
X#ifdef OLDCURSES
X if (attr)
X wstandout(win);
X waddstr(win, str);
X if (attr)
X wstandend(win);
X#else /* OLDCURSES */
X
X#ifdef NOPROMOTE
X /* does the capability exist? */
X do_it = 0;
X if ((attr & A_STANDOUT) && enter_standout_mode)
X do_it++;
X if ((attr & A_UNDERLINE) && enter_underline_mode)
X do_it++;
X if ((attr & A_REVERSE) && (enter_reverse_mode || enter_standout_mode))
X do_it++;
X if ((attr & A_BLINK) && enter_blink_mode)
X do_it++;
X if ((attr & A_BOLD) && enter_bold_mode)
X do_it++;
X if ((attr & A_DIM) && enter_dim_mode)
X do_it++;
X#else /* NOPROMOTE */
X do_it = 1;
X#endif /* NOPROMOTE */
X
X if (do_it)
X wattron(win, attr);
X /* print the string */
X waddstr(win, str);
X if (do_it)
X wattroff(win, attr);
X#endif /* OLDCURSES */
X return(0);
X}
X
X/*
X * Change video attributes while printing a character.
X */
X
Xwattrch(win, attr, c)
XWINDOW *win;
Xchtype attr;
Xchar c;
X{
X int do_it;
X
X if (c == '\0')
X return(0);
X#ifdef OLDCURSES
X if (attr)
X wstandout(win);
X waddch(win, (chtype) c);
X if (attr)
X wstandend(win);
X#else /* OLDCURSES */
X
X#ifdef NOPROMOTE
X /* does the capability exist? */
X do_it = 0;
X if ((attr & A_STANDOUT) && enter_standout_mode)
X do_it++;
X if ((attr & A_UNDERLINE) && enter_underline_mode)
X do_it++;
X if ((attr & A_REVERSE) && (enter_reverse_mode || enter_standout_mode))
X do_it++;
X if ((attr & A_BLINK) && enter_blink_mode)
X do_it++;
X if ((attr & A_BOLD) && enter_bold_mode)
X do_it++;
X if ((attr & A_DIM) && enter_dim_mode)
X do_it++;
X#else /* NOPROMOTE */
X do_it = 1;
X#endif /* NOPROMOTE */
X
X if (do_it)
X wattron(win, attr);
X /* print the character */
X waddch(win, (chtype) c);
X if (do_it)
X wattroff(win, attr);
X#endif /* OLDCURSES */
X return(0);
X}
X
X
X/*
X * Change video attributes while printing a number.
X */
X
Xwattrnum(win, attr, num)
XWINDOW *win;
Xchtype attr;
Xint num;
X{
X int do_it;
X char buf[40];
X
X sprintf(buf, "%d", num);
X
X#ifdef OLDCURSES
X if (attr)
X wstandout(win);
X waddstr(win, buf);
X if (attr)
X wstandend(win);
X#else /* OLDCURSES */
X
X#ifdef NOPROMOTE
X /* does the capability exist? */
X do_it = 0;
X if ((attr & A_STANDOUT) && enter_standout_mode)
X do_it++;
X if ((attr & A_UNDERLINE) && enter_underline_mode)
X do_it++;
X if ((attr & A_REVERSE) && (enter_reverse_mode || enter_standout_mode))
X do_it++;
X if ((attr & A_BLINK) && enter_blink_mode)
X do_it++;
X if ((attr & A_BOLD) && enter_bold_mode)
X do_it++;
X if ((attr & A_DIM) && enter_dim_mode)
X do_it++;
X#else /* NOPROMOTE */
X do_it = 1;
X#endif /* NOPROMOTE */
X
X if (do_it)
X wattron(win, attr);
X /* print the character */
X waddstr(win, buf);
X if (do_it)
X wattroff(win, attr);
X#endif /* OLDCURSES */
X return(0);
X}
X
X/*
X * Prompt for a Yes or No answer. Echo the single key input as words.
X * Handle the funny cursor movement problems with magic cookie terminals.
X * Returns a 1 on yes.
X */
X
Xint
Xyes_prompt(win, y, x, attr, str)
XWINDOW *win;
Xint y, x;
Xchtype attr;
Xchar *str;
X{
X int ret_code, ans;
X char new_str[80], *strcpy(), *strcat();
X /* sanity checking */
X if (strlen(str) > 71)
X *(str+71) = '\0';
X /* build and display the prompt */
X strcpy(new_str, str);
X strcat(new_str, "? (y/n):");
X mvwattrstr(win, y, x, attr, new_str);
X wmove(win, y, strlen(new_str)+x+2);
X wrefresh(win);
X
X ret_code = -1;
X while (ret_code == -1) {
X /* if inside a script */
X if (status->dup_fd != -1)
X ans = wait_key(win, 5);
X else
X ans = wgetch(win);
X
X switch (ans) {
X case -1:
X case 'y':
X case 'Y':
X waddstr(win, "Yes");
X ret_code = 1;
X break;
X case 'n':
X case 'N':
X case ESC:
X waddstr(win, "No");
X ret_code = 0;
X break;
X default:
X beep();
X
X }
X }
X wrefresh(win);
X return(ret_code);
X}
X
X/*
X * Handy routine for clear-to-end-of-line. Fixes up the box if requested.
X */
X
Xint
Xclear_line(win, y, x, re_box)
XWINDOW *win;
Xint y, x, re_box;
X{
X if (wmove(win, y, x) == ERR)
X return(ERR);
X
X wclrtoeol(win);
X
X if (re_box) {
X mvwaddch(win, y, win->_maxx-1, (chtype) ACS_VLINE);
X wmove(win, y, x);
X }
X return(0);
X}
X
X/*
X * Routine to make a horizontal line. Does NOT do a wrefresh().
X */
X
Xint
Xhorizontal(win, x, y, len)
XWINDOW *win;
Xint x, y, len;
X{
X wmove(win, x, y);
X
X while (len--)
X waddch(win, ACS_HLINE);
X
X return(0);
X}
X
X/*
X * Wait for a key or time out. Returns a -1 on timeout. This is similar
X * to the half-delay mode in the newer versions of curses(3).
X */
X
Xstatic int wk_flag;
Xstatic int wk_force();
X
X/* ARGSUSED */
Xint
Xwait_key(win, sec)
XWINDOW *win;
Xunsigned int sec;
X{
X int key;
X unsigned int alarm();
X#ifdef WGETCH_BROKE
X char c;
X#endif /* WGETCH_BROKE */
X
X signal(SIGALRM, (SIG_TYPE(*) ()) wk_force);
X wk_flag = 0;
X
X alarm(sec);
X
X#ifdef BSD
X if (setjmp(wk_buf))
X return(-1);
X#endif /* BSD */
X
X#ifdef WGETCH_BROKE
X read(0, &c, 1);
X key = c & 0x7f;
X#else /* WGETCH_BROKE */
X key = wgetch(win);
X#endif /* WGETCH_BROKE */
X
X if (wk_flag)
X return(-1);
X alarm(0);
X return(key);
X}
X
X/* ARGSUSED */
Xstatic int
Xwk_force(dummy)
Xint dummy;
X{
X#ifdef BSD
X longjmp(wk_buf, 1);
X#else /* BSD */
X signal(SIGALRM, (SIG_TYPE(*) ()) wk_force);
X wk_flag = 1;
X return(0);
X#endif /* BSD */
X}
X
X/*
X * Here are some routines that are probably missing from the older
X * flavors of curses(3).
X */
X
X#ifdef OLDCURSES
X/*
X * Make the terminal bell go off
X */
X
Xint
Xbeep()
X{
X fputc(BEL, stderr);
X return(0);
X}
X
X/*
X * Take the terminal out of the "curses mode". The t_mode structure was
X * captured before we initialized the curses mode.
X */
X
Xint
Xresetterm()
X{
X extern char _putchar();
X extern struct sgttyb t_mode;
X
X ioctl(0, TIOCSETP, &t_mode);
X tputs(TE, 1, _putchar);
X tputs(VE, 1, _putchar);
X return(0);
X}
X
X/*
X * Put the terminal back into the "curses mode". The c_mode structure was
X * captured after we initialized the curses mode.
X */
X
Xint
Xfixterm()
X{
X extern char _putchar();
X extern struct sgttyb c_mode;
X
X ioctl(0, TIOCSETP, &c_mode);
X tputs(TI, 1, _putchar);
X tputs(VS, 1, _putchar);
X return(0);
X}
X#endif /* OLDCURSES */
END_OF_FILE
if test 8961 -ne `wc -c <'pcomm-2.0/curses.c'`; then
echo shar: \"'pcomm-2.0/curses.c'\" unpacked with wrong size!
fi
# end of 'pcomm-2.0/curses.c'
fi
if test -f 'pcomm-2.0/dial.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'pcomm-2.0/dial.c'\"
else
echo shar: Extracting \"'pcomm-2.0/dial.c'\" \(9367 characters\)
sed "s/^X//" >'pcomm-2.0/dial.c' <<'END_OF_FILE'
X/*
X * The routines that dial the modem and listen for the return codes.
X */
X
X#define HZ 60
X
X#include <stdio.h>
X#include <ctype.h>
X#include "config.h"
X#include "dial_dir.h"
X#include "misc.h"
X#include "modem.h"
X#include "param.h"
X
X#ifdef BSD
X#include <sys/time.h>
X#else /* BSD */
X#include <sys/types.h>
X#include <sys/times.h>
X#endif /* BSD */
X
X#ifdef UNIXPC
X#include <sys/phone.h>
X#endif /* UNIXPC */
X
Xstatic void do_pause();
Xstatic int match();
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, skip;
X char s[100], number[40], *strcpy(), *strcat(), *n, *strchr();
X void send_str();
X#ifdef UNIXPC
X extern int fd;
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] = '\0';
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. To prevent
X * this action, prepend a "\" to the character.
X */
X i = 0;
X skip = 0;
X n = dir->number[dir->q_num[num]];
X while (*n) {
X if (*n == '\\' && !skip) {
X skip++;
X n++;
X continue;
X }
X if (!strchr("-() ", *n) || skip)
X number[i++] = *n;
X n++;
X skip = 0;
X }
X number[i] = '\0';
X /* add it to the string */
X strcat(s, number);
X strcat(s, modem->suffix[modem->m_cur]);
X#ifdef DEBUG
X fprintf(stderr, "raw dial string: \"%s\"\n", s);
X#endif /* DEBUG */
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(fd, PIOCSETP, &pbuf);
X sleep(1);
X /* connect the dialer */
X ioctl(fd, PIOCRECONN);
X sleep(2);
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(fd, PIOCSETP, &pbuf);
X break;
X case '%':
X pbuf.c_lineparam = DATA|DTMF;
X ioctl(fd, PIOCSETP, &pbuf);
X break;
X default:
X ioctl(fd, PIOCDIAL, n);
X break;
X }
X n++;
X }
X /*
X * It seems that the OBM doesn't always talk reliably to
X * other types of modems (most notibly Telebits). Here
X * is some witchcraft to fix the problem.
X */
X ioctl(fd, PIOCOVSPD);
X return;
X }
X#endif /* UNIXPC */
X
X send_str(s, SLOW);
X return;
X}
X
X/*
X * Send a string to the modem. Performs all the character synonym
X * translations.
X */
X
Xvoid
Xsend_str(s, slow)
Xchar *s;
Xint slow;
X{
X extern int fd;
X int skip, has_pause;
X char *strchr();
X unsigned int sleep();
X /* empty string? */
X if (s == NULL || *s == '\0')
X return;
X
X /* contains a pause? */
X has_pause = 0;
X if (strchr(s, '~'))
X has_pause++;
X
X tty_flush(fd, 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 /* send the literal character */
X if (skip) {
X skip = 0;
X write(fd, s, 1);
X if (has_pause || slow)
X tty_drain(fd);
X if (slow)
X do_pause();
X#ifdef DEBUG
X fprintf(stderr, "send_str: \"%c\", %02x, %03o, %d\n", *s, *s, *s, *s);
X#endif /* DEBUG */
X s++;
X continue;
X }
X /* turn off the special meaning */
X if (*s == '\\') {
X skip++;
X s++;
X continue;
X }
X /* pause synonym */
X if (*s == param->pause_char) {
X sleep(1);
X s++;
X continue;
X }
X /* carriage return synonym */
X if (*s == param->cr_char)
X *s = '\r';
X /* 2 character control sequence */
X if (*s == param->ctrl_char) {
X s++;
X /* premature EOF? */
X if (*s == '\0')
X break;
X /* upper and lower case */
X if (*s > '_')
X *s -= 96;
X else
X *s -= 64;
X }
X /* escape synonym */
X if (*s == param->esc_char)
X *s = ESC;
X /* modem break synonym */
X if (*s == param->brk_char) {
X tty_break(fd);
X sleep(1);
X s++;
X continue;
X }
X
X write(fd, s, 1);
X#ifdef DEBUG
X fprintf(stderr, "send_str: \"%c\", %02x, %03o, %d\n", *s, *s, *s, *s);
X#endif /* DEBUG */
X /*
X * Because the pause char makes the timing critical, we
X * wait until the buffer is clear before we continue.
X */
X if (has_pause || slow)
X tty_drain(fd);
X if (slow)
X do_pause();
X s++;
X }
X return;
X}
X
X/*
X * Read the result codes coming back from the modem. Test for the 7
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 *
Xread_codes(tic)
Xint tic;
X{
X int i, j, k;
X char c;
X static char rc_buf[512];
X static int rc_index;
X#ifdef UNIXPC
X extern int fd;
X unsigned int sleep();
X struct updata pbuf;
X /* special case for OBM */
X if (!strcmp(modem->mname[modem->m_cur], "OBM")) {
X ioctl(fd, PIOCGETP, &pbuf);
X
X /*
X * The OBM doesn't use a return message to announce the
X * connection to a remote, so we fake one. The 1200
X * is quite arbitrary... it is not an indicator of the
X * connected baud rate.
X */
X if (pbuf.c_linestatus & MODEMCONNECTED)
X return("1200");
X
X sleep(1);
X return(NULL);
X }
X#endif /* UNIXPC */
X if (tic == 0)
X rc_index = 0;
X /* search for key words */
X for (; rc_index<511; rc_index++) {
X if ((i = getc_line(1)) <= 0)
X return(NULL);
X
X c = i & 0x7f;
X#ifdef DEBUG
X fprintf(stderr, "read_codes: \"%c\", %02x, %03o, %d\n", c, c, c, c);
X#endif /* DEBUG */
X /* no NULLs please */
X if (c == '\0') {
X if (rc_index)
X rc_index--;
X continue;
X }
X rc_buf[rc_index] = c;
X rc_buf[rc_index+1] = '\0';
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 if (match(rc_buf, modem->con_384[modem->m_cur]))
X return("38400");
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 * OK.. this is the tricky part. What if the modem returns
X * the modulation rate (in lieu of the DTE rate)? For
X * example, the message is "CONNECT 14400", but the DTE
X * is locked at 38400.
X */
X if (modem->lock_sp[modem->t_cur]) {
X for (j=0; j<512; j++) {
X if (rc_buf[j] == '\0')
X break;
X if (isdigit(rc_buf[j])) {
X k = atoi(&rc_buf[j]);
X switch(k) {
X case 7200:
X return("7200");
X case 12000:
X return("12000");
X case 14400:
X return("14400");
X }
X break;
X }
X }
X }
X
X }
X /* ran out of buffer? */
X return("ERROR");
X}
X
X/*
X * Test for a match between two character strings. A non-zero return code
X * means that s2 was found at the end of s1.
X */
X
Xstatic int
Xmatch(s1, s2)
Xchar *s1, *s2;
X{
X register int i;
X int skip, diff;
X char new[40];
X /* if no string to match */
X if (*s2 == '\0')
X return(0);
X /* translate synonyms */
X i = 0;
X skip = 0;
X while (*s2) {
X /* literal character */
X if (skip) {
X skip = 0;
X new[i++] = *s2;
X s2++;
X continue;
X }
X /* turn off the special meaning */
X if (*s2 == '\\') {
X skip++;
X s2++;
X continue;
X }
X /* carriage return synonym */
X if (*s2 == param->cr_char)
X *s2 = '\r';
X
X /* 2 character control sequence */
X if (*s2 == param->ctrl_char) {
X s2++;
X if (*s2 == '\0')
X break;
X if (*s2 > '_')
X *s2 -= 96;
X else
X *s2 -= 64;
X }
X /* escape synonym */
X if (*s2 == param->esc_char)
X *s2 = ESC;
X
X new[i++] = *s2;
X s2++;
X }
X new[i] = '\0';
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}
X
X/*
X * Apparently some modems can't take input at the rated speed while
X * in the command mode. Therefore, a 0.10 sec pause a required between
X * characters.
X */
X
Xstatic void
Xdo_pause()
X{
X#ifdef HAVE_USLEEP
X usleep(100000);
X#else /* HAVE_USLEEP */
X /* Hey! I know these routines are a hack */
X#ifdef BSD
X struct timeval tv;
X struct timezone tz;
X double t1;
X
X gettimeofday(&tv, &tz);
X t1 = tv.tv_sec + (tv.tv_usec / 1000000.0);
X do
X gettimeofday(&tv, &tz);
X while ((tv.tv_sec + (tv.tv_usec / 1000000.0) - t1) < 0.1);
X#else /* BSD */
X struct tms t;
X long t1;
X
X t1 = times(&t);
X while ((times(&t) - t1) < HZ/10)
X ;
X#endif /* BSD */
X#endif /* HAVE_USLEEP */
X return;
X}
END_OF_FILE
if test 9367 -ne `wc -c <'pcomm-2.0/dial.c'`; then
echo shar: \"'pcomm-2.0/dial.c'\" unpacked with wrong size!
fi
# end of 'pcomm-2.0/dial.c'
fi
if test -f 'pcomm-2.0/p_lib.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'pcomm-2.0/p_lib.c'\"
else
echo shar: Extracting \"'pcomm-2.0/p_lib.c'\" \(7341 characters\)
sed "s/^X//" >'pcomm-2.0/p_lib.c' <<'END_OF_FILE'
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 a static area containing the PARAM structure. All errors
X * are fatal.
X */
X
Xstruct PARAM *
Xread_param()
X{
X FILE *fp, *uid_fopen();
X int i, line, oops;
X char buf[200], *temp_token, *str, *str_dup(), *findfile();
X char message[80], *str_tok();
X static char *token[NUM_PARAM] = {"D_BAUD", "D_PARITY",
X "D_DATA_BITS", "D_STOP_BITS", "HOT_KEY", "ASCII_HOT", "D_DUPLEX",
X "FLOW_CTRL", "CR_IN", "CR_OUT", "LOGFILE", "DUMPFILE", "STRIP",
X "PAUSE_CHAR", "CR_CHAR", "CTRL_CHAR", "ESC_CHAR", "BRK_CHAR",
X "ABORT", "C_DELAY", "R_DELAY", "LOCAL_ECHO", "EXPAND", "CR_DELAY",
X "PACE", "CR_UP", "LF_UP", "TIMER", "CR_DN", "LF_DN", "LD_PLUS",
X "LD_MINUS", "LD_AT", "LD_POUND", "MAC_1", "MAC_2", "MAC_3",
X "MAC_4", "MAC_5", "MAC_6", "MAC_7", "MAC_8", "MAC_9", "MAC_0"};
X static struct PARAM p;
X void error_win();
X
X if ((p.p_path = findfile("pcomm.param")) == NULL)
X error_win(1, "Support file \"pcomm.param\" is missing", "or no read permission");
X
X if (!(fp = uid_fopen(p.p_path, "r"))) {
X sprintf(buf, "\"%s\" for read", p.p_path);
X error_win(1, "Can't open parameter file", buf);
X }
X
X oops = 0;
X line = 0;
X for (i=0; i<NUM_PARAM; i++) {
X line++;
X if (fgets(buf, 200, fp) == NULL) {
X sprintf(message, "is truncated at line %d", line);
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", line);
X oops++;
X break;
X }
X if (!(str = str_tok((char *) NULL, '\n'))) {
X sprintf(message, "is missing a parameter at line %d", line);
X oops++;
X break;
X }
X /* sanity checking */
X if (strcmp(temp_token, token[i])) {
X sprintf(message, "is corrupted at line %d", line);
X oops++;
X break;
X }
X
X switch (i) {
X /* used in ls_menu() */
X case LINE_SET:
X p.d_baud = (unsigned int) atoi(str);
X break;
X case LINE_SET+1:
X p.d_parity = *str;
X break;
X case LINE_SET+2:
X p.d_data_bits = atoi(str);
X break;
X case LINE_SET+3:
X p.d_stop_bits = atoi(str);
X break;
X
X /* used in term_setup() */
X case TERM_SETUP:
X p.hot_key = atoi(str);
X break;
X case TERM_SETUP+1:
X p.ascii_hot = str_dup(str);
X break;
X case TERM_SETUP+2:
X p.d_duplex = str_dup(str);
X break;
X case TERM_SETUP+3:
X p.flow_ctrl = str_dup(str);
X break;
X case TERM_SETUP+4:
X p.cr_in = str_dup(str);
X break;
X case TERM_SETUP+5:
X p.cr_out = str_dup(str);
X break;
X
X /* used in gen_setup() */
X case GEN_SETUP:
X p.logfile = str_dup(str);
X break;
X case GEN_SETUP+1:
X p.dumpfile = str_dup(str);
X break;
X case GEN_SETUP+2:
X p.strip = str_dup(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 = str_dup(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.local_echo = str_dup(str);
X break;
X case ASCII_SETUP+1:
X p.expand = str_dup(str);
X break;
X case ASCII_SETUP+2:
X p.cr_delay = atoi(str);
X break;
X case ASCII_SETUP+3:
X p.pace = str_dup(str);
X break;
X case ASCII_SETUP+4:
X p.cr_up = str_dup(str);
X break;
X case ASCII_SETUP+5:
X p.lf_up = str_dup(str);
X break;
X case ASCII_SETUP+6:
X p.timer = atoi(str);
X break;
X case ASCII_SETUP+7:
X p.cr_dn = str_dup(str);
X break;
X case ASCII_SETUP+8:
X p.lf_dn = str_dup(str);
X break;
X
X /* used in d_revise() */
X case LD_CODES:
X p.ld_plus = str_dup(str);
X break;
X case LD_CODES+1:
X p.ld_minus = str_dup(str);
X break;
X case LD_CODES+2:
X p.ld_at = str_dup(str);
X break;
X case LD_CODES+3:
X p.ld_pound = str_dup(str);
X break;
X
X /* used in macro() */
X case MACROS:
X p.mac_1 = str_dup(str);
X break;
X case MACROS+1:
X p.mac_2 = str_dup(str);
X break;
X case MACROS+2:
X p.mac_3 = str_dup(str);
X break;
X case MACROS+3:
X p.mac_4 = str_dup(str);
X break;
X case MACROS+4:
X p.mac_5 = str_dup(str);
X break;
X case MACROS+5:
X p.mac_6 = str_dup(str);
X break;
X case MACROS+6:
X p.mac_7 = str_dup(str);
X break;
X case MACROS+7:
X p.mac_8 = str_dup(str);
X break;
X case MACROS+8:
X p.mac_9 = str_dup(str);
X break;
X case MACROS+9:
X p.mac_0 = str_dup(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". A non-zero return code means non-fatal
X * error.
X */
X
Xint
Xup_param()
X{
X FILE *fp, *uid_fopen();
X char buf[80];
X void error_win();
X /* open for write */
X if (!(fp = uid_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_DATA_BITS=%d\n", param->d_data_bits);
X fprintf(fp, "D_STOP_BITS=%d\n", param->d_stop_bits);
X fprintf(fp, "HOT_KEY=%d\n", param->hot_key);
X fprintf(fp, "ASCII_HOT=%s\n", param->ascii_hot);
X fprintf(fp, "D_DUPLEX=%s\n", param->d_duplex);
X fprintf(fp, "FLOW_CTRL=%s\n", param->flow_ctrl);
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, "LOCAL_ECHO=%s\n", param->local_echo);
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}
END_OF_FILE
if test 7341 -ne `wc -c <'pcomm-2.0/p_lib.c'`; then
echo shar: \"'pcomm-2.0/p_lib.c'\" unpacked with wrong size!
fi
# end of 'pcomm-2.0/p_lib.c'
fi
if test -f 'pcomm-2.0/terminal.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'pcomm-2.0/terminal.c'\"
else
echo shar: Extracting \"'pcomm-2.0/terminal.c'\" \(8778 characters\)
sed "s/^X//" >'pcomm-2.0/terminal.c' <<'END_OF_FILE'
X/*
X * Start the terminal dialogue, scan the TTY, keyboard, and the "script"
X * for input, watch for the hot key so we can execute an option.
X */
X
X#include <stdio.h>
X#include <curses.h>
X#include <signal.h>
X#include "config.h"
X#include "dial_dir.h"
X#include "ipc.h"
X#include "misc.h"
X#include "modem.h"
X#include "param.h"
X#include "status.h"
X#include "xmodem.h"
X
X#ifdef BSD
X#ifndef SIGCLD
X#define SIGCLD SIGCHLD
X#endif /* SIGCLD */
X#include <sys/file.h>
X#else /* BSD */
X#include <fcntl.h>
X#endif /* BSD */
X
X#ifdef UNIXPC
X#include <sys/phone.h>
X#endif /* UNIXPC */
X
Xstatic void key_input();
Xstatic int cr_lf;
X
Xvoid
Xterminal(script)
Xchar *script;
X{
X extern int fd;
X int ret_code;
X void tty_input(), st_line(), term_mode(), cmd_input(), do_script();
X void is_active(), ipc_init();
X
X ipc_init(fd, status->cmd_ipc);
X /* if not starting with -f option */
X if (dir->q_num[0] == -1) {
X erase();
X refresh();
X st_line("");
X }
X /* put stdin/stdout in terminal mode */
X resetterm();
X term_mode();
X cr_lf = !strcmp(param->cr_out, "CR/LF");
X
X /* play a script from command line */
X if (script != NULL && *script != '\0')
X do_script(script);
X
X /* the main loop ! */
X /* CONSTCOND */
X while (1) {
X ret_code = ipc_poll(fd, status->cmd_ipc);
X
X if (ret_code & TTY_READY)
X tty_input();
X
X if (ret_code & KEY_READY)
X key_input();
X
X /*
X * This is the reason for the 1 sec "timeout" of the
X * poll/select call... to periodically check the status
X * of the "script" for input.
X */
X if (status->dup_fd != -1)
X is_active();
X /* do a command from a script */
X if (ret_code & CMD_READY)
X cmd_input();
X }
X /* NOTREACHED */
X}
X
X/*
X * There is something ready to be read from the keyboard.
X */
X
Xstatic void
Xkey_input()
X{
X extern int fd;
X int i, k;
X char c, lf=10, *str_rep(), *keymac, *script, *script_menu();
X void help_screen(), line_set(), n_shell(), load_vs(), send_str();
X void release_port(), list_dir(), pexit(), st_line(), chg_dir();
X void screen_dump(), info(), term_mode(), macro(), stop_script();
X void setup_menu(), xfer_menu(), data_logging(), pass_thru();
X void half_duplex(), do_script(), vs_clear(), tty_restart();
X void log_toggle(), lpr_toggle();
X
X read(0, &c, 1);
X c &= 0x7f;
X /* stop the script? */
X if (status->dup_fd != -1 && c == ESC) {
X stop_script();
X return;
X }
X /* is it the hot key? */
X if (c == param->hot_key) {
X
X script = NULL;
X /*
X * Put the terminal in the curses mode, load the
X * virtual screen and add the status line at the bottom.
X */
X fixterm();
X load_vs();
X st_line("");
X#ifndef OLDCURSES
X keypad(stdscr, TRUE);
X#endif /* OLDCURSES */
X i = wgetch(stdscr);
X /* map an additional hot key to -1 */
X if (i == param->hot_key)
X i = -1;
X
X keymac = "";
X /* look for options */
X k = -1;
X switch (i) {
X case -1: /* 2 "hots" means send 1 */
X k = param->hot_key;
X break;
X case '0': /* help screen */
X help_screen(param->ascii_hot);
X break;
X case 'd':
X case 'D': /* dialing directory */
X if (dial_menu()) {
X if (!dial_win(25))
X script = dir->aux[0];
X }
X break;
X case 'r':
X case 'R': /* redial */
X if (redial()) {
X if (!dial_win(25))
X script = dir->aux[0];
X }
X break;
X case 'm':
X case 'M': /* keyboard macros */
X macro();
X break;
X case 'p':
X case 'P': /* line settings */
X if (ls_menu())
X line_set();
X break;
X case 'x':
X case 'X': /* exit */
X pexit();
X break;
X case '4': /* Unix gateway */
X n_shell();
X break;
X case '5': /* Command files */
X script = script_menu();
X break;
X case 'i':
X case 'I': /* program info screen */
X info(MANUAL_CLEAR);
X break;
X case 's': /* setup menu */
X case 'S':
X setup_menu();
X break;
X case 'c': /* clear the screen */
X case 'C':
X erase();
X vs_clear(0);
X break;
X case 'b':
X case 'B': /* change directory */
X chg_dir();
X break;
X case 'e':
X case 'E': /* toggle duplex */
X if (dir->duplex[0] == 'F')
X dir->duplex[0] = 'H';
X else
X dir->duplex[0] = 'F';
X
X /* show changes */
X st_line("");
X k = wait_key(stdscr, 2);
X break;
X case 'h':
X case 'H': /* hang up phone */
X release_port(VERBOSE);
X break;
X case 'l':
X case 'L': /* print toggle */
X lpr_toggle();
X /* show changes */
X st_line("");
X k = wait_key(stdscr, 2);
X break;
X case '3': /* toggle CR - CR/LF */
X if (!strcmp(param->cr_in, "CR"))
X param->cr_in = str_rep(param->cr_in, "CR/LF");
X else
X param->cr_in = str_rep(param->cr_in, "CR");
X /* show changes */
X st_line("");
X k = wait_key(stdscr, 2);
X break;
X case '7': /* break key */
X if (fd != -1)
X tty_break(fd);
X
X st_line(" break");
X break;
X#ifndef OLDCURSES
X case KEY_UP:
X#endif /* OLDCURSES */
X case 'u':
X case 'U': /* send files */
X xfer_menu(UP_LOAD);
X break;
X#ifndef OLDCURSES
X case KEY_DOWN:
X case '\n':
X#endif /* OLDCURSES */
X case 'n':
X case 'N': /* receive files */
X xfer_menu(DOWN_LOAD);
X break;
X case 't':
X case 'T':
X pass_thru();
X break;
X case 'f':
X case 'F': /* list directory */
X list_dir();
X break;
X case 'g': /* screen dump */
X case 'G':
X screen_dump();
X st_line(" screen dump");
X k = wait_key(stdscr, 2);
X break;
X case '1': /* data logging */
X data_logging();
X break;
X case '2': /* toggle log */
X if (!strcmp(status->log_path, "NOT_DEFINED")) {
X beep();
X st_line(" no log file");
X k = wait_key(stdscr, 2);
X break;
X }
X log_toggle();
X /* show changes */
X st_line("");
X k = wait_key(stdscr, 2);
X break;
X /*
X * The following are the keyboard macros
X * corresponding to the shifted number keys.
X * (Too many keys... [control] [A] [shift] [1]
X * is hardly a shortcut!)
X */
X case '!':
X keymac = param->mac_1;
X break;
X case '@':
X keymac = param->mac_2;
X break;
X case '#':
X keymac = param->mac_3;
X break;
X case '$':
X keymac = param->mac_4;
X break;
X case '%':
X keymac = param->mac_5;
X break;
X case '^':
X keymac = param->mac_6;
X break;
X case '&':
X keymac = param->mac_7;
X break;
X case '*':
X keymac = param->mac_8;
X break;
X case '(':
X keymac = param->mac_9;
X break;
X case ')':
X keymac = param->mac_0;
X break;
X default:
X fputc(BEL, stderr);
X break;
X }
X
X /*
X * Repaint the stdscr (if we are already talking),
X * get the stdin/stdout out of the curses mode and
X * into the terminal mode.
X */
X if (fd != -1) {
X touchwin(stdscr);
X refresh();
X }
X resetterm();
X term_mode();
X /* restart stopped flow control */
X tty_restart();
X
X /*
X * Some of the output processing options have to be
X * faked... Unfortunately, adding a LF to CR on
X * output is one of them.
X */
X cr_lf = !strcmp(param->cr_out, "CR/LF");
X
X /* play the script */
X if (script != NULL && *script != '\0')
X do_script(script);
X
X /* send the macro */
X if (*keymac != '\0')
X send_str(keymac, FAST);
X
X /*
X * If you pressed a key during one of the sleeping
X * periods (typically the delay to see the status
X * line change), let the keyboard value fall thru
X * to the write() below.
X */
X if (k == -1)
X return;
X c = (char) k;
X }
X /* ignore errors if fd == -1 */
X write(fd, &c, 1);
X
X /*
X * If you're using the half duplex mode, characters don't get
X * echoed by the driver (cause you don't type them!)
X */
X if (dir->duplex[0] == 'H')
X half_duplex(c);
X /* map cr to cr_lf? */
X if (c == '\r' && cr_lf) {
X write(fd, &lf, 1);
X
X if (dir->duplex[0] == 'H') {
X write(1, &lf, 1);
X half_duplex(lf);
X }
X }
X return;
X}
X
X/*
X * Hang up the phone but remain in the Pcomm command state. Uses the
X * hang_up string only, does *not* drop the DTR!
X */
X
Xvoid
Xhang_up(verbose)
Xint verbose;
X{
X extern int fd;
X void send_str(), st_line(), tty_restart();
X unsigned int sleep();
X /* sanity checking */
X if (modem == NULL)
X return;
X /* anything to hang up? */
X if (modem->m_cur == -1 || fd == -1)
X return;
X
X if (verbose)
X st_line("disconnecting");
X /* special case for OBM */
X if (!strcmp(modem->mname[modem->m_cur], "OBM")) /* EMPTY */ {
X#ifdef UNIXPC
X char buf[80];
X void line_set();
X
X ioctl(fd, PIOCDISC);
X /*
X * The PIOCDISC ioctl screws up the file descriptor!!!
X * No other phone(7) ioctl can fix it. Whatever it does,
X * it seems to escape detection with PIOCGETA and TCGETA.
X * The best I can do is close the port and start over.
X */
X sprintf(buf, "/dev/%s", modem->tty[modem->t_cur]);
X close(fd);
X fd = open(buf, O_RDWR|O_NDELAY);
X line_set();
X tty_noblock(fd, FALSE);
X#endif /* UNIXPC */
X }
X else {
X tty_restart();
X send_str(modem->hang_up[modem->m_cur], SLOW);
X sleep(1);
X }
X
X if (verbose)
X st_line("");
X
X status->connected = 0;
X return;
X}
END_OF_FILE
if test 8778 -ne `wc -c <'pcomm-2.0/terminal.c'`; then
echo shar: \"'pcomm-2.0/terminal.c'\" unpacked with wrong size!
fi
# end of 'pcomm-2.0/terminal.c'
fi
if test -f 'pcomm-2.0/x_batch.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'pcomm-2.0/x_batch.c'\"
else
echo shar: Extracting \"'pcomm-2.0/x_batch.c'\" \(8917 characters\)
sed "s/^X//" >'pcomm-2.0/x_batch.c' <<'END_OF_FILE'
X/*
X * Routines to support the batch protocols.
X */
X
X#include <stdio.h>
X#include <ctype.h>
X#include <curses.h>
X#include "config.h"
X#include "misc.h"
X#include "xmodem.h"
X
Xstatic char *fix_name();
Xstatic void change_name(), unfix_name(), change_name();
X
X/*
X * Send the file name for the modem7 batch. Only uses 11 characters
X * of the filename. Returns zero on success or the standard error codes.
X */
X
Xint
Xsend_modem7(win, name)
XWINDOW *win;
Xchar *name;
X{
X char *new_name;
X unsigned char sum, calc_sum();
X
X /* convert to 11 character name */
X new_name = fix_name(name);
X sum = calc_sum((unsigned char *) new_name, 12);
X
X putc_line(ACK);
X /* for each character in the name */
X while (*new_name != CTRLZ) {
X putc_line((unsigned char) *new_name);
X
X switch (getc_line(3)) {
X case -1: /* timed out */
X clear_line(win, 12, 24, TRUE);
X waddstr(win, "NO RESPONSE");
X wrefresh(win);
X return(ERROR);
X case ACK: /* got it! */
X break;
X case CAN: /* cancel transmission */
X if (getc_line(2) == CAN) {
X beep();
X clear_line(win, 12, 24, TRUE);
X wattrstr(win, A_BOLD, "REMOTE ABORTED");
X wrefresh(win);
X return(CANCEL);
X }
X /* FALLTHRU */
X default:
X clear_line(win, 12, 24, TRUE);
X waddstr(win, "NAME FAILED");
X wrefresh(win);
X return(ERROR);
X }
X new_name++;
X }
X putc_line(CTRLZ);
X /* verify the checksum */
X if (getc_line(10) != sum) {
X putc_line('u');
X clear_line(win, 12, 24, TRUE);
X waddstr(win, "CHECKSUM FAILED");
X wrefresh(win);
X return(ERROR);
X }
X putc_line(ACK);
X return(0);
X}
X
X/*
X * Receive a modem7 file name. Returns zero on success, the standard error
X * codes, or a -1 on the end-of-batch. (Oddly enough, the end-of-batch code
X * is the same as the code for a user abort)
X */
X
Xint
Xrcv_modem7(win, default_err)
XWINDOW *win;
Xint default_err;
X{
X extern char file_name[15];
X int i, j, err_method, err_count, got_it;
X unsigned char sum, calc_sum();
X char temp_name[13];
X
X err_method = default_err;
X if (default_err == CRC_CHECKSUM)
X err_method = CRC;
X
X err_count = 0;
X got_it = 0;
X while (err_count < MAX_ERRORS) {
X /* switch to checksum? */
X if (default_err == CRC_CHECKSUM && err_count > MAX_ERRORS/2)
X err_method = CHECKSUM;
X
X if (err_method == CRC)
X putc_line('C');
X else
X putc_line(NAK);
X /* what'd we get? */
X switch (getc_line(10)) {
X case -1: /* timed out */
X clear_line(win, 12, 24, TRUE);
X wattrstr(win, A_BOLD, "NO RESPONSE");
X wrefresh(win);
X err_count++;
X break;
X case ACK: /* ready to go... */
X got_it++;
X break;
X default: /* huh? */
X clear_line(win, 12, 24, TRUE);
X wattrstr(win, A_BOLD, "BAD HEADER");
X wrefresh(win);
X err_count++;
X }
X if (got_it)
X break;
X }
X if (!got_it)
X return(ERROR);
X /* get the name */
X for (i=0; i<12; i++) {
X j = getc_line(3);
X
X switch (j) {
X case -1: /* timed out */
X clear_line(win, 12, 24, TRUE);
X wattrstr(win, A_BOLD, "NO RESPONSE");
X wrefresh(win);
X return(ERROR);
X case EOT: /* end of batch? */
X return(-1);
X case CAN: /* cancel transmission */
X if (getc_line(2) == CAN) {
X beep();
X clear_line(win, 12, 24, TRUE);
X wattrstr(win, A_BOLD, "REMOTE ABORTED");
X wrefresh(win);
X return(CANCEL);
X }
X /* FALLTHRU */
X case 'u': /* bad name character */
X beep();
X clear_line(win, 12, 24, TRUE);
X wattrstr(win, A_BOLD, "BAD NAME");
X wrefresh(win);
X return(ERROR);
X default: /* the name... */
X temp_name[i] = j & 0xff;
X if (j != CTRLZ)
X putc_line(ACK);
X break;
X }
X }
X temp_name[12] = '\0';
X /* send our checksum */
X sum = calc_sum((unsigned char *) temp_name, 12);
X putc_line(sum);
X /* do they agree? */
X if (getc_line(10) != ACK) {
X beep();
X clear_line(win, 12, 24, TRUE);
X wattrstr(win, A_BOLD, "BAD NAME");
X wrefresh(win);
X return(ERROR);
X }
X /* load the file_name array */
X unfix_name(temp_name);
X /* any name collisions? */
X change_name(win, file_name);
X return(0);
X}
X
X/*
X * Send the block 0 information for a ymodem batch transfer. Uses only
X * the name component of the path and the file size.
X */
X
Xint
Xsend_ymodem(win, file, size)
XWINDOW *win;
Xchar *file;
Xlong size;
X{
X unsigned short crc, calc_crc();
X char *strcpy(), *memset();
X unsigned char buf[133];
X /* start with a clean block */
X memset((char *) buf, '\0', 133);
X /* the header */
X buf[0] = SOH;
X buf[1] = 0;
X buf[2] = 255;
X
X /*
X * The block zero consists of the file name (no path component),
X * a NULL, and the file length (as a string). The end of batch
X * marker is an empty block.
X */
X if (*file != '\0') {
X strcpy((char *) &buf[3], file);
X sprintf((char *) &buf[strlen(file)+4], "%ld", size);
X }
X /* the crc */
X crc = calc_crc(&buf[3], 128);
X buf[131] = crc >> 8;
X buf[132] = crc & 0xff;
X /* the block count */
X mvwaddstr(win, 7, 24, "0 ");
X
X return(send_block(win, buf, 133));
X}
X
X/*
X * Receive the block 0 information for a ymodem batch transfer. We
X * only use the file name and the size (if present). Currently doesn't
X * support full path names.
X */
X
Xint
Xrcv_ymodem(win)
XWINDOW *win;
X{
X extern unsigned char buf[1029];
X extern long file_length;
X extern char file_name[15];
X int code, length_is_at;
X long atol();
X
X file_length = 0L;
X file_name[0] = '\0';
X /* read the zero block */
X if (code = rcv_block(win, 1, 1024, 0))
X return(code);
X /* at end of batch */
X if (buf[3] == '\0')
X return(0);
X /* get the file name */
X change_name(win, (char *) &buf[3]);
X /* any trouble? */
X if (file_name[0] == '\0') {
X putc_line(CAN);
X return(0);
X }
X /*
X * The file length is placed after the NULL of the file name
X * and is terminated by another NULL. If the length is missing,
X * atol() will see a NULL and return 0.
X */
X length_is_at = strlen((char *) &buf[3]) + 4;
X file_length = atol((char *) &buf[length_is_at]);
X return(0);
X}
X
X/*
X * Handle file name collisions. Prepend an "X" to the name until you find
X * a name that doesn't already exist. Creates a NULL name on error.
X * Loads the global character array "file_name".
X */
X
Xstatic void
Xchange_name(win, str)
XWINDOW *win;
Xchar *str;
X{
X extern char file_name[15];
X register int i;
X int modified;
X char temp[15], ans[15], *s, *strrchr(), *strcpy(), *strncat();
X char *strncpy();
X unsigned int sleep();
X /* dissect the name component */
X if ((s = strrchr(str, '/')))
X strncpy(temp, ++s, 15);
X else
X strncpy(temp, str, 15);
X temp[14] = '\0';
X
X strcpy(ans, temp);
X file_name[0] = '\0';
X /* write permission on directory? */
X if (access(".", 2)) {
X beep();
X clear_line(win, 12, 24, TRUE);
X wattrstr(win, A_BOLD, "NO WRITE ON DIRECTORY");
X wrefresh(win);
X return;
X }
X /* prepend up to 13 "X"s */
X modified = 0;
X for (i=1; i<14; i++) {
X if (access(ans, 0)) {
X if (modified) {
X beep();
X clear_line(win, 12, 24, TRUE);
X waddstr(win, "NAME COLLISION");
X wrefresh(win);
X sleep(1);
X }
X strcpy(file_name, ans);
X return;
X }
X
X modified++;
X strcpy(temp, "X");
X strncat(temp, ans, 13);
X temp[14] = '\0';
X strcpy(ans, temp);
X }
X beep();
X clear_line(win, 12, 24, TRUE);
X waddstr(win, "BAD NAME");
X wrefresh(win);
X return;
X}
X
X/*
X * Convert a perfectly good Unix file name to fit the CP/M file name
X * rules. Used for the modem7 batch file transfer. Returns a pointer
X * to a static area containing the new name.
X */
X
Xstatic char *
Xfix_name(path)
Xchar *path;
X{
X int i, dot;
X char *s, *name, temp[15], *ext, *strncpy(), *strrchr();
X static char ans[13];
X /* ignore the path component */
X if (s = strrchr(path, '/'))
X strncpy(temp, ++s, 15);
X else
X strncpy(temp, path, 15);
X temp[14] = '\0';
X name = temp;
X
X ext = "";
X dot = 0;
X for (i=strlen(temp)-1; i>=0; i--) {
X if (temp[i] == '.' && !dot) {
X dot = 1;
X temp[i] = '\0';
X ext = &temp[i+1];
X }
X if (islower(temp[i]))
X temp[i] = toupper(temp[i]);
X }
X /* if null name component */
X if (*name == '\0')
X name = "X";
X /* if name too long */
X if (strlen(name) > 8)
X *(name+8) = '\0';
X /* if extension too long */
X if (strlen(ext) > 3)
X *(ext+3) = '\0';
X
X sprintf(ans, "%-8.8s%-3.3s%c", temp, ext, CTRLZ);
X return(ans);
X}
X
X/*
X * Convert a CP/M style filename into a legal Unix file name. Loads the
X * global character array "file_name".
X */
X
Xstatic void
Xunfix_name(cpm_name)
Xchar *cpm_name;
X{
X extern char file_name[15];
X register int i, n;
X int dot;
X char temp[15], *strcpy();
X
X file_name[0] = '\0';
X if (*cpm_name == '\0')
X return;
X
X strcpy(temp, cpm_name);
X /* 8 character of the name */
X n = 0;
X for (i=0; i<8; i++) {
X if (temp[i] != ' ') {
X if (isupper(temp[i]))
X file_name[n++] = tolower(temp[i]);
X else
X file_name[n++] = temp[i];
X }
X }
X /* 3 character extension */
X dot = 0;
X for (i=8; i<11; i++) {
X if (temp[i] != ' ') {
X if (!dot) {
X dot++;
X file_name[n++] = '.';
X }
X if (isupper(temp[i]))
X file_name[n++] = tolower(temp[i]);
X else
X file_name[n++] = temp[i];
X }
X }
X file_name[n] = '\0';
X return;
X}
END_OF_FILE
if test 8917 -ne `wc -c <'pcomm-2.0/x_batch.c'`; then
echo shar: \"'pcomm-2.0/x_batch.c'\" unpacked with wrong size!
fi
# end of 'pcomm-2.0/x_batch.c'
fi
if test -f 'pcomm-2.0/x_menu.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'pcomm-2.0/x_menu.c'\"
else
echo shar: Extracting \"'pcomm-2.0/x_menu.c'\" \(7412 characters\)
sed "s/^X//" >'pcomm-2.0/x_menu.c' <<'END_OF_FILE'
X/*
X * Open a window to display the choices of file transfer protocols and
X * prompt for the file name(s).
X */
X
X#include <stdio.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <curses.h>
X#include "extrnl.h"
X#include "misc.h"
X#include "xmodem.h"
X
Xstatic char *get_names(), *get_extrnl();
X
Xvoid
Xxfer_menu(up)
Xint up;
X{
X extern int fd;
X extern char *null_ptr;
X WINDOW *xm_win, *newwin();
X char buf[2048], *list, *strcat(), *strcpy();
X int type, is_batch, i, ans, num_extrnl, n;
X void xfer_win(), xfer_ascii(), do_extrnl(), error_win();
X
X num_extrnl = (up) ? extrnl->up_entries : extrnl->dn_entries;
X xm_win = newwin(14+num_extrnl, 20, 2, 45);
X
X mvwaddstr(xm_win, 2, 3, "1) xmodem");
X mvwaddstr(xm_win, 3, 3, "2) xmodem-1k");
X mvwaddstr(xm_win, 4, 3, "3) modem7");
X mvwaddstr(xm_win, 5, 3, "4) ymodem");
X mvwaddstr(xm_win, 6, 3, "5) ymodem-g");
X mvwaddstr(xm_win, 7, 3, "6) ASCII");
X
X for (i=0; i<num_extrnl; i++)
X mvwprintw(xm_win, i+8, 3, "%d) %-12.12s", i+7, extrnl->name[up][i]);
X mvwaddstr(xm_win, i+8, 3, "E) (external)");
X mvwaddstr(xm_win, i+10, 3, "<ESC> to Abort");
X mvwaddstr(xm_win, i+11, 3, "Protocol:");
X box(xm_win, VERT, HORZ);
X if (up)
X mvwattrstr(xm_win, 0, 6, A_BOLD, " Upload ");
X else
X mvwattrstr(xm_win, 0, 5, A_BOLD, " Download ");
X
X wmove(xm_win, i+11, 13);
X wrefresh(xm_win);
X /* get the protocol */
X type = -1;
X while ((ans = wgetch(xm_win)) != ESC) {
X switch (ans) {
X case '1':
X type = XMODEM;
X break;
X case '2':
X type = XMODEM_1k;
X break;
X case '3':
X type = MODEM7;
X break;
X case '4':
X type = YMODEM;
X break;
X case '5':
X type = YMODEM_G;
X break;
X case '6':
X type = XASCII;
X break;
X case '7':
X if (num_extrnl >= 1)
X type = EXT_1;
X else
X beep();
X break;
X case '8':
X if (num_extrnl >= 2)
X type = EXT_2;
X else
X beep();
X break;
X case '9':
X if (num_extrnl >= 3)
X type = EXT_3;
X else
X beep();
X break;
X case 'e':
X case 'E':
X type = EXT_MANUAL;
X break;
X default:
X beep();
X }
X if (type != -1)
X break;
X }
X werase(xm_win);
X wrefresh(xm_win);
X delwin(xm_win);
X /* chicken'd out */
X if (type == -1)
X return;
X
X if (fd == -1) {
X error_win(0, "Not currently connected to any host", "");
X return;
X }
X /* which protocol? */
X is_batch = 0;
X switch(type) {
X case MODEM7:
X case YMODEM:
X case YMODEM_G: /* built-in protocols */
X is_batch++;
X /* FALLTHRU */
X case XMODEM:
X case XMODEM_1k: /* non-batch built-ins */
X list = null_ptr;
X /*
X * When receiving in a batch mode, don't prompt
X * for file names.
X */
X if (up || !is_batch) {
X if (!(list = get_names(up, type, is_batch)))
X break;
X }
X xfer_win(list, up, type);
X break;
X case XASCII: /* ascii xfer, yuck! */
X if (list = get_names(up, type, FALSE))
X xfer_ascii(list, up);
X break;
X case EXT_1:
X case EXT_2:
X case EXT_3: /* one of the externals */
X n = type -NUM_INTERNAL -1;
X strcpy(buf, extrnl->command[up][n]);
X /* see if we need to prompt for files */
X if (extrnl->prompt[up][n] == 'Y') {
X if (list = get_names(up, type, TRUE)) {
X strcat(buf, " ");
X strcat(buf, list);
X }
X else
X break;
X }
X do_extrnl(buf);
X break;
X case EXT_MANUAL: /* the manual external protocol */
X if (list = get_extrnl(up))
X do_extrnl(list);
X break;
X }
X return;
X}
X
Xchar *protocol[NUM_INTERNAL] = {"xmodem", "xmodem-1k", "modem7", "ymodem",
X "ymodem-g", "ASCII"};
X
X/*
X * Prompt for a list of files for the transfer programs. Since expand()
X * is used, it returns a pointer to a static area. Returns a NULL if
X * you chicken'd out.
X */
X
Xstatic char *
Xget_names(up, type, is_batch)
Xint up, type, is_batch;
X{
X int got_it, n;
X WINDOW *gn_win, *newwin();
X char *ans, *file, *list, buf[40], *expand(), *get_str(), *strtok();
X void st_line();
X struct stat stbuf;
X
X touchwin(stdscr);
X refresh();
X st_line("");
X
X n = type -NUM_INTERNAL -1;
X
X gn_win = newwin(7, 70, 5, 5);
X mvwaddstr(gn_win, 3, 4, "Enter filename: ");
X box(gn_win, VERT, HORZ);
X if (up) {
X if (type <= NUM_INTERNAL)
X sprintf(buf, " Send %s ", protocol[type -1]);
X else
X sprintf(buf, " Send %s ", extrnl->name[up][n]);
X }
X else {
X if (type <= NUM_INTERNAL)
X sprintf(buf, " Receive %s ", protocol[type -1]);
X else
X sprintf(buf, " Receive %s ", extrnl->name[up][n]);
X }
X mvwattrstr(gn_win, 0, 3, A_BOLD, buf);
X
X /* CONSTCOND */
X while (1) {
X wmove(gn_win, 3, 20);
X wrefresh(gn_win);
X /* get the answers */
X if (is_batch)
X ans = get_str(gn_win, 60, "", "\n");
X else
X ans = get_str(gn_win, 60, "", " \t\n");
X
X if (ans == NULL || *ans == '\0') {
X list = NULL;
X break;
X }
X list = expand(ans);
X /* batches are checked on-the-fly */
X if (is_batch)
X break;
X /*
X * Here we have the opportunity to determine the read and
X * write permissions before things get started. Much nicer
X * than finding out later when there's no way to fix it.
X * Only checks the first file.
X */
X file = strtok(list, " \t");
X /* sanity checking */
X if (!stat(file, &stbuf)) {
X if ((stbuf.st_mode & S_IFREG) != S_IFREG) {
X beep();
X clear_line(gn_win, 4, 15, TRUE);
X mvwattrstr(gn_win, 4, 15, A_BOLD, "Not a regular file");
X wrefresh(gn_win);
X wait_key(gn_win, 3);
X clear_line(gn_win, 4, 15, TRUE);
X clear_line(gn_win, 3, 20, TRUE);
X continue;
X }
X }
X /* check read permission */
X if (up) {
X if (access(file, 0)) {
X beep();
X mvwattrstr(gn_win, 4, 15, A_BOLD, "Can't find file");
X wrefresh(gn_win);
X wait_key(gn_win, 3);
X clear_line(gn_win, 4, 15, TRUE);
X clear_line(gn_win, 3, 20, TRUE);
X continue;
X }
X if (access(file, 4)) {
X beep();
X mvwattrstr(gn_win, 4, 15, A_BOLD, "No read permission");
X wrefresh(gn_win);
X wait_key(gn_win, 3);
X clear_line(gn_win, 4, 15, TRUE);
X clear_line(gn_win, 3, 20, TRUE);
X continue;
X }
X break;
X }
X /* check write permission */
X got_it = 0;
X switch(can_write(file)) {
X case DENIED:
X beep();
X clear_line(gn_win, 4, 15, TRUE);
X mvwattrstr(gn_win, 4, 15, A_BOLD, "No write permission");
X wrefresh(gn_win);
X wait_key(gn_win, 3);
X clear_line(gn_win, 4, 15, TRUE);
X clear_line(gn_win, 3, 20, TRUE);
X break;
X case OK_BUT_EXISTS:
X if (!yes_prompt(gn_win, 4, 15, A_BOLD, "File exists, overwrite")) {
X clear_line(gn_win, 4, 15, TRUE);
X clear_line(gn_win, 3, 20, TRUE);
X break;
X }
X /* FALLTHRU */
X case WRITE_OK:
X got_it++;
X break;
X }
X if (got_it)
X break;
X }
X werase(gn_win);
X wrefresh(gn_win);
X delwin(gn_win);
X
X return(list);
X}
X
X/*
X * Prompt for the Unix command line to be used as an external file
X * transfer program. Since expand() is used, it returns a pointer to
X * a static area.
X */
X
Xstatic char *
Xget_extrnl(up)
Xint up;
X{
X WINDOW *ge_win, *newwin();
X char *ans, *cmd, *get_str(), *expand();
X void st_line();
X
X touchwin(stdscr);
X refresh();
X st_line("");
X /* prompt for command line */
X ge_win = newwin(7, 70, 5, 5);
X mvwaddstr(ge_win, 3, 4, "Enter Unix command: ");
X box(ge_win, VERT, HORZ);
X
X if (up)
X mvwattrstr(ge_win, 0, 3, A_BOLD, " Send (external) ");
X else
X mvwattrstr(ge_win, 0, 3, A_BOLD, " Receive (external) ");
X
X wmove(ge_win, 3, 24);
X wrefresh(ge_win);
X /* get the line */
X ans = get_str(ge_win, 60, "", "\n");
X if (ans == NULL || *ans == '\0')
X cmd = NULL;
X else
X cmd = expand(ans);
X
X werase(ge_win);
X wrefresh(ge_win);
X delwin(ge_win);
X return(cmd);
X}
END_OF_FILE
if test 7412 -ne `wc -c <'pcomm-2.0/x_menu.c'`; then
echo shar: \"'pcomm-2.0/x_menu.c'\" unpacked with wrong size!
fi
# end of 'pcomm-2.0/x_menu.c'
fi
if test -f 'pcomm-2.0/xmodem.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'pcomm-2.0/xmodem.c'\"
else
echo shar: Extracting \"'pcomm-2.0/xmodem.c'\" \(7985 characters\)
sed "s/^X//" >'pcomm-2.0/xmodem.c' <<'END_OF_FILE'
X/*
X * Miscellaneous routines to support the xmodem file transfer protocols.
X */
X
X#define TMP_FILE "trunXXXXXX"
X
X#include <stdio.h>
X#include <signal.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X#include "config.h"
X#include "misc.h"
X#include "param.h"
X#include "xmodem.h"
X
X#ifdef BSD
X#include <setjmp.h>
Xjmp_buf gl_buf, rl_buf;
X#endif /* BSD */
X
Xstatic int uid_link(), uid_unlink();
X
X/*
X * Calculate the CRC for the given buffer
X */
X
Xunsigned short
Xcalc_crc(buf, len)
Xunsigned char *buf;
Xint len;
X{
X register int i;
X unsigned short crc;
X static unsigned short crctab[256] = {
X 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
X 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
X 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
X 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
X 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
X 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
X 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
X 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
X 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
X 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
X 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
X 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
X 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
X 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
X 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
X 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
X 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
X 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
X 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
X 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
X 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
X 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
X 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
X 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
X 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
X 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
X 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
X 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
X 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
X 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
X 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
X 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0};
X
X crc = 0;
X for (i=0; i<len; i++)
X crc = (crc<<8) ^ crctab[(crc>>8) ^ *buf++];
X
X return(crc);
X}
X
X/*
X * Calculate the checksum for the given buffer.
X */
X
Xunsigned char
Xcalc_sum(buf, len)
Xunsigned char *buf;
Xint len;
X{
X unsigned char sum;
X
X sum = 0;
X while (--len >= 0)
X sum += *buf++;
X
X return(sum);
X}
X
X/*
X * Get a single character from the line with a specified time-out period
X * in seconds. If the function times-out, it returns a -1.
X */
X
Xstatic int gl_flag;
Xstatic int gl_force();
X
Xint
Xgetc_line(sec)
Xunsigned int sec;
X{
X extern int fd;
X char c;
X unsigned int alarm();
X
X signal(SIGALRM, (SIG_TYPE(*) ()) gl_force);
X gl_flag = 0;
X
X alarm(sec);
X
X#ifdef BSD
X if (setjmp(gl_buf))
X return(-1);
X#endif /* BSD */
X
X if (read(fd, &c, 1) <= 0) {
X alarm(0);
X return(-1);
X }
X if (gl_flag)
X return(-1);
X alarm(0);
X return(c & 0xff);
X}
X
X/* ARGSUSED */
Xstatic int
Xgl_force(dummy)
Xint dummy;
X{
X#ifdef BSD
X longjmp(gl_buf, 1);
X#else /* BSD */
X signal(SIGALRM, (SIG_TYPE(*) ()) gl_force);
X gl_flag = 1;
X return(0);
X#endif /* BSD */
X}
X
X/*
X * Same as above, but reads a bunch of characters. The return code is
X * now just a success/fail indicator.
X */
X
Xstatic int rl_flag;
Xstatic int rl_force();
X
Xint
Xfread_line(buf, len, sec)
Xunsigned char *buf;
Xunsigned int len, sec;
X{
X extern int fd;
X int n;
X unsigned int try, alarm();
X
X signal(SIGALRM, (SIG_TYPE(*) ()) rl_force);
X rl_flag = 0;
X
X alarm(sec);
X while (len) {
X /* read at most CLIST_SIZ chars */
X try = (len > CLIST_SIZ) ? CLIST_SIZ : len;
X#ifdef BSD
X if (setjmp(rl_buf))
X return(-1);
X#endif /* BSD */
X if ((n = read(fd, (char *) buf, try)) <= 0) {
X alarm(0);
X return(-1);
X }
X if (rl_flag)
X return(-1);
X len -= n;
X buf = buf + n;
X }
X alarm(0);
X return(0);
X}
X
X/* ARGSUSED */
Xstatic int
Xrl_force(dummy)
Xint dummy;
X{
X#ifdef BSD
X longjmp(rl_buf, 1);
X#else /* BSD */
X signal(SIGALRM, (SIG_TYPE(*) ()) rl_force);
X rl_flag = 1;
X return(0);
X#endif /* BSD */
X}
X
X/*
X * Put a character on the TTY line. This serves no useful purpose other
X * than making the code look pretty.
X */
X
Xint
Xputc_line(c)
Xunsigned char c;
X{
X extern int fd;
X
X return(write(fd, (char *) &c, 1));
X}
X
X/*
X * Cancel the file transfer. Send several ^X's to the remote, followed
X * by an equal number of backspaces (in case they have already aborted and
X * we're really at the command line).
X */
X
Xvoid
Xcancel_xfer(up)
Xint up;
X{
X extern char file_name[15];
X
X if (!up && !strcmp(param->abort, "DELETE"))
X unlink(file_name);
X
X putc_line(CAN);
X putc_line(CAN);
X putc_line(CAN);
X putc_line(BS);
X putc_line(BS);
X putc_line(BS);
X return;
X}
X
X/*
X * Shorten a file to a predetermined length. Used to remove the ^Z
X * padding from the end of files. (Heaven help us, if one day a binary
X * file actually has ^Z's as part of the end of the file).
X */
X
Xint
Xfix_length(file, len)
Xchar *file;
Xlong len;
X{
X FILE *fp, *tempfp, *uid_fopen();
X register int num;
X char *mktemp(), tempfile[128], buf[BUFSIZ], *strcpy();
X char *s, *strrchr(), *strcat();
X struct stat stbuf;
X
X if (stat(file, &stbuf) < 0)
X return(1);
X /* see if we have any work to do */
X if (len >= stbuf.st_size)
X return(0);
X
X if (!(fp = uid_fopen(file, "r")))
X return(1);
X
X /*
X * The temporary file should be in the same directory as the
X * file being received because otherwise we'd have no way of
X * guaranteeing they would be in the same file system. (Hard
X * links across different file systems aren't allowed).
X */
X strcpy(tempfile, file);
X if (s = strrchr(tempfile, '/'))
X *++s = '\0';
X else
X strcpy(tempfile, "./");
X
X strcat(tempfile, TMP_FILE);
X mktemp(tempfile);
X
X if (!(tempfp = uid_fopen(tempfile, "w"))) {
X fclose(fp);
X return(1);
X }
X
X while (len != 0L) {
X num = (len > BUFSIZ) ? BUFSIZ : (int) len;
X fread(buf, sizeof(char), num, fp);
X if (fwrite(buf, sizeof(char), num, tempfp) != num) {
X fclose(fp);
X fclose(tempfp);
X return(1);
X }
X len -= (unsigned int) num;
X }
X
X fclose(fp);
X fclose(tempfp);
X
X if (uid_unlink(file) < 0)
X return(1);
X
X if (uid_link(tempfile, file) < 0)
X return(1);
X
X if (uid_unlink(tempfile) < 0)
X return(1);
X
X return(0);
X}
X
Xstatic int
Xuid_link(path1, path2)
Xchar *path1, *path2;
X{
X int ret;
X
X#ifdef SETUID_BROKE
X int status;
X void _exit();
X
X switch(fork()) {
X case 0:
X setuid(getuid());
X setgid(getgid());
X _exit(link(path1, path2));
X case -1:
X fprintf(stderr, "uid_link: Can't fork\n");
X return(-1);
X default:
X if (wait(&status) == -1) {
X fprintf(stderr, "uid_link: wait failed\n");
X return(-1);
X }
X ret = status >> 8;
X }
X#else /* SETUID_BROKE */
X int euid, egid;
X
X euid = geteuid();
X egid = getegid();
X
X setuid(getuid());
X setgid(getgid());
X
X ret = link(path1, path2);
X
X setuid(euid);
X setgid(egid);
X#endif /* SETUID_BROKE */
X return(ret);
X}
X
Xstatic int
Xuid_unlink(path)
Xchar *path;
X{
X int ret;
X
X#ifdef SETUID_BROKE
X int status;
X void _exit();
X
X switch(fork()) {
X case 0:
X setuid(getuid());
X setgid(getgid());
X _exit(unlink(path));
X case -1:
X fprintf(stderr, "uid_unlink: Can't fork\n");
X return(-1);
X default:
X if (wait(&status) == -1) {
X fprintf(stderr, "uid_unlink: wait failed\n");
X return(-1);
X }
X ret = status >> 8;
X }
X#else /* SETUID_BROKE */
X int euid, egid;
X
X euid = geteuid();
X egid = getegid();
X
X setuid(getuid());
X setgid(getgid());
X
X ret = unlink(path);
X
X setuid(euid);
X setgid(egid);
X#endif /* SETUID_BROKE */
X return(ret);
X}
END_OF_FILE
if test 7985 -ne `wc -c <'pcomm-2.0/xmodem.c'`; then
echo shar: \"'pcomm-2.0/xmodem.c'\" unpacked with wrong size!
fi
# end of 'pcomm-2.0/xmodem.c'
fi
echo shar: End of archive 4 \(of 8\).
cp /dev/null ark4isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 8 archives.
rm -f ark[1-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0
--
Frank Kaefer # fkk@stasys.sta.sub.org # Starnberg, Germany
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads