egray@fthood.UUCP (03/13/88)
Hello netlanders! This is "pcomm"... the long-awaited replacement for my "mdm" program. Pcomm is a public domain telecommunication program for Unix designed to operate similar to the popular MSDOS program, ProComm. ProComm (TM) is copyrighted by Datastorm Technologies Inc. The source code is quite large... (about 300k total) and is broken down into 6 parts for easier mailing. Because of it's size, I'm posting half the code on one day, and the other half the next. The program has a minor quirk which may be irritating to some... In order to get pop-up windows to work while communicating with another system, the program has to keep a duplicate copy of what it thinks is on the screen. This "virtual screen" is only used to repaint the background during the transition from the terminal mode to the command mode. The problem is that the virtual screen currently doesn't "understand" escape sequences. For example, when the screen is repainted, instead of clearing the screen, the string "^[[2J" will appear. Since the virtual screen is ONLY USED in the command mode, the quirk doesn't detract from the usefulness of the program (in my humble opinion). No bug reports on this, please... I'm working on it! There is a shell archive, "Unixpc.shar" (included in the distribution) that contains the files specific to the AT&T Unix PC 7300. Have fun... Emmet P. Gray US Army, HQ III Corps & Fort Hood ...!ihnp4!uiucuxc!fthood!egray Attn: AFZF-DE-ENV Directorate of Engineering & Housing Environmental Management Office Fort Hood, TX 76544-5057 ----------------------------------------------------------------------------- #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # Readme # Release.notes # Doc # Pcomm.1 # Pcomm.dial_dir # Pcomm.modem # Pcomm.param # This archive created: Fri Mar 11 07:34:59 1988 export PATH; PATH=/bin:/usr/bin:$PATH echo shar: "extracting 'Readme'" '(7859 characters)' if test -f 'Readme' then echo shar: "will not over-write existing file 'Readme'" else sed 's/^X//' << \SHAR_EOF > 'Readme' X X Pcomm X A Unix Telecommunication Program X XRequirements: X X Pcomm will not run on terminals with a screen size of less than X 80 columns by 24 lines or on terminals that lack cursor movement X capabilities. For terminals without arrow keys, use the letter X "U" in place of "up arrow" and the letter "N" in place of X "down arrow". X X Running Pcomm from a dialup line at 1200 baud will be make the X windows incredibly slow. X XPortability: X X This program was written with AT&T System V in mind. It makes X use of System V specific routines such as those in termio(7). X There is currently no port to Berkeley or v7 Unix. X X This program can make use of the newer curses(3) routines from X SVR2. There is a compile-time definition OLDCURSES for compatibility X with older flavors of curses(3). None of the functionality is X lost using older curses, only some of the whistles and bells. X X Included in the distribution package is a shell script named X "Unixpc.shar" that contains the Makefile specific for the AT&T X Unix PC 7300. X X Pcomm makes use of the bold, blinking and standout video attributes. X My concept of "standout" and "reverse" might be different than X yours (I like "standout" to be a brighter version of "reverse"). X Check your terminfo database... X X Flavors of curses without the keypad() function won't be able to X recognize arrow keys on the terminal, so users will have to X substitute the letters described above for the arrow keys. X XThings to do: X X There are many pre-processor definitions located in the source X code that alter the way pcomm works, or gives the location of other X files. The following list shows the location and default settings X of these definitions: X X LOG_CALLS Should pcomm keep a log of all phone calls? The X default in admin.c is no (#undef). If defined, X the path to the log file is in LOGFILE. X X LIMIT_LD Should access to long distance dialing be limited X to privileged users? The default in admin.c is X no (#undef). If defined, the group to check is in X GRPNAME. X X LPRINT This is the pretty line print program. (This is not X the name of the device). The default in d_print.c X is "/usr/bin/lprint". X X MAX_PASS The maximum number of dialing attempts before we X give up. The default in di_win.c is 25. X X DEFAULT The directory containing the default support files. X It is not intended that users have write permission X on these files. The default in init.c is X "/usr/local/lib/pcomm". X X LPR The generic line printer program. (This is not the X name of the device). The default in input.c is X "/usr/bin/lpr". X X LOCKDIR The location of the UUCP lock files. The default X in port.c is "/usr/spool/uucp". (HoneyDanBer UUCP X normally uses /usr/spool/locks). X X ASCII_PID Should the pid (process ID) in the UUCP lock file X be ASCII encoded? The default in port.c is no X (#undef). (HoneyDanBer UUCP normally uses ASCII pids). X X NUM_DIR The maximum slots in the dialing directory. The X default in dial_dir.h is 100. X X NUM_QUEUE The maximum slots in the dialing queue. The default X in dial_dir.h is 10. X X NOPROMOTE Should missing video attributes be promoted to X standout? The default in misc.h is no (#undef). X X NUM_TTY The maximum number of ttys used for dialout. The X default in modem.h is 10. X X NUM_MODEM The maximum number of different types of modems used X for dialout. The default in modem.h is 10. X X MAX_ERRORS The maximum number of errors for a single block X before we give up on a file transfer. The default X in xmodem.h is 10. X X The compile-time definition SGID is specific to my system, but X others might find it useful. On my system, all programs that X access the dialout modems, are set-group-id to "uucp". (This is X because normal users don't have write permission to the devices, X the lock directory, or the phone.call logfile). The use of X SGID will assure that the real group id is restored during shell X escapes, open()s, etc. The access(2) routine is used to determine X read and write permissions prior to opening files. X X The distribution package contains three sample support files named X "Pcomm.dial_dir", "Pcomm.modem", and "Pcomm.param". These files X should be renamed to change the upper case "P" to a lower case X "p" and copied into the directory given in the DEFAULT definition X described above. X XDocumentation: X X The reference documentation file, "Doc" is designed to run thru X the Unix "pr" command before being sent to the printer. For example: X X pr -h " Pcomm Reference Manual " | lpr X X The file "Pcomm.1" is a nroff manual page suitable for copying X into /usr/man/man1. X XSetup: X X Before pcomm can be used properly, the tty/modem database must be X configured to match your system. The "pcomm.modem" file should X be edited by the "TTY Setup" and "Modem Setup" menus. X X The shell archive "Unixpc.shar" contains the Pcomm.modem file X specific to the AT&T Unix PC 7300. (Its codes are NOT intuitive) X XWhere similarities end: X X When pcomm is first executed, it hasn't yet selected a communications X port to use, so characters typed at the blank screen are ignored. X To get a port without pcomm doing the dialing, select an empty X entry in the dialing directory, or use the manual dial option with X the phone number set to a single space character. The second field X in the status line will show what tty port is currently in use. X X Since all printing goes through the Unix print spooler, the printer X logging feature will not output characters as they appear on the X screen. Printing will actually start when the print logging is X toggled off (and the complete print job is sent to the spool). X X Pcomm doesn't emulate any terminals... Whatever terminal you're on X is what the remote system sees. X X Pcomm doesn't have a script language or command interpreter. The X index field of the dialing directory is used instead to act as a X shortcut into the dialing directory from the "-f" command line X option. The index field is also used to specify a particular tty X to be used (as opposed to searching the list of ttys for the first X free one). This feature must be used on direct connections with X other machines. For example, if tty12 is a hard-wired port to X "System A", then the dialing directory entry for "System A" would X have "tty12" in the index field. X XKnown limitations: X X The keyboard macro feature is not implemented at this time. X X The true screen contents are lost when the "hot key" is pressed. X Pcomm attempts to compensate (rather poorly) by repainting a X virtual screen of what it thinks the true screen should look like. X Escape sequences in the virtual screen image will be ignored when X the background is repainted. For example, if you're on a vt100 X and you recieve a ^[[2J to clear the screen, the screen *will* be X cleared... but when the screen is repainted, it will contain the X characters ^[, [, 2, J (instead of performing the function). X X The disp_tty() routine in s_tty.c currently does not support a X NUM_TTY definition of greater than 10. X X For some strange reason, the first keystroke is "lost" after a X file transfer is complete or after starting data logging. X XFuture directions: X X The virtual screen routines need a lot of work. The most commonly X used escape sequences (known to terminfo) will be processed. X X I plan to have an option at compile time to have the virtual screen X buffer held on disk (v7) or in shared memory (SVR2). X X The input routine is designed so it could be a standalone program X that gets called from pcomm. I plan to have an option at compile X time to have input() compiled into pcomm or as a separate program. X X XEmmet P. Gray US Army, HQ III Corps & Fort Hood X...!ihnp4!uiucuxc!fthood!egray Attn: AFZF-DE-ENV X Directorate of Engineering & Housing X Environmental Management Office X Fort Hood, TX 76544-5057 SHAR_EOF if test 7859 -ne "`wc -c < 'Readme'`" then echo shar: "error transmitting 'Readme'" '(should have been 7859 characters)' fi fi echo shar: "extracting 'Release.notes'" '(853 characters)' if test -f 'Release.notes' then echo shar: "will not over-write existing file 'Release.notes'" else sed 's/^X//' << \SHAR_EOF > 'Release.notes' X X Pcomm version 1.0 X XThings that have changed: X X I've added a bunch of parameters to the pcomm.param and pcomm.modem X files, so the files used with the beta release won't work with the X 1.0 release. X X Pcomm will attempt to determine if the modem has synchronized at X a baud rate different that what is expected, and make changes to X the line settings as appropriate. X X The quit and interrupt signals are now ignored. X X All of the file transfer protocols are now functional. X X The directory search order used to find the support files has been X changed slightly X XThings left to do: X X Work on the virtual screen routines. X XHave fun... X XEmmet P. Gray US Army, HQ III Corps & Fort Hood X...!ihnp4!uiucuxc!fthood!egray Attn: AFZF-DE-ENV X Directorate of Engineering & Housing X Environmental Management Office X Fort Hood, TX 76544-5057 SHAR_EOF if test 853 -ne "`wc -c < 'Release.notes'`" then echo shar: "error transmitting 'Release.notes'" '(should have been 853 characters)' fi fi echo shar: "extracting 'Doc'" '(32879 characters)' if test -f 'Doc' then echo shar: "will not over-write existing file 'Doc'" else sed 's/^X//' << \SHAR_EOF > 'Doc' X X X X X X X X X X X PPPPPP CCCC OOOO MM MM MM MM X P P C O O M M M M M M M M X PPPPPP C O O M M M M M M X P C O O M M M M X P CCCC OOOO M M M M X X X X X X X X X Pcomm Reference Manual X X version 1.0 X X X X X written by X X Emmet P. Gray X ...!ihnp4!uiucuxc!fthood!egray X X X X X X X Pcomm is a public domain telecommunications program for Unix that X is designed to operate similar to the MSDOS program, ProComm. X ProComm (TM) is copyrighted by Datastorm Technologies, Inc. This X is a completely new program and contains no ProComm source code. X This is not a Datastorm product. X X X Table of Contents X X X 1. INTRODUCTION .................... 3 X 1.1 Requirements ................... 3 X 1.2 Support files .................. 3 X X 2. RUNNING PCOMM ................... 4 X 2.1 Hot key ........................ 4 X 2.2 Status line .................... 4 X 2.3 Help screen .................... 5 X 2.4 Exit pcomm ..................... 5 X X 3. SETUP SCREENS ................... 6 X 3.1 Prompting ...................... 6 X 3.2 TTY setup ...................... 7 X 3.3 Modem setup .................... 8 X 3.4 Terminal setup ................. 9 X 3.5 General setup .................. 10 X 3.6 ASCII transfer setup ........... 11 X X 4. MAJOR FUNCTIONS ................. 13 X 4.1 Dialing directory .............. 13 X 4.2 Redial ......................... 15 X 4.3 Keyboard macros ................ 15 X 4.4 Line settings .................. 15 X 4.5 Exit pcomm ..................... 16 X 4.6 Unix gateway ................... 16 X X 5. UTILITY FUNCTIONS ............... 17 X 5.1 Program information ............ 17 X 5.2 Setup screen ................... 17 X 5.3 Change directory ............... 17 X 5.4 Clear screen ................... 17 X 5.5 Toggle duplex .................. 17 X 5.6 Hangup the phone ............... 17 X 5.7 Printer logging ................ 18 X 5.8 Toggle CR - CR/LF .............. 18 X 5.9 Break .......................... 18 X X 6. FILE FUNCTIONS .................. 19 X 6.1 Send files ..................... 19 X 6.2 Receive files .................. 20 X 6.3 Directory ...................... 20 X 6.4 Screen dump .................... 21 X 6.5 Start data logging ............. 21 X 6.6 Toggle logging ................. 21 X X 7. DIALING WINDOW .................. 22 X X1. INTRODUCTION X X Pcomm is a public domain, menu driven, telecommunication program X designed to provide the same "ease of use" as similar programs X available in MSDOS. Some of its features are: X X o+ Large dialing directory X o+ Automatic redial feature X o+ Supports several file transfer protocols X o+ Data logging (log of the terminal session) X o+ Printer logging X o+ Screen dump X o+ User customization X X Pcomm does not emulate any particular terminal. Whatever terminal X you're on, is what the remote system "sees". X X1.1 Requirements X X Pcomm will not run on terminals with a screen size of less than X 80 columns by 24 lines or on terminals that lack cursor movement X capabilities. For terminals without arrow keys, use the letter "U" X in place of "up arrow" and the letter "N" in place of "down arrow". X X1.2 Support files X X Pcomm uses three support files, namely: X X pcomm.dial_dir the dialing directory X pcomm.modem the modem/tty database X pcomm.param the start-up default parameters X X There is a default directory (typically "/usr/local/lib/pcomm") X where the "standard" support files live. Since the average user X would not have write permission on these files, it's assumed that X you'll copy these standard files to your own directory and edit X them to suit your needs. X X Pcomm can use the environmental variable "PCOMM" to search for X these "private" support files. If used, the variable must contain X the path to the directory containing the files. X X The following directories are searched to find the support files: X X o+ directory given with the "-d" option X o+ directory in the PCOMM environmental variable X o+ the current working directory X o+ the global default directory X X2. RUNNING PCOMM X X Pcomm has the following command line syntax. X X pcomm [-d directory] [-f index] X X The "-d" option allows you to specify an additional path to be used X when searching for the pcomm support files. X X The "-f" option is used to specify automatic dialing of an entry in X the dialing directory. The "index" field in the dialing directory X (described later) is checked against the string given on the command X line. If a match is found, that entry is automatically dialed. X X2.1 Hot key X X Pcomm uses a "hot key" to precede each command. (The value of the X hot key is a user tunable parameter, but for the purpose of this X document we'll assume the hot key is defined as control-A). X X The hot key is used to put pcomm in the command mode. For example, X to get the help screen, you'd type control-A (to get to the command X mode) then the number 0 (to display the help screen). When a command X is completed, pcomm returns to the terminal mode. X X NOTE: While in the command mode, the communications with the remote X system is temporarily suspended. X X2.2 Status line X X Whenever pcomm is in the command mode (or is not currently connected X to a remote) a status line is displayed at the bottom of the screen. X A typical status line might look like this: X X+-----------------------------------------------------------------------------+ X| ^A-0 HELP | No TTY | FDX | 1200 E71 | LOG OFF | PTR OFF | CR | CR | X+-----------------------------------------------------------------------------+ X X The eight fields of the status line are: X X o+ help screen command (or a temporary message) X o+ name of the tty device in use X o+ duplex mode (FDX = full duplex, HDX = half duplex) X o+ current line settings X o+ status of data logging option X o+ status of printer logging option X o+ incoming CR translation X o+ outgoing CR translation X X X2.3 Help screen X X The help screen gives a brief review of all the available commands. X To access the help screen type ^A and '0' (zero). The typical help X screen would look like this: X X+-----------------------------------------------------------------------------+ X| P C O M M H E L P | X|-----------------------------------------------------------------------------| X| | X| Major Functions Utility Functions File Functions | X| | X| Dialing Directory . ^A-D Program Info ..... ^A-I Send files .... ^A-up | X| Auto Redial ....... ^A-R Setup Screen ..... ^A-S Receive files . ^A-dn | X| Keyboard Macros ... ^A-M Change Directory . ^A-B Directory ..... ^A-F | X| Line Settings ..... ^A-P Clear Screen ..... ^A-C Screen Dump ... ^A-G | X| Exit Pcomm ........ ^A-X Toggle Duplex .... ^A-E Start Data Log. ^A-1 | X| Unix Gateway ...... ^A-4 Hangup Phone ..... ^A-H Toggle Log .... ^A-2 | X| Printer On/Off ... ^A-L | X| Toggle CR/CR-LF .. ^A-3 | X| Break Key ........ ^A-7 | X| | X+-------------------------- Press any key to continue ------------------------+ X X2.4 Exit pcomm X X To exit pcomm, you'd type ^A and 'x' to access the exit window. X X +-- Exit -----------------------+ X | | X | Exit to Unix? (y/n): _ | X | | X +-------------------------------+ X X To exit, you'd press the letter 'y' (carriage return not required). X X3. SETUP SCREENS X X Pcomm allows you to change many of the default parameters. The setup X screen is accessed by typing ^A and 's'. The following screen is X typical and shows the sub-menu choices: X X ----------------------- Setup Menu ---------------------------- X X 1) TTY Setup X 2) Modem Setup X 3) Terminal Setup X 4) General Setup X 5) ASCII Transfer Setup X S) Save setup to disk X X --------------------------------------------------------------- X OPTION ==> _ Press ESC to exit X X To select one of the sub-menu choices, you'd type the number (or X letter) at the "OPTION ==>" prompt. To exit from a sub-menu and X return to this setup menu screen, you'd press the escape key. X X Changes made affect the current pcomm session only. To make the X changes become the default, you'd select the 's' option. X X3.1 Prompting X X There are several different types of prompts used in the setup X screens. The prompts use the bottom two lines on the display for X user input and to give more information on what is being asked. X Pcomm will beep at any illegal input. The escape key 'ESC' will X abort any prompt. The prompt types are: X X o+ Character prompt. Asks you to input a single character. X X o+ String prompt. Asks you to input a word or group of X characters. X X o+ Numeric prompt. Asks you for a number. X X o+ Menu prompt. Shows a selection and allows you to to X choose the current selection by pressing the carriage return X or change the selection by pressing the space bar. X X3.2 TTY setup X X The TTY setup screen contains the list of devices (ports) that pcomm X is allowed to use, and what is attached to each port. A typical TTY X setup screen might look like this: X X ------------------------- TTY Setup --------------------------- X X TTY name Modem name Maximum baud X X 1) tty10 HAYES 1200 X 2) tty11 HAYES 2400 X 3) tty12 DIRECT 9600 X 4) 0 X 5) 0 X 6) 0 X 7) 0 X 8) 0 X 9) 0 X 10) 0 X X 11) Add a TTY entry X 12) Delete a TTY entry X X --------------------------------------------------------------- X OPTION ==> _ Press ESC to return X X You may edit an entry by typing the entry number at the prompt. X To add an entry, you'd type '11' at the prompt, etc. X X The tty setup fields are: X X 1) The tty name. This is the name of the serial port that X pcomm will be allowed to use. Notice that the path component X of the name, "/dev/" is not used. X X 2) The modem name. This a keyword that is used later to link X the modem database with the tty database. The name could be X any combination of letters or numbers (both upper and lower X case). X X NOTE: All hard-wired ports (ports without modems attached) X *must* use the word "DIRECT" for the modem name. X X 3) The maximum baud rate is highest rating of the modem (or X the connected baud rate of hard-wired ports). The baud rate X is selected from a "menu prompt". X X3.3 Modem setup X X The modem setup contains the commands to make the modem dial, hangup X the phone, etc. A typical modem setup screen might look like this: X X -------------------------- Modem Setup -------------------------- X X 1) Modem name ............. HAYES X X 2) Modem init string ...... ATS7=45S11=70! X 3) Dialing command ........ ATDT X 4) Dialing cmd suffix ..... ! X 5) Hangup string .......... ~~+++~~ATH0! X 6) 300 baud connect ....... CONNECT! X 7) 1200 baud connect ...... CONNECT 1200 X 8) 2400 baud connect ...... CONNECT 2400 X 9) 4800 baud connect ...... X 10) 9600 baud connect ..... X 11) 19200 baud connect .... X 12) No connect string 1 ... BUSY X 13) No connect string 2 ... VOICE X 14) No connect string 3 ... NO CARRIER X 15) No connect string 4 ... X X --------------------------------------------------------------- X OPTION ==> _ Press ESC to return X X The fields of the modem setup are: X X 1) Modem name. This is the keyword that links the modem X database with the tty database. A menu prompt is used to X select the modem name (and the remaining parameters that go X with it). X X 2) Modem initialization string. This is sent to the modem X whenever the port is selected. Consult your modem manual for X the codes to be used. Notice the use of the "!" character, X this is the "character synonym" for the carriage return. X X NOTE: See section 3.5 for the complete list of character synonyms. X X 3) Dialing command. The first part of the command to make X the modem dial. It is assumed that the phone number will X immediately follow. X X 4) Dialing command suffix. The last part of the command to X make the modem dial. Typically this would be the carriage X return "character synonym". X X 5) Hangup string. The command to make the modem hangup the X phone. The character synonym for a 1 second pause is the X tilde "~" character. X X 6-11) Connect strings. The return message when the modem is X connected to the remote. If different messages are returned X depending on which baud rate is selected, they should be X specified. X X NOTE: If two connect strings are similar, (one is contained entirely X in another) then it is possible that the return code from the modem X will not match the correct connect string. To prevent this from X happening, use the command synonym for the carriage return to X terminate the shorter connect string. X X 12-15) No connect strings. The messages returned by the X modem when no connection is made. X X3.4 Terminal setup X X The terminal setup allows you to define the hot key and the mapping X of the end-of-line characters. A typical terminal setup menu would X look like this: X X ---------------------- Terminal Setup -------------------------- X X 1) Hot key ................ 1 X 2) ASCII version of hot ... ^A X X 3) Duplex ................. FULL X 4) Flow control ........... XON/XOFF X 5) CR translation (in) .... CR X 6) CR translation (out) ... CR X X --------------------------------------------------------------- X OPTION ==> _ Press ESC to return X X The fields in the terminal setup are: X X 1) Hot key. This is the decimal code for the user definable X hot key. Consult an ASCII/decimal conversion chart for the X decimal values of other characters. X X 2) ASCII version of hot key. This is the printable version X of the hot key used by pcomm in the help screen and status X line. X X 3) Duplex. A menu prompt is shown to select between FULL X duplex and HALF duplex. In the half duplex mode, characters X sent to the remote system are also sent to the the screen. X (The duplex mode can also be change "on the fly" by the X ^A-E command.) X X NOTE: Due to a technical limitation in pcomm, data logging and X print logging will not work correctly in the half duplex mode. X X 4) Flow control. A menu prompt is shown to select between X XON/XOFF flow control and NONE. The flow control selected X here is only used during the terminal session, not during X file transfers. X X 5-6) CR translations. The end-of-line characters for both X incoming and outgoing carriage returns can be altered to suit X the remote system's needs. A menu prompt provides the X following choices: X X o+ CR (no translation) X o+ CR/NL translate CR to CR/NL X X The incoming CR translation can also be changed "on the fly" X with the ^A-3 command. X X3.5 General setup X X The general setup allows you to define the character synonyms and X the default files used by the screen dump and other features. A X typical general setup screen might look like this: X X ------------------------ General Setup ----------------------- X X 1) Default log file ....... pcomm.log X 2) Screen dump file ....... pcomm.dump X X 3) Strip high bit ........ YES X X 4) Pause character ........ ~ X 5) CR character ........... ! X 6) CTRL character ......... ^ X 7) ESC character .......... | X X 8) Aborted downloads ...... KEEP X X 9) Connect delay time ..... 35 X 10) Pause between redials . 5 X X --------------------------------------------------------------- X OPTION ==> _ Press ESC to return X X The general setup fields are: X X 1) Default log file. The file name to be used as the default X when the data logging is actived (^A-1). You can override X this default at run time. X X 2) Screen dump file. The file name to be used for the screen X dump command (^A-G). X X 3) Strip high bit. Should pcomm strip the eighth bit on X incoming and outgoing characters? A menu prompts allows you X to select YES or NO. This feature is not used during file X transfers. X X 4-7) Character synonyms. These are symbols that pcomm uses X to translate special characters to the their real values X prior to sending them to the modem. Synonyms are useful for X terminals and editors that balk at special characters. X X 8) Aborted downloads. When a download aborts (fails), should X the partially completed file be kept? The menu prompt allows X "KEEP" or "DELETE". X X 9) Connect delay time. The number of seconds pcomm will wait X for the modem to return a status code. X X 10) Pause between retries. The number of seconds to wait X before pcomm tries to call the number again. X X3.6 ASCII transfer setup X X This setup screen allows you to select options to be used for ASCII X uploads and download. A typical ASCII transfer setup would look X like this: X X ---------------------- ASCII Transfer Setup --------------------- X X ASCII UPLOAD X X 1) Echo locally ........... NO X 2) Expand blank lines ..... NO X 3) CR delay (ms) .......... 0 X 4) Pace the output ........ NO X 5) CR translation ......... NONE X 6) LF translation ......... NONE X X ASCII DOWNLOAD X X 7) Transfer timeout ....... 5 X 8) CR translation ......... STRIP X 9) LF translation ......... NONE X X --------------------------------------------------------------- X OPTION ==> _ Press ESC to return X X The fields are: X X 1) Echo locally. This is similar to the duplex option in X that it copies outgoing characters to the screen. The options X are YES and NO. X X 2) Expand blank lines. Should a blank line (NL alone) be X expanded to a space and NL? Some BBS systems use a blank X line to signal the end of a ASCII upload. The options are X YES and NO. X X 3) CR delay. The delay in milliseconds to be used when X sending a CR. The menu prompt limits the choice to 0, 100, X or 150. X X 4) Pace output. Should each character sent be delayed? Very X old BBS systems may require this. The choice is YES or NO. X X 5) CR translation. The menu prompt provides the following X choices for upload translations: X X o+ NONE (no translation) X o+ ADD NL translate CR to CR/NL. X o+ STRIP remove the CR character X X 6) LF translation. Same as above except the choices are: X X o+ NONE (no translation) X o+ ADD CR translate NL to CR/NL. X o+ STRIP remove the NL character X X 7) Transfer timeout. The number of seconds to be used to X determine the end of an ASCII download. You can halt the X transfer before the timer goes off by hitting the ESC key. X X 8-9) Same as 5) and 6) above, except for downloading. X X4. MAJOR FUNCTIONS X X When pcomm is invoked without the "-f" command line option, you are X placed in the terminal mode with a blank screen and a status line. X However, since pcomm hasn't yet selected a serial port to use, X characters typed at the blank screen are ignored. X X Normally the first command you'd use is ^A-D to bring up the dialing X directory menu. X X4.1 Dialing directory X X To dial another system, you'd type ^A-D to access the dialing X directory menu, then enter the entry number at the prompt. X X The entry number could be preceded by a special long distance dialing X code such as "#5" in lieu of "5" alone. Long distance codes could X contain access numbers such as those that MCI and Sprint require. X X A typical dialing directory would look like this: X X+----------------------------------------------------------------------------+ X| D I A L I N G D I R E C T O R Y | X|----------------------------------------------------------------------------| X| Name Number Baud P D S Dpx Index/tty | X| 1- Abbey Road 1 (512) 590-6036 2400-N-8-1 F | X| 2- Tel-Med-Com 526-8686 1200-E-7-1 F | X| 3- C Board 1 (619) 722-8724 2400-N-8-1 F | X| 4- Crest 1 (213) 471-2518 2400-N-8-1 F crest | X| 5- Last Chance 1 (219) 762-8411 2400-E-7-1 F | X| 6- Killer 1 (214) 827-1994 1200-E-7-1 F | X| 7- System A (direct) 9600-N-8-1 F tty12 | X| 8- 1200-E-7-1 F | X| 9- 1200-E-7-1 F | X| 10- 1200-E-7-1 F | X| | X| ==> _ R Revise M Manual Dialing Entry to Dial | X| P LD Codes D Delete Entry <cr> Scroll Down | X| up/dn Page L Print Entries ESC Exit | X| | X| LD Codes Active: @ # | X| | X+----------------------------------------------------------------------------+ X X The fields of the dialing directory are: X X o+ Name. The name of the remote system. X X o+ Number. The telephone number to the remote system. X X NOTE: The "(", ")", "-", and space character are for just for looks, X they don't get sent to the modem. X X o+ Line settings. The communications settings to be used X when dialing that entry. The range of values are: X X Baud Parity Data bits Stop bits X X 300 N - none 7 1 X 1200 E - even 8 2 X 2400 O - odd X 4800 X 9600 X 19200 X X o+ Duplex. The duplex mode. Either "F" for full or "H" X for half. X X o+ Index. The string to be used to select this entry with X the "-f" command line option. This field is also used to X specify a particular tty for the entry. X X NOTE: On all hard-wired ports, the index field must be set to the X name of the port. For example, if tty12 is a hard-wired port to X "System A", then the dialing directory entry for "System A" would X have "tty12" in the index field. X X The commands at the dialing directory prompt are: X X R) Revise (or add) a dialing directory entry or long distance X dialing code. Prompts you to save the changes to disk. X X P) Print (display) the long distance dialing codes. X X up/dn) Scroll the dialing directory up or down 10 lines. X Use the up and down arrow keys to access this feature. X X M) Manual dial. Prompts you for a phone number rather than X using a number already in the dialing directory. X X D) Delete an entry or a range of entries. Prompts you to X save the changes to disk. X X L) Print. Send the dialing directory to the printer X or a file of your choice. X X 1-100) Entry number. Dial the phone for that entry number. X X NOTE: To access the port directly without dialing (perhaps to send X the dial codes yourself), select an empty entry or enter a single X space character at the manual dial option. X X <cr> Carriage return. Scroll the dialing directory down one X line. X X4.2 Redial X X The redial feature is a misnomer, it really is a queuing system that X allows pcomm to dial several numbers in a cycle until one of them X answers. X X When you invoke the redial command with ^A-R, you are prompted for a X list of dialing directory numbers. (You may also prepend a long X distance code to the entry number). X X +-- Redial Queue --------------------------------------------------+ X | | X | Directory Entry Number(s): _ | X | | X | (CR for previous numbers) | X +------------------------------------------------------------------+ X X To redial the previous number, press a carriage return alone at X the prompt. X X4.3 Keyboard macros. X X Keyboard macros are not supported at this time. X X4.4 Line settings. X X The line settings menu is invoked by ^A-P. A typical line settings X menu would look like this: X X +-----------------------------------------------+ X | Line Settings | X |-----------------------------------------------| X | | X | Current Settings: 1200,E,7,1 | X | | X | 1) 300,E,7,1 7) 300,N,8,1 | X | 2) 1200,E,7,1 8) 1200,N,8,1 | X | 3) 2400,E,7,1 9) 2400,N,8,1 | X | 4) 4800,E,7,1 10) 4800,N,8,1 | X | 5) 9600,E,7,1 11) 9600,N,8,1 | X | 6) 19200,E,7,1 12) 19200,N,8,1 | X | | X | Parity Data Bits Stop Bits | X | 13) Odd 14) 7 bits 16) 1 bit | X | 15) 8 bits 17) 2 bits | X | | X | 18) Save Changes YOUR CHOICE: _ | X | | X +------------- Press ESC to return -------------+ X X After dialing a remote, the line settings in the dialing directory X entry are automatically used. Therefore the line settings menu is X used to adjust the values or to select the default parameters. You X can make the current setting the default by selecting the "Save X Changes" option. X X The current settings are also displayed in the status line. X X NOTE: During file transfers, certain parameters (namely the data X bits and parity) will be temporarily promoted. X X4.5 Exit pcomm X X To exit pcomm, you'd type ^A-X. X X4.6 Unix gateway. X X To temporarily suspend pcomm and spawn a Unix shell, you'd type X ^A-4. To return to pcomm, you'd exit the shell normally, typically X with "^D" or "exit". X X5. UTILITY FUNCTIONS X X The following commands perform secondary functions. X X5.1 Program information X X To display the opening information screen, you'd type ^A-I. Press X any key to return to the terminal mode. X X5.2 Setup screen X X The setup screens are described in detail in section 3 of this manual. X X5.3 Change directory X X To change the current working directory while still inside pcomm, X you'd type ^A-B. A screen similar to the following would appear: X X +-- Change directory -------------------------------------------+ X | | X | Current directory: /usr/egray | X | New directory: _ | X | | X +---------------------------------------------------------------+ X X Abbrievations known to the shell are acceptable, for example the X "~" character would be translated to the home directory in the csh X or ksh shell. X X5.4 Clear screen. X X To clear the local screen and home the cursor, you'd type ^A-C. X X NOTE: The remote system may not "know" the screen has been cleared, X and may make assumptions about the screen that are incorrect. X X5.5 Toggle Duplex. X X The ^A-E command changes the duplex mode from FULL to HALF, or from X HALF to FULL. The status line shows the current settings. X X5.6 Hangup the phone. X X To hangup the phone, you'd type ^A-H. The word "disconnecting" will X briefly show in the status line. X X NOTE: The hangup string is sent to the modem and then the DTR is X dropped on the line. X X5.7 Printer logging. X X The ^A-L command toggles the printer logging on or off. The current X settings are displayed in the status line. X X NOTE: Since all printing goes to the normal Unix print spool program, X the characters will not print on the printer as they appear on the X screen. The printing will actually begin when the printer logging X is turned *off* and the complete print job is sent to the spool. X X5.8 Toggle CR - CR/LF. X X The ^A-3 command toggles the incoming line termination characters X between CR and CR/LF. The status line show the current settings (in X the next to the last field). X X5.9 Break. X X A ^A-7 sends a modem break to the remote system. The word "break" X is (very) briefly displayed on the status line. X X NOTE: This not the same as the break key on the keyboard (we don't X want to send a break to the local system, we want to sent it to X the *remote*). X X6. FILE FUNCTIONS X X One of the most important features of a telecommunication program is X the ability to transfer files. The following file transfer protocols X are implemented at this time: X X protocol packet error multiple X name size detection files? X --------- -------- ------------ ----- X X xmodem 128 checksum/CRC no X xmodem-1k 128/1024 checksum/CRC no X modem7 128 checksum yes*1 X ymodem 128/1024 CRC yes*2 X ymodem-g 128/1024 none*3 yes X ASCII none none no X X Notes: 1 CP/M style file name X 2 MSDOS style file name and file size X 3 Not needed! X X6.1 Send files. X X To send a file to the remote, you'd first instruct the remote system X to receive the file, then type ^A-"up arrow". The following screen X would appear: X X +----- Upload -----+ X | | X | 1) xmodem | X | 2) xmodem-1k | X | 3) modem7 | X | 4) ymodem | X | 5) ymodem-g | X | 6) ASCII | X | | X | | X | | X | ESC to Abort | X | | X | Protocol: _ | X +------------------+ X X You'd then select the type of protocol at the prompt, and another X window similar to this would appear: X X +-- Send xmodem ------------------------------------------------+ X | | X | | X | Enter filename: _ | X | | X | | X +---------------------------------------------------------------+ X X Now you'd type in the file name or names you'd like to send. X Wildcards known to the shell are acceptable. X X Now the file transfer actually begins. A status screen similar to X the following is displayed during the transfer: X X +-------------- Uploading --------------+ X | | X | Protocol: xmodem | X | File name: main.c | X | File size: 4420 | X | Error check method: CRC | X | Est transfer time: 0:00:50 | X | Block count: 5 | X | Percent complete: 11.2% | X | Bytes transferred: 640 | X | Errors this block: 0 | X | Total error count: 0 | X | Last message: NONE | X | | X +---------- Press ESC to abort ---------+ X X As the transfer progresses, the "block count", "percent complete", X and "bytes transferred" fields will be continuously updated. If X errors occur the "errors this block" and "total error count" fields X will be updated and the "last message" field will contain a message X about the error. X X At the end of the transfer, pcomm will beep and return to the terminal X mode. If an error occurred and the transfer was aborted, you will be X prompted to acknowledge the error by pressing a key before returning X to the terminal mode. X X6.2 Receive files X X To receive a file (or group of files) from a remote system, you'd X instruct the remote system first, then type ^A-"down arrow". X Receiving a file is basically the same as sending a file. X X NOTE: Some systems do not pad the end of the file with control-Z's X and therefore files might grow in length when received. X X NOTE: Due to a technical limitation of pcomm, characters received X during an ASCII download will not reappear on the screen when you X return to the terminal mode. X X6.3 Directory X X To obtain a listing of a directory on the local system while still X running pcomm, you'd type ^A-F. The following screen would appear: X X +-- List Directory ---------------------------------------------+ X | | X | Current directory: /usr/egray | X | File spec (wildcards allowed): _ | X | | X +---------------------------------------------------------------+ X X Abbrievations know to the shell are valid. X X NOTE: Since we're really doing a popen() to the "ls" command, X additional command line options are also valid. X X6.4 Screen dump X X To dump the contents of the current screen (minus any windows showing) X you'd type ^A-G. The contents of the screen are written to the file X specified in the general setup for this purpose. If the file already X exists, the screen contents are appended to the file. The message X "screen dump" will briefly appear in the status line. X X6.5 Start Data log X X To start the data logging, or change the file used for data logging, X you'd type ^A-1. The following screen would appear: X X +-- Start Data Logging -----------------------------------------+ X | | X | Default log file: pcomm.log | X | New log file: _ | X | | X +---------------------------------------------------------------+ X X To keep the default file, just press a carriage return at the prompt, X otherwise, enter a new file name. X X The status of the logging is shown in the status line. X X6.6 Toggle Logging X X To temporarily suspend data logging or to start it again without X being prompted for the file name, you'd type ^A-2. X X The status lines shows the current settings. X X7. DIALING WINDOW X X While pcomm is dialing another system, a screen similar to the X following is shown: X X +--------------------------------------------------------------------+ X | D I A L I N G W I N D O W | X +--------------------------------------------------------------------+ X | | X | System name: C Board | X | Pass number: 1 | X | Elapse time this try: 4 | X | Time at start of dial: 14:53:36 | X | Time at start of this try: 14:53:37 | X | Connect delay time: 35 | X | Pause between tries: 5 | X | Index/tty: | X | Result of last try: | X | | X | SPACE: Recycle DEL: Remove from queue E: Change delay times | X | | X +------------------------ Press ESC to abort ------------------------+ X X The options available during the dialing are: X X SPACE) Press the space bar to stop the dialing of the current X entry and go on to the next entry in the queue. If there is X only one entry in the queue, then that number is immediately X redialed. X X DEL) Press the DEL key to remove the current number from the X queue. X X E) Press the letter "E" to change the connect delay time, or X the pause between retries. You will be prompted to save the X changes to disk. echo shar: "36 control characters may be missing from 'Doc'" SHAR_EOF if test 32879 -ne "`wc -c < 'Doc'`" then echo shar: "error transmitting 'Doc'" '(should have been 32879 characters)' fi fi echo shar: "extracting 'Pcomm.1'" '(6287 characters)' if test -f 'Pcomm.1' then echo shar: "will not over-write existing file 'Pcomm.1'" else sed 's/^X//' << \SHAR_EOF > 'Pcomm.1' X.TH PCOMM 1 local X.SH NAME Xpcomm \- a telecommunication program X.SH SYNOPSIS X.B pcomm X[ X.B -d directory X] X[ X.B -f index X] X.SH DESCRIPTION X.I Pcomm Xis a telecommunication program designed to operate similar to the Xpopular MSDOS program, ProComm. ProComm (TM) is copyrighted by Datastorm XTechnologies, Inc. X.PP XThe '-d' command line option allows the user to specify an additional Xpath to be used when searching for the pcomm support files. X.PP XThe '-f' command line option is used to specify automatic dialing of an Xentry in the dialing directory. The 'index' field in the dialing directory Xis checked against the string given in the command line option. If a Xmatch is found, that entry is automatically dialed. 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 Xo+ help screen command Xo+ tty name in use Xo+ current line settings Xo+ the duplex mode Xo+ status of data logging Xo+ status of printer Xo+ incoming CR translation Xo+ outgoing CR translation X.fi X.RE X.SH COMMANDS XThe following commands are accessible by pressing a user definable 'hot Xkey' and the command letter. The default 'hot key' is control-A. X.TP X.B ^A-0 XDisplays a summary of the available commands. X.TP X.B ^A-D XDisplays the dialing directory. From this screen, the directory Xcan be scrolled up or down 10 lines by pressing the up or down Xarrow keys respectively. To select an entry to dial, just enter Xthe entry number at the prompt. The following sub-commands are Xalso available: X.RS 5 X.TP X.B R XRevise or add an entry. Prompts for entry number or long distance code Xto revise. X.TP X.B D XDelete a dialing directory entry or a range of entries. X.TP X.B P XDisplay the current long distance dialing codes. X.TP X.B L XSend the dialing directory to the line printer. X.TP X.B M XManual dial. Prompts for a phone number. 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.TP X.B ^A-M XAllows the user to maintain a list of keyboard macros assigned to Xspecific keys. When pressed, the string assigned to that key is sent Xto the remote system. X.TP X.B ^A-P XAdjust the current communication line settings. Displays a menu of Xbaud rate, parity, data bit, and stop bit choices. Allows the new choice Xto be saved and become the default. The current line settings are Xshown on the status line. X.TP X.B ^A-X XExit X.I pcomm. X.TP X.B ^A-4 XSpawn a Unix shell while still communicating with the remote system. XUses the 'native' shell as described in the SHELL environmental Xvariable. X.TP X.B ^A-I XDisplays the program information screen. X.TP X.B ^A-S XDisplays a choice of setup screens. The following sub-menus are Xavailable: X.RS 5 X.TP X.B 1 XTTY Setup. Allows for the assignment of modem names to the ttys Xused for dialing. X.TP X.B 2 XModem Setup. Prompts for the dialing instructions for the modem Xnames specified in the TTY setup. X.TP X.B 3 XTerminal Setup. This screen contains the 'hot key' definition and Xcarriage return / line feed translations. X.TP X.B 4 XGeneral Setup. Prompts for default log file name and the set of Xcommand character translations. X.TP X.B 5 XASCII Setup. Additional character translations allowed during ASCII Xfile transfers. X.TP X.B S XSave the changes to disk. X.RE X.TP X.B ^A-B XChanges the current working directory. X.TP X.B ^A-C XClears the local screen. X.TP X.B ^A-E XToggles between full duplex and half duplex mode. The status line Xshows the current duplex mode. X.TP X.B ^A-H XHang up the phone. Disconnects the phone, but remains in X.I pcomm. X.TP X.B ^A-L XToggles 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 line termination characters between the carriage return and Xthe carriage return line feed pair. This affects the terminal session Xonly, not the file transfers. The current settings are shown in the Xstatus 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 XDisplays a menu of file transfer protocols to be used to send files Xto a remote system. X.TP X.B ^A-dn XDisplays file transfer protocols to be used to receive files from a Xremote system. X.TP X.B ^A-F XDisplays the contents of a Unix directory. X.TP X.B ^A-G XDump the contents of the screen to a specified file. Escape Xsequences and special characters will not be represented accurately Xin the file. X.TP X.B ^A-1 XBegin data logging. Prompts the user for the name of the file that Xwill be used to collect a complete record of the terminal session. X.TP X.B ^A-2 XToggles the data logging option without prompting for a new file Xname. The status line shows the current data logging mode. X.SH CONFIGURATION X.I Pcomm Xmust have access to the terminfo or termcap data for the terminal Xbeing used. The minimum capabilities include a screen size of at Xleast 80 columns by 24 lines and cursor movement capabilities. XRunning X.I pcomm Xfrom terminals at relatively slow speeds (i.e.: 1200 baud) will cause Xthe windows 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 Xletter 'U' for 'up arrow' and 'N' for 'down arrow'. X.PP XThere are three pcomm support files that contain information such as Xthe default parameters, the modem/tty database, and dialing directory Xentries. The following directories are searched to find these files: X.PP X.RS 5 X.nf Xo+ directory given with the '-d' option Xo+ directory in the PCOMM environmental variable Xo+ current directory Xo+ default library directory X.fi X.RE X.PP XThe 'index' field in the dialing directory serves two purposes. XThe first use is to act as a short cut into the dialing directory with Xthe '-f' command line option. The second use is to specify a tty name Xfor a given entry. If the 'index' is a valid device name, that Xdevice is used instead of searching the tty database for a free port. X.SH FILES X.nf Xpcomm.dial_dir the dialing directory Xpcomm.modem the modem/tty database Xpcomm.param the start-up default parameters X.fi X.SH SEE ALSO Xxmodem(1), mdm(1) echo shar: "12 control characters may be missing from 'Pcomm.1'" SHAR_EOF if test 6287 -ne "`wc -c < 'Pcomm.1'`" then echo shar: "error transmitting 'Pcomm.1'" '(should have been 6287 characters)' fi fi echo shar: "extracting 'Pcomm.dial_dir'" '(319 characters)' if test -f 'Pcomm.dial_dir' then echo shar: "will not over-write existing file 'Pcomm.dial_dir'" else sed 's/^X//' << \SHAR_EOF > 'Pcomm.dial_dir' XDIR_1=Abbey Road;1 (512) 590-6036;2400-N-8-1;F; XDIR_2=Tel-Med-Com;526-8686;1200-E-7-1;F; XDIR_3=C Board;1 (619) 722-8724;2400-N-8-1;F; XDIR_4=Crest;1 (213) 471-2518;2400-N-8-1;F;crest XDIR_5=Last Chance;1 (219) 762-8411;2400-E-7-1;F; XDIR_6=Killer;1 (214) 827-1994;1200-E-7-1;F; XDIR_7=System A (direct);;9600-E-7-1;F;tty12 SHAR_EOF if test 319 -ne "`wc -c < 'Pcomm.dial_dir'`" then echo shar: "error transmitting 'Pcomm.dial_dir'" '(should have been 319 characters)' fi fi echo shar: "extracting 'Pcomm.modem'" '(248 characters)' if test -f 'Pcomm.modem' then echo shar: "will not over-write existing file 'Pcomm.modem'" else sed 's/^X//' << \SHAR_EOF > 'Pcomm.modem' XTTY_1=tty10;HAYES;1200 XTTY_2=tty11;HAYES;2400 XTTY_3=tty12;DIRECT;9600 XMODEM_1a=HAYES;ATS7=45S11=70!;ATDT;!;~~+++~~ATH0! XMODEM_1b=CONNECT!;CONNECT 1200;CONNECT 2400;;; XMODEM_1c=BUSY;VOICE;NO CARRIER; XMODEM_2a=DIRECT;;;; XMODEM_2b=;;;;; XMODEM_2c=;;;; SHAR_EOF if test 248 -ne "`wc -c < 'Pcomm.modem'`" then echo shar: "error transmitting 'Pcomm.modem'" '(should have been 248 characters)' fi fi echo shar: "extracting 'Pcomm.param'" '(362 characters)' if test -f 'Pcomm.param' then echo shar: "will not over-write existing file 'Pcomm.param'" else sed 's/^X//' << \SHAR_EOF > 'Pcomm.param' XD_BAUD=1200 XD_PARITY=E XD_DBITS=7 XD_SBITS=1 XHOT=1 XASCII_HOT=^A XD_DUPLEX=FULL XFLOW=XON/XOFF XCR_IN=CR XCR_OUT=CR XLOGFILE=pcomm.log XDUMPFILE=pcomm.dump XSTRIP=YES XPAUSE_CHAR=~ XCR_CHAR=! XCTRL_CHAR=^ XESC_CHAR=| XABORT=KEEP XCDELAY=35 XPAUSE=5 XLECHO=NO XEXPAND=NO XCR_DELAY=0 XPACE=NO XCR_UP=NONE XLF_UP=NONE XTIMER=5 XCR_DN=STRIP XLF_DN=NONE XLD_PLUS= XLD_MINUS= XLD_AT=8, XLD_POUND=9 SHAR_EOF if test 362 -ne "`wc -c < 'Pcomm.param'`" then echo shar: "error transmitting 'Pcomm.param'" '(should have been 362 characters)' fi fi exit 0 # End of shell archive
egray@fthood.UUCP (03/13/88)
This is part 2 (of 6) to the Pcomm version 1.0 distribution. Emmet P. Gray US Army, HQ III Corps & Fort Hood ...!ihnp4!uiucuxc!fthood!egray Attn: AFZF-DE-ENV Directorate of Engineering & Housing Environmental Management Office Fort Hood, TX 76544-5057 ------------------------------------------------------------------------------- #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # Makefile # Unixpc.shar # dial_dir.h # misc.h # modem.h # param.h # status.h # xmodem.h # admin.c # chg_dir.c # curses.c # d_delete.c # d_lib.c # d_manual.c # d_menu.c # This archive created: Fri Mar 11 07:35:04 1988 export PATH; PATH=/bin:/usr/bin:$PATH echo shar: "extracting 'Makefile'" '(3099 characters)' if test -f 'Makefile' then echo shar: "will not over-write existing file 'Makefile'" else sed 's/^X//' << \SHAR_EOF > 'Makefile' X# PCOMM X# for a generic Unix box X# X# valid compile time definitions (CFLAGS) are: X# X# OLDCURSES use termcap (in lieu of terminfo) for curses X# UNIXPC use AT&T Unix PC 7300/3b1 specific routines X# SGID retore the real group id before doing anything dangerous X# X# for systems without getcwd(3) or getopt(3) X# X#GETCWD = getcwd.o X#GETOPT = getopt.o X XCC = cc -O XCFLAGS = X#CURSES = -lcurses -ltermlib XCURSES = -lcurses XLDFLAGS = XSHAR = shar -a X XOBJECTS = $(GETCWD) $(GETOPT) admin.o chg_dir.o curses.o d_delete.o d_lib.o \ X d_manual.o d_menu.o d_print.o d_prompt.o d_revise.o data_log.o \ X di_delay.o di_win.o dial.o expand.o help.o info.o init.o input.o \ X line_set.o list_dir.o ls_menu.o m_lib.o main.o n_shell.o p_lib.o \ X pexit.o port.o redial.o s_axfer.o s_gen.o s_menu.o s_modem.o \ X s_prompt.o s_term.o s_tty.o screen.o st_line.o strings.o terminal.o \ X x_ascii.o x_batch.o x_menu.o x_rcv.o x_send.o x_win.o xmodem.o X Xpcomm: $(OBJECTS) X $(CC) $(LDFLAGS) $(OBJECTS) -o pcomm $(CURSES) X Xlint: X lint $(CFLAGS) *.c X Xshar: X $(SHAR) Readme Release.notes Doc Pcomm.1 Pcomm.dial_dir Pcomm.modem \ X Pcomm.param > pcomm_sh.1 X $(SHAR) Makefile dial_dir.h misc.h modem.h param.h status.h xmodem.h \ X admin.c chg_dir.c curses.c d_delete.c d_lib.c d_manual.c d_menu.c \ X d_print.c > pcomm_sh.2 X $(SHAR) d_prompt.c d_revise.c data_log.c di_delay.c di_win.c dial.c \ X expand.c getcwd.c getopt.c help.c info.c init.c input.c > pcomm_sh.3 X $(SHAR) line_set.c list_dir.c ls_menu.c m_lib.c main.c n_shell.c \ X p_lib.c pexit.c port.c redial.c s_axfer.c s_gen.c > pcomm_sh.4 X $(SHAR) s_menu.c s_modem.c s_prompt.c s_term.c s_tty.c screen.c \ X st_line.c strings.c terminal.c x_ascii.c x_batch.c > pcomm_sh.5 X $(SHAR) x_menu.c x_rcv.c x_send.c x_win.c xmodem.c > pcomm_sh.6 X Xadmin.o: dial_dir.h param.h Xchg_dir.o: misc.h Xcurses.o: misc.h Xd_delete.o: dial_dir.h misc.h param.h Xd_lib.o: dial_dir.h param.h status.h Xd_manual.o: dial_dir.h Xd_menu.o: dial_dir.h misc.h param.h Xd_print.o: dial_dir.h misc.h Xd_prompt.o: dial_dir.h misc.h Xd_revise.o: dial_dir.h misc.h param.h Xdata_log.o: misc.h param.h status.h Xdi_delay.o: misc.h param.h Xdi_win.o: dial_dir.h misc.h modem.h param.h status.h Xdial.o: dial_dir.h modem.h param.h status.h Xhelp.o: misc.h Xinit.o: misc.h status.h Xline_set.o: dial_dir.h param.h status.h Xlist_dir.o: misc.h Xls_menu.o: dial_dir.h misc.h param.h Xm_lib.o: modem.h status.h Xmain.o: dial_dir.h modem.h param.h status.h Xp_lib.o: param.h status.h Xpexit.o: dial_dir.h misc.h param.h status.h Xport.o: dial_dir.h modem.h status.h Xredial.o: dial_dir.h misc.h Xs_axfer.o: misc.h param.h Xs_gen.o: misc.h param.h Xs_menu.o: misc.h Xs_modem.o: misc.h modem.h Xs_prompt.o: misc.h Xs_term.o: misc.h param.h Xs_tty.o: misc.h modem.h status.h Xscreen.o: param.h status.h Xst_line.o: dial_dir.h misc.h modem.h param.h status.h Xterminal.o: dial_dir.h modem.h param.h status.h Xx_ascii.o: param.h status.h Xx_batch.o: misc.h xmodem.h Xx_menu.o: misc.h xmodem.h Xx_rcv.o: dial_dir.h misc.h xmodem.h Xx_send.o: dial_dir.h misc.h status.h xmodem.h Xx_win.o: dial_dir.h misc.h status.h xmodem.h Xxmodem.o: param.h status.h xmodem.h SHAR_EOF if test 3099 -ne "`wc -c < 'Makefile'`" then echo shar: "error transmitting 'Makefile'" '(should have been 3099 characters)' fi fi echo shar: "extracting 'Unixpc.shar'" '(5713 characters)' if test -f 'Unixpc.shar' then echo shar: "will not over-write existing file 'Unixpc.shar'" else sed 's/^X//' << \SHAR_EOF > 'Unixpc.shar' X#! /bin/sh X# This is a shell archive, meaning: X# 1. Remove everything above the #! /bin/sh line. X# 2. Save the resulting text in a file. X# 3. Execute the file with /bin/sh (not csh) to create: X# Ifile.sh X# Makefile X# Pcomm.modem X# This archive created: Fri Mar 11 07:34:54 1988 Xexport PATH; PATH=/bin:/usr/bin:$PATH Xecho shar: "extracting 'Ifile.sh'" '(705 characters)' Xif test -f 'Ifile.sh' Xthen X echo shar: "will not over-write existing file 'Ifile.sh'" Xelse Xsed 's/^X//' << \SHAR_EOF > 'Ifile.sh' XXex - $1 << EOF XX1,\$s/^PC/xPC/ XX1,\$s/^BC/xBC/ XX1,\$s/^UP/xUP/ XX1,\$s/^ospeed/xospeed/ XX1,\$s/^LINES/xLINES/ XX1,\$s/^COLS/xCOLS/ XX1,\$s/^tgetflag/xtgetflag/ XX1,\$s/^tgetent/xtgetent/ XX1,\$s/^tgetstr/xtgetstr/ XX1,\$s/^tgetnum/xtgetnum/ XX1,\$s/^tgoto/xtgoto/ XX1,\$s/^tputs/xtputs/ XX1,\$s/^wrefresh/xwrefresh/ XX1,\$s/^initscr/xinitscr/ XX1,\$s/^cbreak/xcbreak/ XX1,\$s/^nl/xnl/ XX1,\$s/^flushinp/xflushinp/ XX1,\$s/^noecho/xnoecho/ XX1,\$s/^savetty/xsavetty/ XX1,\$s/^resetty/xresetty/ XX1,\$s/^echo/xecho/ XX1,\$s/^nocbreak/xnocbreak/ XX1,\$s/^nonl/xnonl/ XX1,\$s/^keypad/xkeypad/ XX1,\$s/^endwin/xendwin/ XX1,\$s/^printw/xprintw/ XX1,\$s/^fixterm/xfixterm/ XX1,\$s/^resetterm/xresetterm/ XX1,\$s/^setterm/xsetterm/ XX1,\$s/^baudrate/xbaudrate/ XXw XXq XXEOF XSHAR_EOF Xif test 705 -ne "`wc -c < 'Ifile.sh'`" Xthen X echo shar: "error transmitting 'Ifile.sh'" '(should have been 705 characters)' Xfi Xfi Xecho shar: "extracting 'Makefile'" '(3372 characters)' Xif test -f 'Makefile' Xthen X echo shar: "will not over-write existing file 'Makefile'" Xelse Xsed 's/^X//' << \SHAR_EOF > 'Makefile' XX# Pcomm XX# for AT&T Unix PC 7300/3b1 XX# XX# valid compile time definitions (CFLAGS) are: XX# XX# OLDCURSES use termcap (in lieu of terminfo) for curses XX# UNIXPC use AT&T Unix PC 7300/3b1 specific routines XX# SGID retore the real group id before doing anything dangerous XX# XX# for systems without getcwd(3) or getopt(3) XX# XX#GETCWD = getcwd.o XX#GETOPT = getopt.o XX XXCC = cc -O XXCFLAGS = -DUNIXPC XXCURSES = -lcurses XXLD = ld -s XXSHAR = shar -a XXSTARTUP = /lib/crt0s.o XXSHAREDLIB = shlib_c.ifile XX XXOBJECTS = $(GETCWD) $(GETOPT) admin.o chg_dir.o curses.o d_delete.o d_lib.o \ XX d_manual.o d_menu.o d_print.o d_prompt.o d_revise.o data_log.o \ XX di_delay.o di_win.o dial.o expand.o help.o info.o init.o input.o \ XX line_set.o list_dir.o ls_menu.o m_lib.o main.o n_shell.o p_lib.o \ XX pexit.o port.o redial.o s_axfer.o s_gen.o s_menu.o s_modem.o \ XX s_prompt.o s_term.o s_tty.o screen.o st_line.o strings.o terminal.o \ XX x_ascii.o x_batch.o x_menu.o x_rcv.o x_send.o x_win.o xmodem.o XX XXOTHERS = setvbuf.o doprnt.o XX XXpcomm: $(OBJECTS) $(OTHERS) $(SHAREDLIB) XX $(LD) $(OBJECTS) $(OTHERS) $(CURSES) $(STARTUP) $(SHAREDLIB) -o pcomm XX XXlint: XX lint $(CFLAGS) *.c XX XXshar: XX $(SHAR) Readme Release.notes Doc Pcomm.1 Pcomm.dial_dir Pcomm.modem \ XX Pcomm.param Ifile.sh > pcomm_sh.1 XX $(SHAR) Makefile dial_dir.h misc.h modem.h param.h status.h xmodem.h \ XX admin.c chg_dir.c curses.c d_delete.c d_lib.c d_manual.c d_menu.c \ XX d_print.c > pcomm_sh.2 XX $(SHAR) d_prompt.c d_revise.c data_log.c di_delay.c di_win.c dial.c \ XX expand.c getcwd.c getopt.c help.c info.c init.c input.c > pcomm_sh.3 XX $(SHAR) line_set.c list_dir.c ls_menu.c m_lib.c main.c n_shell.c \ XX p_lib.c pexit.c port.c redial.c s_axfer.c s_gen.c > pcomm_sh.4 XX $(SHAR) s_menu.c s_modem.c s_prompt.c s_term.c s_tty.c screen.c \ XX st_line.c strings.c terminal.c x_ascii.c x_batch.c > pcomm_sh.5 XX $(SHAR) x_menu.c x_rcv.c x_send.c x_win.c xmodem.c > pcomm_sh.6 XX XXsetvbuf.o: XX ar x /lib/libc.a setvbuf.o XX XXdoprnt.o: XX ar x /lib/libc.a doprnt.o XX XXshlib_c.ifile: XX cp /lib/shlib.ifile shlib_c.ifile XX sh Ifile.sh shlib_c.ifile XX XXadmin.o: dial_dir.h param.h XXchg_dir.o: misc.h XXcurses.o: misc.h XXd_delete.o: dial_dir.h misc.h param.h XXd_lib.o: dial_dir.h param.h status.h XXd_manual.o: dial_dir.h XXd_menu.o: dial_dir.h misc.h param.h XXd_print.o: dial_dir.h misc.h XXd_prompt.o: dial_dir.h misc.h XXd_revise.o: dial_dir.h misc.h param.h XXdata_log.o: misc.h param.h status.h XXdi_delay.o: misc.h param.h XXdi_win.o: dial_dir.h misc.h modem.h param.h status.h XXdial.o: dial_dir.h modem.h param.h status.h XXhelp.o: misc.h XXinit.o: misc.h status.h XXline_set.o: dial_dir.h param.h status.h XXlist_dir.o: misc.h XXls_menu.o: dial_dir.h misc.h param.h XXm_lib.o: modem.h status.h XXmain.o: dial_dir.h modem.h param.h status.h XXp_lib.o: param.h status.h XXpexit.o: dial_dir.h misc.h param.h status.h XXport.o: dial_dir.h modem.h status.h XXredial.o: dial_dir.h misc.h XXs_axfer.o: misc.h param.h XXs_gen.o: misc.h param.h XXs_menu.o: misc.h XXs_modem.o: misc.h modem.h XXs_prompt.o: misc.h XXs_term.o: misc.h param.h XXs_tty.o: misc.h modem.h status.h XXscreen.o: param.h status.h XXst_line.o: dial_dir.h misc.h modem.h param.h status.h XXterminal.o: dial_dir.h modem.h param.h status.h XXx_ascii.o: param.h status.h XXx_batch.o: misc.h xmodem.h XXx_menu.o: misc.h xmodem.h XXx_rcv.o: dial_dir.h misc.h xmodem.h XXx_send.o: dial_dir.h misc.h status.h xmodem.h XXx_win.o: dial_dir.h misc.h status.h xmodem.h XXxmodem.o: param.h status.h xmodem.h XSHAR_EOF Xif test 3372 -ne "`wc -c < 'Makefile'`" Xthen X echo shar: "error transmitting 'Makefile'" '(should have been 3372 characters)' Xfi Xfi Xecho shar: "extracting 'Pcomm.modem'" '(154 characters)' Xif test -f 'Pcomm.modem' Xthen X echo shar: "will not over-write existing file 'Pcomm.modem'" Xelse Xsed 's/^X//' << \SHAR_EOF > 'Pcomm.modem' XXTTY_1=ph1;OBM;1200 XXTTY_2=tty000;DIRECT;19200 XXMODEM_1a=OBM;;%;@; XXMODEM_1b=CONNECT;CONNECT;;;; XXMODEM_1c=;;; XXMODEM_2a=DIRECT;;;; XXMODEM_2b=;;;;; XXMODEM_2c=;;; XSHAR_EOF Xif test 154 -ne "`wc -c < 'Pcomm.modem'`" Xthen X echo shar: "error transmitting 'Pcomm.modem'" '(should have been 154 characters)' Xfi Xfi Xexit 0 X# End of shell archive SHAR_EOF if test 5713 -ne "`wc -c < 'Unixpc.shar'`" then echo shar: "error transmitting 'Unixpc.shar'" '(should have been 5713 characters)' fi fi echo shar: "extracting 'dial_dir.h'" '(815 characters)' if test -f 'dial_dir.h' then echo shar: "will not over-write existing file 'dial_dir.h'" else sed 's/^X//' << \SHAR_EOF > 'dial_dir.h' X/* X * The dialing directory structure. The first eight elements are X * contained in the pcomm.dial_dir file. X */ X X#define NUM_DIR 100 X#define NUM_QUEUE 10 X Xstruct DIAL_DIR { X char *name[NUM_DIR+1]; /* name of system being called */ X char *number[NUM_DIR+1]; /* phone number */ X int baud[NUM_DIR+1]; /* baud rate */ X char parity[NUM_DIR+1]; /* parity */ X int dbits[NUM_DIR+1]; /* data bits */ X int sbits[NUM_DIR+1]; /* stop bits */ X char duplex[NUM_DIR+1]; /* duplex (F = full, H = half) */ X char *index[NUM_DIR+1]; /* command line index (or tty) */ X X int d_entries; /* number of entries in the file */ X int d_cur; /* the current entry */ X int q_num[NUM_QUEUE]; /* entry numbers in the queue */ X char q_ld[NUM_QUEUE]; /* LD codes in the queue */ X}; X X#ifndef MAIN Xextern struct DIAL_DIR *dir; X#endif /* MAIN */ SHAR_EOF if test 815 -ne "`wc -c < 'dial_dir.h'`" then echo shar: "error transmitting 'dial_dir.h'" '(should have been 815 characters)' fi fi echo shar: "extracting 'misc.h'" '(1031 characters)' if test -f 'misc.h' then echo shar: "will not over-write existing file 'misc.h'" else sed 's/^X//' << \SHAR_EOF > 'misc.h' X/* X * Definitions to support the home-grown curses functions and to make the X * old curses routines happy X */ X X#define NOPROMOTE X X#define mvwattrstr(w,y,x,a,s) (wmove(w,y,x)==ERR?ERR:wattrstr(w,a,s)) X#define mvwattrch(w,y,x,a,c) (wmove(w,y,x)==ERR?ERR:wattrch(w,a,c)) X#define mvwattrnum(w,y,x,a,n) (wmove(w,y,x)==ERR?ERR:wattrnum(w,a,n)) X#define mvattrstr(y,x,a,s) (wmove(stdscr,y,x)==ERR?ERR:wattrstr(stdscr,a,s)) X#define mvattrch(y,x,a,c) (wmove(stdscr,y,x)==ERR?ERR:wattrch(stdscr,a,c)) X#define mvattrnum(y,x,a,n) (wmove(stdscr,y,x)==ERR?ERR:wattrnum(stdscr,a,n)) X#define attrstr(a,s) wattrstr(stdscr,a,s) X#define attrch(a,c) wattrch(stdscr,a,c) X#define attrnum(a,n) wattrnum(stdscr,a,n) X X#ifdef OLDCURSES X#ifdef NOPROMOTE X#define A_BOLD 0 X#define A_BLINK 0 X#define A_REVERSE 1 X#define A_DIM 0 X#define A_STANDOUT 1 X#define A_UNDERLINE 0 X#else /* NOPROMOTE */ X#define A_BOLD 1 X#define A_BLINK 1 X#define A_REVERSE 1 X#define A_DIM 1 X#define A_STANDOUT 1 X#define A_UNDERLINE 1 X#endif /* NOPROMOTE */ X#endif /* OLDCURSES */ SHAR_EOF if test 1031 -ne "`wc -c < 'misc.h'`" then echo shar: "error transmitting 'misc.h'" '(should have been 1031 characters)' fi fi echo shar: "extracting 'modem.h'" '(1417 characters)' if test -f 'modem.h' then echo shar: "will not over-write existing file 'modem.h'" else sed 's/^X//' << \SHAR_EOF > 'modem.h' X/* X * The modem and tty databases. The first 3 elements make up the tty X * database, the next 15 make up the modem database. A "tname" in common X * with a "mname" link the two together. X */ X X#define NUM_TTY 10 X#define NUM_MODEM 10 X Xstruct MODEM { X char *tty[NUM_TTY]; /* tty names */ X char *tname[NUM_TTY]; /* modem name */ X int mbaud[NUM_TTY]; /* maximum baud rate */ X X char *mname[NUM_MODEM]; /* modem name (matches tname above) */ X char *init[NUM_MODEM]; /* initialization */ X char *dial[NUM_MODEM]; /* dial command */ X char *suffix[NUM_MODEM]; /* dialing command suffix */ X char *hangup[NUM_MODEM]; /* hang up the modem */ X char *con_3[NUM_MODEM]; /* 300 baud connect message */ X char *con_12[NUM_MODEM]; /* 1200 baud connect message */ X char *con_24[NUM_MODEM]; /* 2400 baud connect message */ X char *con_48[NUM_MODEM]; /* 4800 baud connect message */ X char *con_96[NUM_MODEM]; /* 9600 baud connect message */ X char *con_192[NUM_MODEM]; /* 19200 baud connect message */ X char *no_con1[NUM_MODEM]; /* no connect #1 */ X char *no_con2[NUM_MODEM]; /* no connect #2 */ X char *no_con3[NUM_MODEM]; /* no connect #3 */ X char *no_con4[NUM_MODEM]; /* no connect #4 */ X X int t_entries; /* number of tty entries */ X int m_entries; /* number of modem entries */ X int t_cur; /* current tty entry number */ X int m_cur; /* current modem entry number */ X}; X X#ifndef MAIN Xextern struct MODEM *modem; X#endif /* MAIN */ SHAR_EOF if test 1417 -ne "`wc -c < 'modem.h'`" then echo shar: "error transmitting 'modem.h'" '(should have been 1417 characters)' fi fi echo shar: "extracting 'param.h'" '(2262 characters)' if test -f 'param.h' then echo shar: "will not over-write existing file 'param.h'" else sed 's/^X//' << \SHAR_EOF > 'param.h' X/* X * The standard pcomm parameters. Everything can be altered by using one X * of pcomm's menus. Although editing by hand is not encouraged, the X * pcomm.param file is just an ASCII file. X */ X X#define MAX_CDELAY 120 X#define MIN_CDELAY 10 X#define MAX_PAUSE 120 X#define MIN_PAUSE 1 X#define MAX_TIMER 20 X#define MIN_TIMER 2 X X#define NUM_PARAM 33 X#define LINE_SET 0 X#define TERM_SETUP 4 X#define GEN_SETUP 10 X#define DELAY_TIMES 18 X#define ASCII_SETUP 20 X#define LD_CODES 29 X Xstruct PARAM { X /* 0-3 used in line_set_menu() */ X int d_baud; /* default baud rate */ X char d_parity; /* default parity */ X int d_dbits; /* default data bits */ X int d_sbits; /* default stop bits */ X X /* 4-9 used in term_setup() */ X int hot; /* the decimal code for the hot key */ X char *ascii_hot; /* ascii representation of hot key */ X char *d_duplex; /* default duplex */ X char *flow; /* flow control */ X char *cr_in; /* send as carriage return */ X char *cr_out; /* receive carriage return as */ X X /* 10-17 used in gen_setup() */ X char *logfile; /* default log file */ X char *dumpfile; /* default screen dump file */ X char *strip; /* strip high bit (translate table) */ X char pause_char; /* pause char synonym */ X char cr_char; /* carriage return char synonym */ X char ctrl_char; /* ctrl char synonym */ X char esc_char; /* escape char synonym */ X char *abort; /* destination of aborted downloads */ X X /* 18-19 used in gen_setup() & delay_times() */ X int cdelay; /* connect delay time */ X int pause; /* pause between dialing attempts */ X X /* 20-27 used in ascii_xfer_setup() */ X char *lecho; /* echo locally ? */ X char *expand; /* expand blank lines? */ X int cr_delay; /* carriage return delay (ms) */ X char *pace; /* pace the output ? */ X char *cr_up; /* send carriage return as */ X char *lf_up; /* send line feed as */ X int timer; /* Transfer timeout */ X char *cr_dn; /* receive carriage return as */ X char *lf_dn; /* receive line feed as */ X X /* 28-31 used in d_revise() */ X char *ld_plus; /* + long distance code */ X char *ld_minus; /* - long distance code */ X char *ld_at; /* @ long distance code */ X char *ld_pound; /* # long distance code */ X}; X X#ifndef MAIN Xextern struct PARAM *param; X#endif /* MAIN */ SHAR_EOF if test 2262 -ne "`wc -c < 'param.h'`" then echo shar: "error transmitting 'param.h'" '(should have been 2262 characters)' fi fi echo shar: "extracting 'status.h'" '(631 characters)' if test -f 'status.h' then echo shar: "will not over-write existing file 'status.h'" else sed 's/^X//' << \SHAR_EOF > 'status.h' X/* X * The location of the support files, status flags, and other various X * changeable things. X */ X Xstruct STATUS { X char *p_path; /* pcomm.param file */ X char *d_path; /* pcomm.dial_dir file */ X char *m_path; /* pcomm.modem file */ X char *lock_path; /* UUCP lock file */ X char *vs_path; /* virtual screen file */ X char *log_path; /* data logging file */ X int fd; /* file descriptor for tty */ X int log; /* status of log option */ X int print; /* status of print option */ X int msg; /* the 'msg' status */ X int pid; /* the pid of the child process */ X}; X X#ifndef MAIN Xextern struct STATUS *status; X#endif /* MAIN */ SHAR_EOF if test 631 -ne "`wc -c < 'status.h'`" then echo shar: "error transmitting 'status.h'" '(should have been 631 characters)' fi fi echo shar: "extracting 'xmodem.h'" '(373 characters)' if test -f 'xmodem.h' then echo shar: "will not over-write existing file 'xmodem.h'" else sed 's/^X//' << \SHAR_EOF > 'xmodem.h' X/* X * Definitions for the xmodem stuff. X */ X X#define MAX_ERRORS 10 X X#define SOH 1 X#define STX 2 X#define EOT 4 X#define ACK 6 X#define NAK 21 X#define CAN 24 X#define CTRLZ 26 X X#define PROTOCOLS 6 X#define XMODEM 0 X#define XMODEM_1k 1 X#define MODEM7 2 X#define YMODEM 3 X#define YMODEM_G 4 X#define XASCII 5 X X#define ABORT (-1) X#define ERROR (-2) X#define CANCEL (-3) SHAR_EOF if test 373 -ne "`wc -c < 'xmodem.h'`" then echo shar: "error transmitting 'xmodem.h'" '(should have been 373 characters)' fi fi echo shar: "extracting 'admin.c'" '(2871 characters)' if test -f 'admin.c' then echo shar: "will not over-write existing file 'admin.c'" else sed 's/^X//' << \SHAR_EOF > 'admin.c' X/* X * Perform administrative functions. Check to see if the user has X * permission to make long distance calls, and record all phone calls X * made by pcomm. X */ X X#undef LOG_CALLS X#undef LIMIT_LD X X#define LOGFILE "/usr/adm/phone.calls" X#define GRPNAME "uucp" X X#include <stdio.h> X#include <grp.h> X#include "dial_dir.h" X#include "param.h" X X/* X * Make a log of all calls made by pcomm. The argument is the index X * into the queue. X */ X Xint Xlog_calls(i) Xint i; X{ X#ifdef LOG_CALLS X FILE *fp; X char *number, *build_num(), *date, *ctime(), *getlogin(); X long now, time(); X void error_win(); X /* build the complete phone number */ X number = build_num(i); X /* build date and time */ X time(&now); X date = ctime(&now); X date[10] = NULL; X date[16] = NULL; X X if (!(fp = fopen(LOGFILE, "a+"))) X error_win(1, "Can't open phone log file", "Contact your system administrator"); X X fprintf(fp, "pcomm: %s called %s at %s on %s\n", getlogin(), number, &date[11], date); X fclose(fp); X#endif /* LOG_CALLS */ X return (0); X} X X/* X * Check to see if long distance (toll) call is authorized. The argument X * is the index into the queue. X */ X Xint Xlimit_ld(i) Xint i; X{ X#ifdef LIMIT_LD X char *number, *build_num(), *name, *getlogin(); X struct group *getgrnam(), *grpbuf; X X /* if no group, don't bother */ X grpbuf = getgrnam(GRPNAME); X if (!grpbuf || !*grpbuf->gr_mem) X return(0); X /* are you in the group? */ X name = getlogin(); X for (; *grpbuf->gr_mem != NULL; grpbuf->gr_mem++) { X if (!strcmp(*grpbuf->gr_mem, name)) X return(0); X } X /* numbers only... */ X number = build_num(i); X X /* X * Very site specific!!! We use a '9' to get an outside line, X * so any 9 followed by a 1 is a toll call (except for 1-800 X * numbers). X */ X if (!strncmp(number, "91", 2) && strncmp(number, "91800", 5)) { X error_win(0, "You are not authorized to place long distance \(toll\) calls", NULL); X return(1); X } X X if (*number == NULL) { X error_win(0, "You are not authorized direct access to the line", "Use the automatic dialing feature"); X return(1); X } X#endif /* LIMIT_LD */ X return(0); X} X X#ifdef LOG_CALLS || LIMIT_LD X/* X * Put together the complete phone number but strip out the extraneous X * characters. X */ X Xchar * Xbuild_num(i) Xint i; X{ X int j; X char *t, temp[40], *strcpy(), *strcat(); X static char ans[40]; X X temp[0] = NULL; X /* add LD codes ? */ X switch (dir->q_ld[i]) { X case 0: X break; X case '+': X strcpy(temp, param->ld_plus); X break; X case '-': X strcpy(temp, param->ld_minus); X break; X case '@': X strcpy(temp, param->ld_at); X break; X case '#': X strcpy(temp, param->ld_pound); X break; X } X /* add the number */ X strcat(temp, dir->number[dir->q_num[i]]); X X /* copy only digits */ X j = 0; X t = temp; X while (*t) { X if (*t >= '0' && *t <= '9') X ans[j++] = *t; X t++; X } X ans[j] = NULL; X X return(ans); X} X#endif /* LOG_CALLS || LIMIT_LD */ SHAR_EOF if test 2871 -ne "`wc -c < 'admin.c'`" then echo shar: "error transmitting 'admin.c'" '(should have been 2871 characters)' fi fi echo shar: "extracting 'chg_dir.c'" '(1363 characters)' if test -f 'chg_dir.c' then echo shar: "will not over-write existing file 'chg_dir.c'" else sed 's/^X//' << \SHAR_EOF > 'chg_dir.c' X/* X * Open a window to prompt for a new directory. Checks to see if the X * directory exists, but doesn't move to there (yet). Returns the path X * to the new directory, or NULL if you chickened out. X */ X X#include <curses.h> X#include "misc.h" X Xchar * Xchange_dir(fd) Xint fd; X{ X WINDOW *ch_win, *newwin(); X int got_it; X char *ans, *dir, *expand(), *cwd, *getcwd(), cwdbuf[200]; X char *get_str(); X void free_ptr(); X X cwd = getcwd(cwdbuf, 200); X X ch_win = newwin(6, 70, 5, 5); X X mvwprintw(ch_win, 2, 4, "Current directory: %s", cwd); X mvwaddstr(ch_win, 3, 4, "New directory: "); X box(ch_win, '|', '-'); X X mvwattrstr(ch_win, 0, 3, A_BOLD, " Change directory "); X wmove(ch_win, 3, 19); X wrefresh(ch_win); X /* get the answer */ X got_it = 0; X while ((ans = get_str(ch_win, 60, NULL, " ")) != NULL) { X if (*ans == NULL) X break; X /* expand the input */ X dir = expand(ans); X /* if it exists */ X if (!access(dir, 1)) { X got_it++; X break; X } X beep(); X mvwattrstr(ch_win, 4, 15, A_BOLD, "No such directory or no access permission"); X wrefresh(ch_win); X wait_key(ch_win, 3); X /* cleanup the mess */ X clear_line(ch_win, 3, 19, 1); X clear_line(ch_win, 4, 14, 1); X wmove(ch_win, 3, 19); X wrefresh(ch_win); X free_ptr(dir); X } X if (fd == -1) { X werase(ch_win); X wrefresh(ch_win); X } X delwin(ch_win); X if (got_it) X return(dir); X return(NULL); X} SHAR_EOF if test 1363 -ne "`wc -c < 'chg_dir.c'`" then echo shar: "error transmitting 'chg_dir.c'" '(should have been 1363 characters)' fi fi echo shar: "extracting 'curses.c'" '(7649 characters)' if test -f 'curses.c' then echo shar: "will not over-write existing file 'curses.c'" else sed 's/^X//' << \SHAR_EOF > 'curses.c' X/* X * Miscellaneous curses routines. X */ X X#include <stdio.h> X#include <curses.h> X#include <signal.h> X#include <setjmp.h> X#ifdef OLDCURSES X#include <fcntl.h> X#else /* OLDCURSES */ X#include <term.h> X#endif /* OLDCURSES */ X#include "misc.h" 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) 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[80]; X 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 /* an ESC anywhere in the string */ X if (ans == 27) X return(NULL); X X /* illegal character ? */ X if (disallow != NULL && strchr(disallow, ans)) { X beep(); X continue; X } X if (allow != NULL && !strchr(allow, ans)) { X beep(); X continue; X } X /* exceeded the max ? */ X if (count == num) { X beep(); X continue; X } X X buf[count] = ans; X waddch(win, ans); X wrefresh(win); X count++; X } X buf[count] = NULL; 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[80]; X 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 /* an ESC anywhere in the string */ X if (ans == 27) 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) { X beep(); X continue; X } X X buf[count] = ans; X waddch(win, ans); X wrefresh(win); X count++; X } X buf[count] = NULL; 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 misc.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; Xint attr; Xchar *str; X{ X int do_it; X /* if nothing, do nothing */ X if (str == NULL || *str == NULL) 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#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; Xint attr; Xchar c; X{ X int do_it; X X if (c == NULL) X return(0); X#ifdef OLDCURSES X if (attr) X wstandout(win); X waddch(win, c); X if (attr) X wstandend(win); X#else /* OLDCURSES */ 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, 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; Xint attr, num; X{ X int do_it; X char buf[20]; 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#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, attr; Xchar *str; X{ X int save, ret_code; X char new_str[80], *strcpy(), *strcat(); 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 = 0; X save = wgetch(win); X if (save == 'y' || save == 'Y') { X waddstr(win, "Yes"); X ret_code = 1; X } X else X waddstr(win, "No"); 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, '|'); X wmove(win, y, x); X } X return(0); X} X X/* X * Wait for a key or time out. Returns a -1 on timeout. X */ X Xjmp_buf wk_jmp; X Xint Xwait_key(win, sec) XWINDOW *win; Xunsigned int sec; X{ X int c, force_wk(); X unsigned int alarm(); X X signal(SIGALRM, force_wk); X if (setjmp(wk_jmp)) X return(-1); X alarm(sec); X c = wgetch(win); X alarm(0); X return(c); X} Xint Xforce_wk(dummy) Xint dummy; X{ X void longjmp(); X X longjmp(wk_jmp, 1); 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(7, stderr); X return(0); X} X X/* X * Fix the stdin so that a read is satisfied immediately. When read() X * is called it returns the character in the queue, or an error if no X * key was pressed. The window argument is not used! X */ X Xint Xnodelay(win, flag) XWINDOW *win; Xint flag; X{ X if (flag) X fcntl(0, F_SETFL, fcntl(0, F_GETFL, 0) | O_NDELAY); X else X fcntl(0, F_SETFL, fcntl(0, F_GETFL, 0) & ~O_NDELAY); X return(0); X} X X/* X * Take the terminal out of the "curses mode" X */ X Xint Xresetterm() X{ X resetty(); X return(0); X} X X/* X * Put the terminal back into the "curses mode" X */ X Xint Xmyputchar(c) Xchar c; X{ X putchar(c); X} Xint Xfixterm() X{ X tputs(TI, 1, myputchar); X tputs(VS, 1, myputchar); X nonl(); X crmode(); X noecho(); X return(0); X} X#endif /* OLDCURSES */ SHAR_EOF if test 7649 -ne "`wc -c < 'curses.c'`" then echo shar: "error transmitting 'curses.c'" '(should have been 7649 characters)' fi fi echo shar: "extracting 'd_delete.c'" '(1987 characters)' if test -f 'd_delete.c' then echo shar: "will not over-write existing file 'd_delete.c'" else sed 's/^X//' << \SHAR_EOF > 'd_delete.c' X/* X * The delete option of the dialing directory. Prompts for saving X * changes to disk. A return code of 1 means that entries were deleted. 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 Xdelete() X{ X WINDOW *d_win, *newwin(); X int i, first, last; X void free_ptr(); X extern char *null_ptr; X X d_win = newwin(6, 32, 10, 15); X X mvwaddstr(d_win, 2, 2, "Delete entry: thru:"); X box(d_win, '|', '-'); X wmove(d_win, 2, 16); X wrefresh(d_win); X /* get the first of the range */ X while ((first = get_num(d_win, 3)) != -1) { X if (first > 0 && first <= NUM_DIR) X break; X mvwaddstr(d_win, 2, 16, " "); X wmove(d_win, 2, 16); X beep(); X wrefresh(d_win); X } X if (first == -1) { X delwin(d_win); X return(0); X } X /* get the last of the range */ X wmove(d_win, 2, 26); X wrefresh(d_win); X while ((last = get_num(d_win, 3)) != -1) { X if ((first <= last && last <= NUM_DIR) || last == 0) X break; X mvwaddstr(d_win, 2, 26, " "); X wmove(d_win, 2, 26); X beep(); X wrefresh(d_win); X } X if (last == -1) { X delwin(d_win); X return(0); X } X /* if "last" omitted, echo "first" */ X if (!last) { X last = first; X mvwprintw(d_win, 2, 26, "%d", first); X wrefresh(d_win); X } X /* save to disk? */ X if (yes_prompt(d_win, 3, 2, A_BOLD, "Are you sure")) { X /* delete from the physical file */ X if (del_dir(first, last)) { X touchwin(d_win); X wrefresh(d_win); X } X /* X * We don't really care if del_dir() fails because we still X * change the version in memory. X */ X for (i=first; i<=last; i++) { X free_ptr(dir->name[i]); X free_ptr(dir->number[i]); X free_ptr(dir->index[i]); X dir->name[i] = null_ptr; X dir->number[i] = null_ptr; X dir->baud[i] = param->d_baud; X dir->parity[i] = param->d_parity; X dir->dbits[i] = param->d_dbits; X dir->sbits[i] = param->d_sbits; X dir->duplex[i] = *param->d_duplex; X dir->index[i] = null_ptr; X } X delwin(d_win); X return(1); X } X delwin(d_win); X return(0); X} SHAR_EOF if test 1987 -ne "`wc -c < 'd_delete.c'`" then echo shar: "error transmitting 'd_delete.c'" '(should have been 1987 characters)' fi fi echo shar: "extracting 'd_lib.c'" '(6469 characters)' if test -f 'd_lib.c' then echo shar: "will not over-write existing file 'd_lib.c'" else sed 's/^X//' << \SHAR_EOF > 'd_lib.c' X/* X * Routines to manipulate the dialing directory file pcomm.dial_dir X */ X X#include <stdio.h> X#include "dial_dir.h" X#include "param.h" X#include "status.h" X X/* X * Read the dialing directory. Returns a pointer to a static area X * containing the DIAL_DIR structure. All of the entries are created X * reguardless of the number of physical entries in the file. Element X * number zero is reserved for the "manual" entry. All errors are fatal. X */ X Xstruct DIAL_DIR * Xread_dir() X{ X FILE *fp; X int i, j, oops; X char *strdup(), buf[80], *temp_token, *str, *str_tok(), token[20]; X char message[80], *sep; X static struct DIAL_DIR d; X void error_win(); X extern char *null_ptr; X X if (!(fp = fopen(status->d_path, "r"))) { X sprintf(buf, "'%s' for read", status->d_path); X error_win(1, "Can't open dialing directory file", buf); X } X X sep = ";;---;;\n"; X i = 0; X oops = 0; X while (fgets(buf, 80, fp) != NULL) { X i++; X if (i > NUM_DIR) X break; X /* get the token */ X if (!(temp_token = str_tok(buf, '='))) { X sprintf(message, "is missing a token at line %d", i); X oops++; X break; X } X /* X * Parse the rest of the line. This is similar to using X * the "real" strtok() function, but my version returns X * a null pointer if the parameter is missing. Note the X * array of field separators. X */ X for (j=0; j<8; j++) { X if (!(str = str_tok((char *) NULL, sep[j]))) { X sprintf(message, "is missing a parameter at line %d", i); X oops++; X break; X } X switch(j) { X case 0: X d.name[i] = strdup(str); X break; X case 1: X d.number[i] = strdup(str); X break; X case 2: X d.baud[i] = atoi(str); X break; X case 3: X d.parity[i] = *str; X break; X case 4: X d.dbits[i] = atoi(str); X break; X case 5: X d.sbits[i] = atoi(str); X break; X case 6: X d.duplex[i] = *str; X break; X case 7: X d.index[i] = strdup(str); X break; X } X } X if (oops) X break; X /* sanity checking */ X sprintf(token, "DIR_%d", i); X if (strcmp(temp_token, token)) { X sprintf(message, "is corrupted at line %d", i); X oops++; X break; X } X } X fclose(fp); X X if (oops) { X sprintf(buf, "Directory file '%s'", status->d_path); X error_win(1, buf, message); X } X d.d_entries = i; X /* fill in the rest with defaults */ X i++; X for (; i<=NUM_DIR; i++) { X d.name[i] = null_ptr; X d.number[i] = null_ptr; X d.baud[i] = param->d_baud; X d.parity[i] = param->d_parity; X d.dbits[i] = param->d_dbits; X d.sbits[i] = param->d_sbits; X d.duplex[i] = *param->d_duplex; X d.index[i] = null_ptr; X } X /* create an empty "manual" entry */ X d.name[0] = null_ptr; X d.number[0] = null_ptr; X d.baud[0] = param->d_baud; X d.parity[0] = param->d_parity; X d.dbits[0] = param->d_dbits; X d.sbits[0] = param->d_sbits; X d.duplex[0] = *param->d_duplex; X d.index[0] = null_ptr; X /* create an empty queue */ X for (i=0; i<NUM_QUEUE; i++) { X d.q_ld[i] = NULL; X d.q_num[i] = -1; X } X /* the startup d_cur is 0 */ X d.d_cur = 0; X return(&d); X} X X/* X * Update a dialing directory entry. Update only the one entry asked for, X * not the entire image in memory. If the new entry is beyond the end of X * the physical file, then fill in the holes, and update "dir->d_entries". X * A return code of 1 means a non-fatal error. X */ X Xint Xupdate_dir(entry) Xint entry; X{ X FILE *fp_in, *fp_out; X char *temp[NUM_DIR+1], buf[80], *strdup(); X int i; X void error_win(), free_ptr(); X X /* open for read */ X if (!(fp_in = fopen(status->d_path, "r"))) { X sprintf(buf, "'%s' for read", status->d_path); X error_win(1, "Can't open dialing directory file", buf); X } X /* read in a temporary version */ X i = 0; X while (fgets(buf, 80, fp_in) != NULL) X temp[++i] = strdup(buf); X X fclose(fp_in); X /* alter only 1 entry */ X sprintf(buf, "DIR_%d=%s;%s;%d-%c-%d-%d;%c;%s\n", entry, X dir->name[entry], dir->number[entry], dir->baud[entry], X dir->parity[entry], dir->dbits[entry], dir->sbits[entry], X dir->duplex[entry], dir->index[entry]); X X if (entry <= dir->d_entries) X free_ptr(temp[entry]); X temp[entry] = strdup(buf); X /* fill in holes if beyond end */ X if (entry > dir->d_entries+1) { X for (i=dir->d_entries+1; i<entry; i++) { X sprintf(buf, "DIR_%d=;;%d-%c-%d-%d;%c;\n", i, X param->d_baud, param->d_parity, param->d_dbits, X param->d_sbits, *param->d_duplex); X temp[i] = strdup(buf); X } X } X /* update "dir->d_entries" */ X if (entry > dir->d_entries) X dir->d_entries = entry; X X /* open for read */ X if (!(fp_out = fopen(status->d_path, "w"))) { X for (i=1; i<=dir->d_entries; i++) X free_ptr(temp[i]); X sprintf(buf, "'%s'", status->d_path); X error_win(0, "No write permission on directory file", buf); X return(1); X } X /* put it back */ X for (i=1; i<=dir->d_entries; i++) { X fputs(temp[i], fp_out); X free_ptr(temp[i]); X } X X fclose(fp_out); X return(0); X} X X/* X * Delete a range of dialing directory entries. Actually, just copies X * default (empty) entries in place of deleted entries. However, it will X * shrink the file if deletions occur at the physical EOF. A return code X * of 1 means a non-fatal error. X */ X Xint Xdel_dir(first, last) Xint first, last; X{ X FILE *fp_in, *fp_out; X int i; X char *temp[NUM_DIR+1], buf[80], *strdup(); X void error_win(), free_ptr(); X /* sanity checking */ X if (first > dir->d_entries) X return(0); X if (last > dir->d_entries) X last = dir->d_entries; X X /* open for read */ X if (!(fp_in = fopen(status->d_path, "r"))) { X sprintf(buf, "'%s' for read", status->d_path); X error_win(1, "Can't open dialing directory file", buf); X } X /* read in a temporary version */ X i = 0; X while (fgets(buf, 80, fp_in) != NULL) X temp[++i] = strdup(buf); X X fclose(fp_in); X /* delete the range of values */ X for (i=first; i<=last; i++) { X sprintf(buf, "DIR_%d=;;%d-%c-%d-%d;%c;\n", i, param->d_baud, X param->d_parity, param->d_dbits, param->d_sbits, X *param->d_duplex); X free_ptr(temp[i]); X temp[i] = strdup(buf); X } X /* shrink the file? */ X if (last >= dir->d_entries) { X for (i=first; i<=last; i++) X free_ptr(temp[i]); X dir->d_entries = first-1; X } X /* open for write */ X if (!(fp_out = fopen(status->d_path, "w"))) { X for (i=1; i<=dir->d_entries; i++) X free_ptr(temp[i]); X sprintf(buf, "'%s'", status->d_path); X error_win(0, "No write permission on dialing directory file", buf); X return(1); X } X /* put it all back */ X for (i=1; i<=dir->d_entries; i++) { X fputs(temp[i], fp_out); X free_ptr(temp[i]); X } X X fclose(fp_out); X return(0); X} SHAR_EOF if test 6469 -ne "`wc -c < 'd_lib.c'`" then echo shar: "error transmitting 'd_lib.c'" '(should have been 6469 characters)' fi fi echo shar: "extracting 'd_manual.c'" '(1757 characters)' if test -f 'd_manual.c' then echo shar: "will not over-write existing file 'd_manual.c'" else sed 's/^X//' << \SHAR_EOF > 'd_manual.c' X/* X * The manual dial option of the dialing directory. A return code of X * 1 means we're ready to dial. Dialing directory entry 0 is reserved X * for the manual dial option. No sanity checking is done on the input. X */ X X#include <stdio.h> X#include <curses.h> X#include "dial_dir.h" X Xint Xmanual() X{ X WINDOW *m_win, *newwin(); X char *number, *strdup(), *get_str(), ld_code, *strchr(); X void fix_xmc(), free_ptr(); X extern int xmc; X X m_win = newwin(5, 50, 0, 20); X X box(m_win, '|', '-'); X mvwaddstr(m_win, 2, 3, "Phone Number: "); X wrefresh(m_win); X /* get a phone number */ X if ((number = get_str(m_win, 30, NULL, NULL)) == NULL) { X werase(m_win); X wrefresh(m_win); X delwin(m_win); X if (xmc > 0) X fix_xmc(); X return(0); X } X /* is first char an LD code ? */ X ld_code = NULL; X if (strchr("+-@#", *number)) { X ld_code = *number; X number++; X } X /* put it in the queue */ X dir->q_ld[0] = ld_code; X dir->q_num[0] = 0; X /* end of queue marker */ X dir->q_num[1] = -1; X dir->d_cur = 0; X /* build the entry zero */ X free_ptr(dir->name[0]); X free_ptr(dir->number[0]); X dir->name[0] = strdup(number); X dir->number[0] = strdup(number); X /* it overlaps dm_win, so erase it */ X werase(m_win); X wrefresh(m_win); X delwin(m_win); X if (xmc > 0) X fix_xmc(); X return(1); X} X X/* X * Clear the end of the physical screen where the magic cookie got shifted X * Geez, I hate magic cookie terminals... Wyse, are you listening? X */ X Xvoid Xfix_xmc() X{ X WINDOW *cl_win, *newwin(); X X /* X * Since the cookie got shifted off the window, we have to X * create a new window to cover where the cookie ended up. X */ X cl_win = newwin(1, 2, 4, 78); X /* have to touch, otherwise nothing! */ X touchwin(cl_win); X wrefresh(cl_win); X delwin(cl_win); X X return; X} SHAR_EOF if test 1757 -ne "`wc -c < 'd_manual.c'`" then echo shar: "error transmitting 'd_manual.c'" '(should have been 1757 characters)' fi fi echo shar: "extracting 'd_menu.c'" '(6870 characters)' if test -f 'd_menu.c' then echo shar: "will not over-write existing file 'd_menu.c'" else sed 's/^X//' << \SHAR_EOF > 'd_menu.c' X/* X * Routines for the dialing directory menu. X */ X X#include <stdio.h> X#include <curses.h> X#include "dial_dir.h" X#include "misc.h" X#include "param.h" X X/* X * Display the dialing directory and prompt for options. A return code of X * 1 means we're ready to dial. X */ X Xint Xdial_menu() X{ X WINDOW *dm_win, *newwin(); X char buf[5], ld_code; X int ans, start, current, needs_repair, count, x, y, i, ret_code; X void scroll_dir(), active_ld(), disp_ld(), print_dir(); X extern int xmc; X X dm_win = newwin(22, 78, 1, 1); X mvwattrstr(dm_win, 1, 20, A_BOLD, "D I A L I N G D I R E C T O R Y"); X waddstr(dm_win, "\n-----------------------------------------------------------------------------\n"); X wattrstr(dm_win, A_STANDOUT, " Name Number Baud P D S Dpx Index/tty "); X /* show the first 10 entries */ X scroll_dir(dm_win, 1); X X mvwaddstr(dm_win, 15, 4, "==>"); X mvwattrch(dm_win, 15, 14, A_BOLD, 'R'); X waddstr(dm_win, " Revise"); X mvwattrch(dm_win, 15, 32, A_BOLD, 'M'); X waddstr(dm_win, " Manual Dialing"); X mvwaddstr(dm_win, 15, 55, "Entry to Dial"); X X mvwattrch(dm_win, 16, 14, A_BOLD, 'P'); X waddstr(dm_win, " LD Codes"); X mvwattrch(dm_win, 16, 32, A_BOLD, 'D'); X waddstr(dm_win, " Delete Entry"); X mvwattrstr(dm_win, 16, 55, A_BOLD, "<cr>"); X waddstr(dm_win, " Scroll Down"); X X mvwattrstr(dm_win, 17, 14, A_BOLD, "up/dn"); X waddstr(dm_win, " Page"); X mvwattrch(dm_win, 17, 32, A_BOLD, 'L'); X waddstr(dm_win, " Print Entries"); X mvwattrstr(dm_win, 17, 55, A_BOLD, "ESC"); X waddstr(dm_win, " Exit"); X X mvwaddstr(dm_win, 19, 4, "LD Codes Active:"); X /* show which LD codes are active */ X active_ld(dm_win); X X box(dm_win, '|', '-'); X y = 15; X x = 8; X wmove(dm_win, 15, 8); X wrefresh(dm_win); X#ifndef OLDCURSES X keypad(dm_win, 1); X#endif /* OLDCURSES */ X /* prompt for options */ X current = 1; X count = 0; X ld_code = NULL; X ret_code = 0; X do { X needs_repair = 0; X ans = wgetch(dm_win); X /* get an entry number */ X if (ans >= '0' && ans <= '9') { X if (count > 2) { X beep(); X continue; X } X buf[count] = ans; X waddch(dm_win, ans); X wrefresh(dm_win); X count++; X continue; X } X switch (ans) { X case 8: /* do our own backspace */ X if (!count) { X beep(); X break; X } X count--; X if (!count) X ld_code = NULL; X buf[count] = NULL; X getyx(dm_win, y, x); X x--; X wmove(dm_win, y, x); X waddch(dm_win, ' '); X wmove(dm_win, y, x); X wrefresh(dm_win); X break; X#ifndef OLDCURSES X case KEY_UP: X#endif /* OLDCURSES */ X case 'u': X case 'U': /* up arrow key */ X if (current == 1) { X beep(); X break; X } X start = current - 10; X if (start < 1) X start = 1; X current = start; X scroll_dir(dm_win, start); X break; X#ifndef OLDCURSES X case KEY_DOWN: X case '\n': X#endif /* OLDCURSES */ X case 'n': X case 'N': /* down arrow key */ X if (current == NUM_DIR-9) { X beep(); X break; X } X start = current + 10; X if (start > NUM_DIR-9) X start = NUM_DIR-9; X current = start; X scroll_dir(dm_win, start); X break; X case '\r': /* <CR> key */ X if (!count) { X if (current == NUM_DIR-9) { X beep(); X break; X } X current++; X if (current > NUM_DIR-9) X current = NUM_DIR-9; X scroll_dir(dm_win, current); X } X /* X * The CR is used for the scroll-down-one-line X * function, and to terminate numeric input. X */ X else { X buf[count] = NULL; X i = atoi(buf); X if (!i || i > NUM_DIR) { X beep(); X mvwaddstr(dm_win, 15, 8, " "); X x = 8; X count = 0; X break; X } X dir->q_ld[0] = ld_code; X dir->q_num[0] = i; X dir->d_cur = i; X X /* end of queue marker */ X dir->q_num[1] = -1; X X ret_code = 1; X break; X } X break; X case 'r': X case 'R': /* revise */ X if (revise()) { X active_ld(dm_win); X scroll_dir(dm_win, current); X } X touchwin(dm_win); X break; X case 'p': /* display LD codes */ X case 'P': X disp_ld(); X touchwin(dm_win); X needs_repair = 1; X break; X case 'd': X case 'D': /* delete a range of entries */ X if (delete()) X scroll_dir(dm_win, current); X touchwin(dm_win); X break; X case 'm': X case 'M': /* manual dial */ X if (manual()) { X ret_code = 1; X break; X } X touchwin(dm_win); X needs_repair = 1; X break; X case 'l': X case 'L': /* print the entries */ X print_dir(); X touchwin(dm_win); X needs_repair = 1; X break; X case '+': /* LD codes */ X case '-': X case '@': X case '#': X waddch(dm_win, ans); X wrefresh(dm_win); X ld_code = ans; X continue; X case 27: /* ESC key (exit) */ X break; X default: X beep(); X } X if (ret_code) X break; X /* magic cookie terminal ? */ X if (xmc > 0 && needs_repair) { X clear_line(dm_win, 1, 0, 0); X clear_line(dm_win, 3, 0, 0); X wrefresh(dm_win); X mvwattrstr(dm_win, 1, 20, A_BOLD, "D I A L I N G D I R E C T O R Y"); X mvwattrstr(dm_win, 3, 0, A_STANDOUT, " Name Number Baud P D S Dpx Index/tty "); X box(dm_win, '|', '-'); X } X wmove(dm_win, y, x); X wrefresh(dm_win); X } while (ans != 27); X X werase(dm_win); X wrefresh(dm_win); X delwin(dm_win); X return(ret_code); X} X X/* X * Scroll the dialing directory. Actually, we're not doing a real scroll X * function on the screen, we're just repainting 10 lines. X */ X Xvoid Xscroll_dir(win, start) XWINDOW *win; Xint start; X{ X int i; X X wmove(win, 4, 0); X for (i=start; i<start+10; i++) X wprintw(win, X "%4d- %-20.20s %18.18s %5d-%c-%d-%d %c %-14.14s\n", i, 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 return; X} X X/* X * Display the Long Distance codes. Press any key to continue. X */ X Xvoid Xdisp_ld() X{ X WINDOW *ld_win, *newwin(); X X ld_win = newwin(12, 30, 0, 0); X mvwaddstr(ld_win, 1, 5, "Long Distance Codes\n"); X waddstr(ld_win, "------------------------------"); X mvwprintw(ld_win, 3, 2, "+ %-20.20s", param->ld_plus); X mvwprintw(ld_win, 5, 2, "- %-20.20s", param->ld_minus); X mvwprintw(ld_win, 7, 2, "@ %-20.20s", param->ld_at); X mvwprintw(ld_win, 9, 2, "# %-20.20s", param->ld_pound); X box(ld_win, '|', '-'); X X mvwaddstr(ld_win, 11, 8, " Press any key "); X wmove(ld_win, 11, 29); X wrefresh(ld_win); X wgetch(ld_win); X /* it overlaps, so erase it */ X werase(ld_win); X wrefresh(ld_win); X delwin(ld_win); X return; X} X X/* X * Display which of the Long Distance codes are active. X */ X Xvoid Xactive_ld(win) XWINDOW *win; X{ X mvwaddstr(win, 19, 21, " "); X wmove(win, 19, 21); X /* a NULL pointer means not active */ X if (*param->ld_plus != NULL) X waddstr(win, "+ "); X if (*param->ld_minus != NULL) X waddstr(win, "- "); X if (*param->ld_at != NULL) X waddstr(win, "@ "); X if (*param->ld_pound != NULL) X waddstr(win, "# "); X return; X} SHAR_EOF if test 6870 -ne "`wc -c < 'd_menu.c'`" then echo shar: "error transmitting 'd_menu.c'" '(should have been 6870 characters)' fi fi exit 0 # End of shell archive
egray@fthood.UUCP (03/13/88)
This is part 3 (of 6) to the Pcomm version 1.0 distribution. Emmet P. Gray US Army, HQ III Corps & Fort Hood ...!ihnp4!uiucuxc!fthood!egray Attn: AFZF-DE-ENV Directorate of Engineering & Housing Environmental Management Office Fort Hood, TX 76544-5057 ------------------------------------------------------------------------------- #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # 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 # This archive created: Fri Mar 11 07:35:10 1988 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'" '(6180 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 ioctl(status->fd, PIOCDIAL, n); 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 6180 -ne "`wc -c < 'dial.c'`" then echo shar: "error transmitting 'dial.c'" '(should have been 6180 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'" '(3530 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 char *pcomm, *getenv(), temp[200], *path, pbuf[200]; X char *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 3530 -ne "`wc -c < 'init.c'`" then echo shar: "error transmitting 'init.c'" '(should have been 3530 characters)' fi fi exit 0 # End of shell archive
egray@fthood.UUCP (03/14/88)
This is part 5 (of 6) to the Pcomm version 1.0 distribution. Emmet P. Gray US Army, HQ III Corps & Fort Hood ...!ihnp4!uiucuxc!fthood!egray Attn: AFZF-DE-ENV Directorate of Engineering & Housing Environmental Management Office Fort Hood, TX 76544-5057 ------------------------------------------------------------------------------- #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # s_axfer.c # s_gen.c # s_menu.c # s_modem.c # s_prompt.c # s_term.c # s_tty.c # screen.c # st_line.c # strings.c # terminal.c # x_ascii.c # This archive created: Fri Mar 11 07:35:23 1988 export PATH; PATH=/bin:/usr/bin:$PATH echo shar: "extracting 's_axfer.c'" '(3885 characters)' if test -f 's_axfer.c' then echo shar: "will not over-write existing file 's_axfer.c'" else sed 's/^X//' << \SHAR_EOF > 's_axfer.c' X/* X * Display the ASCII transfer setup, query for changes. A return code X * of 1 means something was changed. X */ X X#include <stdio.h> X#include <curses.h> X#include "misc.h" X#include "param.h" X Xint Xascii_xfer_setup() X{ X WINDOW *x_win, *newwin(); X int i, ret_code, num; X char *ans, *str_prompt(), *menu_prompt(), *strdup(); X void free_ptr(); X extern char *v_yes[], *v_cr[], *v_lf[], *v_delay[]; X X x_win = newwin(23, 80, 0, 0); X X waddstr(x_win, "----------------------------- "); X wattrstr(x_win, A_BOLD, "ASCII Transfer Setup"); X waddstr(x_win, " -----------------------------"); X mvwaddstr(x_win, 3, 34, "ASCII UPLOAD"); X mvwprintw(x_win, 5, 22, "1) Echo locally ........... %s", param->lecho); X mvwprintw(x_win, 6, 22, "2) Expand blank lines ..... %s", param->expand); X mvwprintw(x_win, 7, 22, "3) CR delay (ms) .......... %d", param->cr_delay); X mvwprintw(x_win, 8, 22, "4) Pace the output ........ %s", param->pace); X mvwprintw(x_win, 9, 22, "5) CR translation ......... %s", param->cr_up); X mvwprintw(x_win, 10, 22, "6) LF translation ......... %s", param->lf_up); X mvwaddstr(x_win, 12, 32, "ASCII DOWNLOAD"); X mvwprintw(x_win, 14, 22, "7) Transfer timeout ....... %d", param->timer); X mvwprintw(x_win, 15, 22, "8) CR translation ......... %s", param->cr_dn); X mvwprintw(x_win, 16, 22, "9) LF translation ......... %s", param->lf_dn); X mvwprintw(x_win, 19, 0, "--------------------------------------------------------------------------------"); X mvwattrstr(x_win, 20, 0, A_BOLD, "OPTION ==> "); X mvwaddstr(x_win, 20, 60, "Press ESC to return"); X wmove(x_win, 20, 12); X touchwin(x_win); X wrefresh(x_win); X /* get the option number */ X ret_code = 0; X while ((i = get_num(x_win, 1)) != -1) { X switch(i) { X case 1: X if ((ans = menu_prompt(x_win, 5, 50, "Echo locally", v_yes)) != NULL) { X free_ptr(param->lecho); X param->lecho = strdup(ans); X ret_code++; X } X break; X case 2: X if ((ans = menu_prompt(x_win, 6, 50, "Expand blank lines", v_yes)) != NULL) { X free_ptr(param->expand); X param->expand = strdup(ans); X ret_code++; X } X break; X case 3: X if ((ans = menu_prompt(x_win, 7, 50, "CR delay (ms)", v_delay)) != NULL) { X param->cr_delay = atoi(ans); X ret_code++; X } X break; X case 4: X if ((ans = menu_prompt(x_win, 8, 50, "Pace the output", v_yes)) != NULL) { X free_ptr(param->pace); X param->pace = strdup(ans); X ret_code++; X } X break; X case 5: X if ((ans = menu_prompt(x_win, 9, 50, "CR translation (upload)", v_cr)) != NULL) { X free_ptr(param->cr_up); X param->cr_up = strdup(ans); X ret_code++; X } X break; X case 6: X if ((ans = menu_prompt(x_win, 10, 50, "LF translation (upload)", v_lf)) != NULL) { X free_ptr(param->lf_up); X param->lf_up = strdup(ans); X ret_code++; X } X break; X case 7: X if ((num = num_prompt(x_win, 14, 50, "Transfer timeout", NULL)) != -1) { X if (num > MAX_TIMER || num < MIN_TIMER) { X beep(); X /* some reasonable range of values */ X if (num < MIN_TIMER) X num = MIN_TIMER; X else X num = MAX_TIMER; X mvwaddstr(x_win, 14, 50, " "); X wrefresh(x_win); X mvwattrnum(x_win, 14, 50, A_BOLD, num); X wrefresh(x_win); X } X param->timer = num; X ret_code++; X } X break; X case 8: X if ((ans = menu_prompt(x_win, 15, 50, "CR translation (download)", v_cr)) != NULL) { X free_ptr(param->cr_dn); X param->cr_dn = strdup(ans); X ret_code++; X } X break; X case 9: X if ((ans = menu_prompt(x_win, 16, 50, "LF translation (download)", v_lf)) != NULL) { X free_ptr(param->lf_dn); X param->lf_dn = strdup(ans); X ret_code++; X } X break; X default: X beep(); X } X mvwaddch(x_win, 20, 12, ' '); X clear_line(x_win, 21, 0, 0); X clear_line(x_win, 22, 0, 0); X wmove(x_win, 20, 12); X wrefresh(x_win); X } X delwin(x_win); X return(ret_code); X} SHAR_EOF if test 3885 -ne "`wc -c < 's_axfer.c'`" then echo shar: "error transmitting 's_axfer.c'" '(should have been 3885 characters)' fi fi echo shar: "extracting 's_gen.c'" '(4267 characters)' if test -f 's_gen.c' then echo shar: "will not over-write existing file 's_gen.c'" else sed 's/^X//' << \SHAR_EOF > 's_gen.c' X/* X * Display the general setup, query for changes. A return code of 1 X * means something was changed. X */ X X#include <stdio.h> X#include <curses.h> X#include "misc.h" X#include "param.h" X Xint Xgen_setup() X{ X WINDOW *g_win, *newwin(); X int i, num, ret_code; X char c, *ans, *str_prompt(), *menu_prompt(), chr_prompt(); X char *strdup(); X void free_ptr(); X extern char *v_yes[], *v_abort[]; X X g_win = newwin(23, 80, 0, 0); X X waddstr(g_win, "--------------------------------- "); X wattrstr(g_win, A_BOLD, "General Setup"); X waddstr(g_win, " --------------------------------"); X mvwprintw(g_win, 3, 22, "1) Default log file ....... %s", param->logfile); X mvwprintw(g_win, 4, 22, "2) Screen dump file ....... %s", param->dumpfile); X mvwprintw(g_win, 6, 22, "3) Strip high bit ........ %s", param->strip); X mvwprintw(g_win, 8, 22, "4) Pause character ........ %c", param->pause_char); X mvwprintw(g_win, 9, 22, "5) CR character ........... %c", param->cr_char); X mvwprintw(g_win, 10, 22, "6) CTRL character ......... %c", param->ctrl_char); X mvwprintw(g_win, 11, 22, "7) ESC character .......... %c", param->esc_char); X mvwprintw(g_win, 13, 22, "8) Aborted downloads ...... %s", param->abort); X mvwprintw(g_win, 15, 22, "9) Connect delay time ..... %d", param->cdelay); X mvwprintw(g_win, 16, 21, "10) Pause between redials .. %d", param->pause); X mvwprintw(g_win, 19, 0, "--------------------------------------------------------------------------------"); X mvwattrstr(g_win, 20, 0, A_BOLD, "OPTION ==> "); X mvwaddstr(g_win, 20, 60, "Press ESC to return"); X wmove(g_win, 20, 12); X touchwin(g_win); X wrefresh(g_win); X /* get the option number */ X ret_code = 0; X while ((i = get_num(g_win, 2)) != -1) { X switch(i) { X case 1: X if ((ans = str_prompt(g_win, 3, 50, "Default log file", NULL)) != NULL) { X free_ptr(param->logfile); X param->logfile = strdup(ans); X ret_code++; X } X break; X case 2: X if ((ans = str_prompt(g_win, 4, 50, "Default screen dump file", NULL)) != NULL) { X free_ptr(param->dumpfile); X param->dumpfile = strdup(ans); X ret_code++; X } X break; X case 3: X if ((ans = menu_prompt(g_win, 6, 50, "Strip high bit ?", v_yes)) != NULL) { X free_ptr(param->strip); X param->strip = strdup(ans); X ret_code++; X } X break; X case 4: X if ((c = chr_prompt(g_win, 8, 50, "Pause character", "1 second")) != NULL) { X param->pause_char = c; X ret_code++; X } X break; X case 5: X if ((c = chr_prompt(g_win, 9, 50, "CR character", "(carriage return)")) != NULL) { X param->cr_char = c; X ret_code++; X } X break; X case 6: X if ((c = chr_prompt(g_win, 10, 50, "CTRL character", "(control)")) != NULL) { X param->ctrl_char = c; X ret_code++; X } X break; X case 7: X if ((c = chr_prompt(g_win, 11, 50, "ESC character", "(escape)")) != NULL) { X param->esc_char = c; X ret_code++; X } X break; X case 8: X if ((ans = menu_prompt(g_win, 13, 50, "Aborted downloads", v_abort)) != NULL) { X free_ptr(param->abort); X param->abort = strdup(ans); X ret_code++; X } X break; X case 9: X if ((num = num_prompt(g_win, 15, 50, "Connect delay time", "in seconds")) != -1) { X if (num > MAX_CDELAY || num < MIN_CDELAY) { X beep(); X /* some reasonable range of values */ X if (num < MIN_CDELAY) X num = MIN_CDELAY; X else X num = MAX_CDELAY; X mvwaddstr(g_win, 15, 50, " "); X wrefresh(g_win); X mvwattrnum(g_win, 15, 50, A_BOLD, num); X wrefresh(g_win); X } X param->cdelay = num; X ret_code++; X } X break; X case 10: X if ((num = num_prompt(g_win, 16, 50, "Pause between redials", "in seconds")) != -1) { X if (num > MAX_PAUSE || num < MIN_PAUSE) { X beep(); X /* some reasonable range */ X if (num < MIN_PAUSE) X num = MIN_PAUSE; X else X num = MAX_PAUSE; X mvwaddstr(g_win, 16, 50, " "); X wrefresh(g_win); X mvwattrnum(g_win, 16, 50, A_BOLD, num); X wrefresh(g_win); X } X param->pause = num; X ret_code++; X } X break; X default: X beep(); X } X mvwaddstr(g_win, 20, 12, " "); X clear_line(g_win, 21, 0, 0); X clear_line(g_win, 22, 0, 0); X wmove(g_win, 20, 12); X wrefresh(g_win); X } X delwin(g_win); X return(ret_code); X} SHAR_EOF if test 4267 -ne "`wc -c < 's_gen.c'`" then echo shar: "error transmitting 's_gen.c'" '(should have been 4267 characters)' fi fi echo shar: "extracting 's_menu.c'" '(2698 characters)' if test -f 's_menu.c' then echo shar: "will not over-write existing file 's_menu.c'" else sed 's/^X//' << \SHAR_EOF > 's_menu.c' X/* X * Display the setup menu, prompts for a bunch of other menus. X */ X X#include <stdio.h> X#include <curses.h> X#include "misc.h" X Xvoid Xsetup_menu(fd) Xint fd; X{ X WINDOW *s_win, *newwin(); X char *ans, *get_str(); X int param_flag, modem_flag; X void top_line(); X extern int xmc; X X s_win = newwin(23, 80, 0, 0); X X top_line(s_win); X mvwaddstr(s_win, 4, 30, "1) TTY Setup"); X mvwaddstr(s_win, 6, 30, "2) Modem Setup"); X mvwaddstr(s_win, 8, 30, "3) Terminal Setup"); X mvwaddstr(s_win, 10, 30, "4) General Setup"); X mvwaddstr(s_win, 12, 30, "5) ASCII Transfer Setup"); X mvwaddstr(s_win, 14, 30, "S) Save setup to disk"); X mvwaddstr(s_win, 19, 0, "--------------------------------------------------------------------------------"); X mvwattrstr(s_win, 20, 0, A_BOLD, "OPTION ==> "); X mvwaddstr(s_win, 20, 60, " Press ESC to exit"); X wmove(s_win, 20, 12); X wrefresh(s_win); X X param_flag = 0; X modem_flag = 0; X /* get the options */ X while ((ans = get_str(s_win, 1, "12345Ss", NULL)) != NULL) { X if (xmc > 0) { X clear_line(s_win, 0, 0, 0); X wrefresh(s_win); X } X switch(*ans) { X case '1': X if (tty_setup()) X modem_flag = 1; X break; X case '2': X if (modem_setup()) X modem_flag = 1; X break; X case '3': X if (term_setup()) X param_flag = 1; X break; X case '4': X if (gen_setup()) X param_flag = 1; X break; X case '5': X if (ascii_xfer_setup()) X param_flag = 1; X break; X case 's': X case 'S': X if (xmc > 0) X top_line(s_win); X if (param_flag || modem_flag) { X wmove(s_win, 22, 27); X /* X * Writes to disk are not critical, X * the changes are made in memory. X */ X if (param_flag) { X wattrstr(s_win, A_BLINK, "Updating Parameter File"); X wrefresh(s_win); X wait_key(s_win, 3); X if (update_param()) { X touchwin(s_win); X wrefresh(s_win); X } X } X if (modem_flag) { X wattrstr(s_win, A_BLINK, "Updating Modem Database"); X wrefresh(s_win); X wait_key(s_win, 3); X if (update_modem()) { X touchwin(s_win); X wrefresh(s_win); X } X } X clear_line(s_win, 22, 27, 0); X wrefresh(s_win); X } X break; X default: X beep(); X } X touchwin(s_win); X if (xmc > 0) X top_line(s_win); X X mvwaddch(s_win, 20, 12, ' '); X wmove(s_win, 20, 12); X wrefresh(s_win); X } X if (fd == -1) { X werase(s_win); X wrefresh(s_win); X } X delwin(s_win); X return; X} X X/* X * Put the top line on the window. X */ X Xvoid Xtop_line(win) XWINDOW *win; X{ X clear_line(win, 0, 0, 0); X wrefresh(win); X waddstr(win, "---------------------------------- "); X wattrstr(win, A_BOLD, "Setup Menu"); X waddstr(win, " ----------------------------------"); X wrefresh(win); X return; X} SHAR_EOF if test 2698 -ne "`wc -c < 's_menu.c'`" then echo shar: "error transmitting 's_menu.c'" '(should have been 2698 characters)' fi fi echo shar: "extracting 's_modem.c'" '(6556 characters)' if test -f 's_modem.c' then echo shar: "will not over-write existing file 's_modem.c'" else sed 's/^X//' << \SHAR_EOF > 's_modem.c' X/* X * Display the modem setup, query for changes. A return code of 1 means X * something was changed. X */ X X#include <stdio.h> X#include <curses.h> X#include "misc.h" X#include "modem.h" X Xint Xmodem_setup() X{ X WINDOW *mo_win, *newwin(); X int i, j, ret_code, modem_prompt(); X char *ans, *strdup(), *str_prompt(); X void disp_modem(), free_ptr(); X /* the current modem */ X j = 0; X if (modem->m_cur != -1) X j = modem->m_cur; X X mo_win = newwin(23, 80, 0, 0); X X waddstr(mo_win, "---------------------------------- "); X wattrstr(mo_win, A_BOLD, "Modem Setup"); X waddstr(mo_win, " ---------------------------------"); X /* display the current settings */ X disp_modem(mo_win, j); X mvwprintw(mo_win, 19, 0, "--------------------------------------------------------------------------------"); X mvwattrstr(mo_win, 20, 0, A_BOLD, "OPTION ==> "); X mvwaddstr(mo_win, 20, 60, "Press ESC to return"); X wmove(mo_win, 20, 12); X touchwin(mo_win); X wrefresh(mo_win); X /* get the option number */ X ret_code = 0; X while ((i = get_num(mo_win, 2)) != -1) { X switch(i) { X case 1: X j = modem_prompt(mo_win); X break; X case 2: X if ((ans = str_prompt(mo_win, 4, 40, "Modem init string", "sent to the modem once")) != NULL) { X free_ptr(modem->init[j]); X modem->init[j] = strdup(ans); X ret_code++; X } X break; X case 3: X if ((ans = str_prompt(mo_win, 5, 40, "Dialing command", NULL)) != NULL) { X free_ptr(modem->dial[j]); X modem->dial[j] = strdup(ans); X ret_code++; X } X break; X case 4: X if ((ans = str_prompt(mo_win, 6, 40, "Dialing cmd suffix", "typically the CR character")) != NULL) { X free_ptr(modem->suffix[j]); X modem->suffix[j] = strdup(ans); X ret_code++; X } X break; X case 5: X if ((ans = str_prompt(mo_win, 7, 40, "Hangup string", NULL)) != NULL) { X free_ptr(modem->hangup[j]); X modem->hangup[j] = strdup(ans); X ret_code++; X } X break; X case 6: X if ((ans = str_prompt(mo_win, 8, 40, "300 baud connect string", NULL)) != NULL) { X free_ptr(modem->con_3[j]); X modem->con_3[j] = strdup(ans); X ret_code++; X } X break; X case 7: X if ((ans = str_prompt(mo_win, 9, 40, "1200 baud connect string", NULL)) != NULL) { X free_ptr(modem->con_12[j]); X modem->con_12[j] = strdup(ans); X ret_code++; X } X break; X case 8: X if ((ans = str_prompt(mo_win, 10, 40, "2400 baud connect string", NULL)) != NULL) { X free_ptr(modem->con_24[j]); X modem->con_24[j] = strdup(ans); X ret_code++; X } X break; X case 9: X if ((ans = str_prompt(mo_win, 11, 40, "4800 baud connect string", NULL)) != NULL) { X free_ptr(modem->con_48[j]); X modem->con_48[j] = strdup(ans); X ret_code++; X } X break; X case 10: X if ((ans = str_prompt(mo_win, 12, 40, "9600 baud connect string", NULL)) != NULL) { X free_ptr(modem->con_96[j]); X modem->con_96[j] = strdup(ans); X ret_code++; X } X break; X case 11: X if ((ans = str_prompt(mo_win, 13, 40, "19200 baud connect string", NULL)) != NULL) { X free_ptr(modem->con_192[j]); X modem->con_192[j] = strdup(ans); X ret_code++; X } X break; X case 12: X if ((ans = str_prompt(mo_win, 14, 40, "No connect string 1", NULL)) != NULL) { X free_ptr(modem->no_con1[j]); X modem->no_con1[j] = strdup(ans); X ret_code++; X } X break; X case 13: X if ((ans = str_prompt(mo_win, 15, 40, "No connect string 2", NULL)) != NULL) { X free_ptr(modem->no_con2[j]); X modem->no_con2[j] = strdup(ans); X ret_code++; X } X break; X case 14: X if ((ans = str_prompt(mo_win, 16, 40, "No connect string 3", NULL)) != NULL) { X free_ptr(modem->no_con3[j]); X modem->no_con3[j] = strdup(ans); X ret_code++; X } X break; X case 15: X if ((ans = str_prompt(mo_win, 17, 40, "No connect string 4", NULL)) != NULL) { X free_ptr(modem->no_con4[j]); X modem->no_con4[j] = strdup(ans); X ret_code++; X } X break; X default: X beep(); X } X /* clear the previous prompts */ X mvwaddstr(mo_win, 20, 12, " "); X clear_line(mo_win, 21, 0, 0); X clear_line(mo_win, 22, 0, 0); X wmove(mo_win, 20, 12); X wrefresh(mo_win); X } X delwin(mo_win); X return(ret_code); X} X X/* X * Prompts for the modem name. The user selects the currently showing X * choice by hitting a carriage return. Returns the modem entry number. X * DOES NOT change the value of modem->m_cur. X */ X Xint Xmodem_prompt(win) XWINDOW *win; X{ X char ans; X int i; X /* print prompt lines */ X mvwaddstr(win, 22, 0, "Press any key to change, or <CR> to accept"); X mvwaddstr(win, 21, 0, "Modem name: "); X /* show current choice */ X i = 0; X if (modem->m_cur != -1) X i = modem->m_cur; X mvwprintw(win, 21, 12, "%-30.30s", modem->mname[i]); X wmove(win, 21, 12); X wrefresh(win); X /* show the choices one at a time */ X while ((ans = wgetch(win)) != '\r') { X i++; X if (*modem->mname[i] == NULL) X i = 0; X if (ans == 27) X return(0); X mvwprintw(win, 21, 12, "%-30.30s", modem->mname[i]); X wmove(win, 21, 12); X wrefresh(win); X } X /* display the new values */ X disp_modem(win, i); X /* display the name in bold */ X clear_line(win, 2, 40, 0); X wrefresh(win); X mvwattrstr(win, 2, 40, A_BOLD, modem->mname[i]); X X return(i); X} X X/* X * Show the current settings for the given modem entry number. X */ X Xvoid Xdisp_modem(w, i) XWINDOW *w; Xint i; X{ X mvwprintw(w, 2, 12, "1) Modem name ............. %-39.39s", modem->mname[i]); X mvwprintw(w, 4, 12, "2) Modem init string ...... %-39.39s", modem->init[i]); X mvwprintw(w, 5, 12, "3) Dialing command ........ %-39.39s", modem->dial[i]); X mvwprintw(w, 6, 12, "4) Dialing cmd suffix ..... %-39.39s", modem->suffix[i]); X mvwprintw(w, 7, 12, "5) Hangup string .......... %-39.39s", modem->hangup[i]); X mvwprintw(w, 8, 12, "6) 300 baud connect ....... %-39.39s", modem->con_3[i]); X mvwprintw(w, 9, 12, "7) 1200 baud connect ...... %-39.39s", modem->con_12[i]); X mvwprintw(w, 10, 12, "8) 2400 baud connect ...... %-39.39s", modem->con_24[i]); X mvwprintw(w, 11, 12, "9) 4800 baud connect ...... %-39.39s", modem->con_48[i]); X mvwprintw(w, 12, 11, "10) 9600 baud connect ...... %-39.39s", modem->con_96[i]); X mvwprintw(w, 13, 11, "11) 19200 baud connect ..... %-39.39s", modem->con_192[i]); X mvwprintw(w, 14, 11, "12) No connect string 1 .... %-39.39s", modem->no_con1[i]); X mvwprintw(w, 15, 11, "13) No connect string 2 .... %-39.39s", modem->no_con2[i]); X mvwprintw(w, 16, 11, "14) No connect string 3 .... %-39.39s", modem->no_con3[i]); X mvwprintw(w, 17, 11, "15) No connect string 4 .... %-39.39s", modem->no_con4[i]); X return; X} SHAR_EOF if test 6556 -ne "`wc -c < 's_modem.c'`" then echo shar: "error transmitting 's_modem.c'" '(should have been 6556 characters)' fi fi echo shar: "extracting 's_prompt.c'" '(3369 characters)' if test -f 's_prompt.c' then echo shar: "will not over-write existing file 's_prompt.c'" else sed 's/^X//' << \SHAR_EOF > 's_prompt.c' X/* X * Prompting routines used in the setup menus. X */ X X#include <stdio.h> X#include <curses.h> X#include "misc.h" X X/* X * Prompt for a string at line 21 (with optional line 22 for additional X * information). Display the new string in bold at its original location X * in the menu. Used in virtually all of the *_setup() routines. X */ X Xchar * Xstr_prompt(win, y, x, p1, p2) XWINDOW *win; Xint y, x; Xchar *p1, *p2; X{ X char *ans, *get_str(); X extern char *null_ptr; X /* print first prompt last */ X mvwaddstr(win, 22, 0, p2); X mvwaddstr(win, 21, 0, p1); X waddstr(win, ": "); X wrefresh(win); X X if ((ans = get_str(win, 39, NULL, NULL)) == NULL) X return(NULL); X /* check the value */ X if (!strcmp(ans, " ")) X ans = null_ptr; X /* display the value in bold */ X clear_line(win, y, x, 0); X wattrstr(win, A_BOLD, ans); X X return(ans); X} X X/* X * Same as above, except we return a single character. X */ X Xchar Xchr_prompt(win, y, x, p1, p2) XWINDOW *win; Xint y, x; Xchar *p1, *p2; X{ X char *ans, *get_str(); X /* print first prompt last */ X mvwaddstr(win, 22, 0, p2); X mvwaddstr(win, 21, 0, p1); X waddstr(win, ": "); X wrefresh(win); X X if ((ans = get_str(win, 1, NULL, NULL)) == NULL) X return(NULL); X /* display the value in bold */ X mvwaddstr(win, y, x, " "); X wrefresh(win); X mvwattrstr(win, y, x, A_BOLD, ans); X X return(*ans); X} X X/* X * Same as above, except that it prompts for a three digit number. X */ X Xint Xnum_prompt(win, y, x, p1, p2) XWINDOW *win; Xint y, x; Xchar *p1, *p2; X{ X int i, get_num(); X /* print first prompt last */ X mvwaddstr(win, 22, 0, p2); X mvwaddstr(win, 21, 0, p1); X waddstr(win, ": "); X wrefresh(win); X X if ((i = get_num(win, 3)) == -1) X return(-1); X /* display the value in bold */ X mvwaddstr(win, y, x, " "); X wrefresh(win); X mvwattrnum(win, y, x, A_BOLD, i); X /* return the number */ X return(i); X} X X/* X * Prompts for a selection from a menu. We display the prompt lines, X * and show the choices one at a time. The user selects the currently X * showing choice by hitting a carriage return. Unlike the similar X * routines in d_prompt(), the first choice shown is not necessarily X * the current. X */ X Xchar *v_yes[3] = {"YES", "NO", NULL}; Xchar *v_crio[3] = {"CR", "CR/LF", NULL}; Xchar *v_cr[4] = {"NONE", "STRIP", "ADD LF", NULL}; Xchar *v_lf[4] = {"NONE", "STRIP", "ADD CR", NULL}; Xchar *v_abort[3] = {"KEEP", "DELETE", NULL}; Xchar *v_duplex[3] = {"FULL", "HALF", NULL}; Xchar *v_flow[3] = {"NONE", "XON/XOFF", NULL}; Xchar *v_baud[7] = {"300", "1200", "2400", "4800", "9600", "19200", NULL}; Xchar *v_delay[4] = {"0", "100", "150", NULL}; X Xchar * Xmenu_prompt(win, y, x, p, menu) XWINDOW *win; Xint y, x; Xchar *p, *menu[]; X{ X char ans; X int i, cy, cx; X /* print first prompt last */ X mvwaddstr(win, 22, 0, "Press any key to change, or <CR> to accept"); X mvwaddstr(win, 21, 0, p); X waddstr(win, ": "); X /* show first choice */ X i = 0; X getyx(win, cy, cx); X mvwprintw(win, cy, cx, "%-30.30s", menu[i]); X wmove(win, cy, cx); X wrefresh(win); X /* show the choices one at a time */ X while ((ans = wgetch(win)) != '\r') { X i++; X if (*menu[i] == NULL) X i = 0; X if (ans == 27) X return(NULL); X mvwprintw(win, cy, cx, "%-30.30s", menu[i]); X wmove(win, cy, cx); X wrefresh(win); X } X /* display the value in bold */ X clear_line(win, y, x, 0); X wattrstr(win, A_BOLD, menu[i]); X /* return the value */ X return(menu[i]); X} SHAR_EOF if test 3369 -ne "`wc -c < 's_prompt.c'`" then echo shar: "error transmitting 's_prompt.c'" '(should have been 3369 characters)' fi fi echo shar: "extracting 's_term.c'" '(2743 characters)' if test -f 's_term.c' then echo shar: "will not over-write existing file 's_term.c'" else sed 's/^X//' << \SHAR_EOF > 's_term.c' X/* X * Display the terminal setup, query for changes. A return code of 1 X * means something was changed. X */ X X#include <stdio.h> X#include <curses.h> X#include "misc.h" X#include "param.h" X Xint Xterm_setup() X{ X WINDOW *t_win, *newwin(); X int i, num, ret_code; X char *ans, *strdup(), *str_prompt(), *menu_prompt(); X void free_ptr(); X extern char *v_duplex[], *v_crio[], *v_flow[]; X X t_win = newwin(23, 80, 0, 0); X X waddstr(t_win, "-------------------------------- "); X wattrstr(t_win, A_BOLD, "Terminal Setup"); X waddstr(t_win, " --------------------------------"); X mvwprintw(t_win, 4, 22, "1) Hot key ................ %d", param->hot); X mvwprintw(t_win, 6, 22, "2) ASCII version of hot ... %s", param->ascii_hot); X mvwprintw(t_win, 9, 22, "3) Duplex ................. %s", param->d_duplex); X mvwprintw(t_win, 11, 22, "4) Flow control ........... %s", param->flow); X mvwprintw(t_win, 13, 22, "5) CR translation (in) .... %s", param->cr_in); X mvwprintw(t_win, 15, 22, "6) CR translation (out) ... %s", param->cr_out); X mvwprintw(t_win, 19, 0, "--------------------------------------------------------------------------------"); X mvwattrstr(t_win, 20, 0, A_BOLD, "OPTION ==> "); X mvwaddstr(t_win, 20, 60, "Press ESC to return"); X wmove(t_win, 20, 12); X touchwin(t_win); X wrefresh(t_win); X /* get the option number */ X ret_code = 0; X while ((i = get_num(t_win, 1)) != -1) { X switch(i) { X case 1: X if ((num = num_prompt(t_win, 4, 50, "Hot key", "decimal code for the hot key")) != -1) { X param->hot = num; X ret_code = 1; X } X break; X case 2: X if ((ans = str_prompt(t_win, 6, 50, "ASCII version of hot key", "(printable version)")) != NULL) { X free_ptr(param->ascii_hot); X param->ascii_hot = strdup(ans); X ret_code = 1; X } X break; X case 3: X if ((ans = menu_prompt(t_win, 9, 50, "Duplex", v_duplex)) != NULL ) { X free_ptr(param->d_duplex); X param->d_duplex = strdup(ans); X ret_code = 1; X } X break; X case 4: X if ((ans = menu_prompt(t_win, 11, 50, "Flow control", v_flow)) != NULL ) { X free_ptr(param->flow); X param->flow = strdup(ans); X ret_code = 1; X } X break; X case 5: X if ((ans = menu_prompt(t_win, 13, 50, "CR translation (in)", v_crio)) != NULL ) { X free_ptr(param->cr_in); X param->cr_in = strdup(ans); X ret_code = 1; X } X break; X case 6: X if ((ans = menu_prompt(t_win, 15, 50, "CR translation (out)", v_crio)) != NULL ) { X free_ptr(param->cr_out); X param->cr_out = strdup(ans); X ret_code = 1; X } X break; X default: X beep(); X } X mvwaddch(t_win, 20, 12, ' '); X clear_line(t_win, 21, 0, 0); X clear_line(t_win, 22, 0, 0); X wmove(t_win, 20, 12); X wrefresh(t_win); X } X delwin(t_win); X return(ret_code); X} SHAR_EOF if test 2743 -ne "`wc -c < 's_term.c'`" then echo shar: "error transmitting 's_term.c'" '(should have been 2743 characters)' fi fi echo shar: "extracting 's_tty.c'" '(4775 characters)' if test -f 's_tty.c' then echo shar: "will not over-write existing file 's_tty.c'" else sed 's/^X//' << \SHAR_EOF > 's_tty.c' X/* X * Display the tty setup, query for changes. A return code of 1 X * means something was changed. X */ X X#include <stdio.h> X#include <curses.h> X#include "misc.h" X#include "modem.h" X#include "status.h" X Xint Xtty_setup() X{ X WINDOW *tt_win, *newwin(); X char *strdup(), buf[80]; X int num, i, j, ret_code; X void disp_tty(), create_modem(), delete_modem(), error_win(); X void delete_tty(); X extern char *null_ptr; X X tt_win = newwin(23, 80, 0, 0); X X waddstr(tt_win, "----------------------------------- "); X wattrstr(tt_win, A_BOLD, "TTY Setup"); X waddstr(tt_win, " ----------------------------------"); X mvwaddstr(tt_win, 2, 22, "TTY name"); X mvwaddstr(tt_win, 2, 37, "Modem name"); X mvwaddstr(tt_win, 2, 51, "Maximum baud"); X /* display the current tty list */ X disp_tty(tt_win); X /* prompt for options */ X mvwprintw(tt_win, 15, 20, "%d) Add a TTY entry", NUM_TTY+1); X mvwprintw(tt_win, 16, 20, "%d) Delete a TTY entry", NUM_TTY+2); X mvwprintw(tt_win, 19, 0, "--------------------------------------------------------------------------------"); X mvwattrstr(tt_win, 20, 0, A_BOLD, "OPTION ==> "); X mvwaddstr(tt_win, 20, 60, "Press ESC to return"); X wmove(tt_win, 20, 12); X touchwin(tt_win); X wrefresh(tt_win); X /* get the option number */ X ret_code = 0; X while ((i = get_num(tt_win, 2)) != -1) { X /* if beyond t_entries, fake it */ X if (i>modem->t_entries && i<=NUM_TTY) X i=999; X /* change an entry */ X if (i>=1 && i<=NUM_TTY) { X if (tty_prompt(tt_win, i-1)) X break; X /* requires modem update ? */ X create_modem(modem->tname[i-1]); X delete_modem(); X X ret_code++; X } X /* add a entry */ X if (i == NUM_TTY+1) { X if (modem->t_entries == NUM_TTY) { X sprintf(buf, "'%s'", status->m_path); X error_win(0, "No empty TTY slots in", buf); X continue; X } X /* prompt for info */ X j = modem->t_entries; X if (tty_prompt(tt_win, j)) X break; X /* add modem entry ? */ X modem->t_entries++; X create_modem(modem->tname[j]); X X ret_code++; X } X /* delete an entry */ X if (i == NUM_TTY+2) { X mvwaddstr(tt_win, 21, 0, "Entry number to delete: "); X wrefresh(tt_win); X while ((num = get_num(tt_win, 4)) != -1) { X /* valid range */ X if (!num || num>modem->t_entries) { X beep(); X mvwaddstr(tt_win, 21, 24, " "); X wrefresh(tt_win); X continue; X } X delete_tty(num-1); X delete_modem(); X X /* show the new list */ X disp_tty(tt_win); X ret_code = 1; X } X X } X if (i == 0 || i>NUM_TTY+2) X beep(); X mvwaddstr(tt_win, 20, 12, " "); X clear_line(tt_win, 21, 0, 0); X clear_line(tt_win, 22, 0, 0); X wmove(tt_win, 20, 12); X wrefresh(tt_win); X } X delwin(tt_win); X return(ret_code); X} X X/* X * Display the current tty list. No scrolling yet, so if your NUM_TTY is X * greater than ten, this routine will need some work. X */ X Xvoid Xdisp_tty(win) XWINDOW *win; X{ X int i; X X for (i=0; i<NUM_TTY; i++) X mvwprintw(win, i+4, 20, "%2d) %-14.14s %-14.14s %d\n", X i+1, modem->tty[i], modem->tname[i], modem->mbaud[i]); X return; X} X X/* X * Prompt the user for the TTY database info. A return code of 1 means a X * user abort. The second argument is the zero based index. X */ X Xtty_prompt(win, i) XWINDOW *win; Xint i; X{ X char *ans, *temp_tty, *temp_tname, *str_prompt(), *menu_prompt(); X extern char *v_baud[]; X void free_ptr(); X /* get temp tty */ X if ((ans = str_prompt(win, i+4, 24, "TTY name", NULL)) == NULL) X return(1); X X temp_tty = strdup(ans); X clear_line(win, 21, 0, 0); X X /* get temp tname */ X if ((ans = str_prompt(win, i+4, 39, "Modem name", NULL)) == NULL) X return(1); X X temp_tname = strdup(ans); X clear_line(win, 21, 0, 0); X X /* get maximum baud */ X if ((ans = menu_prompt(win, i+4, 55, "Maximum baud", v_baud)) == NULL) X return(1); X X wrefresh(win); X /* store 'em for real */ X free_ptr(modem->tty[i]); X free_ptr(modem->tname[i]); X X modem->tty[i] = strdup(temp_tty); X modem->tname[i] = strdup(temp_tname); X modem->mbaud[i] = atoi(ans); X X free_ptr(temp_tty); X free_ptr(temp_tname); X return(0); X} X X/* X * Delete a tty entry. Since the list must be contiguous, we collapse the X * list to cover the hole we made. X */ X Xvoid Xdelete_tty(i) Xint i; X{ X int j; X char *strdup(); X void free_ptr(); X extern char *null_ptr; X /* collapse the list */ X for (j=i; j<modem->t_entries-1; j++) { X free_ptr(modem->tty[j]); X free_ptr(modem->tname[j]); X modem->tty[j] = strdup(modem->tty[j+1]); X modem->tname[j] = strdup(modem->tname[j+1]); X modem->mbaud[j] = modem->mbaud[j+1]; X } X j = modem->t_entries-1; X /* zap the entry */ X free_ptr(modem->tty[j]); X free_ptr(modem->tname[j]); X modem->tty[j] = null_ptr; X modem->tname[j] = null_ptr; X modem->mbaud[j] = 0; X /* update the count */ X modem->t_entries--; X if (modem->t_cur >= modem->t_entries) X modem->t_cur = -1; X return; X} SHAR_EOF if test 4775 -ne "`wc -c < 's_tty.c'`" then echo shar: "error transmitting 's_tty.c'" '(should have been 4775 characters)' fi fi echo shar: "extracting 'screen.c'" '(1421 characters)' if test -f 'screen.c' then echo shar: "will not over-write existing file 'screen.c'" else sed 's/^X//' << \SHAR_EOF > 'screen.c' X/* X * Routines to read and copy the virtual screen image file. X */ X X#define MAX_COL 128 X X#include <stdio.h> X#include <curses.h> X#include "param.h" X#include "status.h" X X/* X * Do a screen dump. Actually, the screen is already dumped, all we X * do is copy the file. X */ X Xvoid Xscreen_dump() X{ X FILE *fp_in, *fp_out; X char buf[MAX_COL+2]; X void error_win(); X /* not guaranteed to exist yet */ X if (!(fp_in = fopen(status->vs_path, "r"))) X return; X /* open for append */ X if (!(fp_out = fopen(param->dumpfile, "a"))) { X fclose(fp_in); X sprintf(buf, "'%s' for write", param->dumpfile); X error_win(0, "Can't open screen dump file", buf); X return; X } X /* skip the x, y coordinates */ X fgets(buf, 10, fp_in); X X while (fgets(buf, MAX_COL+2, fp_in) != NULL) X fputs(buf, fp_out); X X fclose(fp_in); X fclose(fp_out); X X return; X} X X/* X * Read the virtual screen file and paint its contents to the X * stdscr with curses. Leave the cursor where it belongs. X */ X Xvoid Xload_vs() X{ X FILE *fp; X int row, col, i; X char buf[MAX_COL+2]; X /* not guaranteed to exist yet */ X if (!(fp = fopen(status->vs_path, "r"))) X return; X /* get the x, y coordinates */ X fgets(buf, 10, fp); X sscanf(buf, "%d,%d\n", &row, &col); X X clearok(stdscr, TRUE); X i = 0; X while (fgets(buf, MAX_COL+2, fp) != NULL) { X buf[COLS] = NULL; X mvaddstr(i++, 0, buf); X } X move(row, col); X refresh(); X clearok(stdscr, FALSE); X X fclose(fp); X return; X} SHAR_EOF if test 1421 -ne "`wc -c < 'screen.c'`" then echo shar: "error transmitting 'screen.c'" '(should have been 1421 characters)' fi fi echo shar: "extracting 'st_line.c'" '(1815 characters)' if test -f 'st_line.c' then echo shar: "will not over-write existing file 'st_line.c'" else sed 's/^X//' << \SHAR_EOF > 'st_line.c' X/* X * Display the status line. Up to now, we've never really cared how X * large the physical screen was... but now we want the status line X * on the bottom. X */ X X#include <curses.h> X#include "dial_dir.h" X#include "misc.h" X#include "modem.h" X#include "param.h" X#include "status.h" X Xvoid Xstatus_line(message) Xchar *message; X{ X WINDOW *sl_win, *newwin(); X int d, x, y; X static char *dn[2] = {"FDX", "HDX"}; X static char *ln[2] = {"LOG OFF", "LOG ON"}; X static char *pn[2] = {"PTR OFF", "PTR ON "}; X char buf[80], field_one[15], *cur_tty; X extern int xmc; X X /* X * Sometimes curses() doesn't remember where the cursor is on X * the screen, so we move it to the opposite corner to guarantee X * that the status line is on the bottom. X */ X getyx(stdscr, y, x); X move(0, COLS-1); X refresh(); X X sl_win = newwin(1, 80, LINES-1, 0); X /* duplex message */ X d = 0; X if (dir->duplex[dir->d_cur] == 'H') X d = 1; X /* the current tty */ X cur_tty = "No TTY"; X if (modem->t_cur != -1) X cur_tty = modem->tty[modem->t_cur]; X X /* X * The philosophy is: If you press a command sequence that X * doesn't generate a window on the screen, then show the user X * what's going on in the status line. X */ X if (message == NULL) X sprintf(field_one, " %4.4s-0 HELP ", param->ascii_hot); X else X sprintf(field_one, " %-13.13s", message); X X sprintf(buf, "%s | %-9.9s| %s | %5d %c%d%d | %-7.7s | %-7.7s | %-5.5s| %-5.5s", X field_one, cur_tty, dn[d], dir->baud[dir->d_cur], X dir->parity[dir->d_cur], dir->dbits[dir->d_cur], X dir->sbits[dir->d_cur], ln[status->log], pn[status->print], X param->cr_in, param->cr_out); X X if (xmc > 0) { X touchwin(sl_win); X werase(sl_win); X wrefresh(sl_win); X } X wattrstr(sl_win, A_STANDOUT, buf); X wrefresh(sl_win); X /* go ahead and delete it now */ X delwin(sl_win); X move(y, x); X return; X} SHAR_EOF if test 1815 -ne "`wc -c < 'st_line.c'`" then echo shar: "error transmitting 'st_line.c'" '(should have been 1815 characters)' fi fi echo shar: "extracting 'strings.c'" '(1349 characters)' if test -f 'strings.c' then echo shar: "will not over-write existing file 'strings.c'" else sed 's/^X//' << \SHAR_EOF > 'strings.c' X/* X * Miscellaneous string routines. X */ X X#include <stdio.h> X X/* X * Do a fancy string copy. If NULL, return null. If pointer to NULL, then X * return the special 'null_ptr' variable. If a normal copy, allocate the X * memory first. X */ X Xchar * Xstrdup(str) Xchar *str; X{ X char *ret, *malloc(), *strcpy(); X extern char *null_ptr; X X if (str == NULL) X return(NULL); X /* if pointer to null */ X if (*str == NULL) X return(null_ptr); X X ret = malloc((unsigned int) strlen(str)+1); X strcpy(ret, str); X return(ret); X} X X/* X * Perform the free(2) function, but check for NULL and the special X * 'null_ptr' variable first. X */ X Xvoid Xfree_ptr(str) Xchar *str; X{ X extern char *null_ptr; X void free(); X X if (str != NULL && (long) str != (long) null_ptr) X free(str); X return; X} X X/* X * This routine is similar to strtok(3). But our version handles null X * strings and takes a single separator character as an argument. X * Returns a NULL on end of string or error. X */ X Xchar * Xstr_tok(str, c) Xchar *str, c; X{ X char *strchr(); X static char *ptr, *sep; X extern char *null_ptr; X /* start at beginning */ X if (str != NULL) X ptr = str; X else X ptr = sep; X /* at the end ? */ X if (*ptr == NULL) X return(NULL); X /* no separator ? */ X if (!(sep = strchr(ptr, c))) X return(NULL); X /* zap the sep, move past it */ X *sep = NULL; X sep++; X X return(ptr); X} SHAR_EOF if test 1349 -ne "`wc -c < 'strings.c'`" then echo shar: "error transmitting 'strings.c'" '(should have been 1349 characters)' fi fi echo shar: "extracting 'terminal.c'" '(8039 characters)' if test -f 'terminal.c' then echo shar: "will not over-write existing file 'terminal.c'" else sed 's/^X//' << \SHAR_EOF > 'terminal.c' X/* X * Start the terminal dialogue, fork the input routine, watch for the X * hot key so we can execute an option. X */ X X#include <stdio.h> X#include <curses.h> X#include <signal.h> X#ifdef UNIXPC X#include <sys/phone.h> X#include <fcntl.h> X#endif /* UNIXPC */ X#include "dial_dir.h" X#include "modem.h" X#include "param.h" X#include "status.h" X Xterminal(input_status) Xint input_status; X{ X int i, k, cr_lf; X char c, lf=10, *strdup(), *new_dir, *change_dir(); X void help_screen(), line_set(), native_shell(), load_vs(); X void setup_menu(), hang_up(), input_on(), list_dir(), pexit(); X void status_line(), free_ptr(), screen_dump(), input_off(); X X /* if starting out in command mode */ X if (!input_status) X status_line(NULL); X /* put the terminal in raw mode */ X resetterm(); X cr_lf = raw_mode(); X X if (input_status) X input_on(); X X while(1) { X read(0, &c, 1); X /* is it the hot key? */ X if (c == param->hot) { X /* suspend input */ X input_status = 0; X if (status->pid != -1) X kill(status->pid, SIGINT); X X /* X * Put in terminal in the curses mode and add X * the status line at the bottom. X */ X fixterm(); X status_line(NULL); X#ifndef OLDCURSES X keypad(stdscr, 1); X#endif /* OLDCURSES */ X i = wgetch(stdscr); X /* map the hot key to -1 */ X if (i == param->hot) X i = -1; X /* X * Load the virtual screen from the file. On X * very busy systems, the file might not "appear" X * fast enough for this routine to detect it. X * Or worse, it may contain partially written X * information. X */ X load_vs(); X /* look for options */ X k = -1; X switch (i) { X case -1: /* 2 'hots' means send 1 */ X k = param->hot; X break; X case '0': /* help screen */ X help_screen(param->ascii_hot, status->fd); X break; X case 'd': X case 'D': /* dialing directory */ X if (dial_menu()) X input_status = dial_win(); X break; X case 'r': X case 'R': /* redial */ X if (redial(status->fd)) X input_status = dial_win(); X break; X case 'p': X case 'P': /* line settings */ X if (line_set_menu(status->fd)) { X line_set(); X } X break; X case 'x': X case 'X': /* exit */ X pexit(status->fd); X break; X case '4': /* Unix gateway */ X native_shell(); X break; X case 'i': X case 'I': /* Program info screen */ X info(status->fd); X break; X case 's': /* setup menu */ X case 'S': X setup_menu(status->fd); X break; X case 'c': /* clear the screen */ X case 'C': X unlink(status->vs_path); X clear(); X clear_absolute(stdscr); X break; X case 'b': X case 'B': /* Change directory */ X if ((new_dir = change_dir(status->fd)) != NULL) { X chdir(new_dir); X free_ptr(new_dir); X } X break; X case 'e': X case 'E': /* toggle duplex */ X if (dir->duplex[dir->d_cur] == 'F') X dir->duplex[dir->d_cur] = 'H'; X else X dir->duplex[dir->d_cur] = 'F'; X line_set(); X X /* show changes */ X status_line(NULL); X k = wait_key(stdscr, 2); X break; X case 'h': X case 'H': /* hang up phone */ X hang_up(1); X input_off(); X break; X case 'l': X case 'L': /* toggle printer */ X status->print = status->print ? 0 : 1; X if (status->pid != -1) X kill(status->pid, SIGUSR2); X X /* show changes */ X status_line(NULL); 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 = strdup("CR/LF"); X else X param->cr_in = strdup("CR"); X input_off(); X input_status = 1; X X /* show changes */ X status_line(NULL); X k = wait_key(stdscr, 2); X break; X case '7': /* break key */ X if (status->fd != -1) X ioctl(status->fd, TCSBRK, 0); X X status_line(" break"); X break; X#ifndef OLDCURSES X case KEY_UP: X#endif /* OLDCURSES */ X case 'u': X case 'U': /* send files */ X input_status = xfer_menu(1); X break; X#ifndef OLDCURSES X case KEY_DOWN: X case '\n': X#endif /* OLDCURSES */ X case 'n': X case 'N': /* receive files */ X input_status = xfer_menu(0); X break; X case 'f': X case 'F': /* list directory */ X list_dir(status->fd); X break; X case 'g': /* screen dump */ X case 'G': X screen_dump(); X status_line(" screen dump"); X k = wait_key(stdscr, 2); X break; X case '1': /* data logging */ X input_status = data_logging(status->fd); X break; X case '2': /* toggle log */ X if (!strcmp(status->log_path, "NOT_DEFINED")) { X beep(); X status_line(" no log file"); X k = wait_key(stdscr, 2); X break; X } X status->log = status->log ? 0 : 1; X if (status->pid != -1) X kill(status->pid, SIGUSR1); X X /* show changes */ X status_line(NULL); X k = wait_key(stdscr, 2); X break; X default: X fputc(7, stderr); X break; X } X X /* X * Repaint the stdscr (if we are already talking), X * get the terminal out of the curses mode and X * into the raw mode. X */ X if (status->fd != -1) { X touchwin(stdscr); X refresh(); X } X resetterm(); X cr_lf = raw_mode(); X /* re-start input routine */ X if (input_status) X input_on(); X else { X /* un-suspend (is that a word?) */ X if (status->pid != -1) X kill(status->pid, SIGINT); 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 continue; X c = k; X } X write(status->fd, &c, 1); X /* map cr to cr_lf ? */ X if (cr_lf) X write(status->fd, &lf, 1); X } X} X X/* X * Put the terminal in the raw mode. We've divided up the responsibility X * for the line settings options between the serial port and the tty driver X * for the stdin and stdout. The return code is the cr_lf mapping. X */ X Xint Xraw_mode() X{ X int ret_code; X struct termio tbuf; X X ioctl(0, TCGETA, &tbuf); X X tbuf.c_cc[4] = 1; /* VMIN */ X tbuf.c_cc[5] = 0; /* VTIME */ X tbuf.c_iflag = 0; X tbuf.c_oflag = 0; X tbuf.c_lflag = 0; X X /* X * Some of the output processing options have to be faked... X * Unfortunately, adding a LF to CR is one of them. X */ X ret_code = 0; X if (!strcmp(param->cr_out, "CR/LF")) X ret_code++; X /* duplex */ X if (dir->duplex[dir->d_cur] == 'H') X tbuf.c_lflag = ECHO; X X ioctl(0, TCSETA, &tbuf); X ioctl(0, TCFLSH, 2); X return(ret_code); X} X X/* X * Fire up the input routine... X */ X Xvoid Xinput_on() X{ X int pid, add_lf; X /* if no tty, or already on */ X if (status->pid != -1 || status->fd == -1) X return; X /* input cr translations */ X add_lf = !strcmp(param->cr_in, "CR/LF"); X X /* fork the input routine */ X if (!(pid = fork())) X input(status->fd, add_lf, status->log, status->print, X LINES, COLS, status->vs_path, status->log_path); X X status->pid = pid; X return; X} X X/* X * shut it down... X */ X Xvoid Xinput_off() X{ X if (status->pid != -1) { X kill(status->pid, SIGTERM); X status->pid = -1; X } X return; X} X X/* X * Hang up the phone but remain in the pcomm command state. X */ X Xvoid Xhang_up(verbose) Xint verbose; X{ X void send_str(), status_line(); X#ifdef UNIXPC X char buf[20], *strcpy(), *strcat(); X#endif /* UNIXPC */ X X /* anything to hang up? */ X if (modem->m_cur == -1) X return; X X if (verbose) X status_line("disconnecting"); X /* special case for OBM */ X#ifdef UNIXPC X if (!strcmp(modem->mname[modem->m_cur], "OBM")) { X ioctl(status->fd, PIOCDISC); X /* X * The PIOCDISC ioctl prevents writes on the file descriptor! X * No other phone(7) ioctl can fix it... Whatever it does, it X * seems to escape detection with PIOCGETA and TCGETA. The X * best I can do is close the descriptor and start over. X */ X close(status->fd); X strcpy(buf, "/dev/"); X strcat(buf, modem->tty[modem->t_cur]); X status->fd = open(buf, O_RDWR|O_NDELAY); X fcntl(status->fd, F_SETFL, fcntl(status->fd, F_GETFL, 0) & ~O_NDELAY); X } X else X#endif /* UNIXPC */ X send_str(modem->hangup[modem->m_cur]); X X if (verbose) X status_line(NULL); X return; X} SHAR_EOF if test 8039 -ne "`wc -c < 'terminal.c'`" then echo shar: "error transmitting 'terminal.c'" '(should have been 8039 characters)' fi fi echo shar: "extracting 'x_ascii.c'" '(5950 characters)' if test -f 'x_ascii.c' then echo shar: "will not over-write existing file 'x_ascii.c'" else sed 's/^X//' << \SHAR_EOF > 'x_ascii.c' X/* X * Transfer a file using just XON/XOFF flow control. Currently limited to X * 7 bit ASCII codes. (If this causes too much trouble, I'll change it). X */ X X#include <stdio.h> X#include <fcntl.h> X#include <curses.h> X#include <signal.h> X#include "param.h" X#include "status.h" X Xvoid Xxfer_ascii(list, up) Xchar *list; Xint up; X{ X int cr_lf; X char *file, *strtok(); X void send_ascii(), rcv_ascii(), line_set(), status_line(); X unsigned int sleep(); X X /* only one file from list */ X file = strtok(list, " "); X X cr_lf = ascii_mode(up); X if (up) { X /* un-suspend the input routine */ X if (status->pid != -1) X kill(status->pid, SIGINT); X X send_ascii(file, cr_lf); X /* re-suspend the input routine */ X if (status->pid != -1) X kill(status->pid, SIGINT); X } X else X rcv_ascii(file, cr_lf); X X /* X * Restoring the tty modes is easier than setting them... The X * fixterm() and line_set() routines fix most of the damage. X */ X fcntl(0, F_SETFL, fcntl(0, F_GETFL, 0) & ~O_NDELAY); X fixterm(); X line_set(); X sleep(1); X X status_line("xfer complete"); X sleep(2); X return; X} X X/* X * Put the tty line in a mode suitable for the ASCII transfer. Puts the X * terminal in the raw, non-blocking mode. Returns the status of the X * cr_lf parameter flag. X */ X Xint Xascii_mode(up) Xint up; X{ X int cr_lf; X struct termio tbuf; X void input_off(); X X ioctl(status->fd, TCGETA, &tbuf); X tbuf.c_oflag = 0; X /* flow control & 8th bit stripping */ X if (up) { X tbuf.c_iflag = (ISTRIP|IXON|IXANY); X X /* use NL delays if no CR */ X if (!strcmp(param->cr_up, "STRIP")) X tbuf.c_oflag = (OPOST|ONLRET); X X /* CR delay times */ X switch (param->cr_delay) { X case 0: X tbuf.c_oflag = 0; X break; X case 100: X tbuf.c_oflag |= (OPOST|CR2); X break; X case 150: X tbuf.c_oflag |= (OPOST|CR3); X break; X } X } X /* if down loading */ X else { X tbuf.c_iflag = (ISTRIP|IXOFF); X /* kill the input routine */ X input_off(); X } X X ioctl(status->fd, TCSETA, &tbuf); X ioctl(status->fd, TCFLSH, 2); X /* out of curses mode */ X resetterm(); X cr_lf = raw_mode(); X /* non-blocking mode */ X fcntl(0, F_SETFL, fcntl(0, F_GETFL, 0) | O_NDELAY); X return(cr_lf); X} X X/* X * Send a file. The local echo option is independent of the duplex option, X * and would very rarely be used since the characters are most likely X * being echoed on the screen anyway. X */ X Xvoid Xsend_ascii(file, cr_lf) Xchar *file; Xint cr_lf; X{ X FILE *fp; X int i, j, strip_cr, strip_lf, add_cr, add_lf, expand, last; X int lecho, pace; X unsigned int sleep(); X unsigned char c; X /* permission already checked */ X if (!(fp = fopen(file, "r"))) X return; X /* ASCII transfer options */ X strip_cr = !strcmp(param->cr_up, "STRIP"); X add_lf = !strcmp(param->cr_up, "ADD LF"); X strip_lf = !strcmp(param->lf_up, "STRIP"); X add_cr = !strcmp(param->lf_up, "ADD CR"); X expand = !strcmp(param->expand, "YES"); X lecho = !strcmp(param->lecho, "YES"); X pace = !strcmp(param->pace, "YES"); X X last = 0; X while ((i = fgetc(fp)) != EOF) { X /* any keyboard activity? */ X switch(j = getchar()) { X case -1: /* no key was pressed */ X break; X case 27: /* ESC key for abort */ X fclose(fp); X ioctl(status->fd, TCFLSH, 2); X return; X default: /* send the char */ X c = j; X putc_line(c); X if (c == 13 && cr_lf) X putc_line(10); X break; X } X c = i; X /* expand blank lines */ X if (expand && last == 10 && c == 10) X putc_line(' '); X last = c; X X /* CR translations */ X if (c == 13 && strip_cr) X continue; X if (c == 13 && add_lf) { X putc_line(c); X putc_line(10); X continue; X } X /* LF translations */ X if (c == 10 && strip_lf) X continue; X if (c == 10 && add_cr) { X putc_line(13); X putc_line(c); X continue; X } X putc_line(c); X /* X * There's really no mechanism for delaying characters X * going to the output, so we fake it by waiting for X * each character to clear the I/O buffer. X */ X if (pace) X ioctl(status->fd, TCSBRK, 1); X if (lecho) X write(1, (char *) &c, 1); X } X sleep(1); X ioctl(status->fd, TCSBRK, 1); X fclose(fp); X return; X} X X/* X * Receive a file. The timer is used to end the transfer. This is not X * that much different from the data logging option. The use of getc_line() X * and non-blocking input makes it seem like full duplex, but it's not. X * Beware that while the timer is active the keyboard is deaf. Input is X * NOT loaded into the virtual screen!! X */ X Xvoid Xrcv_ascii(file, cr_lf) Xchar *file; Xint cr_lf; X{ X FILE *fp; X int i, strip_cr, strip_lf, add_cr, add_lf, got_first; X unsigned int delay; X unsigned char c; X /* permission already checked */ X if (!(fp = fopen(file, "w"))) X return; X /* ASCII transfer options */ X strip_cr = !strcmp(param->cr_dn, "STRIP"); X add_lf = !strcmp(param->cr_dn, "ADD LF"); X strip_lf = !strcmp(param->lf_dn, "STRIP"); X add_cr = !strcmp(param->lf_dn, "ADD CR"); X X got_first = 0; X delay = 1; X while (1) { X /* keyboard activity */ X switch (i = getchar()) { X case -1: /* no key was pressed */ X break; X case 27: /* ESC key */ X fclose(fp); X return; X default: /* send it */ X c = i; X putc_line(c); X if (c == 13 && cr_lf) X putc_line(10); X break; X } X /* read a character */ X if ((i = getc_line(delay)) == -1) { X /* X * The transfer timeout is not activated until the X * first character is received. Until then, it polls X * the line for one second and loops backs for X * keyboard input. X */ X if (got_first) { X fclose(fp); X return; X } X continue; X } X got_first = 1; X delay = param->timer; X c = i & 0177; X /* display it on the screen */ X write(1, (char *) &c, 1); X /* CR translations */ X if (c == 13 && strip_cr) X continue; X if (c == 13 && add_lf) { X fputc((char) c, fp); X fputc(10, fp); X continue; X } X /* LF translations */ X if (c == 10 && strip_lf) X continue; X if (c == 10 && add_cr) { X fputc(13, fp); X fputc((char) c, fp); X continue; X } X fputc((char) c, fp); X } X} SHAR_EOF if test 5950 -ne "`wc -c < 'x_ascii.c'`" then echo shar: "error transmitting 'x_ascii.c'" '(should have been 5950 characters)' fi fi exit 0 # End of shell archive
egray@fthood.UUCP (03/14/88)
This is part 4 (of 6) to the Pcomm version 1.0 distribution. Emmet P. Gray US Army, HQ III Corps & Fort Hood ...!ihnp4!uiucuxc!fthood!egray Attn: AFZF-DE-ENV Directorate of Engineering & Housing Environmental Management Office Fort Hood, TX 76544-5057 ------------------------------------------------------------------------------- #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # input.c # line_set.c # list_dir.c # ls_menu.c # m_lib.c # main.c # n_shell.c # p_lib.c # pexit.c # port.c # redial.c # This archive created: Fri Mar 11 07:35:16 1988 export PATH; PATH=/bin:/usr/bin:$PATH echo shar: "extracting 'input.c'" '(6599 characters)' if test -f 'input.c' then echo shar: "will not over-write existing file 'input.c'" else sed 's/^X//' << \SHAR_EOF > 'input.c' X/* X * The input routines. These routines are run as a child process to the X * main pcomm program. X */ X X#define LPR "/usr/bin/lpr" X X#define MAX_ROW 64 X#define MAX_COL 128 X X#include <stdio.h> X#include <signal.h> X#include <setjmp.h> X Xjmp_buf i_jmp; Xunsigned char vs[MAX_ROW][MAX_COL+2]; Xint row, col; X X/* X * Read the serial port and write the characters to the screen. Watch X * for signals from the parent process to toggle the fancy options. X * Writes the characters received to a virtual screen buffer. X */ Xint Xinput(fd, add_lf, log, print, max_row, max_col, vs_file, log_file) Xint fd, add_lf, log, print, max_row, max_col; Xchar *vs_file, *log_file; X{ X FILE *logfp, *lprfp, *popen(); X int hold, skip_row, got_sig(); X unsigned char c; X char lf=10; X void _exit(); X /* set the trap for the signals */ X signal(SIGALRM, SIG_IGN); X signal(SIGUSR1, got_sig); X signal(SIGUSR2, got_sig); X signal(SIGINT, got_sig); X signal(SIGTERM, got_sig); X /* resonable limits */ X if (max_row > MAX_ROW) X max_row = MAX_ROW; X if (max_col > MAX_COL) X max_col = MAX_COL; X /* read previous screen */ X if (!access(vs_file, 0)) { X read_vs(vs_file, max_row, max_col); X skip_row = 0; X } X else X skip_row = 1; X X hold = 0; X /* startup file pointers */ X if (print) X lprfp = popen(LPR, "w"); X X if (log && strcmp(log_file, "NOT_DEFINED")) X logfp = fopen(log_file, "a"); X X switch(setjmp(i_jmp)) { X case 0: /* no signal */ X break; X case 1: /* toggle the data logging */ X signal(SIGUSR1, got_sig); X if (!strcmp(log_file, "NOT_DEFINED")) { X log = 0; X break; X } X log = log ? 0 : 1; X if (log) X logfp = fopen(log_file, "a"); X else X fclose(logfp); X break; X case 2: /* toggle the printer */ X signal(SIGUSR2, got_sig); X print = print ? 0 : 1; X if (print) X lprfp = popen(LPR, "w"); X else { X putc(014, lprfp); X pclose(lprfp); X } X break; X case 3: /* suspend the input */ X signal(SIGINT, got_sig); X hold = hold ? 0 : 1; X if (hold) X write_vs(vs_file, max_row, max_col); X break; X case 4: /* cleanup and go home */ X signal(SIGTERM, got_sig); X if (log) X fclose(logfp); X if (print) { X putc(014, lprfp); X pclose(lprfp); X } X _exit(0); X break; X } X /* any signal will awaken pause() */ X if (hold) X pause(); X /* clear if vs_path doesn't exist */ X if (access(vs_file, 0)) X clear_vs(max_row, max_col); X /* X * The very first screen we see after dialing has the "Connected to..." X * message at row 0, therefore we start our virtual screen at row 1. X */ X if (skip_row) { X skip_row = 0; X row = 1; X } X X while(1) { X if (read(fd, (char *) &c, 1) <= 0) X continue; X /* send to logfile */ X if (log) { X if (c == 015 && add_lf) X fwrite(&lf, 1, 1, logfp); X /* no carriage returns in logfile */ X if (c != 015) X fwrite((char *) &c, 1, 1, logfp); X } X /* send to printer too ? */ X if (print) X fwrite((char *) &c, 1, 1, lprfp); X X /* put a char in virtual screen */ X putchar_vs(c, add_lf, max_row, max_col); X X write(1, (char *) &c, 1); X /* add LF to CR ? */ X if (add_lf) X write(1, &lf, 1); X } X} X X/* X * Figure out which signal we just received, and fix the return code of X * the setjmp function above to the proper value. X */ X Xint Xgot_sig(sig) Xint sig; X{ X void longjmp(); X X switch(sig) { X case SIGUSR1: X longjmp(i_jmp, 1); X case SIGUSR2: X longjmp(i_jmp, 2); X case SIGINT: X longjmp(i_jmp, 3); X case SIGTERM: X longjmp(i_jmp, 4); X } X} X X/* X * Put a character in the virtual screen. This routine saves incoming X * character in a two dimensional buffer designed to mimic the real X * screen. CURRENTLY DOES NOT UNDERSTAND ESCAPE SEQUENCES! X */ X Xint Xputchar_vs(c, add_lf, max_row, max_col) Xunsigned char c; Xint add_lf, max_row, max_col; X{ X int tab_stop; X X switch(c) { X case 8: /* destructive back space */ X col--; X if (col < 0) X col = 0; X vs[row][col] = ' '; X break; X case 9: /* tab character */ X tab_stop = col + 8 - (col % 8); X /* if wrap around */ X if (tab_stop >= max_col) { X /* spaces up to eol */ X for (; col<max_col; col++) X vs[row][col] = ' '; X row++; X if (row >= max_row) X scroll_vs(max_row, max_col); X X /* the remainder of the tab */ X col = tab_stop - max_col; X } X else { X for (; col<tab_stop; col++) X vs[row][col] = ' '; X } X break; X case 13: /* carriage return */ X col = 0; X if (!add_lf) X break; X /* fall thru...*/ X case 10: /* line feed */ X row++; X if (row >= max_row) X scroll_vs(max_row, max_col); X break; X default: /* a normal character */ X vs[row][col] = c; X col++; X /* wrap around */ X if (col >= max_col) { X col = 0; X row++; X if (row >= max_row) X scroll_vs(max_row, max_col); X } X break; X } X return; X} X X/* X * Save the virtual screen to a file. X */ X Xint Xwrite_vs(vs_file, max_row, max_col) Xchar *vs_file; Xint max_row, max_col; X{ X FILE *fp; X int i; X X if (!(fp = fopen(vs_file, "w"))) X return(1); X /* current x y coordinates */ X fprintf(fp, "%d,%d\n", row, col); X X for (i=0; i<max_row; i++) { X vs[i][max_col] = NULL; X fprintf(fp, "%s\n", vs[i]); X } X fclose(fp); X return(0); X} X X/* X * Get the virtual screen image from the file. Since input() gets X * killed from time to time, the vs_path file is the only way to retain X * the screen image. X */ X Xint Xread_vs(vs_file, max_row, max_col) Xchar *vs_file; Xint max_row, max_col; X{ X FILE *fp; X int i; X char buf[10]; X /* in case the fopen fails... */ X row = 0; X col = 0; X /* not guaranteed to exist yet */ X if (!(fp = fopen(vs_file, "r"))) X return(1); X /* get the x, y coordinates */ X fgets(buf, 10, fp); X scanf(buf, "%d,%d\n", &row, &col); X X /* read the file into the vs array */ X for (i=0; i<max_row; i++) { X fgets((char *) vs[i], MAX_COL+2, fp); X vs[i][max_col] = NULL; X } X X fclose(fp); X return(0); X} X X/* X * If the user clears the screen with the ^A-C command, the input X * has to be in sync. The way it gets notified, is that the vs_path X * file disappears. X */ X Xint Xclear_vs(max_row, max_col) Xint max_row, max_col; X{ X int i, j; X X for (i=0; i<max_row; i++) { X vs[i][max_col] = NULL; X for (j=0; j<max_col; j++) X vs[i][j] = ' '; X } X /* home the "cursor" */ X row = 0; X col = 0; X return(0); X} X X/* X * Do a software scroll on the virtual screen. Does not alter the X * 'col' variable. X */ X Xint Xscroll_vs(max_row, max_col) Xint max_row, max_col; X{ X int i, j; X char *strcpy(); X /* move 'em up 1 line */ X for (i=0; i<max_row-1; i++) X strcpy((char *) vs[i], (char *) vs[i+1]); X /* clear the bottom line */ X for (j=0; j<max_col; j++) X vs[max_row-1][j] = ' '; X X row = max_row -1; X return(0); X} SHAR_EOF if test 6599 -ne "`wc -c < 'input.c'`" then echo shar: "error transmitting 'input.c'" '(should have been 6599 characters)' fi fi echo shar: "extracting 'line_set.c'" '(2130 characters)' if test -f 'line_set.c' then echo shar: "will not over-write existing file 'line_set.c'" else sed 's/^X//' << \SHAR_EOF > 'line_set.c' X/* X * Change the communication line settings to the new values. X */ X X#include <stdio.h> X#include <termio.h> X#include "dial_dir.h" X#include "param.h" X#include "status.h" X Xvoid Xline_set() X{ X struct termio tbuf; X X /* X * The manual dial entry also serves to store the previous X * line settings. How else would the manual dial entry X * know what line setting to use? X */ X if (dir->d_cur != 0) { X dir->baud[0] = dir->baud[dir->d_cur]; X dir->parity[0] = dir->parity[dir->d_cur]; X dir->dbits[0] = dir->dbits[dir->d_cur]; X dir->sbits[0] = dir->sbits[dir->d_cur]; X } X /* nothing to do! */ X if (status->fd == -1) X return; X /* get the current settings */ X ioctl(status->fd, TCGETA, &tbuf); X /* set some beginning values */ X tbuf.c_cc[4] = 1; X tbuf.c_cc[5] = 0; X tbuf.c_oflag = 0; X tbuf.c_iflag = 0; X tbuf.c_cflag = (CREAD|HUPCL); X tbuf.c_lflag = 0; X X /* X * I don't think there's any need for output flow control... (I don't X * know about you guys, but I can't type faster than the host can X * receive!) Besides, the file transfers reset this anyway. X */ X if (*param->flow == 'X') X tbuf.c_iflag |= IXOFF; X /* strip high bit ? */ X if (*param->strip == 'Y') X tbuf.c_iflag |= ISTRIP; X /* the baud rate */ X switch (dir->baud[dir->d_cur]) { X case 300: X tbuf.c_cflag |= B300; X break; X case 1200: X tbuf.c_cflag |= B1200; X break; X case 2400: X tbuf.c_cflag |= B2400; X break; X case 4800: X tbuf.c_cflag |= B4800; X break; X case 9600: X tbuf.c_cflag |= B9600; X break; X case 19200: X /* X * Be careful here... some systems use EXTA in lieu X * of B19200. X */ X tbuf.c_cflag |= B19200; X break; X } X /* the parity */ X switch (dir->parity[dir->d_cur]) { X case 'N': X break; X case 'O': X tbuf.c_cflag |= (PARENB|PARODD); X break; X case 'E': X tbuf.c_cflag |= PARENB; X break; X } X /* the data bits */ X if (dir->dbits[dir->d_cur] == 8) X tbuf.c_cflag |= CS8; X else X tbuf.c_cflag |= CS7; X /* the stop bits */ X if (dir->sbits[dir->d_cur] == 2) X tbuf.c_cflag |= CSTOPB; X X /* now set 'em! */ X ioctl(status->fd, TCSETA, &tbuf); X ioctl(status->fd, TCFLSH, 2); X return; X} SHAR_EOF if test 2130 -ne "`wc -c < 'line_set.c'`" then echo shar: "error transmitting 'line_set.c'" '(should have been 2130 characters)' fi fi echo shar: "extracting 'list_dir.c'" '(1479 characters)' if test -f 'list_dir.c' then echo shar: "will not over-write existing file 'list_dir.c'" else sed 's/^X//' << \SHAR_EOF > 'list_dir.c' X/* X * Do a shell escape with an 'ls' command X */ X X#include <stdio.h> X#include <curses.h> X#include "misc.h" X Xvoid Xlist_dir(fd) Xint fd; X{ X WINDOW *ls_win, *newwin(); X FILE *pfp, *native_popen(); X int lines, oops; X char *ans, *cwd, *getcwd(), buf[200], *get_str(); X X ls_win = newwin(6, 70, 8, 5); X X cwd = getcwd(buf, 200); X X mvwprintw(ls_win, 2, 4, "Current directory: %s", cwd); X mvwaddstr(ls_win, 3, 4, "File spec (wildcards allowed): "); X box(ls_win, '|', '-'); X X mvwattrstr(ls_win, 0, 3, A_BOLD, " List Directory "); X wmove(ls_win, 3, 35); X wrefresh(ls_win); X X if ((ans = get_str(ls_win, 60, NULL, NULL)) == NULL) { X if (fd == -1) { X werase(ls_win); X wrefresh(ls_win); X } X delwin(ls_win); X return; X } X /* popen() an ls */ X sprintf(buf, "ls -aC %s", ans); X pfp = native_popen(buf, "r"); X /* make a bigger window */ X werase(ls_win); X wrefresh(ls_win); X delwin(ls_win); X ls_win = newwin(LINES-1, COLS, 0, 0); X X oops = 0; X lines = 0; X while (fgets(buf, BUFSIZ, pfp) != NULL) { X waddstr(ls_win, buf); X lines++; X if (lines == LINES-2) { X lines = 0; X mvwaddstr(ls_win, LINES-2, 28, "Press any key for more"); X wrefresh(ls_win); X if (wgetch(ls_win) == 27) { X oops++; X break; X } X werase(ls_win); X wrefresh(ls_win); X } X } X native_pclose(pfp); X X if (!oops) { X mvwaddstr(ls_win, LINES-2, 25, "Press any key to continue"); X wrefresh(ls_win); X wgetch(ls_win); X } X if (fd == -1) { X werase(ls_win); X wrefresh(ls_win); X } X delwin(ls_win); X return; X} SHAR_EOF if test 1479 -ne "`wc -c < 'list_dir.c'`" then echo shar: "error transmitting 'list_dir.c'" '(should have been 1479 characters)' fi fi echo shar: "extracting 'ls_menu.c'" '(4820 characters)' if test -f 'ls_menu.c' then echo shar: "will not over-write existing file 'ls_menu.c'" else sed 's/^X//' << \SHAR_EOF > 'ls_menu.c' X/* X * Routines for displaying current line settings and prompting for changes. X */ X X#include <stdio.h> X#include <curses.h> X#include "dial_dir.h" X#include "misc.h" X#include "param.h" X X/* X * Display the current line settings and prompt for changes. A return X * code of 1 means settings were changed. X */ X Xint Xline_set_menu(fd) Xint fd; X{ X WINDOW *l_win, *newwin(); X int num, ret_code; X void disp_settings(); X X l_win = newwin(20, 47, 0, 16); X X mvwattrstr(l_win, 1, 16, A_BOLD, "Line Settings"); X waddstr(l_win, "\n----------------------------------------------"); X mvwaddstr(l_win, 6, 5, "1) 300,E,7,1 7) 300,N,8,1"); X mvwaddstr(l_win, 7, 5, "2) 1200,E,7,1 8) 1200,N,8,1"); X mvwaddstr(l_win, 8, 5, "3) 2400,E,7,1 9) 2400,N,8,1"); X mvwaddstr(l_win, 9, 5, "4) 4800,E,7,1 10) 4800,N,8,1"); X mvwaddstr(l_win, 10, 5, "5) 9600,E,7,1 11) 9600,N,8,1"); X mvwaddstr(l_win, 11, 5, "6) 19200,E,7,1 12) 19200,N,8,1"); X mvwaddstr(l_win, 13, 4, "Parity Data Bits Stop Bits"); X mvwaddstr(l_win, 14, 4, "13) Odd 14) 7 bits 16) 1 bit"); X mvwaddstr(l_win, 15, 18, "15) 8 bits 17) 2 bits"); X mvwaddstr(l_win, 17, 4, "18) Save Changes"); X mvwattrstr(l_win, 17, 28, A_BOLD, "YOUR CHOICE:"); X wmove(l_win, 17, 41); X box(l_win, '|', '-'); X X mvwaddstr(l_win, 19, 14, " Press ESC to return "); X /* display current settings */ X disp_settings(l_win); X wmove(l_win, 17, 41); X wrefresh(l_win); X /* get the options */ X ret_code = 0; X while ((num = get_num(l_win, 2)) != -1) { X switch(num) { X case 1: X dir->baud[dir->d_cur] = 300; X dir->parity[dir->d_cur] = 'E'; X dir->dbits[dir->d_cur] = 7; X dir->sbits[dir->d_cur] = 1; X break; X case 2: X dir->baud[dir->d_cur] = 1200; X dir->parity[dir->d_cur] = 'E'; X dir->dbits[dir->d_cur] = 7; X dir->sbits[dir->d_cur] = 1; X break; X case 3: X dir->baud[dir->d_cur] = 2400; X dir->parity[dir->d_cur] = 'E'; X dir->dbits[dir->d_cur] = 7; X dir->sbits[dir->d_cur] = 1; X break; X case 4: X dir->baud[dir->d_cur] = 4800; X dir->parity[dir->d_cur] = 'E'; X dir->dbits[dir->d_cur] = 7; X dir->sbits[dir->d_cur] = 1; X break; X case 5: X dir->baud[dir->d_cur] = 9600; X dir->parity[dir->d_cur] = 'E'; X dir->dbits[dir->d_cur] = 7; X dir->sbits[dir->d_cur] = 1; X break; X case 6: X dir->baud[dir->d_cur] = 19200; X dir->parity[dir->d_cur] = 'E'; X dir->dbits[dir->d_cur] = 7; X dir->sbits[dir->d_cur] = 1; X break; X case 7: X dir->baud[dir->d_cur] = 300; X dir->parity[dir->d_cur] = 'N'; X dir->dbits[dir->d_cur] = 8; X dir->sbits[dir->d_cur] = 1; X break; X case 8: X dir->baud[dir->d_cur] = 1200; X dir->parity[dir->d_cur] = 'N'; X dir->dbits[dir->d_cur] = 8; X dir->sbits[dir->d_cur] = 1; X break; X case 9: X dir->baud[dir->d_cur] = 2400; X dir->parity[dir->d_cur] = 'N'; X dir->dbits[dir->d_cur] = 8; X dir->sbits[dir->d_cur] = 1; X break; X case 10: X dir->baud[dir->d_cur] = 4800; X dir->parity[dir->d_cur] = 'N'; X dir->dbits[dir->d_cur] = 8; X dir->sbits[dir->d_cur] = 1; X break; X case 11: X dir->baud[dir->d_cur] = 9600; X dir->parity[dir->d_cur] = 'N'; X dir->dbits[dir->d_cur] = 8; X dir->sbits[dir->d_cur] = 1; X break; X case 12: X dir->baud[dir->d_cur] = 19200; X dir->parity[dir->d_cur] = 'N'; X dir->dbits[dir->d_cur] = 8; X dir->sbits[dir->d_cur] = 1; X break; X case 13: X dir->parity[dir->d_cur] = 'O'; X break; X case 14: X dir->dbits[dir->d_cur] = 7; X break; X case 15: X dir->dbits[dir->d_cur] = 8; X break; X case 16: X dir->sbits[dir->d_cur] = 1; X break; X case 17: X dir->sbits[dir->d_cur] = 2; X break; X case 18: X /* copy the current settings */ X param->d_baud = dir->baud[dir->d_cur]; X param->d_parity = dir->parity[dir->d_cur]; X param->d_dbits = dir->dbits[dir->d_cur]; X param->d_sbits = dir->sbits[dir->d_cur]; X /* X * We've changed the values in memory even X * if the update fails. X */ X if (update_param()) { X touchwin(l_win); X wrefresh(l_win); X } X break; X default: X beep(); X } X ret_code++; X disp_settings(l_win); X mvwaddstr(l_win, 17, 41, " "); X wmove(l_win, 17, 41); X wrefresh(l_win); X } X if (fd == -1) { X werase(l_win); X wrefresh(l_win); X } X delwin(l_win); X return(ret_code); X} X X/* X * Display the current settings. Formats the entire string at one X * time, in case you've got a magic cookie terminal. X */ X Xvoid Xdisp_settings(win) XWINDOW *win; X{ X char buf[40]; X extern int xmc; X X sprintf(buf, "Current Settings: %5d,%c,%d,%d", dir->baud[dir->d_cur], X dir->parity[dir->d_cur], dir->dbits[dir->d_cur], X dir->sbits[dir->d_cur]); X X if (xmc > 0) { X touchwin(win); X clear_line(win, 4, 8, 1); X wrefresh(win); X } X mvwattrstr(win, 4, 8, A_BOLD, buf); X return; X} SHAR_EOF if test 4820 -ne "`wc -c < 'ls_menu.c'`" then echo shar: "error transmitting 'ls_menu.c'" '(should have been 4820 characters)' fi fi echo shar: "extracting 'm_lib.c'" '(9489 characters)' if test -f 'm_lib.c' then echo shar: "will not over-write existing file 'm_lib.c'" else sed 's/^X//' << \SHAR_EOF > 'm_lib.c' X/* X * Routines to manipulate the pcomm.modem file X */ X X#include <stdio.h> X#include "modem.h" X#include "status.h" X X/* X * Read the modem database file. Returns a pointer to a static area X * containing the MODEM structure. All modem entries and all tty entries X * are created reguardless of the number of physical entries in the file. X */ X Xstruct MODEM * Xread_modem() X{ X FILE *fp; X int i, tty, mod, line, oops, m_line, start, stop; X char *strdup(), buf[200], message[80], token[40], *str_tok(), *str; X char *temp_token, *t_sep, *m_sep, *m_letter; X static struct MODEM m; X void error_win(); X extern char *null_ptr; X X if (!(fp = fopen(status->m_path, "r"))) { X sprintf(buf, "'%s' for read", status->m_path); X error_win(1, "Can't open modem file", buf); X } X X t_sep = ";;\n"; X m_sep = ";;;;\n;;;;;\n;;;\n"; X m_letter = "abc"; X oops = 0; X tty = 0; X mod = 0; X line = 0; X m_line = 0; X while (fgets(buf, 200, fp) != NULL) { X line++; X if (tty >= NUM_TTY || mod >= NUM_MODEM) X break; X /* get the token */ X if (!(temp_token = str_tok(buf, '='))) { X sprintf(message, "is missing a token at line %d", line); X oops++; X break; X } X if (*temp_token != 'T' && *temp_token != 'M') { X sprintf(message, "is corrupted at line %d", line); X oops++; X break; X } X /* the tty database */ X if (*temp_token == 'T') { X /* X * This is similar to the "real" strtok() command X * but this one returns a null pointer on a missing X * attribute. Note the use of the field separator X * array. X */ X for (i=0; i<3; i++) { X if (!(str = str_tok((char *) NULL, t_sep[i]))) { X sprintf(message, "is missing a parameter at line %d", line); X oops++; X break; X } X switch(i) { X case 0: X m.tty[tty] = strdup(str); X break; X case 1: X m.tname[tty] = strdup(str); X break; X case 2: X m.mbaud[tty] = atoi(str); X break; X } X } X if (oops) X break; X /* sanity checking */ X sprintf(token, "TTY_%d", tty+1); X if (strcmp(token, temp_token)) { X sprintf(message, "is corrupted at line %d", line); X oops++; X break; X } X tty++; X continue; X } X /* the modem database */ X else { X sprintf(token, "MODEM_%d%c", mod+1, m_letter[m_line]); X if (strcmp(token, temp_token)) { X sprintf(message, "is corrupted at line %d", line); X oops++; X break; X } X /* X * There are three lines to the modem database. They X * distinguished by the letters a, b, and, c appended X * to the entry number. X */ X switch(m_line) { X case 0: X start = 0; X stop = 5; X break; X case 1: X start = 5; X stop = 11; X break; X case 2: X start = 11; X stop = 15; X break; X } X for (i=start; i<stop; i++) { X if (!(str = str_tok((char *) NULL, m_sep[i]))) { X sprintf(message, "is missing a parameter at line %d", line); X oops++; X break; X } X switch(i) { X case 0: X m.mname[mod] = strdup(str); X break; X case 1: X m.init[mod] = strdup(str); X break; X case 2: X m.dial[mod] = strdup(str); X break; X case 3: X m.suffix[mod] = strdup(str); X break; X case 4: X m.hangup[mod] = strdup(str); X break; X case 5: X m.con_3[mod] = strdup(str); X break; X case 6: X m.con_12[mod] = strdup(str); X break; X case 7: X m.con_24[mod] = strdup(str); X break; X case 8: X m.con_48[mod] = strdup(str); X break; X case 9: X m.con_96[mod] = strdup(str); X break; X case 10: X m.con_192[mod] = strdup(str); X break; X case 11: X m.no_con1[mod] = strdup(str); X break; X case 12: X m.no_con2[mod] = strdup(str); X break; X case 13: X m.no_con3[mod] = strdup(str); X break; X case 14: X m.no_con4[mod] = strdup(str); X break; X } X } X if (oops) X break; X m_line++; X if (m_line >= 3) { X m_line = 0; X mod++; X } X } X } X fclose(fp); X X if (oops) { X sprintf(buf, "Modem file '%s'", status->m_path); X error_win(1, buf, message); X } X m.t_entries = tty; X m.m_entries = mod; X m.t_cur = -1; X m.m_cur = -1; X /* fill in the rest */ X for (; tty<NUM_TTY; tty++) { X m.tty[tty] = null_ptr; X m.tname[tty] = null_ptr; X m.mbaud[tty] = 0; X } X for (; mod<NUM_MODEM; mod++) { X m.mname[mod] = null_ptr; X m.init[mod] = null_ptr; X m.dial[mod] = null_ptr; X m.suffix[mod] = null_ptr; X m.hangup[mod] = null_ptr; X X m.con_3[mod] = null_ptr; X m.con_12[mod] = null_ptr; X m.con_24[mod] = null_ptr; X m.con_48[mod] = null_ptr; X m.con_96[mod] = null_ptr; X m.con_192[mod] = null_ptr; X X m.no_con1[mod] = null_ptr; X m.no_con2[mod] = null_ptr; X m.no_con3[mod] = null_ptr; X m.no_con4[mod] = null_ptr; X } X return(&m); X} X X/* X * Update the modem database. Other routines actually do the changes X * or deletions in memory. A return code of 1 means non-fatal error. X */ X Xint Xupdate_modem() X{ X FILE *fp; X char buf[80]; X int i; X void error_win(); X X /* open for write */ X if (!(fp = fopen(status->m_path, "w"))) { X sprintf(buf, "'%s'", status->m_path); X error_win(0, "No write permission on modem file", buf); X return(1); X } X /* put back the tty entries */ X for (i=0; i<modem->t_entries; i++) X fprintf(fp, "TTY_%d=%s;%s;%d\n", i+1, modem->tty[i], X modem->tname[i], modem->mbaud[i]); X X /* put back the modem entries */ X for (i=0; i<modem->m_entries; i++) { X fprintf(fp, "MODEM_%da=%s;%s;%s;%s;%s\n", i+1, modem->mname[i], X modem->init[i], modem->dial[i], modem->suffix[i], X modem->hangup[i]); X X fprintf(fp, "MODEM_%db=%s;%s;%s;%s;%s;%s\n", i+1, X modem->con_3[i], modem->con_12[i], modem->con_24[i], X modem->con_48[i], modem->con_96[i], modem->con_192[i]); X X fprintf(fp, "MODEM_%dc=%s;%s;%s;%s\n", i+1, modem->no_con1[i], X modem->no_con2[i], modem->no_con3[i], modem->no_con4[i]); X } X X fclose(fp); X return(0); X} X X/* X * See if the new modem is already in the database. If it's not, X * then create a slot for it and update the modem->m_cur variable. X */ X Xvoid Xcreate_modem(str) Xchar *str; X{ X int i; X char *strdup(), buf[80]; X void error_win(), free_ptr(); X /* modem entry already exists? */ X for (i=0; i<modem->m_entries; i++) { X if (!strcmp(str, modem->mname[i])) X return; X } X /* empty slot available? */ X if (modem->m_entries == NUM_MODEM) { X sprintf(buf, "'%s'", status->m_path); X error_win(0, "No empty modem slots in", buf); X return; X } X /* create a new entry */ X free_ptr(modem->mname[modem->m_entries]); X modem->mname[modem->m_entries] = strdup(str); X X /* update number of entries */ X modem->m_entries++; X return; X} X X/* X * See if the modem names in the list still need to be in the database. X * If you find a "lost" entry, delete it and collapse the list. X */ X Xvoid Xdelete_modem() X{ X int i, j, match; X char *strdup(); X void free_ptr(); X extern char *null_ptr; X X for (i=0; i<modem->m_entries; i++) { X match = 0; X for (j=0; j<modem->t_entries; j++) { X if (!strcmp(modem->mname[i], modem->tname[j])) { X match = 1; X break; X } X } X /* found a "lost" modem name */ X if (!match) { X for (j=i; j<modem->m_entries-1; j++) { X free_ptr(modem->mname[j]); X free_ptr(modem->init[j]); X free_ptr(modem->dial[j]); X free_ptr(modem->suffix[j]); X free_ptr(modem->hangup[j]); X X free_ptr(modem->con_3[j]); X free_ptr(modem->con_12[j]); X free_ptr(modem->con_24[j]); X free_ptr(modem->con_48[j]); X free_ptr(modem->con_96[j]); X free_ptr(modem->con_192[j]); X X free_ptr(modem->no_con1[j]); X free_ptr(modem->no_con2[j]); X free_ptr(modem->no_con3[j]); X free_ptr(modem->no_con4[j]); X X /* copy the info */ X modem->mname[j] = strdup(modem->mname[j+1]); X modem->init[j] = strdup(modem->init[j+1]); X modem->dial[j] = strdup(modem->dial[j+1]); X modem->suffix[j] = strdup(modem->suffix[j+1]); X modem->hangup[j] = strdup(modem->hangup[j+1]); X X modem->con_3[j] = strdup(modem->con_3[j+1]); X modem->con_12[j] = strdup(modem->con_12[j+1]); X modem->con_24[j] = strdup(modem->con_24[j+1]); X modem->con_48[j] = strdup(modem->con_48[j+1]); X modem->con_96[j] = strdup(modem->con_96[j+1]); X modem->con_192[j] = strdup(modem->con_192[j+1]); X X modem->no_con1[j] = strdup(modem->no_con1[j+1]); X modem->no_con2[j] = strdup(modem->no_con2[j+1]); X modem->no_con3[j] = strdup(modem->no_con3[j+1]); X modem->no_con4[j] = strdup(modem->no_con4[j+1]); X } X j = modem->m_entries -1; X X free_ptr(modem->mname[j]); X free_ptr(modem->init[j]); X free_ptr(modem->dial[j]); X free_ptr(modem->suffix[j]); X free_ptr(modem->hangup[j]); X X free_ptr(modem->con_3[j]); X free_ptr(modem->con_12[j]); X free_ptr(modem->con_24[j]); X free_ptr(modem->con_48[j]); X free_ptr(modem->con_96[j]); X free_ptr(modem->con_192[j]); X X free_ptr(modem->no_con1[j]); X free_ptr(modem->no_con2[j]); X free_ptr(modem->no_con3[j]); X free_ptr(modem->no_con4[j]); X X /* create an empty entry */ X modem->mname[j] = null_ptr; X modem->init[j] = null_ptr; X modem->dial[j] = null_ptr; X modem->suffix[j] = null_ptr; X modem->hangup[j] = null_ptr; X X modem->con_3[j] = null_ptr; X modem->con_12[j] = null_ptr; X modem->con_24[j] = null_ptr; X modem->con_48[j] = null_ptr; X modem->con_96[j] = null_ptr; X modem->con_192[j] = null_ptr; X X modem->no_con1[j] = null_ptr; X modem->no_con2[j] = null_ptr; X modem->no_con3[j] = null_ptr; X modem->no_con4[j] = null_ptr; X X /* update the counts */ X modem->m_entries--; X if (modem->m_cur >= modem->m_entries) X modem->m_cur = -1; X return; X } X } X return; X} SHAR_EOF if test 9489 -ne "`wc -c < 'm_lib.c'`" then echo shar: "error transmitting 'm_lib.c'" '(should have been 9489 characters)' fi fi echo shar: "extracting 'main.c'" '(4860 characters)' if test -f 'main.c' then echo shar: "will not over-write existing file 'main.c'" else sed 's/^X//' << \SHAR_EOF > 'main.c' X/* X * Pcomm is a public domain telecommunication program for Unix X * designed to operate similar to the popular MSDOS program, ProComm. X * ProComm (TM) is copyrighted by Datastorm Technologies, Inc. X * X * Emmet P. Gray US Army, HQ III Corps & Fort Hood X * ...!ihnp4!uiucuxc!fthood!egray Attn: AFZF-DE-ENV X * Directorate of Engineering & Housing X * Environmental Management Office X * Fort Hood, TX 76544-5057 X * Beta release 7 Feb 88 X * Release 1.0 12 Mar 88 X */ X X#include <stdio.h> X#include <signal.h> X#include <curses.h> X#ifndef OLDCURSES X#include <term.h> X#endif /* OLDCURSES */ X#include <sys/types.h> X#include <sys/stat.h> X#define MAIN X#include "dial_dir.h" X#include "modem.h" X#include "param.h" X#include "status.h" X X#ifdef OLDCURSES Xchar bp[1024]; X#define cbreak crmode X#endif /* OLDCURSES */ X Xstruct PARAM *param; Xstruct DIAL_DIR *dir; Xstruct STATUS *status; Xstruct MODEM *modem; Xint xmc; Xchar *null_ptr; X Xmain(argc, argv) Xint argc; Xchar *argv[]; X{ X int c, ret_code, i, code, quit(); X char *mytty, *ttyname(), *term, *getenv(), *index, *strdup(); X char *extra_dir, buf[80], message[80]; X struct PARAM *read_param(); X struct DIAL_DIR *read_dir(); X struct STATUS *init(); X struct MODEM *read_modem(); X struct stat stbuf; X void exit(), error_win(), input_on(), free_ptr(); X extern char *optarg; X#ifdef OLDCURSES X char *tgetstr(), ocbuf[20]; X char *ocbufptr = ocbuf; X#endif /* OLDCURSES */ X X signal(SIGINT, SIG_IGN); X signal(SIGQUIT, SIG_IGN); X signal(SIGTERM, quit); X signal(SIGHUP, quit); X X null_ptr = ""; X index = NULL; X extra_dir = NULL; X /* the command line */ X while ((c = getopt(argc, argv, "d:f:")) != EOF) { X switch (c) { X case 'd': /* the extra directory to search */ X extra_dir = strdup(optarg); X break; X case 'f': /* the index into the dialing dir */ X index = strdup(optarg); X break; X case '?': /* default */ X fprintf(stderr, "Usage: pcomm [-d directory] [-f index]\n"); X exit(1); X break; X } X } X /* get terminal type */ X term = getenv("TERM"); X if (term == NULL || *term == NULL) { X fprintf(stderr, "Windows not supported (TERM not defined)\n"); X exit(1); X } X /* see if terminfo entry exists */ X#ifdef OLDCURSES X ret_code = tgetent(bp, term); X#else /* OLDCURSES */ X setupterm(term, 1, &ret_code); X#endif /* OLDCURSES */ X if (ret_code != 1) { X fprintf(stderr, "Windows not supported (no terminfo data for '%s')\n", term); X exit(1); X } X /* minimum screen size */ X#ifdef OLDCURSES X if (tgetnum("co") < 80 || tgetnum("li") < 24) { X#else /* OLDCURSES */ X if (columns < 80 || lines < 24) { X#endif /* OLDCURSES */ X fprintf(stderr, "Windows not supported (minimum 80x24 screen required)\n"); X exit(1); X } X /* must have cursor movement */ X#ifdef OLDCURSES X if (tgetstr("cm", &ocbufptr) == NULL) { X#else /* OLDCURSES */ X if (cursor_address == NULL) { X#endif /* OLDCURSES */ X fprintf(stderr, "Windows not supported (terminal too dumb)\n"); X exit(1); X } X /* load magic cookie variable */ X#ifdef OLDCURSES X xmc = tgetnum("sg"); X#else /* OLDCURSES */ X xmc = magic_cookie_glitch; X#endif /* OLDCURSES */ X /* ok... now lets go! */ X initscr(); X nonl(); X cbreak(); X noecho(); X X param = (struct PARAM *) NULL; X modem = (struct MODEM *) NULL; X dir = (struct DIAL_DIR *) NULL; X /* show the herald, return status */ X status = init(extra_dir, index); X /* get 'msgs' status */ X mytty = ttyname(0); X stat(mytty, &stbuf); X chmod(mytty, 0600); X status->msg = stbuf.st_mode & 0777; X /* read the support files */ X param = read_param(); X dir = read_dir(); X modem = read_modem(); X /* short-cut to dialing window ? */ X code = 0; X if (index != NULL) { X for (i=1; i<dir->d_entries+1; i++) { X if (!strcmp(dir->index[i], index)) { X dir->q_num[0] = i; X dir->d_cur = i; X break; X } X } X /* if match is found */ X if (dir->q_num[0] != -1) X code = dial_win(); X else { X sprintf(buf, "Can't find index '%s' in dialing directory file", index); X sprintf(message, "'%s'", status->d_path); X error_win(0, buf, message); X } X free_ptr(index); X } X /* start terminal dialogue */ X terminal(code); X exit(0); X} X X/* X * Something dreadful happened... Cleanup the mess we made with the X * tty driver and release the phone line. X */ X Xint Xquit() X{ X void cleanup(); X X cleanup(1); X /* never returns... */ X return(0); X} X X/* X * Check write permission with the real UID and GID. Returns a 0 on X * permission denied, 1 on OK, and 2 on OK-but the file already exists. X */ X Xint Xcan_write(file) Xchar *file; X{ X char *p, path[200], *strcpy(), *strrchr(); X X p = strcpy(path, file); X /* dissect the path component */ X if (p = strrchr(path, '/')) X *(p++) = NULL; X else X strcpy(path, "."); X /* if it already exists */ X if (!access(file, 0)) { X if (!access(file, 2)) X return(2); X return(0); X } X /* if path is writable */ X if (!access(path, 2)) X return(1); X return(0); X} SHAR_EOF if test 4860 -ne "`wc -c < 'main.c'`" then echo shar: "error transmitting 'main.c'" '(should have been 4860 characters)' fi fi echo shar: "extracting 'n_shell.c'" '(1369 characters)' if test -f 'n_shell.c' then echo shar: "will not over-write existing file 'n_shell.c'" else sed 's/^X//' << \SHAR_EOF > 'n_shell.c' X/* X * Spawn a 'native' shell. 'Native' means the shell found in the SHELL X * environmental variable. X */ X X#include <stdio.h> X#include <signal.h> X#include <curses.h> X Xvoid Xnative_shell() X{ X WINDOW *sh_win, *newwin(); X int (*istat)(), (*qstat)(), status, pid, w; X char *shell, *shellpath, *getenv(), *strrchr(); X unsigned int sleep(); X void _exit(); X /* a full window */ X sh_win = newwin(LINES, COLS, 0, 0); X X clear_absolute(sh_win); X waddstr(sh_win, "Pcomm <=> Unix gateway, use ^D or 'exit' to return\n"); X wrefresh(sh_win); X /* out of curses mode */ X resetterm(); X X shellpath = getenv("SHELL"); X if (shellpath == NULL || *shellpath == NULL) X shellpath = "/bin/sh"; X X shell = strrchr(shellpath, '/') + 1; X X if (!(pid = fork())) { X#ifdef SGID X setgid(getgid()); X#endif /* SGID */ X execl(shellpath, shell, "-i", 0); X _exit(1); X } X istat = signal(SIGINT, SIG_IGN); X qstat = signal(SIGQUIT, SIG_IGN); X X while ((w = wait(&status)) != pid && w != -1) X ; X X signal(SIGINT, istat); X signal(SIGQUIT, qstat); X /* back to curses mode */ X fixterm(); X sleep(1); X X clear_absolute(stdscr); X delwin(sh_win); X return; X} X X/* X * Clear the screen absolutely! It's incrediblely hard to get curses() to X * clear the screen when it thinks its already clear. X */ X Xint Xclear_absolute(win) XWINDOW *win; X{ X clearok(curscr, 1); X wrefresh(win); X clearok(curscr, 0); X return(0); X} SHAR_EOF if test 1369 -ne "`wc -c < 'n_shell.c'`" then echo shar: "error transmitting 'n_shell.c'" '(should have been 1369 characters)' fi fi echo shar: "extracting 'p_lib.c'" '(5786 characters)' if test -f 'p_lib.c' then echo shar: "will not over-write existing file 'p_lib.c'" else sed 's/^X//' << \SHAR_EOF > 'p_lib.c' X/* X * Routines to manipulate the pcomm.param file. X */ X X#include <stdio.h> X#include "param.h" X#include "status.h" X X/* X * Read the parameter structure from the pcomm.param file. Returns a X * pointer to the PARAM structure. All errors are fatal. X */ X Xstruct PARAM * Xread_param() X{ X FILE *fp; X int i, oops; X char buf[80], *temp_token, *str, *strdup(); X char message[80], *str_tok(); X static char *token[NUM_PARAM] = {"D_BAUD", "D_PARITY", "D_DBITS", X "D_SBITS", "HOT", "ASCII_HOT", "D_DUPLEX", "FLOW", "CR_IN", "CR_OUT", X "LOGFILE", "DUMPFILE", "STRIP", "PAUSE_CHAR", "CR_CHAR", "CTRL_CHAR", X "ESC_CHAR", "ABORT", "CDELAY", "PAUSE", "LECHO", "EXPAND", "CR_DELAY", X "PACE", "CR_UP", "LF_UP", "TIMER", "CR_DN", "LF_DN", "LD_PLUS", X "LD_MINUS", "LD_AT", "LD_POUND"}; X static struct PARAM p; X void error_win(); X /* read permission already checked */ X fp = fopen(status->p_path, "r"); X X oops = 0; X for (i=0; i<NUM_PARAM; i++) { X if (fgets(buf, 80, fp) == NULL) { X sprintf(message, "is truncated at line %d", i+1); X oops++; X break; X } X /* parse the input line */ X if (!(temp_token = str_tok(buf, '='))) { X sprintf(message, "is missing a token at line %d", i+1); X oops++; X break; X } X if (!(str = str_tok((char *) NULL, '\n'))) { X sprintf(message, "is missing a parameter at line %d", i+1); X oops++; X break; X } X /* sanity checking */ X if (strcmp(temp_token, token[i])) { X sprintf(message, "is corrupted at line %d", i+1); X oops++; X break; X } X X switch(i) { X /* used in line_set_menu() */ X case LINE_SET: X p.d_baud = atoi(str); X break; X case LINE_SET+1: X p.d_parity = *str; X break; X case LINE_SET+2: X p.d_dbits = atoi(str); X break; X case LINE_SET+3: X p.d_sbits = atoi(str); X break; X X /* used in term_setup() */ X case TERM_SETUP: X p.hot = atoi(str); X break; X case TERM_SETUP+1: X p.ascii_hot = strdup(str); X break; X case TERM_SETUP+2: X p.d_duplex = strdup(str); X break; X case TERM_SETUP+3: X p.flow = strdup(str); X break; X case TERM_SETUP+4: X p.cr_in = strdup(str); X break; X case TERM_SETUP+5: X p.cr_out = strdup(str); X break; X X /* used in gen_setup() */ X case GEN_SETUP: X p.logfile = strdup(str); X break; X case GEN_SETUP+1: X p.dumpfile = strdup(str); X break; X case GEN_SETUP+2: X p.strip = strdup(str); X break; X case GEN_SETUP+3: X p.pause_char = *str; X break; X case GEN_SETUP+4: X p.cr_char = *str; X break; X case GEN_SETUP+5: X p.ctrl_char = *str; X break; X case GEN_SETUP+6: X p.esc_char = *str; X break; X case GEN_SETUP+7: X p.abort = strdup(str); X break; X X /* used in gen_setup() delay_times() */ X case DELAY_TIMES: X p.cdelay = atoi(str); X break; X case DELAY_TIMES+1: X p.pause = atoi(str); X break; X X /* used in ascii_xfer_setup() */ X case ASCII_SETUP: X p.lecho = strdup(str); X break; X case ASCII_SETUP+1: X p.expand = strdup(str); X break; X case ASCII_SETUP+2: X p.cr_delay = atoi(str); X break; X case ASCII_SETUP+3: X p.pace = strdup(str); X break; X case ASCII_SETUP+4: X p.cr_up = strdup(str); X break; X case ASCII_SETUP+5: X p.lf_up = strdup(str); X break; X case ASCII_SETUP+6: X p.timer = atoi(str); X break; X case ASCII_SETUP+7: X p.cr_dn = strdup(str); X break; X case ASCII_SETUP+8: X p.lf_dn = strdup(str); X break; X X /* used in d_revise() */ X case LD_CODES: X p.ld_plus = strdup(str); X break; X case LD_CODES+1: X p.ld_minus = strdup(str); X break; X case LD_CODES+2: X p.ld_at = strdup(str); X break; X case LD_CODES+3: X p.ld_pound = strdup(str); X break; X } X } X fclose(fp); X if (oops) { X sprintf(buf, "Parameter file '%s'", status->p_path); X error_win(1, buf, message); X } X return(&p); X} X X/* X * Write the updated param structure to disk. The values in memory should X * have already been "purified". Later, we'll update only the entries that X * have been explicitly asked for. A return code of 1 means non-fatal error. X */ X Xint Xupdate_param() X{ X FILE *fp; X char buf[80]; X void error_win(); X /* open for write */ X if (!(fp = fopen(status->p_path, "w"))) { X sprintf(buf, "'%s'", status->p_path); X error_win(0, "No write permission on parameter file", buf); X return(1); X } X X fprintf(fp, "D_BAUD=%d\n", param->d_baud); X fprintf(fp, "D_PARITY=%c\n", param->d_parity); X fprintf(fp, "D_DBITS=%d\n", param->d_dbits); X fprintf(fp, "D_SBITS=%d\n", param->d_sbits); X fprintf(fp, "HOT=%d\n", param->hot); X fprintf(fp, "ASCII_HOT=%s\n", param->ascii_hot); X fprintf(fp, "D_DUPLEX=%s\n", param->d_duplex); X fprintf(fp, "FLOW=%s\n", param->flow); X fprintf(fp, "CR_IN=%s\n", param->cr_in); X fprintf(fp, "CR_OUT=%s\n", param->cr_out); X fprintf(fp, "LOGFILE=%s\n", param->logfile); X fprintf(fp, "DUMPFILE=%s\n", param->dumpfile); X fprintf(fp, "STRIP=%s\n", param->strip); X fprintf(fp, "PAUSE_CHAR=%c\n", param->pause_char); X fprintf(fp, "CR_CHAR=%c\n", param->cr_char); X fprintf(fp, "CTRL_CHAR=%c\n", param->ctrl_char); X fprintf(fp, "ESC_CHAR=%c\n", param->esc_char); X fprintf(fp, "ABORT=%s\n", param->abort); X fprintf(fp, "CDELAY=%d\n", param->cdelay); X fprintf(fp, "PAUSE=%d\n", param->pause); X fprintf(fp, "LECHO=%s\n", param->lecho); X fprintf(fp, "EXPAND=%s\n", param->expand); X fprintf(fp, "CR_DELAY=%d\n", param->cr_delay); X fprintf(fp, "PACE=%s\n", param->pace); X fprintf(fp, "CR_UP=%s\n", param->cr_up); X fprintf(fp, "LF_UP=%s\n", param->lf_up); X fprintf(fp, "TIMER=%d\n", param->timer); X fprintf(fp, "CR_DN=%s\n", param->cr_dn); X fprintf(fp, "LF_DN=%s\n", param->lf_dn); X fprintf(fp, "LD_PLUS=%s\n", param->ld_plus); X fprintf(fp, "LD_MINUS=%s\n", param->ld_minus); X fprintf(fp, "LD_AT=%s\n", param->ld_at); X fprintf(fp, "LD_POUND=%s\n", param->ld_pound); X X fclose(fp); X return(0); X} SHAR_EOF if test 5786 -ne "`wc -c < 'p_lib.c'`" then echo shar: "error transmitting 'p_lib.c'" '(should have been 5786 characters)' fi fi echo shar: "extracting 'pexit.c'" '(2142 characters)' if test -f 'pexit.c' then echo shar: "will not over-write existing file 'pexit.c'" else sed 's/^X//' << \SHAR_EOF > 'pexit.c' X/* X * Exit pcomm. A user requested abort. There are a lot of things to do X * before we exit! X */ X X#include <stdio.h> X#include <curses.h> X#include "dial_dir.h" X#include "misc.h" X#include "param.h" X#include "status.h" X Xvoid Xpexit(fd) Xint fd; X{ X WINDOW *ex_win, *newwin(); X void cleanup(), status_line(); X X ex_win = newwin(5, 33, 3, 7); X X box(ex_win, '|', '-'); X mvwattrstr(ex_win, 0, 3, A_BOLD, " Exit "); X if (yes_prompt(ex_win, 2, 4, A_BLINK, "Exit to Unix")) { X status_line(" exiting"); X cleanup(0); X } X if (fd == -1) { X werase(ex_win); X wrefresh(ex_win); X } X delwin(ex_win); X return; X} X X/* X * Do the cleanup detail before we exit. X */ X Xvoid Xcleanup(val) Xint val; X{ X void release_port(), input_off(), exit(), status_line(); X char *ttyname(); X /* kill the input routine */ X input_off(); X /* zap the virtual screen file */ X unlink(status->vs_path); X /* release the port */ X release_port(0); X /* erase the window we made */ X touchwin(stdscr); X clear(); X refresh(); X endwin(); X /* return the tty chmod */ X chmod(ttyname(0), status->msg); X exit(val); X} X X/* X * Open a window to display an error message. Handles both fatal and X * non-fatal errors X */ X Xvoid Xerror_win(code, line_one, line_two) Xint code; Xchar *line_one, *line_two; X{ X WINDOW *e_win, *newwin(); X void cleanup(), status_line(); X X e_win = newwin(7, 70, 9, 5); X /* display the nasty note */ X mvwaddstr(e_win, 2, 4, line_one); X mvwaddstr(e_win, 3, 4, line_two); X box(e_win, '|', '-'); X X if (code) { X mvwattrstr(e_win, 0, 4, A_BOLD, " Error "); X mvwattrstr(e_win, 5, 24, A_BLINK, "Press any key to exit"); X wmove(e_win, 5, 46); X } X else { X mvwattrstr(e_win, 0, 4, A_BOLD, " Warning "); X mvwattrstr(e_win, 5, 22, A_BLINK, "Press any key to continue"); X wmove(e_win, 5, 48); X } X beep(); X wrefresh(e_win); X X wgetch(e_win); X werase(e_win); X wrefresh(e_win); X delwin(e_win); X X if (code) { X /* X * Since this routine gets called if there is an error reading X * the support files, the dir and param structures can't be X * guaranteed to exist yet. X */ X if (dir != NULL && param != NULL) X status_line(" exiting"); X cleanup(code); X } X return; X} SHAR_EOF if test 2142 -ne "`wc -c < 'pexit.c'`" then echo shar: "error transmitting 'pexit.c'" '(should have been 2142 characters)' fi fi echo shar: "extracting 'port.c'" '(6122 characters)' if test -f 'port.c' then echo shar: "will not over-write existing file 'port.c'" else sed 's/^X//' << \SHAR_EOF > 'port.c' X/* X * Routines to get or release a tty port. X */ X X#define LOCKDIR "/usr/spool/uucp" X#undef ASCII_PID X X#include <stdio.h> X#include <fcntl.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 "status.h" X Xint getty_status; X/* X * Finds a free (or requested) serial port. Creates a lock file to hold X * it for our use. Loads the modem database. A return code of 1 means X * all ports (or the requested port) are busy. X */ X Xint Xget_port() X{ X int i, j, k, progpid, fd, list[NUM_TTY]; X char file[80], buf[80], message[80], *strdup(); X void error_win(), line_set(), release_port(), send_str(); X void free_ptr(); X X /* X * If we already have a port, see if it is good enough for the X * current request. X */ X if (status->fd != -1) { X if (!strcmp(dir->index[dir->d_cur], modem->tty[modem->t_cur]) || X modem->mbaud[modem->t_cur] >= dir->baud[dir->d_cur]) { X /* X * Re-initialize the modem because the baud X * rate (or other parameters) may have changed. X */ X line_set(); X send_str(modem->init[modem->m_cur]); X return(0); X } X } X release_port(1); X X /* X * See if you want a specific tty port. If the index field in the X * dialing directory is a valid device name, then use that tty. X */ X sprintf(buf, "/dev/%s", dir->index[dir->d_cur]); X list[0] = -1; X /* if index is a valid device */ X if (!access(buf, 0)) { X for (i=0; i<modem->t_entries; i++) { X /* and it exists in modem database */ X if (!strcmp(dir->index[dir->d_cur], modem->tty[i])) { X list[0] = i; X list[1] = -1; X break; X } X } X } X X /* X * Create a list of acceptable ttys. It searches the tty database X * for the requested baud rate. X */ X k = 0; X if (list[0] == -1) { X for (i=0; i<modem->t_entries; i++) { X /* skip ports with no modems */ X if (!strcmp(modem->tname[i], "DIRECT")) X continue; X X /* can handle requested baud rate ? */ X if (modem->mbaud[i] >= dir->baud[dir->d_cur]) X list[k++] = i; X } X /* the end of list marker */ X list[k] = -1; X } X /* empty list ? */ X if (list[0] == -1) { X sprintf(message, "No modem at a %d baud rating exists in", dir->baud[dir->d_cur]); X sprintf(file, "modem file '%s'", status->m_path); X error_win(0, message, file); X return(1); X } X /* check the list for a free port */ X i = 0; X while (list[i] != -1) { X /* create a lock file name */ X sprintf(file, "%s/LCK..%s", LOCKDIR, modem->tty[list[i]]); X X /* X * See if the lock file exists... We DO NOT look to see X * if the pid in the file is still active. Maybe I'll X * change this later... X */ X if (access(file, 0)) { X getty_status = set_getty(modem->tty[list[i]], 0); X X if ((fd = open(file, O_CREAT|O_WRONLY, 0666)) < 0) { X set_getty(modem->tty[list[i]], 1); X sprintf(buf, "'%s'", file); X error_win(1, "Can't create the lockfile", buf); X } X#ifdef ASCII_PID X sprintf(buf, "%10d\n", getpid()); X write(fd, buf, 11); X#else /* ASCII_PID */ X progpid = getpid(); X write(fd, (char *)&progpid, sizeof(int)); X#endif /* ASCII_PID */ X close(fd); X /* store the new values */ X free_ptr(status->lock_path); X status->lock_path = strdup(file); X modem->t_cur = list[i]; X X /* open the device (hold DTR high) */ X sprintf(buf, "/dev/%s", modem->tty[list[i]]); X if ((fd = open(buf, O_RDWR|O_NDELAY)) < 0) { X set_getty(modem->tty[list[i]], 1); X sprintf(file, "Can't open port '%s' for read and write", buf); X error_win(1, file, NULL); X } X X /* turn off the "no delay" mode */ X fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NDELAY); X status->fd = fd; X /* change line settings */ X line_set(); X /* load the modem data base */ X for (j=0; j<modem->m_entries; j++) { X if (!strcmp(modem->tname[list[i]], modem->mname[j])) { X modem->m_cur = j; X break; X } X } X /* initialize the modem */ X send_str(modem->init[j]); X return(0); X } X i++; X } X error_win(0, "All ports are busy now, try again later", NULL); X return(1); X} X X/* X * Release the port. Closes the file descriptor and removes the X * lock file X */ X Xvoid Xrelease_port(verbose) Xint verbose; X{ X char buf[80]; X extern char *null_ptr; X void free_ptr(), hang_up(); X X /* X * The modem structure can't be guaranteed to exist yet. For example, X * an error in reading one of the other support files would cause X * this routine to be used before the MODEM structure gets allocated. X */ X if (modem == NULL) X return; X /* close the port */ X if (status->fd != -1) { X ioctl(status->fd, TCFLSH, 2); X /* X * Since HUPCL is set, the close() should drop the DTR and X * hang up the modem (provided you've got the modem to X * respond to DTR). Since this is not guaranteed, we send X * the hangup string first. X */ X hang_up(verbose); X close(status->fd); X } X /* remove the lock */ X if (*status->lock_path != NULL) { X if (unlink(status->lock_path)) { X sprintf(buf, "'%s'", status->lock_path); X error_win(0, "Can't remove the lock file", buf); X } X free_ptr(status->lock_path); X status->lock_path = null_ptr; X } X /* turn the getty back on? */ X if (getty_status) X set_getty(modem->tty[modem->t_cur], 1); X /* cleanup the structure */ X status->fd = -1; X modem->m_cur = -1; X modem->t_cur = -1; X return; X} X X/* X * Turn the /etc/getty on or off for the specified port. A return code X * of 1 means that the getty was on. Systems with uugetty or dedicated X * dialout ports won't need this routine. X */ X Xint Xset_getty(tty, on) Xchar *tty; Xint on; X{ X#ifdef UNIXPC X int i, ret_code; X char buf[40]; X unsigned int sleep(); X /* the last three characters */ X i = strlen(tty) -3; X X ret_code = 0; X if (on) { X sprintf(buf, "setgetty %s 1", tty+i); X system(buf); X } X else { X sprintf(buf, "setgetty %s 0", tty+i); X if (system(buf) == 512) X ret_code = 1; X sleep(1); X } X return(ret_code); X#else /* UNIXPC */ X /* X * If you don't have one of these cute little routines, you X * might wanna write one. It should check for an existing lock X * file, edit the /etc/inittab file, and issue an init -q. X * Obviously the program would be suid to root. X */ X return(0); X#endif /* UNIXPC */ X} SHAR_EOF if test 6122 -ne "`wc -c < 'port.c'`" then echo shar: "error transmitting 'port.c'" '(should have been 6122 characters)' fi fi echo shar: "extracting 'redial.c'" '(2216 characters)' if test -f 'redial.c' then echo shar: "will not over-write existing file 'redial.c'" else sed 's/^X//' << \SHAR_EOF > 'redial.c' X/* X * The redial option (actually a misnomer, it's really a queuing system). X * We expect a space-separated list of dialing directory entries (although X * new users always try to put in a phone number). A return code of 1 X * means we're ready to dial. X */ X X#include <stdio.h> X#include <curses.h> X#include "dial_dir.h" X#include "misc.h" X Xint Xredial(fd) Xint fd; X{ X WINDOW *rd_win, *newwin(); X char *ans, *entry, *get_str(), *strchr(), *strtok(); X int i, oops, number, ret_code; X X rd_win = newwin(6, 70, 5, 5); X X mvwaddstr(rd_win, 4, 23, "(CR for previous numbers)"); X mvwaddstr(rd_win, 2, 4, "Directory Entry Number(s): "); X box(rd_win, '|', '-'); X X mvwattrstr(rd_win, 0, 3, A_BOLD, " Redial Queue "); X wmove(rd_win, 2, 31); X wrefresh(rd_win); X /* get the string of numbers */ X ret_code = 0; X while ((ans = get_str(rd_win, 35, "0123456789+-@# ", NULL)) != NULL) { X oops = 0; X if (*ans == NULL) { X /* use previous queue */ X if (dir->q_num[0] != -1) { X ret_code = 1; X break; X } X /* there is no previous queue */ X beep(); X mvwattrstr(rd_win, 3, 4, A_BOLD, "No previous numbers"); X wrefresh(rd_win); X wait_key(rd_win, 3); X clear_line(rd_win, 3, 4, 1); X wmove(rd_win, 2, 31); X wrefresh(rd_win); X continue; X } X /* parse the queue values */ X entry = strtok(ans, " "); X for (i=0; i<NUM_QUEUE; i++) { X if (*entry == NULL) { X dir->q_num[i] = -1; X continue; X } X /* is there a LD code ? */ X dir->q_ld[i] = NULL; X if (strchr("+-@#", *entry)) { X dir->q_ld[i] = *entry; X entry++; X } X X /* X * Zero is valid here, because it means use X * the current entry information. X */ X number = atoi(entry); X if (number < -1 || number > NUM_DIR) { X beep(); X mvwattrstr(rd_win, 3, 4, A_BOLD, "Invalid directory entry number"); X wrefresh(rd_win); X wait_key(rd_win, 3); X clear_line(rd_win, 3, 4, 1); X clear_line(rd_win, 2, 31, 1); X wrefresh(rd_win); X oops++; X break; X } X /* store the number in the queue */ X dir->q_num[i] = number; X entry = strtok((char *) NULL, " "); X } X if (oops) X continue; X ret_code = 1; X break; X } X if (fd == -1) { X werase(rd_win); X wrefresh(rd_win); X } X delwin(rd_win); X return(ret_code); X} SHAR_EOF if test 2216 -ne "`wc -c < 'redial.c'`" then echo shar: "error transmitting 'redial.c'" '(should have been 2216 characters)' fi fi exit 0 # End of shell archive
egray@fthood.UUCP (03/14/88)
This is part 6 (of 6) to the Pcomm version 1.0 distribution. Emmet P. Gray US Army, HQ III Corps & Fort Hood ...!ihnp4!uiucuxc!fthood!egray Attn: AFZF-DE-ENV Directorate of Engineering & Housing Environmental Management Office Fort Hood, TX 76544-5057 ------------------------------------------------------------------------------- #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # x_batch.c # x_menu.c # x_rcv.c # x_send.c # x_win.c # xmodem.c # This archive created: Fri Mar 11 07:35:29 1988 export PATH; PATH=/bin:/usr/bin:$PATH echo shar: "extracting 'x_batch.c'" '(7780 characters)' if test -f 'x_batch.c' then echo shar: "will not over-write existing file 'x_batch.c'" else sed 's/^X//' << \SHAR_EOF > 'x_batch.c' X/* X * Routines to support the batch protocols. X */ X X#include <stdio.h> X#include <ctype.h> X#include <curses.h> X#include "misc.h" X#include "xmodem.h" X X/* X * Send the file name for the modem7 batch. Only uses 11 characters X * of the filename. X */ X Xint Xsend_modem7(win, name) XWINDOW *win; Xchar *name; X{ X char *new_name, *fix_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 ACK: /* got it! */ X break; X case CAN: /* cancel transmission */ X if (getc_line(2) == CAN) { X beep(); X clear_line(win, 12, 24, 1); X wattrstr(win, A_BOLD, "REMOTE ABORTED"); X wrefresh(win); X return(CANCEL); X } X /* fall thru... */ X default: X clear_line(win, 12, 24, 1); 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, 1); 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 modem 7 file name. A return code of 1 means the end of the X * batch transfers. X */ X Xint Xrcv_modem7(win, default_err) XWINDOW *win; Xint default_err; X{ X int i, c, err_method, err_count, got_it; X unsigned char sum, calc_sum(); X char temp_name[13]; X extern char *null_ptr, file_name[15]; X void change_name(), unfix_name(); X /* send the first char */ X err_method = default_err; X err_count = 0; X got_it = 0; X while (err_count < MAX_ERRORS) { X /* switch to checksum? */ X if (default_err == 1 && err_count > MAX_ERRORS/2) X err_method = 0; X X if (err_method) X putc_line('C'); X else X putc_line(NAK); X /* what'd we get? */ X if (getc_line(10) == ACK) { X got_it++; X break; X } X err_count++; X } X if (!got_it) X return(ERROR); X /* get the name */ X for (i=0; i<12; i++) { X c = getc_line(3); X X switch(c) { 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, 1); X wattrstr(win, A_BOLD, "REMOTE ABORTED"); X wrefresh(win); X return(CANCEL); X } X /* fall thru... */ X case 'u': /* bad name character */ X beep(); X clear_line(win, 12, 24, 1); X wattrstr(win, A_BOLD, "BAD NAME"); X wrefresh(win); X return(ERROR); X default: /* the name... */ X temp_name[i] = c; X if (c != CTRLZ) X putc_line(ACK); X break; X } X } X temp_name[12] = NULL; 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, 1); 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; Xint size; X{ X int i, crc; X char *strcpy(); X unsigned char buf[133]; X /* start with a clean block */ X for (i=0; i<132; i++) X buf[i] = NULL; 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 != NULL) { X strcpy((char *) &buf[3], file); X sprintf((char *) &buf[strlen(file)+4], "%d", size); X } X /* the crc */ X crc = calc_crc(&buf[3], 128); X buf[131] = crc >> 8; X buf[132] = crc; 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 int code, length_is_at; X extern unsigned char buf[1029]; X extern int file_length; X extern char file_name[15]; X X file_length = 0; X file_name[0] = NULL; 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] == NULL) X return(0); X /* get the file name */ X change_name(win, (char *) &buf[3]); X /* any trouble ?? */ X if (file_name[0] == NULL) { 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 * atoi() will see a NULL and return 0. X */ X length_is_at = strlen((char *) &buf[3]) + 4; X file_length = atoi((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 Xvoid Xchange_name(win, str) XWINDOW *win; Xchar *str; X{ X int i, modified; X char temp[15], ans[15], *s, *strrchr(), *strcpy(), *strncat(); X unsigned int sleep(); X extern char file_name[15]; X /* dissect the name component */ X if ((s = strrchr(str, '/'))) X strcpy(temp, s++); X else X strcpy(temp, str); X X strcpy(ans, temp); X file_name[0] = NULL; X /* write permission on directory ? */ X if (access(".", 2)) { X beep(); X clear_line(win, 12, 24, 1); 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, 1); 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] = NULL; X strcpy(ans, temp); X } X beep(); X clear_line(win, 12, 24, 1); 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 the new name. X */ X Xchar * Xfix_name(path) Xchar *path; X{ X int dot; X char *s, *name, temp[15], *ext, *strcpy(), *strrchr(); X static char ans[13]; X /* ignore the path component */ X if (s = strrchr(path, '/')) X strcpy(temp, s++); X else X strcpy(temp, path); X name = temp; X X ext = NULL; X dot = 0; X for (s = name; *s; ++s) { X if (*s == '.' && !dot) { X dot = 1; X *s = NULL; X ext = s + 1; X } X if (islower(*s)) X *s = toupper(*s); X } X /* if null name component */ X if (*name == NULL) X name = "X"; X /* if name too long */ X if (strlen(name) > 8) X *(name+8) = NULL; X /* if extension too long */ X if (strlen(ext) > 3) X *(ext+3) = NULL; 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 Xvoid Xunfix_name(cpm_name) Xchar *cpm_name; X{ X int i, n, dot; X char temp[15]; X extern char file_name[15]; X X file_name[0] = NULL; X if (!*cpm_name) 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] = NULL; X return; X} SHAR_EOF if test 7780 -ne "`wc -c < 'x_batch.c'`" then echo shar: "error transmitting 'x_batch.c'" '(should have been 7780 characters)' fi fi echo shar: "extracting 'x_menu.c'" '(4000 characters)' if test -f 'x_menu.c' then echo shar: "will not over-write existing file 'x_menu.c'" else sed 's/^X//' << \SHAR_EOF > 'x_menu.c' X/* X * Open a window to display the choices of file transfer protocols and X * prompt for the file name(s). A return code of 1 means turn the X * input routine back on. X */ X X#include <stdio.h> X#include <curses.h> X#include "misc.h" X#include "xmodem.h" X Xint Xxfer_menu(up) Xint up; X{ X WINDOW *xm_win, *newwin(); X char *list, *get_names(); X int type, is_batch; X extern char *null_ptr; X void xfer_win(), xfer_ascii(), free_ptr(); X X xm_win = newwin(15, 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 mvwaddstr(xm_win, 11, 3, "ESC to Abort"); X mvwaddstr(xm_win, 13, 3, "Protocol:"); X box(xm_win, '|', '-'); 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, 13, 13); X wrefresh(xm_win); X /* get the protocol */ X while ((type = get_num(xm_win, 1)) != -1) { X if (type >=1 && type <= PROTOCOLS) X break; X beep(); X mvwaddch(xm_win, 13, 13, ' '); X wmove(xm_win, 13, 13); X wrefresh(xm_win); X } X /* is a batch protocol ? */ X is_batch = 0; X switch (type-1) { X case MODEM7: X case YMODEM: X case YMODEM_G: X is_batch++; X break; X default: X break; X } X werase(xm_win); X wrefresh(xm_win); X delwin(xm_win); X X touchwin(stdscr); X refresh(); X X if (type == -1) X return(0); X type--; X X /* X * When receiving files in one of the batch modes, there is X * need to prompt for a list of file names. X */ X list = null_ptr; X if (up || !is_batch) { X if (!(list = get_names(up, type, is_batch))) X return(0); X } X /* if ascii transfer */ X if (type == XASCII) { X xfer_ascii(list, up); X free_ptr(list); X if (up) X return(0); X return(1); X } X xfer_win(list, up, type); X free_ptr(list); X return(1); X} X X/* X * Prompt for a list of files for the transfer programs. A NULL return X * code means you chickened out. X */ X Xchar * Xget_names(up, type, is_batch) Xint up, type, is_batch; X{ X int can; X WINDOW *gn_win, *newwin(); X char *ans, *list, *file, buf[40], *expand(), *get_str(), *strtok(); X static char *direction[2] = {"Receive", "Send"}; X static char *protocol[PROTOCOLS] = {"xmodem", "xmodem-1k", "modem7", X "ymodem", "ymodem-g", "ASCII"}; X /* prompt for file spec */ X gn_win = newwin(7, 70, 5, 5); X X mvwaddstr(gn_win, 3, 4, "Enter filename: "); X box(gn_win, '|', '-'); X sprintf(buf, " %s %s ", direction[up], protocol[type]); X X while (1) { X mvwattrstr(gn_win, 0, 3, A_BOLD, buf); 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, NULL, NULL); X else X ans = get_str(gn_win, 60, NULL, " "); X X if (ans == NULL || *ans == NULL) { X list = NULL; X break; X } X list = expand(ans); X /* batchs check "on the fly" */ X if (is_batch) X break; X /* X * The non-batch protocols don't check read and write X * permission on the fly, so we check 'em here. Since X * they aren't batch, we use only one file. X */ X file = strtok(list, " "); X /* check read permission */ X if (up) { X if (access(file, 4)) { X beep(); X mvwattrstr(gn_win, 4, 15, A_BOLD, "Can't find or no read permission"); X wrefresh(gn_win); X wait_key(gn_win, 3); X clear_line(gn_win, 4, 15, 1); X clear_line(gn_win, 3, 20, 1); X wrefresh(gn_win); X } X else X break; X } X /* check write permission */ X else { X if (!(can = can_write(file))) { X beep(); X clear_line(gn_win, 4, 15, 1); 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, 1); X clear_line(gn_win, 3, 20, 1); X wrefresh(gn_win); X } X if (can == 2) { X if (!yes_prompt(gn_win, 4, 15, A_BOLD, "File exists, overwrite")) { X list = NULL; X break; X } X } X if (can) X break; X } X } X werase(gn_win); X wrefresh(gn_win); X delwin(gn_win); X X touchwin(stdscr); X refresh(); X return(list); X} SHAR_EOF if test 4000 -ne "`wc -c < 'x_menu.c'`" then echo shar: "error transmitting 'x_menu.c'" '(should have been 4000 characters)' fi fi echo shar: "extracting 'x_rcv.c'" '(10526 characters)' if test -f 'x_rcv.c' then echo shar: "will not over-write existing file 'x_rcv.c'" else sed 's/^X//' << \SHAR_EOF > 'x_rcv.c' X/* X * Receive a list of files using a version of Ward Christensen's file X * transfer protocol. A return code of 1 means the user must acknowledge X * an error condition. X */ X X#include <stdio.h> X#include <curses.h> X#include "dial_dir.h" X#include "misc.h" X#include "xmodem.h" X Xunsigned char buf[1029]; Xchar file_name[15]; Xint file_length, err_method, tot_err, block_size; X Xint Xrcv_xmodem(win, list, type, fast) XWINDOW *win; Xchar *list; Xint type, fast; X{ X FILE *fp; X int default_err, is_batch, max_block, code, file_count, i, got_hdr; X int block, recv, hours, mins, secs; X float percent, performance; X unsigned char blk; X unsigned int sleep(); X char *file, *name, *strcpy(), *strrchr(), *strtok(); X void cancel_xfer(); X X /* X * What type of xmodem? The default_err means: 0=checksum only, X * 1=CRC or checksum, 2=CRC only, and 3=none. X */ X switch(type) { X case XMODEM: X mvwaddstr(win, 2, 24, "xmodem"); X default_err = 1; X is_batch = 0; X max_block = 128; X break; X case XMODEM_1k: X mvwaddstr(win, 2, 24, "xmodem-1k"); X default_err = 1; X is_batch = 0; X max_block = 1024; X break; X case MODEM7: X mvwaddstr(win, 2, 24, "modem7"); X default_err = 0; X is_batch = 1; X max_block = 128; X break; X case YMODEM: X mvwaddstr(win, 2, 24, "ymodem"); X default_err = 2; X is_batch = 1; X max_block = 1024; X performance = 1.09; X break; X case YMODEM_G: X mvwaddstr(win, 2, 24, "ymodem-g"); X default_err = 3; X is_batch = 1; X max_block = 1024; X performance = 1.02; X break; X } X X tot_err = 0; X file_count = 0; X mvwaddstr(win, 11, 24, "0 "); X X while (1) { X file_count++; X file_length = 0; X /* user supplied name */ X if (!is_batch) { X if (file_count > 1) X break; X X file = strtok(list, " "); X /* dissect the file name */ X if ((name = strrchr(file, '/'))) X strcpy(file_name, name++); X else X strcpy(file_name, file); X } X /* get the modem7 file name */ X if (type == MODEM7) { X if (code = rcv_modem7(win, default_err)) X return(code +1); X X file = file_name; X } X /* get the block 0 */ X if (type == YMODEM || type == YMODEM_G) { X if (code = send_first(win, max_block, default_err)) X return(code +1); X X if (code = rcv_ymodem(win)) X return(code +1); X X /* at the end? */ X if (buf[3] == NULL) { X beep(); X wrefresh(win); X putc_line(ACK); X sleep(1); X return(0); X } X file = file_name; X } X /* any trouble ? */ X if (file_name[0] == NULL) X continue; X X clear_line(win, 3, 24, 1); X waddstr(win, file_name); X /* if file length is known */ X if (file_length) { X mvwprintw(win, 4, 24, "%-10d", file_length); X X secs = (file_length * 10.0 / dir->baud[dir->d_cur]) * performance; X hours = secs / 3600; X mins = (secs % 3600) / 60; X secs = (secs % 3600) % 60; X X mvwprintw(win, 6, 24, "%d:%02d:%02d", hours, mins, secs); X } X /* some starting numbers */ X mvwaddstr(win, 7, 24, "0 "); X if (file_length && fast) X mvwaddstr(win, 8, 24, "0% "); X if (fast) X mvwaddstr(win, 9, 24, "0 "); X mvwaddstr(win, 10, 24, "0 "); X clear_line(win, 12, 24, 1); X waddstr(win, "NONE"); X wrefresh(win); X X /* X * If the user supplied the name, write permission is checked X * by the get_names() routine in xfer_menu(). If a modem7 X * or ymodem supplied name, the permission is checked by the X * rcv_modem7() and rcv_ymodem() routines. X */ X /* open the file */ X if (!(fp = fopen(file, "w"))) { X beep(); X clear_line(win, 12, 24, 1); X wattrstr(win, A_BOLD, "CAN'T OPEN FILE"); X wrefresh(win); X cancel_xfer(); X return(1); X } X /* ACK the block 0 */ X if (type == YMODEM || type == YMODEM_G) X putc_line(ACK); X X if (code = send_first(win, max_block, default_err)) { X fclose(fp); X cancel_xfer(); X return(code +1); X } X /* here we go... */ X blk = 1; X block = 1; X recv = 0; X got_hdr = 1; X while (1) { X code = rcv_block(win, got_hdr, max_block, blk); X X if (code < 0) { X fclose(fp); X cancel_xfer(); X return(code +1); X } X got_hdr = 0; X /* are we done? */ X if (buf[0] == EOT) { X if (!is_batch) { X beep(); X wrefresh(win); X sleep(1); X } X break; X } X /* if not a duplicate block */ X if (!code) { X fwrite((char *) &buf[3], sizeof(buf[0]), block_size, fp); X mvwprintw(win, 7, 24, "%-5d", block); X if (fast) { X recv += block_size; X mvwprintw(win, 9, 24, "%-10d", recv); X } X blk++; X block++; X } X /* X * If the length is known, give the same status X * report as uploading X */ X if (file_length && fast) { X percent = recv * 100.0 / file_length; X if (percent > 100.0) X percent = 100.0; X mvwprintw(win, 8, 24, "%0.1f%%", percent); X } X wrefresh(win); X putc_line(ACK); X } X if (file_length && fast) { X mvwaddstr(win, 8, 24, "100% "); X wrefresh(win); X } X /* X * If the file length is not known, then search backwards X * from the end of the file until you find a character that X * is not the ^Z padding character X */ X if (!file_length) { X for (i=block_size+2; i>2; i--) { X if (buf[i] != CTRLZ) X break; X } X file_length = recv - block_size + i -2; X } X fclose(fp); X fix_length(file_name, file_length); X /* ACK the EOT */ X putc_line(ACK); X } X return(0); X} X X/* X * Send the first character to start the transmission and set the error X * checking method. Returns the standard error codes or 0 on success. X * The variables err_method and block_size are global. X */ X Xint Xsend_first(win, max_block, default_err) XWINDOW *win; Xint max_block, default_err; X{ X int i, err_count; X unsigned int sleep(); X /* default error method */ X err_method = default_err; X if (err_method > 1) X err_method--; X /* send the first char */ X err_count = 0; X while (err_count < MAX_ERRORS*2) { X mvwprintw(win, 10, 24, "%-2d", err_count); X X /* check for keyboard abort */ X if (wgetch(win) == 27) { X beep(); X clear_line(win, 12, 24, 1); X waddstr(win, "ABORTED"); X wrefresh(win); X sleep(3); X return(ABORT); X } X /* switch to checksum? */ X if (default_err == 1 && err_count > MAX_ERRORS) X err_method = 0; X X /* send error method code */ X clear_line(win, 5, 24, 1); X switch (err_method) { X case 0: X waddstr(win, "CHECKSUM"); X putc_line(NAK); X break; X case 1: X waddstr(win, "CRC"); X putc_line('C'); X break; X case 2: X waddstr(win, "NONE"); X putc_line('G'); X break; X } X /* X * We've cut the delay time in half, so we double X * the allowable errors X */ X if ((i = getc_line(5)) == -1) { X err_count++; X clear_line(win, 12, 24, 1); X waddstr(win, "NO RESPONSE"); X wrefresh(win); X continue; X } X buf[0] = i; X X switch(buf[0]) { X case SOH: /* small block follows */ X block_size = 128; X return(0); X case STX: /* large block follows */ X if (max_block == 1024) { X block_size = 1024; X return(0); X } X /* fall thru */ X default: X err_count++; X clear_line(win, 12, 24, 1); X waddstr(win, "BAD HEADER"); X wrefresh(win); X /* read some garbage... */ X fread_line(buf, 1028, 3); X putc_line(NAK); X break; X } X } X beep(); X clear_line(win, 12, 24, 1); X wattrstr(win, A_BOLD, "TIMED OUT"); X wrefresh(win); X return(ERROR); X} X X/* X * Receive a block of info from the host. Returns a 0 on success, a 1 on X * a duplicate block or the standard error codes. The variables X * err_method and block_size are global. X */ X Xint Xrcv_block(win, got_hdr, max_block, blk) XWINDOW *win; Xint got_hdr, max_block; Xunsigned char blk; X{ X int i, err_count, bad_block, out_of_sync, crc; X unsigned int packet, sleep(); X unsigned char calc_sum(), crc_1, crc_2; X X err_count = 0; X while (err_count < MAX_ERRORS) { X mvwprintw(win, 10, 24, "%-2d", err_count); X mvwprintw(win, 11, 24, "%-3d", tot_err); X X /* scan the keyboard for abort */ X if (wgetch(win) == 27) { X beep(); X clear_line(win, 12, 24, 1); X waddstr(win, "ABORTED"); X wrefresh(win); X sleep(3); X return(ABORT); X } X /* have we already got a hdr? */ X if (!got_hdr) { X if ((i = getc_line(10)) == -1) { X err_count++; X tot_err++; X clear_line(win, 12, 24, 1); X waddstr(win, "NO RESPONSE"); X wrefresh(win); X continue; X } X buf[0] = i; X /* what'd we get? */ X switch(buf[0]) { X case EOT: /* we're done! */ X clear_line(win, 12, 24, 1); X waddstr(win, "TRANSFER COMPLETE"); X wrefresh(win); X sleep(1); X return(0); X case SOH: /* small block follows */ X block_size = 128; X break; X case STX: /* large block follows */ X if (max_block == 1024) { X block_size = 1024; X break; X } X /* fall thru... */ X default: X err_count++; X tot_err++; X clear_line(win, 12, 24, 1); X waddstr(win, "BAD HEADER"); X wrefresh(win); X X /* flush a bad packet */ X fread_line(buf, 1028, 5); X putc_line(NAK); X continue; X } X } X got_hdr = 0; X /* read the rest of the packet */ X packet = block_size + 2 + (err_method ? 2 : 1); X if (fread_line(&buf[1], packet, 10) == -1) { X clear_line(win, 12, 24, 1); X waddstr(win, "TIMED OUT"); X wrefresh(win); X putc_line(NAK); X err_count++; X tot_err++; X continue; X } X X /* X * Validation of the packet includes checking the X * block number, its complement, and the crc/checksum. X */ X out_of_sync = 0; X if (buf[1] != blk || buf[2] != (unsigned char) ~blk) X out_of_sync++; X X bad_block = 0; X switch(err_method) { X case 0: /* checksum */ X if (buf[block_size +3] != calc_sum(&buf[3], block_size)) X bad_block++; X break; X case 1: /* CRC */ X crc = calc_crc(&buf[3], block_size); X crc_1 = crc >> 8; X crc_2 = crc; X if (buf[block_size +3] != crc_1 || buf[block_size +4] != crc_2) X bad_block++; X break; X case 2: /* none */ X return(0); X } X /* handle errors */ X if (bad_block) { X clear_line(win, 12, 24, 1); X if (err_method) X waddstr(win, "CRC FAILED"); X else X waddstr(win, "CHECKSUM FAILED"); X wrefresh(win); X putc_line(NAK); X err_count++; X tot_err++; X continue; X } X /* not really an error */ X if (out_of_sync) { X /* X * If a perfect packet is off by 1 block number, X * (a lost ACK could cause this) then treat it as X * a good block but don't write it to disk. X */ X if (buf[1] == (unsigned char) blk-1) X return(1); X X clear_line(win, 12, 24, 1); X waddstr(win, "OUT OF SYNC"); X wrefresh(win); X putc_line(NAK); X err_count++; X tot_err++; X continue; X } X return(0); X } X beep(); X clear_line(win, 12, 24, 1); X waddstr(win, "TOO MANY ERRORS"); X wrefresh(win); X return(ERROR); X} SHAR_EOF if test 10526 -ne "`wc -c < 'x_rcv.c'`" then echo shar: "error transmitting 'x_rcv.c'" '(should have been 10526 characters)' fi fi echo shar: "extracting 'x_send.c'" '(10461 characters)' if test -f 'x_send.c' then echo shar: "will not over-write existing file 'x_send.c'" else sed 's/^X//' << \SHAR_EOF > 'x_send.c' X/* X * Send a list of files using a version of Ward Christensen's file X * transfer protocol. A non-zero return code means an error must be X * acknowledged by the user. X */ X X#include <stdio.h> X#include <curses.h> X#include <sys/types.h> X#include <sys/stat.h> X#include "dial_dir.h" X#include "status.h" X#include "misc.h" X#include "xmodem.h" X Xint tot_err, err_method; X Xint Xsend_xmodem(win, list, type, fast) XWINDOW *win; Xchar *list; Xint type, fast; X{ X FILE *fp; X int i, block_size, file_count, secs, mins, hours, size, xmit_size; X int big_blocks, small_blocks, err_count, got_it, num, block, sent; X int crc, is_batch, code, max_block, default_err; X char *file, *strtok(), *name, *strrchr(); X unsigned char buf[1029], blk, calc_sum(); X unsigned int packet, sleep(); X float performance, percent; X struct stat sbuf; X X /* X * What type of xmodem? The default_err means: 0=checksum only, X * 1=checksum or CRC, 2=CRC only, and 3=none. X */ X switch(type) { X case XMODEM: X mvwaddstr(win, 2, 24, "xmodem"); X is_batch = 0; X default_err = 1; X max_block = 128; X performance = 1.36; X break; X case XMODEM_1k: X mvwaddstr(win, 2, 24, "xmodem-1k"); X is_batch = 0; X default_err = 1; X max_block = 1024; X performance = 1.09; X break; X case MODEM7: X mvwaddstr(win, 2, 24, "modem7"); X is_batch = 1; X default_err = 0; X max_block = 128; X performance = 1.36; X break; X case YMODEM: X mvwaddstr(win, 2, 24, "ymodem"); X is_batch = 1; X default_err = 2; X max_block = 1024; X performance = 1.09; X break; X case YMODEM_G: X mvwaddstr(win, 2, 24, "ymodem-g"); X is_batch = 1; X default_err = 3; X max_block = 1024; X performance = 1.02; X break; X } X X tot_err = 0; X file_count = 0; X mvwaddstr(win, 11, 24, "0 "); X X /* each one in the list */ X file = strtok(list, " "); X do { X /* is it a batch type ? */ X file_count++; X if (file_count > 1 && !is_batch) X break; X /* display the name */ X clear_line(win, 3, 24, 1); X if ((name = strrchr(file, '/'))) X name++; X else X name = file; X waddstr(win, name); X wrefresh(win); X /* get the file size */ X if (stat(file, &sbuf) < 0) { X beep(); X clear_line(win, 12, 24, 1); X wattrstr(win, A_BOLD, "CAN'T FIND FILE"); X wrefresh(win); X sleep(3); X continue; X } X X size = sbuf.st_size; X mvwprintw(win, 4, 24, "%-10d", size); X clear_line(win, 5, 24, 1); X X if (access(file, 4)) { X beep(); X clear_line(win, 12, 24, 1); X wattrstr(win, A_BOLD, "PERMISSION DENIED"); X wrefresh(win); X sleep(3); X continue; X } X if (!(fp = fopen(file, "r"))) { X beep(); X clear_line(win, 12, 24, 1); X wattrstr(win, A_BOLD, "CAN'T OPEN FILE"); X wrefresh(win); X sleep(3); X continue; X } X /* get the xmit size */ X block_size = max_block; X big_blocks = 0; X small_blocks = 0; X if (block_size == 128) { X small_blocks = size / 128; X if (size % 128) X small_blocks++; X } X else { X big_blocks = size / 1024; X small_blocks = (size % 1024) / 128; X if (size % 128) X small_blocks++; X X if (small_blocks == 8 && !big_blocks) { X big_blocks++; X small_blocks = 0; X } X /* if tiny file */ X if (big_blocks == 0) X block_size = 128; X } X X xmit_size = (big_blocks * 1024) + (small_blocks * 128); X /* add block 0 to the size */ X if (type == YMODEM || type == YMODEM_G) X xmit_size += 128; X X secs = (xmit_size * 10.0 / dir->baud[dir->d_cur]) * performance; X hours = secs / 3600; X mins = (secs % 3600) / 60; X secs = (secs % 3600) % 60; X X mvwprintw(win, 6, 24, "%d:%02d:%02d", hours, mins, secs); X X /* some starting numbers */ X mvwaddstr(win, 7, 24, " "); X mvwaddstr(win, 8, 24, "0% "); X mvwaddstr(win, 9, 24, "0 "); X mvwaddstr(win, 10, 24, "0 "); X clear_line(win, 12, 24, 1); X waddstr(win, "NONE"); X wrefresh(win); X /* send the batch stuff */ X switch (type) { X case MODEM7: X if (code = rcv_first(win, default_err)) { X fclose(fp); X return(code +1); X } X X if (send_modem7(win, name)) { X fclose(fp); X return(1); X } X break; X case YMODEM: X case YMODEM_G: X if (code = rcv_first(win, default_err)) { X fclose(fp); X return(code +1); X } X X if (code = send_ymodem(win, name, size)) { X fclose(fp); X /* X * CANCEL now means that the other X * end can't open that file. X */ X if (code == CANCEL) X break; X return(code +1); X } X xmit_size -= 128; X break; X default: X code = 0; X break; X } X /* remote can't receive that file ? */ X if (code == CANCEL) X break; X /* wait for first character */ X if (code = rcv_first(win, default_err)) { X fclose(fp); X return(code +1); X } X /* here we go... */ X sent = 0; X block = 1; X blk = 1; X while (num = fread((char *) &buf[3], sizeof(buf[0]), block_size, fp)) { X X /* fill short block */ X if (num < block_size) { X for (i=num; i<block_size; i++) X buf[i+3] = CTRLZ; X } X X /* show current stats */ X mvwprintw(win, 7, 24, "%-5d", block); X if (fast) { X percent = sent * 100.0 / xmit_size; X mvwprintw(win, 8, 24, "%0.1f%%", percent); X mvwprintw(win, 9, 24, "%-10d", sent); X } X wrefresh(win); X X /* build the header */ X if (block_size == 128) X buf[0] = SOH; X else X buf[0] = STX; X X buf[1] = blk; X buf[2] = ~blk; X X /* build the error detection stuff */ X switch (err_method) { X case 0: /* checksum */ X buf[block_size+3] = calc_sum(&buf[3], block_size); X packet = block_size +4; X break; X case 1: /* CRC */ X crc = calc_crc(&buf[3], block_size); X buf[block_size+3] = crc >> 8; X buf[block_size+4] = crc; X packet = block_size +5; X break; X case 2: /* none */ X buf[block_size+3] = 0; X buf[block_size+4] = 0; X packet = block_size +5; X break; X } X X /* send the block */ X if (code = send_block(win, buf, packet)) { X fclose(fp); X return(code +1); X } X block++; X blk++; X sent += block_size; X X /* change block size ? */ X if (xmit_size - sent < 1024) X block_size = 128; X } X mvwaddstr(win, 8, 24, "100% "); X mvwprintw(win, 9, 24, "%-10d", sent); X /* at the end of the file */ X err_count = 0; X got_it = 0; X while (err_count < MAX_ERRORS) { X putc_line(EOT); X if (getc_line(10) == ACK) { X got_it++; X break; X } X err_count++; X } X clear_line(win, 12, 24, 1); X if (!got_it) { X /* X * So what??? We don't do anything if there is X * no acknowledge from the host!! X */ X waddstr(win, "NO ACKNOWLEDGE"); X } X else X waddstr(win, "TRANSFER COMPLETE"); X if (!is_batch) X beep(); X wrefresh(win); X sleep(2); X /* prepare to start again */ X fclose(fp); X } while (file = strtok((char *) NULL, " ")); X X /* X * The end of batch markers... For modem7 it's an ACK and EOT, for X * ymodem, it's an empty block 0. X */ X switch (type) { X case MODEM7: X if (code = rcv_first(win, default_err)) X return(code +1); X putc_line(ACK); X putc_line(EOT); X beep(); X wrefresh(win); X break; X case YMODEM: X case YMODEM_G: X if (code = rcv_first(win, default_err)) X return(code +1); X X if (code = send_ymodem(win, NULL, 0)) X return(code +1); X beep(); X wrefresh(win); X break; X default: X break; X } X return(0); X} X X/* X * Wait for the first character to start the transmission. This first X * character also sets the crc/checksum method. Returns the standard X * error codes, or 0 on success. The variable err_method is global. X */ X Xint Xrcv_first(win, default_err) XWINDOW *win; Xint default_err; X{ X int err_count; X unsigned int sleep(); X X err_count = 0; X while (err_count < MAX_ERRORS) { X X /* scan the keyboard for abort */ X if (wgetch(win) == 27) { X beep(); X clear_line(win, 12, 24, 1); X waddstr(win, "ABORTED"); X wrefresh(win); X sleep(3); X return(ABORT); X } X X /* scan the tty line */ X switch(getc_line(10)) { X case NAK: /* checksum marker */ X if (default_err < 2) { X mvwaddstr(win, 5, 24, "CHECKSUM"); X err_method = 0; X return(0); X } X err_count++; X break; X case 'C': /* CRC marker */ X if (default_err == 1 || default_err == 2) { X mvwaddstr(win, 5, 24, "CRC"); X err_method = 1; X return(0); X } X err_count++; X break; X case 'G': /* ymodem-g marker */ X if (default_err == 3) { X mvwaddstr(win, 5, 24, "NONE"); X err_method = 2; X return(0); X } X err_count++; X break; X case CAN: /* two CAN's and you're out! */ X if (getc_line(2) == CAN) { X beep(); X clear_line(win, 12, 24, 1); X wattrstr(win, A_BOLD, "REMOTE ABORTED"); X wrefresh(win); X return(CANCEL); X } X /* fall thru... */ X default: X err_count++; X break; X } X clear_line(win, 12, 24, 1); X waddstr(win, "BAD HEADER"); X mvwprintw(win, 10, 24, "%-2d", err_count); X wrefresh(win); X } X /* failed to get it right ? */ X beep(); X clear_line(win, 12, 24, 1); X wattrstr(win, A_BOLD, "TIMED OUT"); X wrefresh(win); X return(ERROR); X} X X/* X * Send a block of data, scan the keyboard for a user abort, and check X * the return codes from the host. Returns standard error codes or 0 X * on success. X */ X Xint Xsend_block(win, blk, packet) XWINDOW *win; Xunsigned char *blk; Xunsigned int packet; X{ X int err_count; X X err_count = 0; X while (err_count < MAX_ERRORS) { X /* write the block */ X write(status->fd, (char *) blk, packet); X /* scan the keyboard */ X if (wgetch(win) == 27) { X beep(); X clear_line(win, 12, 24, 1); X waddstr(win, "ABORTED"); X wrefresh(win); X sleep(3); X return(ABORT); X } X /* ymodem-g doesn't need ACKs */ X if (err_method == 2) X return(0); X /* wait for acknowledge */ X switch(getc_line(10)) { X case ACK: /* Hooray!! we got it */ X return(0); X case NAK: /* show our disappointment... */ X clear_line(win, 12, 24, 1); X if (err_method) X waddstr(win, "CRC FAILED"); X else X waddstr(win, "CHECKSUM FAILED"); X err_count++; X tot_err++; X break; X case CAN: /* two CAN's and you're out! */ X if (getc_line(2) == CAN) { X beep(); X clear_line(win, 12, 24, 1); X wattrstr(win, A_BOLD, "REMOTE ABORTED"); X wrefresh(win); X return(CANCEL); X } X /* fall thru... */ X default: X clear_line(win, 12, 24, 1); X waddstr(win, "RESENDING"); X err_count++; X tot_err++; X break; X } X mvwprintw(win, 10, 24, "%-2d", err_count); X mvwprintw(win, 11, 24, "%-3d", tot_err); X wrefresh(win); X } X /* failed to get it right */ X beep(); X clear_line(win, 12, 24, 1); X wattrstr(win, A_BOLD, "TOO MANY ERRORS"); X wrefresh(win); X return(ERROR); X} SHAR_EOF if test 10461 -ne "`wc -c < 'x_send.c'`" then echo shar: "error transmitting 'x_send.c'" '(should have been 10461 characters)' fi fi echo shar: "extracting 'x_win.c'" '(2758 characters)' if test -f 'x_win.c' then echo shar: "will not over-write existing file 'x_win.c'" else sed 's/^X//' << \SHAR_EOF > 'x_win.c' X/* X * Display the file transfer window, and invoke the transfer protocol. X */ X X#include <stdio.h> X#include <curses.h> X#include "dial_dir.h" X#include "misc.h" X#include "status.h" X#include "xmodem.h" X Xvoid Xxfer_win(list, up, type) Xchar *list; Xint up, type; X{ X WINDOW *xf_win, *newwin(); X int ret_code, fast, my_speed; X void xmodem_mode(), input_off(), line_set(), error_win(); X struct termio tbuf; X X if (status->fd == -1) { X error_win(0, "Not currently connected to any host", NULL); X return; X } X X xf_win = newwin(15, 44, 2, 30); X /* X * This window should be in the non-blocking mode, so we can X * scan the keyboard for input while transferring a file. X */ X nodelay(xf_win, 1); X /* basic window stuff */ X mvwaddstr(xf_win, 2, 14, "Protocol:"); X mvwaddstr(xf_win, 3, 13, "File name:"); X mvwaddstr(xf_win, 4, 13, "File size:"); X mvwaddstr(xf_win, 5, 4, "Error check method:"); X mvwaddstr(xf_win, 6, 5, "Est transfer time:"); X mvwaddstr(xf_win, 7, 11, "Block count:"); X mvwaddstr(xf_win, 8, 6, "Percent complete:"); X mvwaddstr(xf_win, 9, 5, "Bytes transferred:"); X mvwaddstr(xf_win, 10, 5, "Errors this block:"); X mvwaddstr(xf_win, 11, 5, "Total error count:"); X mvwaddstr(xf_win, 12, 10, "Last message: NONE"); X box(xf_win, '|', '-'); X X if (up) X mvwattrstr(xf_win, 0, 17, A_BOLD, " Uploading "); X else X mvwattrstr(xf_win, 0, 16, A_BOLD, " Downloading "); X mvwaddstr(xf_win, 14, 12, " Press ESC to abort "); X wrefresh(xf_win); X /* fix up the terminal mode */ X input_off(); X xmodem_mode(status->fd); X X /* X * Is your terminal slower than the xfer baud rate? For example: X * I'm at home with my PC and 1200 baud modem, I call my system X * at work so I can use their 2400 baud modems to call some other X * system. In this case, I don't wanna spend too much time updating X * my screen at 1200 baud, when I'm transferring the file at 2400 baud. X */ X my_speed = 0; X fast = 0; X X ioctl(0, TCGETA, &tbuf); X /* only reasonable values are here */ X switch(tbuf.c_cflag & CBAUD) { X case B300: X my_speed = 300; X break; X case B1200: X my_speed = 1200; X break; X case B2400: X my_speed = 2400; X break; X case B4800: X my_speed = 4800; X break; X case B9600: X my_speed = 9600; X break; X case B19200: X my_speed = 19200; X break; X } X if (my_speed >= dir->baud[dir->d_cur]) X fast++; X X if (up) X ret_code = send_xmodem(xf_win, list, type, fast); X else X ret_code = rcv_xmodem(xf_win, list, type, fast); X X nodelay(xf_win, 0); X /* prompt for a key on errors */ X if (ret_code) { X beep(); X clear_line(xf_win, 13, 9, 1); X wattrstr(xf_win, A_BOLD, "Press any key to continue"); X wrefresh(xf_win); X wgetch(xf_win); X } X werase(xf_win); X wrefresh(xf_win); X delwin(xf_win); X /* undo what xmodem_mode() did */ X line_set(); X return; X} SHAR_EOF if test 2758 -ne "`wc -c < 'x_win.c'`" then echo shar: "error transmitting 'x_win.c'" '(should have been 2758 characters)' fi fi echo shar: "extracting 'xmodem.c'" '(4611 characters)' if test -f 'xmodem.c' then echo shar: "will not over-write existing file 'xmodem.c'" else sed 's/^X//' << \SHAR_EOF > 'xmodem.c' X/* X * Miscellaneous routines to support the xmodem file transfer protocols. X */ X X#include <stdio.h> X#include <signal.h> X#include <termio.h> X#include <setjmp.h> X#include <sys/types.h> X#include <sys/stat.h> X#include "param.h" X#include "status.h" X#include "xmodem.h" X X/* X * Calculate the CRC for the given buffer X */ X Xint Xcalc_crc(buf, len) Xunsigned char *buf; Xint len; X{ X int crc, i; X X crc = 0; X while (--len >= 0) { X /* X * Some fancy foot work here... The algorithm looks good X * in assembly, but in C it looks horrible! X */ X crc = crc ^ (int) *buf++ << 8; X for (i=0; i<8; i++) { X if (crc & 0x8000) X crc = crc << 1 ^ 0x1021; X else X crc = crc << 1; X } X } X return(crc & 0xffff); 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 character from the line with a specified time-out period in X * seconds. If the function times-out, it returns a -1. X */ X Xjmp_buf gl_jmp; X Xint Xgetc_line(sec) Xunsigned int sec; X{ X int force_gl(); X unsigned char c; X unsigned int alarm(); X X signal(SIGALRM, force_gl); X if (setjmp(gl_jmp)) X return(-1); X X alarm(sec); X if (read(status->fd, (char *) &c, 1) <= 0) { X alarm(0); X return(-1); X } X alarm(0); X return(c); X} Xint Xforce_gl(dummy) Xint dummy; X{ X void longjmp(); X X longjmp(gl_jmp, 1); 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 Xjmp_buf rl_jmp; X Xint Xfread_line(buf, len, sec) Xunsigned char *buf; Xunsigned int len, sec; X{ X int i, force_rl(); X unsigned int alarm(); X X signal(SIGALRM, force_rl); X if (setjmp(rl_jmp)) X return(-1); X X alarm(sec); X /* X * Later, this will have some fine tuning to use more than X * single character I/O. X */ X for (i=0; i<len; i++) { X if (read(status->fd, (char *) buf++, 1) <= 0) { X alarm(0); X return(-1); X } X } X alarm(0); X return(0); X} Xint Xforce_rl(dummy) Xint dummy; X{ X void longjmp(); X X longjmp(rl_jmp, 1); 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 return(write(status->fd, (char *) &c, 1)); X} X X/* X * Put the tty driver in the mode suitable for xmodem transfers. X */ X Xvoid Xxmodem_mode(fd) Xint fd; X{ X struct termio tbuf; X X ioctl(fd, TCGETA, &tbuf); X /* X * Turn off the XON/XOFF flow control, turn off echoing, and X * switch to 8 bit no parity. Later, the VTIME and VMIN variables X * will be fine tuned, to allow for more efficient I/O. X */ X tbuf.c_cc[4] = 1; /* VMIN */ X tbuf.c_cc[5] = 0; /* VTIME */ X tbuf.c_iflag = 0; /* no flow control or mapping */ X tbuf.c_oflag = 0; /* no char mapping or delays */ X tbuf.c_lflag = 0; /* no echo or signals */ X tbuf.c_cflag &= ~PARENB; /* no parity */ X tbuf.c_cflag &= ~CSIZE; X tbuf.c_cflag |= CS8; /* 8 bit */ X X ioctl(fd, TCSETA, &tbuf); X ioctl(fd, TCFLSH, 2); X return; X} X X/* X * Cancel the file transfer. Send several ^X's to the remote, followed X * by an equal number of backspace (in case they have already aborted and X * we're really at the command line). X */ X Xvoid Xcancel_xfer() X{ X extern char file_name[15]; X X if (!strcmp(param->abort, "DELETE")) X unlink(file_name); X X putc_line(CAN); X putc_line(CAN); X putc_line(CAN); X putc_line(8); X putc_line(8); X putc_line(8); 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; Xint len; X{ X FILE *fp, *tempfp; X int num; X char *tempfile, *mktemp(); X unsigned char buf[BUFSIZ]; 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 = 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 tempfile = mktemp("trunXXXXXX"); X if (!(tempfp = fopen(tempfile, "w"))) { X fclose(fp); X return(1); X } X X while(len) { X num = (len > BUFSIZ) ? BUFSIZ : len; X fread((char *) buf, sizeof(buf[0]), num, fp); X fwrite((char *) buf, sizeof(buf[0]), num, tempfp); X len -= num; X } X X fclose(fp); X fclose(tempfp); X X if (unlink(file) < 0) X return(1); X X if (link(tempfile, file) < 0) X return(1); X X if (unlink(tempfile) < 0) X return(1); X X return(0); X} SHAR_EOF if test 4611 -ne "`wc -c < 'xmodem.c'`" then echo shar: "error transmitting 'xmodem.c'" '(should have been 4611 characters)' fi fi exit 0 # End of shell archive
kevin@kosman.UUCP (Kevin O'Gorman) (03/17/88)
I just went to unpack Pcomm, and there are four files that report errors in transmission. I am afraid it's tab expansion in two of them, and I don't quite know what to think of the other two. Anyway, here's what they look like after unpacking: -rw-rw-rw- 1 root users 32936 Mar 16 14:20 Doc -rw-rw-rw- 1 root users 6352 Mar 16 14:20 Pcomm.1 -rw-rw-rw- 1 root users 1033 Mar 16 14:21 getopt.c -rw-rw-rw- 1 root users 4774 Mar 16 14:21 s_tty.c Anyone have a good set? Anyone else have this problem? Is any of this significant?
ccs@lazlo.UUCP (Clifford C. Skolnick) (02/09/89)
I'm trying to get the latest pcomm running smoothly on my system. All seems to be going well, except for the dialing directory. It seems when I call up the directory, garbage appears to the left of the newly created boxed window. Does anyone else have this problem? A quick look at the code did not provide any insight. BTW I'm running 3.51, but did not install terminfo, and I did set the thing to compile with OLDCURSES defined. Cliff -- Clifford C. Skolnick | "You told me time makes it easy, but you never told me UUCP: ccs@lazlo.UUCP | time stands still" -- Gary Numan Phone: (716) 427-8046 | [Space for rent] | ...!rutgers!rochester!kodak!pcid!gizzmo!lazlo!ccs
kevin@kosman.UUCP (Kevin O'Gorman) (02/11/89)
In article <149@lazlo.UUCP> ccs@lazlo.UUCP (Clifford C. Skolnick) writes: >I'm trying to get the latest pcomm running smoothly on my system. All seems >to be going well, except for the dialing directory. It seems when I call up >the directory, garbage appears to the left of the newly created boxed >window. Does anyone else have this problem? A quick look at the code did >not provide any insight. BTW I'm running 3.51, but did not install terminfo, >and I did set the thing to compile with OLDCURSES defined. No such trouble here, unless you count the fact that the window starts in column two, so the stuff underneath shows through in column 1. I'm running terminfo, though.