egray@fthood.UUCP (02/04/89)
This is the Pcomm version 1.2 distribution package. 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. Some of the new features in v1.2 are: 1) Support for Berkeley flavors of Unix. (I'll admit that the Berkeley port could use some more testing). 2) Auto-login scripts (using Unix shell scripts). 3) External file transfer programs can have their names imbedded into the list of available protocols. 4) Faster operation through tunable I/O buffering. The distribution package is quite large... (about 450k total) and is broken into 8 parts for easier mailing. To keep from choaking any mailer along the way, I'm posting this over a two day period. There is a shell archive called "Unixpc.shar" that contains the files specific to the AT&T Unix PC 7300/3b1. Here is a complete manifest of the distribution package: Doc curses.c getopt.c passthru.c terminal.c Makefile d_delete.c help.c pexit.c tty_att.c Matches.1 d_lib.c info.c port.c tty_ucb.c Modem_break.1 d_manual.c init.c redial.c vcs.c Pcomm.1 d_menu.c input.c s_axfer.c vcs.h Pcomm.dial_dir d_print.c list_dir.c s_extrnl.c waitfor.c Pcomm.extrnl d_prompt.c ls_menu.c s_gen.c x_ascii.c Pcomm.modem d_revise.c m_lib.c s_menu.c x_batch.c Pcomm.param data_log.c macro.c s_modem.c x_extrnl.c Readme di_delay.c main.c s_prompt.c x_menu.c Release.notes di_win.c matches.c s_term.c x_rcv.c Sample dial.c misc.h s_tty.c x_send.c Unixpc.shar dial_dir.h modem.h screen.c x_win.c Waitfor.1 e_lib.c modem_break.c script.c xmodem.c admin.c expand.c n_shell.c st_line.c xmodem.h chg_dir.c extrnl.h p_lib.c status.h config.h getcwd.c param.h strings.c By the way, I intend to post bug fixes to comp.sources.bugs. Have fun... Emmet P. Gray US Army, HQ III Corps & Fort Hood ...!uunet!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: # Doc # This archive created: Fri Feb 3 07:35:14 1989 export PATH; PATH=/bin:/usr/bin:$PATH echo shar: "extracting 'Doc'" '(61114 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.2 X X X X X written by X X Emmet P. Gray X ...!uunet!uiucuxc!fthood!egray X X X X X X X Pcomm is a public domain telecommunication program for Unix that X is designed to operate similar to the MSDOS program, ProComm. X ProComm (TM) is copyrighted by Datastorm Technologies, Inc. X This is a completely new program and contains no ProComm source X code. This is not a Datastorm product. X X X X Table of Contents X X X X X 1. INTRODUCTION .......... 3 5. UTILITY FUNCTIONS ..... 20 X 1.1 Abbreviations ........ 3 5.1 Program information .. 20 X 1.2 Requirements ......... 3 5.2 Setup screen ......... 20 X 1.3 Support files ........ 4 5.3 Change directory ..... 20 X 5.4 Clear screen ......... 20 X 2. RUNNING PCOMM ......... 5 5.5 Toggle duplex ........ 20 X 2.1 Hot key .............. 5 5.6 Hang up the phone .... 20 X 2.2 Status line .......... 5 5.7 Printer logging ...... 21 X 2.3 Help screen .......... 6 5.8 Toggle CR - CR/LF .... 21 X 2.4 Exit Pcomm ........... 6 5.9 Break ................ 21 X X 3. SETUP SCREENS ......... 7 6. FILE FUNCTIONS ........ 22 X 3.1 Prompting ............ 7 6.1 External protocols ... 22 X 3.2 TTY setup ............ 8 6.2 Send files ........... 22 X 3.3 Modem setup........... 9 6.3 Receive files ........ 24 X 3.4 Terminal setup ....... 10 6.4 Pass thru mode ....... 24 X 3.5 General setup ........ 11 6.5 Directory ............ 25 X 3.6 ASCII transfer setup . 12 6.6 Screen dump .......... 25 X 3.7 External protocol .... 14 6.7 Start data logging ... 25 X 6.8 Toggle logging ....... 26 X 4. MAJOR FUNCTIONS ....... 15 X 4.1 Dialing dierctory .... 15 7. DIALING WINDOW ........ 27 X 4.2 Redial ............... 17 X 4.3 Keyboard macros ...... 17 8. AUTO-LOGIN SCRIPTS .... 28 X 4.4 Line settings ........ 18 8.1 Waitfor Command ...... 28 X 4.5 Exit Pcomm ........... 19 8.2 Matches Command ...... 29 X 4.6 Unix gateway ......... 19 8.3 Modem_break Command .. 29 X 8.4 Examples ............. 30 X X X X X X X Appendix A - Typical Modem Configuration ...... 31 X Appendix B - AT&T Unix PC 7300/3b1 Dial Codes . 32 X Appendix C - Using Telebit Trailblazers ....... 34 X X 1. 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 Auto-login shell scripts X +o Automatic redial feature X +o Supports popular file transfer protocols X +o External file transfer program support X +o Data logging (log of the terminal session) X +o Printer logging X +o Screen dump X +o Shell escapes X +o Help screen X +o Keyboard macros X +o User customization X +o Administrative logging of phone calls X +o Administrative limits on long distance access X X Pcomm does not emulate any particular terminal. Whatever X terminal you're on, is what the remote system "sees". X X 1.1 Abbreviations X X Pcomm uses the notation "^A-X" to mean control-A followed by the X letter X. The dash (-) in the notation is just for clarity; it X is not included in the actual command sequence. Also, there is X no distinction between upper and lower case letters. X X The following abbreviations appear in Pcomm: X X <CR> carriage return key (sometimes labeled "Enter") X <ESC> escape key X <SPACE> space bar X <DEL> del key X <up> up arrow key X <down> down arrow key X LF line feed character (control-J) X CR carriage return character (control-M) X X 1.2 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 X "U" in place of "up arrow" and the letter "N" in place of "down X arrow" (the letter "D" would have been a more obvious choice, X but, unfortunately, it is used elsewhere). X X 1.3 Support files X X Pcomm uses four support files, namely: X X pcomm.dial_dir the dialing directory X pcomm.extrnl the external file transfer programs 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 won't have write permission on these files, it's assumed that X they will copy one or more of these standard files to their own X directories and edit them to suit their needs. X X Pcomm can use the environmental variable "PCOMM" to search for X these "private" support files. If used, the variable must X contain the path to the directory containing the files. You can X "mix and match" the use of standard and private support files. X For example, the pcomm.modem file is rarely changed by the user X so there would be no need to copy that file to the private X directory. X X Pcomm also uses normal Unix shell scripts to perform the "chat" X sequences necessary to automatically log a user onto a system. X X The following directories are searched to find the support X files and the auto-login shell scripts: 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 default directory (compiled into Pcomm) X X 2. RUNNING PCOMM X X Pcomm has the following command line syntax. X X pcomm [-d directory] [-f system name] X X The "-d" option allows you to specify an additional path to be X used when searching for the Pcomm support files. This option is X often useful for "borrowing" someone else's dialing directory. X X The "-f" option is used to specify automatic dialing of an entry X in the dialing directory. The "name" field in the dialing X directory (described later) is checked against the string given X on the command line. If a match is found, that entry is X automatically dialed. The match does not consider upper and X lower case differences. X X 2.1 Hot key X X Pcomm uses a "hot key" to precede each command. (The value of X the hot key is a user tunable parameter, but for the purpose of X this 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 X example, to get the help screen, you type control-A (to get to X the command mode) then the number 0 (to display the help X screen). When a command is completed, Pcomm returns to the X terminal mode. X X NOTE: While in the command mode, the communication with the X remote system is temporarily suspended. X X 2.2 Status line X X Whenever Pcomm is in the command mode (or is not currently X connected to a remote) a status line is displayed at the bottom X of the screen. 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 2.3 Help screen X X The help screen gives a brief review of all the available X commands. To access the help screen type ^A and "0" (zero). X The typical help screen will 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-<down>| X | Keyboard Macros .. ^A-M Change Directory. ^A-B Pass Thru Mode. ^A-T | X | Line Settings .... ^A-P Clear Screen .... ^A-C Directory ..... ^A-F | X | Exit Pcomm ....... ^A-X Toggle Duplex ... ^A-E Screen Dump ... ^A-G | X | Unix Gateway ..... ^A-4 Hang Up Phone ... ^A-H Start Data Log. ^A-1 | X | Printer On/Off .. ^A-L Toggle Log .... ^A-2 | X | Toggle CR-CR/LF . ^A-3 | X | Break Key ....... ^A-7 | X | | X +------------------------ Press any key to continue ------------------------+ X X 2.4 Exit Pcomm X X To exit Pcomm, you 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 press the letter "y" (carriage return not required). X X 3. SETUP SCREENS X X Pcomm allows you to change many of the default parameters. The X setup screen is accessed by typing ^A and "s". The following X screen 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 6) External Proctol 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 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 press the escape key. X X Changes made affect the current Pcomm session only. To make the X changes become the default, you select the "s" option. X X 3.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 X for user input and to give more information on what is being X asked. Pcomm will beep at any illegal input. The escape key X <ESC> will abort any prompt. The prompt types are: X X +o Character prompt. Asks you to input a single X 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 X choose the current selection by pressing the carriage X return or change the selection by pressing the space X bar. X X 3.2 TTY setup X X The TTY setup allows you to assign the serial ports that Pcomm X is allowed to use, and what is attached to each port. A typical X TTY setup screen might look like this: X X -------------------------- TTY Setup --------------------------- X X TTY name Modem name Init speed X X 1) tty10 HAYES 0 X 2) tty11 HAYES 0 X 3) tty12 DIRECT 0 X 4) tty13 TELEBIT 0 X 5) tty13 FAST_TELEBIT 0 X 6) 0 X 7) 0 X 8) 0 X 9) 0 X 10) 0 X X A) Add a TTY entry X D) 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 type "A" at the prompt, etc. X X The TTY setup fields are: X X 1) TTY name. This is the name of the serial port that X Pcomm will be allowed to use. Notice that the path X component of the name, "/dev/" is not used. X X 2) Modem name. This a key word that is used later to X link the modem database with the TTY database. The name X could be any combination of letters or numbers (both X upper and lower 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) Init speed. Normally Pcomm will initialize the modem X at the baud rate in the dialing directory. If the init X speed is non-zero, the initialization string is always X sent at the specified baud rate. The baud rate is X selected from a "menu prompt". See Appendix C for more X information about the use of this feature. X X NOTE: It is often best to put the fastest modem/TTYs at the end X of the TTY database. X X 3.3 Modem setup X X The modem setup contains the commands to make the modem dial, X hang up the phone, etc. A typical modem setup screen might look X like this: X X -------------------------- Modem Setup ------------------------- X X 1) Modem name (1 of 4) ... HAYES X 2) Modem init string ..... ATS7=45S11=70E0Q0V1X4&D2! X 3) Dialing command ....... ATDT X 4) Dialing cmd suffix .... ! X 5) Hang up string ........ ~~+++~~ATH0! X 6) Auto baud detect ...... Y X 7) 300 baud connect ...... CONNECT! X 8) 1200 baud connect ..... CONNECT 1200 X 9) 2400 baud connect ..... CONNECT 2400 X 10) 4800 baud connect ..... X 11) 9600 baud connect ..... X 12) 19200 baud connect .... X 13) No connect string 1 ... BUSY X 14) No connect string 2 ... VOICE X 15) No connect string 3 ... NO CARRIER X 16) 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 key word that links the X modem database with the TTY database. A menu prompt is X used to select the modem name (and the remaining X parameters that go with it). The "(1 of 4)" field X indicates there are additional modems in the database. X X 2) Modem initialization string. This is sent to the X modem whenever the port is selected. Consult your modem X manual for the codes to be used. Notice the use of the X "!" character. This is the "character synonym" for the X carriage return. X X NOTE: See section 3.5 for the complete list of character X synonyms. To remove the special meaning of a character synonym, X you must prepend a "\" to the character. X X 3) Dialing command. The first part of the command to X make the modem dial. It is assumed that the phone X number will immediately follow. X X 4) Dialing command suffix. The last part of the command X to make the modem dial. Typically this will be the X carriage return "character synonym". X X 5) Hang up string. The command to make the modem hang X up the phone. The character synonym for a 1 second X pause is the tilde "~" character. X X 6) Auto baud detect. Should Pcomm attempt to change the X baud rate of the TTY to the baud rate matching the X connect string? This feature requires the connect X strings to be unique. X X 7-12) Connect strings. The return messages when the X modem has connected to the remote. If different X messages are returned for each baud rate at which the X modem answers, then they should be specified. X X NOTE: Pcomm uses the connect strings to determine which baud X rates the modem is capable of supporting. For example, if the X 4800 baud connect string is empty, Pcomm assumes the modem X can not support 4800 baud. X X NOTE: If two connect strings are very similar, (for example, X "CONNECT" is entirely contained in "CONNECT 1200"), it is X possible that the return code from the modem will match the X incorrect string. To prevent this from happening, use the X command synonym for the carriage return to terminate the shorter X string (for example, use "CONNECT!" instead of "CONNECT"). X X 13-16) No connect strings. The messages returned by the X modem when no connection is made. X X 3.4 Terminal setup X X The terminal setup allows you to define the hot key and the X mapping of the end-of-line characters. A typical terminal setup X menu will look like this: X X ---------------------- Terminal Setup -------------------------- X X 1) Hot key (decimal) ...... 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 X definable hot key. Consult an ASCII/decimal conversion X chart for the decimal values of other characters. X X 2) ASCII version of hot key. This is the printable X version of the hot key used by Pcomm in the help screen X and status line. X X 3) Duplex. A menu prompt is shown to select between X FULL duplex and HALF duplex. In the half duplex mode, X characters sent to the remote system are also sent to X the screen. (The duplex mode can also be changed "on X the fly" by the ^A-E command.) X X 4) Flow control. A menu prompt is shown to select X between XON/XOFF flow control and NONE. The flow X control selected here is used only during the terminal X session, not during file transfers. X X 5-6) CR translations. The end-of-line characters for X both incoming and outgoing carriage returns can be X altered to suit the remote system's needs. A menu X prompt provides the following choices: X X +o CR (no translation) X +o CR/LF translate CR to CR/LF X X The incoming CR translation can also be changed "on the X fly" with the ^A-3 command. X X 3.5 General setup X X The general setup allows you to define the character synonyms X and the default files used by the screen dump and other X features. A 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 8) Break character ........ % X X 9) Aborted downloads ...... KEEP X X 10) Connect delay (sec) .... 35 X 11) Redial delay (sec) ..... 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 X default when the data logging is activated (^A-1). The X log file name can be changed "on the fly" by the ^A-1 X command. X X 2) Screen dump file. The file name to be used for the X screen dump command (^A-G). X X 3) Strip high bit. Should Pcomm strip the eighth bit on X incoming and outgoing characters? A menu prompt allows X you to select YES or NO. This feature is not used X during file transfers. X X 4-8) Character synonyms. These are symbols that Pcomm X uses to represent special characters (or perform special X functions) when sending commands to the modem. Synonyms X are useful for entering and displaying special X characters in a human readable form. The synonyms are: X X +o Pause for 1 second X +o The carriage return character (control-M) X +o Convert the next character to control-xx X +o The escape character (control-[) X +o Send a modem break X X NOTE: To prevent the special meaning of one of these characters X prepend a "\" to it. X X 9) Aborted downloads. When a download aborts (fails), X should the partially completed file be kept? The menu X prompt allows "KEEP" or "DELETE". X X 10) Connect delay. The number of seconds Pcomm will X wait for the modem to return a status code. X X 11) Redial delay. The number of seconds to wait before X Pcomm tries to call the number again. X X 3.6 ASCII transfer setup X X This setup screen allows you to select options to be used for X ASCII uploads and downloads. A typical ASCII transfer setup X will look 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 ......... ADD CR X X ASCII DOWNLOAD X X 7) Transfer timeout (sec) . 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 X in that it copies outgoing characters to the screen. X The options are YES and NO. X X 2) Expand blank lines. Should a blank line (LF alone) X be expanded to a space and LF? Some BBS systems use a X blank line to signal the end of an ASCII upload. The X options are 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, X 100, or 150. X X 4) Pace output. Should each character sent be delayed? X Very old BBS systems may require this. The choice is X YES or NO. X X 5) CR translation. The menu prompt provides the X following choices for upload translations: X X +o NONE (no translation) X +o ADD LF translate CR to CR/LF 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 LF to CR/LF X +o STRIP remove the LF character X X 7) Transfer timeout. The number of seconds to be used X to determine the end of an ASCII download. You can halt X the transfer before the timer goes off by hitting the X <ESC> key. X X 8-9) Same as 5) and 6) above, except the translations X apply to ASCII downloading. X X 3.7 External protocol setup X X This setup screen allows you to imbed the name of external file X transfer programs into the list of available protocols. When X transferring files, the external program name will appear on the X list of options along with the built-in protocols. X X -------------------- External Protocol Setup ------------------- X X UPLOAD X X Name Command Line Requires file list? X 1) zmodem sz Y X 2) N X 3) N X X DOWNLOAD X X Name Command Line Requires file list? X 4) zmodem rz N X 5) N X 6) N X X ---------------------------------------------------------------- X OPTION ==> _ Press <ESC> to return X X To change a line (or add a new one), enter the line number at X the prompt. You will be prompted for the Name, the Command X Line, and the 'Requires file list?' flag. To remove an entry, X enter a single space character at the Name prompt. X X The Command Line is the Unix command that you would normally X type in to invoke the program (minus the names of the files to X be transferred). The last field in the setup is used to X indicate whether or not Pcomm should prompt for a list of file X names to be added to the command. X X NOTE: Pcomm adds a single space character and the file names X (if any) to the end of the command. X X NOTE: The program itself isn't "imbedded" into Pcomm (it still X gets called like any other external program), only the name and X invocation information is actually incorporated into Pcomm. X X 4. MAJOR FUNCTIONS X X When Pcomm is invoked without the "-f" command line option, X you're placed in the terminal mode with a blank screen and a X status line. However, since Pcomm hasn't yet selected a serial X port to use, characters typed at the blank screen are ignored. X Normally the first command you'll use is ^A-D to bring up the X dialing directory menu. X X 4.1 Dialing directory X X To dial another system, you 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 X dialing code such as "#5" in lieu of "5" alone. Long distance X codes could contain access numbers such as those that MCI and X Sprint require. X X A typical dialing directory will 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 Script/TTY | X | 1- Abbey Road 1 (512) 590-6036 2400-N-8-1 F | X | 2- Tel-Med-Com 555-8686 9600-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 Sample | 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) 19200-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>/<down> 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 characters are just for X looks, and don't get sent to the modem. To prevent the X stripping of one of these characters, prepend a "\" to it. 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 Script/TTY. The name of the shell script to be used X as a auto-login "chat" sequence. This field is also X used to specify a particular TTY for the entry. X X NOTE: On all hard-wired ports, the script field is used to X contain the name of the port. For example, if tty12 is a X hard-wired port to "System A", then the dialing directory entry X for "System A" will have "tty12" in the script field. X X The commands at the dialing directory prompt are: X X R) Revise (or add) a dialing directory entry or long X distance dialing code. Prompts you to save the changes X to disk. A typical revise screen would look like this: X X +--------------------------------------------------------------+ X | | X | Entry to revise? _ (Entry Number, +,-,@,#) | X | | X +--------------------------------------------------------------+ X X If a dialing directory entry is selected, each field of X the entry is shown with its current settings. You can X enter a new value, press a carriage return to skip past X a field, or enter a single space character to erase a X field. An <ESC> at any field will abort the command. X X P) Print (display) the long distance dialing codes. X X <up>/<down>) Scroll the dialing directory up or down 10 X lines. Use the up and down arrow keys to access this X feature. X X M) Manual dial. Prompts you for a phone number rather X than using a number already in the dialing directory. X X D) Delete an entry or a range of entries. Prompts you X to save the changes to disk. X X L) Print. Send the dialing directory to the printer or X a file of your choice. X X 1-100) Entry number. Dial the phone for that entry X number. If the script field contains the name of a X valid Unix shell script, that script is "played" after X the connection is made to perform the auto-login "chat" X sequences. See section 8 of this manual for more X details on the format and use of auto-login shell X scripts. X X NOTE: To access the port directly without dialing (perhaps to X send the dial codes yourself), select an empty entry or enter a X single space character at the phone number prompt of the manual X dial option. X X <CR> Carriage return. Scroll the dialing directory down X one line. X X 4.2 Redial X X The redial feature is a misnomer; it really is a queuing system X that allows Pcomm to dial several numbers in a cycle until one X of them answers. X X When you invoke the redial command with ^A-R, you're prompted X for a list of dialing directory numbers. (You may also prepend X a long 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. An <ESC> aborts this command. X X 4.3 Keyboard macros X X Keyboard macros are used as a shortcut to send commonly used X strings to the remote system with only a few keystrokes. The X characters used to identify the macros are the shifted number X keys. For example, if the string "hello" was assigned to the X "!" key (the shifted number 1 key), then when you press ^A-!, X the string "hello" is sent to the remote. X X To review or edit the keyboard macros, you type ^A-M. The X following screen will appear: X X +------------------------------------------------------+ X | Keyboard Macros | X |------------------------------------------------------| X | | X | ^A-! hello | X | ^A-@ | X | ^A-# | X | ^A-$ | X | ^A-% | X | ^A-^ | X | ^A-& | X | ^A-* | X | ^A-( | X | ^A-) | X | | X | Macro key to revise: _ | X | | X +---------------- Press <ESC> to continue -------------+ X X To edit a macro, you type the macro key character (without the X leading hot key). After typing the new string information, you X will be prompted to save the changes to disk. To erase an entry X enter a single space character. X X NOTE: All of the character synonyms described in section 3.5 X are available for use with the keyboard macros. X X 4.4 Line settings X X The line settings menu is invoked by ^A-P. A typical line X settings menu will 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 While dialing a remote, the line settings in the dialing X directory entry are automatically used. Therefore the line X settings menu is used to fine tune the values during a terminal X session or to select the parameters for manual dialing. You can X make the current setting the default by selecting the "Save X Changes" option. X X The current line settings are also displayed in the status line. X X NOTE: During file transfers, certain parameters (namely the X data bits and parity) will be temporarily changed. The status X line will *not* reflect these temporary promotions. X X 4.5 Exit Pcomm X X To exit Pcomm, you type ^A-X. The phone is hung up (if a call X was in progress), the print and data logging features are X closed, and the TTY resources are released. X X NOTE: Pcomm drops the DTR (Data Terminal Ready) on the port X before exiting to Unix. X X 4.6 Unix gateway X X To temporarily suspend Pcomm and spawn a Unix shell, you type X ^A-4. To return to Pcomm, you exit the shell normally, X typically with ^D or "exit". X X NOTE: The SHELL environmental variable is used to determine X which program to invoke. X X 5. UTILITY FUNCTIONS X X The following commands perform secondary functions. X X 5.1 Program information X X To display the opening information screen, you type ^A-I. Press X any key to return to the terminal mode. X X 5.2 Setup screen X X The setup screens are described in detail in section 3 of this X manual. X X 5.3 Change directory X X To change the current working directory while still inside X Pcomm, you type ^A-B. A screen similar to the following will X appear: X X +-- Change directory ------------------------------------------+ X | | X | Current directory: /usr/egray | X | New directory: _ | X | | X +--------------------------------------------------------------+ X X Abbreviations known to the shell are acceptable; for example, X the "~" character will be translated to the home directory in X the csh or ksh shell. X X 5.4 Clear screen X X To clear the local screen and home the cursor, you type ^A-C. X X NOTE: The remote system may not "know" the screen has been X cleared, and may make assumptions about the screen that are X incorrect. X X 5.5 Toggle duplex X X The ^A-E command changes the duplex mode from FULL to HALF, or X from HALF to FULL. The status line shows the current duplex X mode. X X 5.6 Hang up the phone X X To hang up the phone, you type ^A-H. The word "disconnecting" X will briefly show in the status line. X X NOTE: Pcomm drops the DTR (Data Terminal Ready) after sending X the hang up string. X X 5.7 Printer logging X X The ^A-L command toggles the printer logging on or off. The X current printer status is displayed in the status line. X X NOTE: Since all printing goes to the normal Unix print spool X program, the characters will not print on the printer as they X appear on the screen. The printing will actually begin when the X printer logging is turned *off* and the complete print job is X sent to the spool. X X NOTE: Due to a technical limitation of Pcomm, characters typed X while in the half duplex mode will not appear in the print log. X X 5.8 Toggle CR - CR/LF X X The ^A-3 command toggles the incoming line termination X characters between CR and CR/LF. The status line shows X the current settings (in the next to the last field). X X 5.9 Break X X The ^A-7 command sends a modem break to the remote system. The X word "break" is (very) briefly displayed on the status line. X X NOTE: This not the same as the break key on the keyboard (we X don't want to send a break to the local system, we want to send X it to the *remote*). X X 6. FILE FUNCTIONS X X One of the most important features of a telecommunication X program is the ability to transfer files. The following file X transfer protocols are implemented: 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 zmodem *4 128/1024 CRC yes X (external) ? ? ? X X Notes: 1 CP/M style file name X 2 MSDOS style file name and file size X 3 Not needed! X 4 zmodem is implemented as an external program X X NOTE: The built-in protocols that send file name information, X convert the Unix style file name to fit the MSDOS name X restrictions. X X 6.1 External protocols X X The external "protocol" is really a method of running an X external program from Pcomm to accomplish a file transfer. The X most common use of this feature would be to run Kermit or some X proprietary program. X X Frequently used external file transfer programs (such as zmodem) X can have their names imbedded into the list of available X protocols by using the External Protocol Setup in section 3.7. X X To abort an external file transfer, you hit the <ESC> key. All X other characters typed at the keyboard are ignored. X X NOTE: The external protocol feature can also be used (misused?) X to pipe the output of a Unix command to the remote. X X 6.2 Send files X X To send a file to the remote, you'll first have to instruct the X remote system to receive the file, then type ^A-"up arrow". The X following screen will 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 | 7) zmodem | X | E) (external) | X | | X | <ESC> to Abort | X | | X | Protocol: _ | X +------------------+ X X You then select the type of protocol at the prompt, and another X window similar to this will appear: X X +-- Send xmodem -----------------------------------------------+ X | | X | Enter filename: _ | X | | X +--------------------------------------------------------------+ X X Now you 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 screen similar to the X 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 X complete", and "bytes transferred" fields will be continuously X updated. If errors occur the "errors this block" and "total X error count" fields will be updated and the "last message" field X will contain a message about the error. X X At the end of the transfer, Pcomm will beep and return to the X terminal mode. If an error occurred and the transfer was X aborted, you will be prompted to acknowledge the error by X pressing a key before returning to the terminal mode. X X 6.3 Receive files X X To receive a file (or group of files) from a remote system, X you'll have to first instruct the remote system, then type X ^A-"down arrow". Receiving a file is basically the same as X sending a file. X X NOTE: Some systems do not pad the end of the file with X control-Z's and therefore files might grow in length when X received. X X NOTE: Due to a technical limitation of Pcomm, characters X received during an ASCII download will not reappear on the X screen when you return to the terminal mode. X X 6.4 Pass thru mode X X The pass through mode is used when you have two or more machines X in a communications daisy chain. The following diagram shows X an example of this type of arrangement: X X +---------+ +---------+ +---------+ X | IBM PC | | Unix | | IBM PC | X | running | -------> | running | -------> | running | X | ProComm | <------- | Pcomm | <------- | RBBS | X +---------+ +---------+ +---------+ X X If a file is to be transferred from the last machine to the X first machine, the middle machine must appear completely X transparent. The middle machine must "forward the data" without X altering it in any way. The pass through mode "expires" after a X designated period of inactivity, after which the user is X returned to the terminal mode. X X To access the pass through mode, you type ^A-T. The following X screen will appear: X X +-- Pass Thru Mode --------------------------------------------+ X | | X | Enter the expiration time (5-60 sec) : _ | X | | X +--------------------------------------------------------------+ X X NOTE: While in the pass through mode, no Pcomm command to the X middle machine will be honored. Therefore, the *only* way to X exit this mode is to not type anything on the keyboard until the X expiration period has elapsed. X X NOTE: The baud rates to and from the middle machine need not be X the same, however the slowest speed determines the overall speed X of the transfer (the weakest link in the chain). X X 6.5 Directory X X To obtain a listing of a directory on the local system while X still running Pcomm, you type ^A-F. The following screen will X appear: X X +-- List Directory --------------------------------------------+ X | | X | Current directory: /usr/egray | X | File spec (wildcards allowed): _ | X | | X +--------------------------------------------------------------+ X X Abbreviations known to the shell are valid. Output is sent X through a "more" like program. X X NOTE: Since we're really doing a popen() to the "ls" command, X additional command line options are also valid. X X 6.6 Screen dump X X To dump the contents of the current screen (minus any windows X showing) you type ^A-G. The contents of the screen are written X to the file specified in the general setup for this purpose. If X the file already exists, the screen contents are appended to the X file. The message "screen dump" will briefly appear in the X status line. X X NOTE: The screen contents are subject to the available VCS X (video command sequence) emulation, so an exact representation X is not guaranteed. X X 6.7 Start data log X X To start the data logging, or change the file used for data X logging, you type ^A-1. The following screen will 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 X prompt, otherwise, enter a new file name. If the file already X exits, the new data is appended to the file. X X The status of the logging is shown in the status line. X X NOTE: Due to a technical limitation of Pcomm, characters typed X while in the half duplex mode will not appear in the log file. X X 6.8 Toggle logging X X To temporarily suspend data logging or to start it again without X being prompted for the file name, you type ^A-2. X X 7. 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 | Redial delay time: 5 | X | Script/TTY: | X | Result of last try: | X | | X | <SPACE>: Recycle <DEL>: Remove from queue E: Change delays | X | | X +------------------------- Press <ESC> to abort -----------------------+ X X The options available during the dialing window are: X X SPACE) Press the space bar to stop the dialing of the X current entry and go on to the next entry in the queue. X If there is only one entry in the queue, that number is X redialed. X X DEL) Press the DEL key to remove the current number from X the queue. X X E) Press the letter "E" to change the connect delay X time, or the redial delay time (the pause between X dialing attempts). You will be prompted to save the X changes to disk. X X NOTE: While the DEL and E options are being processed, the X dialing is temporarily suspended. X X 8. AUTO-LOGIN SCRIPTS X X Pcomm doesn't have a built-in script language, instead it uses X Unix shell scripts (Bourne shell, C shell, or Korn shell) to X perform the necessary "chat" sequences to log a user on to a X remote system. X X Since shell scripts are run "outside" of Pcomm, they cannot X contain Pcomm commands. For example, an auto-login script X cannot dial a phone number or turn on the data logging feature. X The auto-login scripts are run *after* the connection to the X remote system has been made. X X You may hit the <ESC> key at any time to abort an auto-login X script before it has completed. All other characters typed at X the keyboard are ignored. X X WARNING: Any file that has a "clear text" (un-encrypted) X version of your password is a significant security threat. You X should remove the read permission to all others. X X In order to assist in the creation of auto-login scripts, the X following external programs have been provided. X X 8.1 Waitfor Command X X The waitfor command has the following syntax: X X waitfor -n string X X where "n" is the number of seconds to wait and "string" is the X string to wait for. X X Waitfor returns a 0 if the string was found, a 1 if it didn't X find the string within the allotted time, and a -1 if there was X an error. Waitfor returns immediately if the string is found. X X The waitfor command would typically be used in a script to X indicate that the desired prompt has appeared. For example: X X waitfor -5 "ogin:" X if [ "$?" -eq 0 ] X then X echo "egray" X fi X X would wait up to 5 seconds for the string "ogin:". If the X return code is 0 (the strings did apear), send the string X "egray" (my user ID). X X NOTE: Upper and lower case letters are considered different. X If you are not sure if the prompt is "Login:" or "login:", then X skip the first letter in the string and use "ogin:". X X 8.2 Matches Command X X The matches command has the following syntax: X X matches string1 string2 X X Matches returns a 0 if string2 is contained in string1, and X returns a 1 if it does not. Unlike waitfor, the matches command X does not read the TTY port. X X The matches command could be used to test string values such as: X X read junk X matches $junk "login failed" X if [ "$?" -eq 0 ] X then X exit X fi X X 8.3 Modem_break Command X X The modem_break command performs a modem break on the TTY. It X would often be used to tell the remote system to switch to X another baud rate. X X The modem_break program has no command line arguments. X X 8.4 Examples X X It is not my intention to teach the reader the fundamentals of X Unix shell programming. There are several good books on the X subject available in stores. X X Remember to add execute permission to the file and remove the X read permission to all others. X X The simplest auto-login script may contain the following: X X # send a <CR> X echo "" X # wait 5 seconds for the login prompt X waitfor -5 ogin: X # send my user ID X echo "egray" X # wait 5 seconds for the password prompt X waitfor -5 assword: X # send my password X echo "abcdefg" X # return to Pcomm X exit 0 X X A more complex script is required if the user must send a modem X break to syncronize the baud rate of the remote. For example: X X echo "" X try=0 X # loop until done X while true X do X # wait 5 seconds for the login prompt X waitfor -5 ogin: X # test the exit code of the waitfor command X if [ "$?" -eq 0 ] X then X # send my user ID and exit the loop X echo "egray" X break X fi X X # increment the number of attempts X try=`expr $try + 1` X # test to see if we should give up X if [ "$try" -eq 5 ] X then X exit 1 X fi X X # send a modem break and loop again X modem_break X echo "" X done X # wait 5 seconds for the password prompt X waitfor -5 assword: X # test the return code from waitfor X if [ "$?" -eq 0 ] X then X # send my password X echo "abcdefg" X else X exit 1 X fi X # return to Pcomm X exit 0 X X Appendix A X X Typical Modem Configuration X X I can't begin to describe how to configure every modem to work X with Pcomm. There are, however, several guidelines that will X apply to virtually any modem. X X 1) Pcomm doesn't care about the DCD (Data Carrier X Detect) settings of the modem. X X 2) It would be nice (but not essential) if the loss of X the DTR (Data Terminal Ready) caused the modem to hang X up. X X 3) Pcomm doesn't care if commands are echoed back by the X modem (it might save a few milliseconds if echoing was X turned off). X X 4) Some sort of result codes are required. Numeric X result codes are ok... but since they are displayed on X the screen, word result codes will make more sense. X X 5) If the modem can return different result codes for X each baud rate at which it answers, then by all means, X use them. X X 6) Anything that is returned by the modem, but not X listed in the modem setup, is ignored. X X 7) Systems running uugetty (the bi-directional version X of getty that comes with HDB uucp) should include extra X commands in the initialization string to assure that X uugetty switches to its dial out mode. Normally, X "AT!~AT!~" causes enough dialogue to force uugetty to X release the line. X X For example, a 2400 baud Hayes compatible modem might be X configured with the following command: X X AT S7=45 S11=70 E0 Q0 V1 X4 &D2 X X AT Hayes attention command X S7=45 Wait 45 seconds for an answer X S11=70 70 ms touch tone dialing X E0 Don't echo commands (not essential) X Q0 Turn result codes on X V1 Return word result codes X X4 Use as many result codes as you've got X &D2 Hang up when DTR is lost (nice to have) X X X Appendix B X X AT&T Unix PC 7300/3b1 X Dial Codes X X The dialing codes used by the OBM (On Board Modem) are not X straight-forward. The modem setup, as distributed, looks like X this: X X -------------------------- Modem Setup ------------------------- X X 1) Modem name (1 of 2) ... OBM X 2) Modem init string ..... X 3) Dialing command ....... % X 4) Dialing cmd suffix .... @ X 5) Hang up string ........ X 6) Auto baud detect ...... N X 7) 300 baud connect ...... CONNECT X 8) 1200 baud connect ..... CONNECT X 9) 2400 baud connect ..... X 10) 4800 baud connect ..... X 11) 9600 baud connect ..... X 12) 19200 baud connect .... X 13) No connect string 1 ... X 14) No connect string 2 ... X 15) No connect string 3 ... X 16) No connect string 4 ... X X ---------------------------------------------------------------- X OPTION ==> _ Press <ESC> to return X X The relevant fields of the modem setup are: X X 1) Modem name. This must be "OBM". X X NOTE: Pcomm uses the modem name as a flag to determine which X dialing method to use. The string "OBM" is a "reserved word" X that Pcomm uses to switch to the AT&T Unix PC 7300/3b1 dialing X method. X X 3) Dialing command. This should be "%" for touch tone X dialing or "^" for pulse dialing. X X 4) Dialing cmd suffix. This must be the "@" character. X X 6) Auto baud detect. The OBM cannot use the auto baud X detect feature. X X 7-8) Connect strings. Although the OBM doesn't actually X return any result codes, these fake fields are required. X X Additional OBM dialing codes from the phone(7) manual: X X "~" wait for next dial tone X "," pause 2 seconds X ":" pause 10 seconds X "&" perform a hookflash X "%" begin tone dialing X "^" begin pulse dialing X X These codes can be inserted into the phone number string, for X example: X X 555-1234~56 dial 555-1234, wait for tone, dial 56 X 9,555-1234 dial 9, wait 2 seconds, dial 555-1234 X %555^1234 dial 555 using tone, 1234 using pulse X X NOTE: The dialing codes for the OBM are not subject to X character synonym translations, therefore the "%", "^", and "~" X characters do NOT have to be preceded by the "\" character to X remove their special meaning. X X Appendix C X X Using Telebit Trailblazers X X The Telebit Trailblazer modem is probably representative of the X newer high speed intelligent modems available today and X therefore warrants a more detailed discussion. X X 1) Locked interface speed X X Trailblazers have the ability to maintain a locked X interface speed with the computer without regard to the X connected baud rate. For example, some people find it X necessary to lock the interface speed at 9600 baud (or X some other speed) for normal operations. However, Pcomm X assumes the interface speed is the same as the connected X baud rate. X X The "init speed" field of the TTY database was created X to solve this problem. If this value is non-zero, Pcomm X will send the initialization string to the modem at this X baud rate. Normally, Pcomm would use the baud rate in X the dialing directory to send the init string. X X The init string would now contain the codes to unlock X the interface, enter the autobaud mode on receipt of a X break, and arrange for the loss of the DTR to return the X modem to its previous locked state. For Telebit X Trailblazers this would be S66=0, S51=255, and S52=2. X X 2) Multiple setups X X Users of Trailblazers often require a different "init X string" or "dial string" depending on the target baud X rate. For example, the init strings for 9600 and 19200 X baud may contain the command "S50=255" (to wait for the X Telebit PEP tones) whereas the slower init strings would X contain "S50=0". X X This problem is solved by creating an additional modem X entry in the modem database. For example, you could X have an entry called "TELEBIT" for baud rates in the X range of 300-2400 and another entry called X "FAST_TELEBIT" for baud rates in the range of X 9600-19200. X X Pcomm uses the connect strings to determine if the modem X can handle the requested baud rate. So, if the X "TELEBIT" entry had connect strings for 300, 1200, and X 2400 baud it would be selected only if the requested X baud rate was in that range. Likewise, the FAST_TELEBIT X would have connect strings only for 9600 and 19200 baud. X X 3) Baud rate synchronization X X In contrast to the Hayes 2400 modem, the Trailblazer X does not immediately synchronize with the serial port X when the baud rate is changed during the modem's command X mode. X X To solve this problem, the init string and dial string X should contain the break character synonym followed by a X sufficient number of A's to allow the modem to X synchronize. The default character synonym for a modem X break is the "%". X X 4) Sample TTY database X X The following is the contents of the sample TTY database: X X TTY name Modem name Init speed X X 1) tty10 HAYES 0 X 2) tty11 HAYES 0 X 3) tty12 DIRECT 0 X 4) tty13 TELEBIT 0 X 5) tty13 FAST_TELEBIT 0 X X Notice that entries 4 and 5 share the same TTY. X X NOTE: The examples assume the modem interface speed is not X locked. See paragraph 1 for additional codes to be added to the X init string if the lock interface feature is used. X X 5) Sample modem database entry for TELEBIT X X The third entry in the sample modem database is for the X Telebit Trailblazer designated for use at slow speeds. X X 1) Modem name (3 of 4) .... TELEBIT X 2) Modem init string ...... %AAAAAATS50=0S2=43S95=0M1! X 3) Dialing command ........ %AAAAAATDTW X 4) Dialing cmd suffix ..... ! X 5) Hang up string ......... ~~+++~~ATH0! X 6) Auto baud detect ....... Y X 7) 300 baud connect ....... CONNECT 300 X 8) 1200 baud connect ...... CONNECT 1200 X 9) 2400 baud connect ...... CONNECT 2400 X 10) 4800 baud connect ..... X 11) 9600 baud connect ..... X 12) 19200 baud connect .... X 13) No connect string 1 ... BUSY X 14) No connect string 2 ... ERROR X 15) No connect string 3 ... NO CARRIER X 16) No connect string 4 ... X X 6) Sample modem database entry for FAST_TELEBIT X X The 4th entry is for the Telebit Trailblazer designated X for use at higher speeds. X X 1) Modem name (4 of 4) .... FAST_TELEBIT X 2) Modem init string ...... %AAAAAATS50=255S2=43S95=0M1! X 3) Dialing command ........ %AAAAAATDTW X 4) Dialing cmd suffix ..... ! X 5) Hang up string ......... ~~+++~~ATH0! X 6) Auto baud detect ....... N X 7) 300 baud connect ....... X 8) 1200 baud connect ...... X 9) 2400 baud connect ...... X 10) 4800 baud connect ..... X 11) 9600 baud connect ..... CONNECT X 12) 19200 baud connect .... CONNECT X 13) No connect string 1 ... BUSY X 14) No connect string 2 ... ERROR X 15) No connect string 3 ... NO CARRIER X 16) No connect string 4 ... echo shar: "48 control characters may be missing from 'Doc'" SHAR_EOF if test 61114 -ne "`wc -c < 'Doc'`" then echo shar: "error transmitting 'Doc'" '(should have been 61114 characters)' fi fi exit 0 # End of shell archive
egray@fthood.UUCP (02/04/89)
This is part 2 (of 8) to the Pcomm v1.2 distribution package. Emmet P. Gray US Army, HQ III Corps & Fort Hood ...!uunet!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 # Matches.1 # Modem_break.1 # Pcomm.1 # Pcomm.dial_dir # Pcomm.extrnl # Pcomm.modem # Pcomm.param # Readme # Release.notes # Sample # Unixpc.shar # Waitfor.1 # This archive created: Fri Feb 3 07:35:17 1989 export PATH; PATH=/bin:/usr/bin:$PATH echo shar: "extracting 'Makefile'" '(5364 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#for 80286 versions of SCO Xenix X#CFLAGS = -Od -DM_TERMINFO -Mle2 -LARGE X#LDFLAGS = -SEG 1000 -F 5000 -Mle2 X#CURSES = -ltinfo -lx X#TERMLIB = -ltinfo -lx X XCFLAGS = -O XLDFLAGS = -s XSHAR = shar -a XBIN = /usr/local/bin X X#for old curses(3) or Berkeley systems X#CURSES = -lcurses -ltermcap X#TERMLIB = -ltermcap XCURSES = -lcurses XTERMLIB = -lcurses X X#for systems without getcwd(3) or getopt(3) X#GETCWD = getcwd.o X#GETOPT = getopt.o X X#for System V or Berkeley worlds X#BSD = -DBSD X#TTY = tty_ucb.o XBSD = XTTY = tty_att.o X XPCOMM = $(GETCWD) $(GETOPT) $(TTY) admin.o chg_dir.o curses.o d_delete.o \ X d_lib.o d_manual.o d_menu.o d_print.o d_prompt.o d_revise.o \ X data_log.o di_delay.o di_win.o dial.o e_lib.o expand.o help.o \ X info.o init.o list_dir.o ls_menu.o m_lib.o macro.o main.o \ X n_shell.o p_lib.o passthru.o pexit.o port.o redial.o s_axfer.o \ X s_extrnl.o s_gen.o s_menu.o s_modem.o s_prompt.o s_term.o \ X s_tty.o screen.o script.o st_line.o strings.o terminal.o x_ascii.o \ X x_batch.o x_extrnl.o x_menu.o x_rcv.o x_send.o x_win.o xmodem.o X XINPUT = input.o vcs.o X Xall: pcomm pcomm_input waitfor matches modem_break X Xpcomm: $(PCOMM) X $(CC) $(LDFLAGS) $(PCOMM) -o pcomm $(CURSES) X Xpcomm_input: $(INPUT) X $(CC) $(LDFLAGS) $(INPUT) -o pcomm_input $(TERMLIB) X Xwaitfor: X $(CC) $(CFLAGS) $(BSD) $(LDFLAGS) waitfor.c -o waitfor X Xmatches: X $(CC) $(CFLAGS) $(LDFLAGS) matches.c -o matches X Xmodem_break: X $(CC) $(CFLAGS) $(BSD) $(LDFLAGS) modem_break.c -o modem_break X Xinstall: X cp pcomm $(BIN) X cp pcomm_input $(BIN) X cp waitfor $(BIN) X cp matches $(BIN) X cp modem_break $(BIN) X# rm pcomm X# rm pcomm_input X# rm waitfor X# rm matches X# rm modem_break X Xlint: X lint -p -Dlint admin.c chg_dir.c curses.c d_delete.c d_lib.c \ X d_manual.c d_menu.c d_print.c d_prompt.c d_revise.c data_log.c \ X di_delay.c di_win.c dial.c e_lib.c expand.c getcwd.c getopt.c \ X help.c info.c init.c list_dir.c ls_menu.c m_lib.c macro.c main.c \ X n_shell.c p_lib.c passthru.c pexit.c port.c redial.c s_axfer.c \ X s_extrnl.c s_gen.c s_menu.c s_modem.c s_prompt.c s_term.c s_tty.c \ X screen.c script.c st_line.c strings.c terminal.c tty_att.c \ X x_ascii.c x_batch.c x_extrnl.c x_menu.c x_rcv.c x_send.c x_win.c \ X xmodem.c X lint -p -Dlint input.c vcs.c X lint -p -Dlint $(BSD) waitfor.c X lint -p -Dlint matches.c X lint -p -Dlint $(BSD) modem_break.c X Xshar: X $(SHAR) Doc > pcomm_sh.1 X $(SHAR) Makefile Matches.1 Modem_break.1 Pcomm.1 Pcomm.dial_dir \ X Pcomm.extrnl Pcomm.modem Pcomm.param Readme Release.notes Sample \ X Unixpc.shar Waitfor.1 > pcomm_sh.2 X $(SHAR) admin.c chg_dir.c config.h curses.c d_delete.c d_lib.c \ X d_manual.c d_menu.c d_print.c d_prompt.c d_revise.c data_log.c \ X di_delay.c > pcomm_sh.3 X $(SHAR) di_win.c dial.c dial_dir.h e_lib.c expand.c extrnl.h \ X getcwd.c getopt.c help.c info.c init.c input.c list_dir.c \ X ls_menu.c > pcomm_sh.4 X $(SHAR) m_lib.c macro.c main.c matches.c misc.h modem.h \ X modem_break.c n_shell.c p_lib.c param.h passthru.c pexit.c \ X port.c > pcomm_sh.5 X $(SHAR) redial.c s_axfer.c s_extrnl.c s_gen.c s_menu.c s_modem.c \ X s_prompt.c s_term.c s_tty.c screen.c script.c st_line.c status.h \ X strings.c > pcomm_sh.6 X $(SHAR) terminal.c tty_att.c tty_ucb.c vcs.c vcs.h waitfor.c \ X x_ascii.c x_batch.c x_extrnl.c > pcomm_sh.7 X $(SHAR) x_menu.c x_rcv.c x_send.c x_win.c xmodem.c xmodem.h \ X > pcomm_sh.8 X Xadmin.o: config.h dial_dir.h param.h Xchg_dir.o: config.h misc.h Xcurses.o: config.h misc.h Xd_delete.o: config.h dial_dir.h misc.h param.h Xd_lib.o: dial_dir.h param.h Xd_manual.o: config.h dial_dir.h misc.h Xd_menu.o: config.h dial_dir.h misc.h param.h Xd_print.o: config.h dial_dir.h misc.h Xd_prompt.o: config.h dial_dir.h misc.h Xd_revise.o: config.h dial_dir.h misc.h param.h Xdata_log.o: config.h misc.h param.h status.h Xdi_delay.o: config.h misc.h param.h Xdi_win.o: config.h dial_dir.h misc.h modem.h param.h Xdial.o: config.h dial_dir.h misc.h modem.h param.h Xe_lib.o: extrnl.h Xexpand.o: config.h Xhelp.o: config.h misc.h Xinit.o: config.h misc.h status.h Xinput.o: config.h misc.h status.h vcs.h Xls_menu.o: config.h dial_dir.h misc.h param.h Xm_lib.o: modem.h Xmacro.o: config.h misc.h param.h Xmain.o: config.h dial_dir.h extrnl.h misc.h modem.h param.h status.h Xn_shell.o: config.h Xp_lib.o: param.h Xpassthru.o: config.h misc.h Xpexit.o: config.h dial_dir.h misc.h param.h status.h Xport.o: config.h dial_dir.h modem.h Xredial.o: config.h dial_dir.h misc.h Xs_axfer.o: config.h misc.h param.h Xs_extrnl.o: config.h extrnl.h misc.h Xs_gen.o: config.h misc.h param.h Xs_menu.o: config.h misc.h Xs_modem.o: config.h misc.h modem.h Xs_prompt.o: config.h misc.h Xs_term.o: config.h misc.h param.h status.h Xs_tty.o: config.h misc.h modem.h Xscreen.o: config.h param.h status.h Xscript.o: config.h dial_dir.h status.h Xst_line.o: config.h dial_dir.h misc.h modem.h param.h status.h Xstrings.o: config.h Xterminal.o: config.h dial_dir.h misc.h modem.h param.h status.h xmodem.h Xtty_att.o: dial_dir.h param.h Xtty_ucb.o: dial_dir.h param.h Xvcs.o: config.h vcs.h Xx_ascii.o: config.h misc.h param.h Xx_batch.o: config.h misc.h xmodem.h Xx_extrnl.o: config.h Xx_menu.o: config.h extrnl.h misc.h xmodem.h Xx_rcv.o: config.h dial_dir.h misc.h xmodem.h Xx_send.o: config.h dial_dir.h misc.h xmodem.h Xx_win.o: config.h dial_dir.h misc.h xmodem.h Xxmodem.o: config.h misc.h param.h xmodem.h X Xwaitfor: waitfor.c Xmatches: matches.c Xmodem_break: modem_break.c SHAR_EOF if test 5364 -ne "`wc -c < 'Makefile'`" then echo shar: "error transmitting 'Makefile'" '(should have been 5364 characters)' fi fi echo shar: "extracting 'Matches.1'" '(635 characters)' if test -f 'Matches.1' then echo shar: "will not over-write existing file 'Matches.1'" else sed 's/^X//' << \SHAR_EOF > 'Matches.1' X.TH MATCHES 1 local X.SH NAME Xmatches \- test if string2 is contained in string1 X.SH SYNOPSIS X.B matches string1 string2 X.SH DESCRIPTION X.I Matches Xreturns a 0 if string2 is contained in string1, otherwise it returns a 1. X.PP X.I Matches Xis designed to be used by X.I Pcomm Xin a shell script for automatically logging a user onto a remote system. X.PP X.SH EXAMPLE X.nf X # read some input X read junk X # test to see the string matches 'login failed' X matches $junk 'login failed' X # test the exit code of the matches command X if [ $? \-eq 0 ] X then X exit 1 X fi X.fi X.SH "SEE ALSO" Xpcomm(1), waitfor(1), modem_break(1), Pcomm Reference Manual SHAR_EOF if test 635 -ne "`wc -c < 'Matches.1'`" then echo shar: "error transmitting 'Matches.1'" '(should have been 635 characters)' fi fi echo shar: "extracting 'Modem_break.1'" '(836 characters)' if test -f 'Modem_break.1' then echo shar: "will not over-write existing file 'Modem_break.1'" else sed 's/^X//' << \SHAR_EOF > 'Modem_break.1' X.TH MODEM_BREAK 1 local X.SH NAME Xmodem_break \- send a modem break X.SH SYNOPSIS X.B modem_break X.SH DESCRIPTION X.I Modem_break Xcreates a ``modem break'' on the stdout. Modem break is a condition of Xa communications line when the line is held ``low'' for 200 ms. It is Xtypically used to tell the remote system to switch to a different Xbaud rate. X.PP X.I Modem_break Xis designed to be used by X.I Pcomm Xin a shell script for automatically logging a user onto a remote system. X.PP X.SH EXAMPLE X.nf X while true X do X # wait 5 seconds for the login prompt X waitfor \-5 login: X # test the exit code of the waitfor command X if [ $? \-eq 0 ] X then X # send my user ID and break out of the loop X echo egray X break X fi X # send a modem break X modem_break X done X.fi X.SH "SEE ALSO" Xpcomm(1), waitfor(1), matches(1), Pcomm Reference Manual SHAR_EOF if test 836 -ne "`wc -c < 'Modem_break.1'`" then echo shar: "error transmitting 'Modem_break.1'" '(should have been 836 characters)' fi fi echo shar: "extracting 'Pcomm.1'" '(8648 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 Xdirectory ] [ X.B \-f Xsystem name X] X.SH DESCRIPTION X.I Pcomm Xis a public domain telecommunication program for Unix that is designed Xto operate similar to the MSDOS program, ProComm. ProComm (TM) is Xcopyrighted by Datastorm Technologies, Inc. X.PP XThe X.I \-d Xoption is used to specify an additional path to search for the Pcomm Xsupport files. X.PP XThe X.I \-f Xoption is used to specify automatic dialing of an entry in the dialing Xdirectory. The X.I name Xfield in the dialing directory is checked against the string given on Xthe command line. If a match is found, that entry is automatically Xdialed. X.PP XWhenever X.I Pcomm Xis in the command mode, a status line is displayed at the bottom of the Xscreen. The eight fields of the status line are: X.PP X.RS 5 X.nf X\(bu help screen command (or a temporary message) X\(bu name of the TTY device in use X\(bu duplex mode (FDX = full duplex, HDX = half duplex) X\(bu current line settings X\(bu status of data logging option X\(bu status of printer logging option X\(bu incoming CR translation X\(bu outgoing CR translation X.fi X.RE X.SH COMMANDS XThe following commands are accessible by pressing a user definable ``hot Xkey'' followed by a letter, number, or arrow key. The default ``hot Xkey'' is control-A. The notation ``^A-X'' means control-A followed by Xthe letter X. The dash (-) is for clarity, and is not a part of the Xcommand sequence. X.TP X.B ^A-0 XHelp Screen. Display a brief review of the available commands. Uses Xthe number zero ``0'' not the letter ``O''. X.TP X.B ^A-D XDialing Directory. The dialing directory screen is used to display and Xmaintain the database of phone number entries, and to select an entry Xfor dialing. To dialan entry, just enter the entry number at the Xprompt. If the ``script'' field contains valid Unix shell script, that Xfile is used to automatically log the user on to the remote system. See Xthe Pcomm Reference Manual for the format and use of the script files. XThe following commands are available from the dialing directory: X.RS 5 X.TP X.B R XRevise (or add) a dialing directory entry or a long distance dialing Xcode. X.TP X.B P XPrint (display) the long distance dialing codes. X.TP X.B up/down XScroll the dialing directory up or down 10 lines. Uses the up and down Xarrow keys. X.TP X.B M XManual dial. Prompts for a phone number rather than using a number Xalready in the dialing directory. X.TP X.B D XDelete an entry or a range of entries. X.TP X.B L XPrint. Send the dialing directory to the printer or a file of your Xchoice. X.RE X.TP X.B ^A-R XAutomatic redial of selected dialing directory entries. Prompts the Xuser for a list of directory entries to be placed in the queue. X.I Pcomm Xwill dial the numbers in a cycle until one of them answers. X.TP X.B ^A-M XAllows the user to maintain a list of keyboard macros assigned to the Xshifted number keys. When pressed, the string assigned to that key is Xsent to the remote system. X.TP X.B ^A-P XAdjust the current communication line settings. Display a menu of baud Xrate, parity, data bit, and stop bit choices. Allows the new choice to Xbe saved and become the default. After dialing a remote, the line Xsettings in the dialing directory entry are automatically used. The Xcurrent line settings are shown in the status line. X.TP X.B ^A-X XExit from X.I Pcomm. X.TP X.B ^A-4 XSpawn a Unix shell while still communicating with the remote system. XUses the ``native'' shell as described in the SHELL environmental Xvariable. X.TP X.B ^A-I XDisplay the program information screen. X.TP X.B ^A-S XDisplay a choice of setup screens. The following sub-menus are Xavailable: X.RS 5 X.TP X.B 1 XTTY Setup. This setup assigns the TTY ports that X.I Pcomm Xis allowed to use, and what is attached to each port. X.TP X.B 2 XModem Setup. The modem setup contains the commands to make the modem Xdial, hang up the phone, etc. X.TP X.B 3 XTerminal Setup. The terminal setup contains the definition of the ``hot Xkey'' and the mapping of the end-of-line characters. X.TP X.B 4 XGeneral Setup. The general setup contains the default log file name, Xand the set of character synonyms. X.TP X.B 5 XASCII Transfer Setup. This setup screen contains additional character Xtranslations allowed during ASCII file transfers. X.TP X.B 6 XExternal Protocol Setup. This setup screen allows the user to imbed the Xnames of external file transfer programs into the list of available Xprotocols. X.TP X.B S XSave the changes to disk. X.RE X.TP X.B ^A-B XChange the current working directory. X.TP X.B ^A-C XClear the local screen and home the cursor. X.TP X.B ^A-E XToggle the duplex mode from full to half, or from half to full. The Xstatus line shows the current duplex mode. X.TP X.B ^A-H XHang up the phone. Disconnect the phone, but remain in X.I Pcomm. X.TP X.B ^A-L XToggle the printer on and off. Since the printer is accessed through Xthe normal Unix spool program, the output is not sent to the printer Xuntil X.B after Xthis feature is turned off. X.TP X.B ^A-3 XToggle the incoming line termination characters between the carriage Xreturn and the carriage return line feed pair. This affects the Xterminal session only, not the file transfers. The current settings are Xshown in the status line. X.TP X.B ^A-7 XSend a modem break. This is X.B not Xthe same as the break key on the keyboard. X.TP X.B ^A-up XDisplay a menu of file transfer protocols to be used to send files to a Xremote system. Uses the up arrow key. X.TP X.B ^A-down XDisplay file transfer protocols to be used to receive files from a Xremote system. Uses the down arrow key. X.TP X.B ^A-F XDisplay the contents of a Unix directory. X.TP X.B ^A-G XDump the contents of the screen to a specified file. Special graphics Xcharacters may not be represented accurately in the file. X.TP X.B ^A-1 XBegin data logging. Prompts the user for the name of the file that will Xbe used to collect a complete record of the terminal session. X.TP X.B ^A-2 XToggle the data logging option without prompting for a new file name. XThe status line shows the current data logging mode. X.SH "FILE TRANSFERS" X.I Pcomm Xunderstands the following file transfer protocols: X.PP X.RS 5 X.nf X.if n .ta 1.5i +1.5i +1.5i +1.5i +1.5i X.if t .ta 1i +1i +1i +1i +1i Xprotocol packet error multiple Xname size method files? X--------- -------- ------------ -------- Xxmodem 128 checksum/CRC no Xxmodem-1k 128/1024 checksum/CRC no Xmodem7 128 checksum yes Xymodem 128/1024 CRC yes Xymodem-g 128/1024 none yes XASCII none none no Xzmodem 128/1024 CRC yes X(external) ? ? ? X.fi X.RE X.PP X.I Pcomm Xcan use an external program, such as Kermit or a proprietary program, to Xtransfer files. Commonly used external programs (such as zmodem in the Xexample above) can have their names imbedded into the list of available Xprotocols. X.PP X.SH CONFIGURATION X.I Pcomm Xmust have access to the terminfo or termcap data for the terminal being Xused. The minimum capabilities include a screen size of at least 80 Xcolumns by 24 lines and cursor movement capabilities. Running X.I Pcomm Xfrom terminals at relatively slow speeds (i.e. 1200 baud) will cause 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 letter ``U'' Xfor ``up arrow'' and ``N'' for ``down arrow''. X.PP XThere are four Pcomm support files that contain the dialing directory, Xthe external file transfer programs, the modem/TTY database, and the Xstart-up default parameters. Users may maintain private versions of Xthese files in a directory of their choice. X.I Pcomm Xalso uses normal Unix shell scripts to perform the ``chat'' sequences Xnecessary to automatically log a user onto a remote system. X.I Pcomm Xuses the environmental variable PCOMM to search for the ``private'' Xsupport file and the auto-login shell scripts. The following directories Xare searched to find the files: X.PP X.RS 5 X.nf X\(bu directory given with the \fI\-d\fP option X\(bu directory in the PCOMM environmental variable X\(bu current directory X\(bu default directory (compiled into Pcomm) X.fi X.RE X.PP XThe ``script'' field in the dialing directory serves two purposes. The Xfirst use is to identify the shell script to use for auto-login. The Xsecond use is to specify a TTY name for a given entry. If the X``script'' is a valid device name, that device is used instead of Xsearching the TTY database for a free port. X.SH FILES X.nf Xpcomm.dial_dir the dialing directory Xpcomm.extrnl the external file transfer programs Xpcomm.modem the modem/TTY database Xpcomm.param the start-up default parameters X.fi X.SH "SEE ALSO" XPcomm Reference Manual, xmodem(1), mdm(1) SHAR_EOF if test 8648 -ne "`wc -c < 'Pcomm.1'`" then echo shar: "error transmitting 'Pcomm.1'" '(should have been 8648 characters)' fi fi echo shar: "extracting 'Pcomm.dial_dir'" '(321 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;555-8686;9600-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;Sample 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);;19200-E-7-1;F;tty12 SHAR_EOF if test 321 -ne "`wc -c < 'Pcomm.dial_dir'`" then echo shar: "error transmitting 'Pcomm.dial_dir'" '(should have been 321 characters)' fi fi echo shar: "extracting 'Pcomm.extrnl'" '(79 characters)' if test -f 'Pcomm.extrnl' then echo shar: "will not over-write existing file 'Pcomm.extrnl'" else sed 's/^X//' << \SHAR_EOF > 'Pcomm.extrnl' XSEND_1=zmodem;sz;Y XSEND_2=;;N XSEND_3=;;N XRCV_1=zmodem;rz;N XRCV_2=;;N XRCV_3=;;N SHAR_EOF if test 79 -ne "`wc -c < 'Pcomm.extrnl'`" then echo shar: "error transmitting 'Pcomm.extrnl'" '(should have been 79 characters)' fi fi echo shar: "extracting 'Pcomm.modem'" '(598 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;0 XTTY_2=tty11;HAYES;0 XTTY_3=tty12;DIRECT;0 XTTY_4=tty13;TELEBIT;0 XTTY_5=tty13;FAST_TELEBIT;0 XMODEM_1a=HAYES;ATS7=45S11=70E0Q0V1X4&D2!;ATDT;!;~~+++~~ATH0! XMODEM_1b=Y;CONNECT!;CONNECT 1200;CONNECT 2400;;; XMODEM_1c=BUSY;VOICE;NO CARRIER; XMODEM_2a=DIRECT;;;; XMODEM_2b=N;;;;;; XMODEM_2c=;;; XMODEM_3a=TELEBIT;%AAAAAATS50=0S2=43S95=0M1!;%AAAAAATDTW;!;~~+++~~ATH0! XMODEM_3b=Y;CONNECT 300;CONNECT 1200;CONNECT 2400;;; XMODEM_3c=BUSY;ERROR;NO CARRIER; XMODEM_4a=FAST_TELEBIT;%AAAAAATS50=255S2=43S95=0M1!;%AAAAAATDTW;!;~~+++~~ATH0! XMODEM_4b=N;;;;;CONNECT;CONNECT XMODEM_4c=BUSY;ERROR;NO CARRIER; SHAR_EOF if test 598 -ne "`wc -c < 'Pcomm.modem'`" then echo shar: "error transmitting 'Pcomm.modem'" '(should have been 598 characters)' fi fi echo shar: "extracting 'Pcomm.param'" '(453 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=| XBRK_CHAR=% XABORT=KEEP XC_DELAY=35 XR_DELAY=5 XLECHO=NO XEXPAND=NO XCR_DELAY=0 XPACE=NO XCR_UP=NONE XLF_UP=ADD CR XTIMER=5 XCR_DN=STRIP XLF_DN=NONE XLD_PLUS= XLD_MINUS= XLD_AT=8, XLD_POUND=9 XMAC_1=hello XMAC_2= XMAC_3= XMAC_4= XMAC_5= XMAC_6= XMAC_7= XMAC_8= XMAC_9= XMAC_0= SHAR_EOF if test 453 -ne "`wc -c < 'Pcomm.param'`" then echo shar: "error transmitting 'Pcomm.param'" '(should have been 453 characters)' fi fi echo shar: "extracting 'Readme'" '(7963 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 XThings to do first: X X 1) Figure out what files you need. There is a shell archive X called "Unixpc.shar" that contains additional (and replacement) X files for users of the AT&T Unix PC 7300/3b1. X X 2) Create a default directory where the Pcomm support files will X go. A good location might be /usr/local/lib/pcomm. X X 3) Copy the sample support files Pcomm.dial_dir, Pcomm.extrnl, X Pcomm.modem, and Pcomm.param to the default directory and rename X them to change the upper case "P" to a lower case "p". The files X should *not* have write permission to all. X X 4) Copy (and rename as appropriate) the Pcomm.1, Waitfor.1, X Matches.1, and Modem_break.1 nroff manuals to the proper /usr/man X directory. X X 5) Print the Doc file by piping the output of the Unix "pr" X command with the title separated by lots of white space (to help X center it), for example: X X pr -h " Pcomm Reference Manual " Doc | lp X XHow to configure Pcomm: X X 1) Edit the "config.h" file to suit your system's needs and your X personal taste. Sites running HoneyDanBer (HDB) UUCP should pay X particular attention to the LOCK_DIR, ASCII_PID, and SETUGID X definitions. The definitions in config.h are: X X BSD Define if you're using a Berkeley flavor of Unix. X You will have to edit the Makefile in several X places. X X UNIXPC If defined, use the dial(3) routines specific X to the AT&T Unix PC 7300/3b1. Useful only if X the On Board Modem (OBM) is to be used. X X OLDCURSES If defined, use the older version of curses(3). X (uses termcap in lieu of terminfo). X X SHAREDMEM If defined, keeps the virtual screen area in X shared memory rather than in a file. X X NOPROMOTE If defined, do not promote missing video X attributes to standout. Normally, curses(3) X attempts to compensate for missing attributes. X X SETUGID If defined, extra precautions are taken before X opening files or doing a shell escape to restore X the real UID/GID. Useful if Pcomm is installed X as a set-user-id or get-group-id program. HDB X programs often are set-user-id to uucp. X X LOG_CALLS If defined, Pcomm will keep an administrative log X of all calls. The log contains the name of the X person making the call, the phone number, and a X date/time stamp. Useful for verifying long X distance phone bills. X X LOGFILE The path to the log file (if LOG_CALLS is X defined). It should have write permission to X all or be writeable under set-user/group-id X conditions. X X LIMIT_LD If defined, Pcomm will limit long distance X (toll) calls to a privileged group. The file X "admin.c" may require tweaking to detect long X distance numbers. X X GROUP_NAME The name of the group that is allowed to make X long distance calls (if LIMIT_LD is defined). X X LPR The path to the line printer program (this is X not the name of the device). X X LPRINT The path to the "pretty" line printer program. X Typically a program that performs a "pr | lp" X function. If none exist, use "pr | lp". X X DEFAULT_DIR The path to the directory that contains the X default Pcomm support files. X X LOCK_DIR The path to the directory where the UUCP lock X files are found. On HDB systems this could X be /usr/spool/locks or /usr/spool/uucp. X X ASCII_PID If defined, the lock files will contain an ASCII X encoded process id (PID). On HDB systems this X is the default. X X XENIX_LOCKS If defined, the last letter of the device name X is folded to lower case when creating the lock X file. Newer version of XENIX may require this. X X KEEP_PORT If defined, the port will be kept open between X dialing attempts to save time. Some systems X may require the modem to be closed and reopened X every time. X X XMC_BROKE Does the status line scroll up when using "magic X cookie" terminals? Some Pyramid and AT&T X systems may require this to be defined. Find a X magic cookie terminal (a Wyse 50 for example), X and see what happens. X X WGETCH_BROKE Does the alarm() system call work correctly with X the wgetch() function? Some Masscomp systems X will require this to be defined. Symptom: the X initial screen doesn't go away by itself after 5 X seconds. X X CLIST_SIZ The size of the serial port character buffer. X The default is 64. X X INPUT_BUF The size of the input buffer (should be about the X same size as CLIST_SIZ). The default is 64. X X OUTPUT_BUF The size of the output buffer (should be about X one half INPUT_BUF). The default is 32. Systems X without dedicated I/O processors may require a X very small INPUT_BUF value to avoid the problem X of a "choppy" display. X X MEMMOVE The name of the memory copy routine (if none, X then use "#undef MEMMOVE"). The default is X "memmove", although quite a few versions of X "memcpy" will work (if they correctly handle X target and source overlap). X X SETUID_BROKE Does your version of Unix allow you to flip-flop X back and forth between the real and effective X user (or group) ID? Some Masscomp systems will X require this to be set. X X 2) Edit the Makefile. There are provisions in the Makefile to X include getcwd(3) and getopt(3) routines if they are missing X from your system. You may want to customize the CFLAGS, X LDFLAGS, and BIN assignments to suit your needs. X X If compiling under Berkeley Unix, you will have to edit the X Makefile on the following lines: X X #for old curses(3) or Berkeley systems X CURSES = -lcurses -ltermcap X TERMLIB = -ltermcap X #CURSES = -lcurses X #TERMLIB = -lcurses X X #for System V or Berkeley worlds X BSD = -DBSD X TTY = tty_ucb.o X #BSD = X #TTY = tty_att.o X X All the defaults in config.h assume a AT&T flavor of Unix, sorry X about that... X X 3) Compile pcomm and pcomm_input. Type "make". The "make X install" option will attempt to copy "pcomm" and "pcomm_input" X into the BIN directory given in the Makefile. However, those X sites running HDB UUCP software may require that you to change X the mode of "pcomm" to be set-user-id to uucp. DO NOT CHANGE X THE SET-UID/GID BITS ON THE "pcomm_input" PROGRAM. X X Three external programs (waitfor, matches, and modem_break) are X included in the distribution to help in creating auto-login X shell scripts. X X 4) Update the sample modem/TTY database. I know I'm asking the X impossible, but... Read section 3 and the Appendices of the Doc X file first, then run Pcomm to update the modem/TTY database by X using the TTY Setup and the Modem Setup menues. You will need X to know: X X o The types and number of modems available for dial out X o The TTY ports attached to the modems X o The range of baud rates at which the modems operate X o How to initialize the modems to suit Pcomm's needs X o How to make the modems dial X X During this step, you will need write permission on the support X files in the default directory. RESIST THE TEMPTATION TO EDIT X THE SUPPORT FILES DIRECTLY. X XPortability considerations: X X 1) Pcomm makes use of the bold, blinking and standout video X attributes. My concept of "standout" and "reverse" might be X different than yours (I like "standout" to be a brighter version X of "reverse"). Some very old versions of curses will ignore the X standout mode if you're on a magic cookie terminal. X X 2) The "port.c" file has a place where you can include your own X routine to toggle the getty process on a port (if required). X X 3) If you compile Pcomm with LOG_CALLS defined, you'll have to X look at the code in "admin.c" to see if the long distance X detection routine is correct for your site. X X 4) Compilers that adhere to the ANSI C Standard will complain at X the declarations of perror(), malloc(), fread(), fwrite(), etc. X There is a "typedef SIG_TYPE" in the config.h file to help X silence the compiler's warning messages about the signal() X return value. X XEmmet P. Gray US Army, HQ III Corps & Fort Hood X...!uunet!uiucuxc!fthood!egray Attn: AFZF-DE-ENV X Directorate of Engineering & Housing X Environmental Management Office X Fort Hood, TX 76544-5057 SHAR_EOF if test 7963 -ne "`wc -c < 'Readme'`" then echo shar: "error transmitting 'Readme'" '(should have been 7963 characters)' fi fi echo shar: "extracting 'Release.notes'" '(8624 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.2 X 4 Feb 89 X XCompatibilities with v1.1: X X The support files used with the v1.1 release are compatible with X the v1.2 release. However, the use of the "index" field (now X called the "script" field) in the pcomm.dial_dir file has X changed dramatically (see below). X XThings that have changed: X X Berkeley flavors of Unix are now supported. There are files X called tty_att.c and tty_ucb.c that contain the code specific X to the AT&T and Berkeley worlds. See the config.h file for X the BSD pre-processor definition. X X Auto-login scripts are now supported. If the script field of X the dialing directory contains the name of a valid Unix shell X script, that shell script is "played" after the connection is X made to perform the auto-login "chat" sequences. A example of a X auto-login Bourne shell script (called Sample) is included in X the distribution. X X Three new external programs. In order to assist in the creation X of the auto-login shell scripts, three external programs are X included in the distribution. X X waitfor - wait for a string, return a 1 if timed out X matches - test if string2 is contained in string1 X modem_break - send a modem break X X There is a new support file called "pcomm.extrnl" that allows X the user to imbed the names of external file transfer programs X into the list of available protocols. (The default file X "Pcomm.extrnl", supplied with the distribution package, contains X definitions for zmodem). X X The pcomm.input program has been changed to use multiple X character buffered writes to the screen. Both the input and X output buffer sizes are tunable parameters in config.h X X Newer versions of Xenix have changed the rules for creating UUCP X lock files. See the config.h file for the description of X XENIX_LOCKS. X X The -f option now looks at the name field of the dialing X directory (rather than the index field). A match is found when X the argument to the -f is contained in a name field (an exact X match is not required). The match does not consider upper and X lower case differences as significant. X XKnown limitations: X X The detection of VCS (video command sequences) is still limited X to a very small subset of possible commands. X X For the VCS emulation to work, the terminfo entries on the host X machine must match the entries on the remote. (Don't assume X your vt100 terminfo data is identical to someone else's). X X The disp_tty() routine in s_tty.c currently does not support a X NUM_TTY definition of greater than 10. X XFuture directions: X X That's about it folks... X X If Pcomm grows any more, I'll break the setup routines out as a X separate program. X XMany thanks to the following people (and many others) for bug reports Xand suggested improvements to the code. X X Andy Fyfe ...ames!elroy!cit-vax!andy X Brian Antoine ...iscuva!tau-ceti!briana X Chad R. Larson ...ncar!noao!nud!anasaz!dcfinc!chad X David MacKenzie ...uunet!rocky2.rockefeller.edu!edf X Gary S. Trujillo ...{linus,bbn,m2c}!spdcc!gnosys!gst X George Pontis ...uunet!moldev!geo X J. Eric Townsend ...uunet!nuchat!flatline!erict X Jim Pickering ...csun!polyslo!rducky!jrp X Jim Sanchez ...uunet!mcvax!syteke!jim X Jonathan Bayer ...uunet!ispi!jbayer X MAJ Dave Dockstader ...twsc4sac@mater1.arpa X Michael Brady ...sun!portal!cup.portal.com!michealnc X X------------------------------------------------------------------------------- X X Pcomm version 1.1 X 21 Aug 88 X XIncompatibilities with v1.0: X X I've added a few more fields to the pcomm.param and pcomm.modem X files. This means that those files created under previous X releases will not be compatible with the v1.1 release. It might X be a good idea to abandon the older files and start over with X the sample files in this release. X XThings that have changed: X X An awful lot of sloppy programming on my part has now been X cleaned up. This means that porting Pcomm to different versions X of Unix will be considerably less painful than before. X X All of the tunable parameters are now in "config.h". X X Pcomm now uses buffered I/O routines. This yields higher X performance I/O at large baud rates. X X File transfers now use high performance CRC calculations. X X If a UUCP lockfile does exist, Pcomm now attempts to determine X if the process is still active. X X An external file transfer program can be invoked from the file X transfer menu. X X The keyboard macro feature is now supported (although it is X rather crude). X X The virtual screen routine now understands a limited subset of X escape sequences. X X The virtual screen can now be held in shared memory or in a file. X X The input routine is now contained in a separate program called X pcomm_input. X X You can now include a "modem break" in a dial or initialization X string. X X A separate "initialization speed" feature was added to support X 9600 baud modems such as the Telebit Trailblazer. See Appendix X C of the Doc file for more info on the use of this feature. X X I've added a transparent pass through mode to be used in a X communications daisy chain. X XKnown limitations: X X Whenever Pcomm makes the transition from the terminal mode to X the command mode, the true screen contents are lost. Pcomm X tries to keep track of what the true screen looks like in an X internal "virtual screen". This means that the escape sequences X known to the hardware have to be emulated in the virtual screen. X Unfortunately, the number of escape sequences that are emulated X is quite small, so the representation of the true screen is X sometimes wrong. X X For the VCS (video command sequence) emulation to work, the X terminfo entries on the host machine must match the entries on X the remote. X X The disp_tty() routine in s_tty.c currently does not support a X NUM_TTY definition of greater than 10. X XFuture directions: X X Continue work on the virtual screen routines. X X Add dial back support. X X Use shared memory to overcome the current limitation of outgoing X characters in the half duplex mode not appearing in the virtual X screen, log files, and print logs. X XMany thanks to the following people for bug reports and ideas for Ximproving the code: X X Andy Pitts ...{mtune,pacbell,kd4nc}!gladys!rbdc!andy X Chris Wiener ...ihnp4!{killer,attnssc}!crlabs!cwiener X David Brierley ...{sun,decuac,cbosgd,gatech,necntc,ukma}!rayssd!dhb X Karl Fox ...cbosgd!mstar!karl X Michael Young ...panda!genrad!mrst!sdti!mjy X Mark Mendel ...ihnp4!umn-cs!hyper!mark X Viet Hoang ...ihnp4!drutx!vgh X X-------------------------------------------------------------------------------- X X Pcomm version 1.0 X 12 Mar 88 X XIncompatibilities with the beta release: X X I've added a bunch of new parameters to the pcomm.param and X pcomm.modem files, so the files used with the beta release won't X work with the v1.0 release. X XThings that have changed: X X Pcomm will attempt to determine if the modem has synchronized at X a baud rate different than 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 X been changed slightly. 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 X like. Escape sequences in the virtual screen image will be X ignored when the background is repainted. For example, if X you're on a vt100 and you receive a ^[[2J to clear the screen, X the screen *will* be cleared... but when the screen is X repainted, it will contain the characters ^[, [, 2, J (instead X 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 X commonly used escape sequences (known to terminfo) will be X processed. X X I plan to have an option at compile time to have the virtual X screen buffer held on disk [] or in shared memory []. X X The input routine is designed so it could be a standalone X program that gets called from Pcomm. [] X X------------------------------------------------------------------------------- X XHave fun... X XEmmet P. Gray US Army, HQ III Corps & Fort Hood X...!uunet!uiucuxc!fthood!egray Attn: AFZF-DE-ENV X Directorate of Engineering & Housing X Environmental Management Office X Fort Hood, TX 76544-5057 SHAR_EOF if test 8624 -ne "`wc -c < 'Release.notes'`" then echo shar: "error transmitting 'Release.notes'" '(should have been 8624 characters)' fi fi echo shar: "extracting 'Sample'" '(994 characters)' if test -f 'Sample' then echo shar: "will not over-write existing file 'Sample'" else sed 's/^X//' << \SHAR_EOF > 'Sample' X: X# X# This is a sample Bourne shell script to log a user onto a remote system. X# Things to remember: X# 1) Script files should have permissions of 700, to prevent others X# from gaining access to your passwords to remote systems. X# 2) The return codes for waitfor are: 0=success, 1=timed out, and X# -1=error. X# Xecho "" Xtry=0 X# loop until done Xwhile true Xdo X # wait 5 seconds for the login prompt X waitfor -5 ogin: X # test the exit code of the waitfor command X if [ "$?" -eq 0 ] X then X # send my user ID and exit the loop X echo "egray" X break X fi X X # increment the number of attempts X try=`expr $try + 1` X # test to see if we should give up X if [ "$try" -eq 5 ] X then X exit 1 X fi X X # send a modem break and loop again X modem_break X echo "" Xdone X# wait 5 seconds for the password prompt Xwaitfor -5 assword: X# test the return code from waifor Xif [ "$?" -eq 0 ] Xthen X # send my password (you're crazy if you think that's my real password) X echo "abcdefg" Xelse X exit 1 Xfi X# return to Pcomm Xexit 0 SHAR_EOF if test 994 -ne "`wc -c < 'Sample'`" then echo shar: "error transmitting 'Sample'" '(should have been 994 characters)' fi fi echo shar: "extracting 'Unixpc.shar'" '(17190 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# Ifile30.sh X# Makefile X# Pcomm.modem X# Readme.7300 X# config.h X# This archive created: Tue Jan 31 09:03:21 1989 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 'Ifile30.sh'" '(254 characters)' Xif test -f 'Ifile30.sh' Xthen X echo shar: "will not over-write existing file 'Ifile30.sh'" Xelse Xsed 's/^X//' << \SHAR_EOF > 'Ifile30.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/^wrefresh/xwrefresh/ XX1,\$s/^initscr/xinitscr/ XX1,\$s/^endwin/xendwin/ XX1,\$s/^printw/xprintw/ XX1,\$s/^setterm/xsetterm/ XXw XXq XXEOF XSHAR_EOF Xif test 254 -ne "`wc -c < 'Ifile30.sh'`" Xthen X echo shar: "error transmitting 'Ifile30.sh'" '(should have been 254 characters)' Xfi Xfi Xecho shar: "extracting 'Makefile'" '(5239 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 XXCFLAGS = -O XXLD = ld -s XXSHAR = shar -a XXBIN = /usr/local/bin XXSHAREDLIB = shlib_c.ifile XXCURSES = -lcurses XX XX#for Unix 3.0 XX#OTHERS = doprnt.o XX#IFILE = Ifile30.sh XXOTHERS = setvbuf.o doprnt.o XXIFILE = Ifile.sh XX XXPCOMM = $(OTHERS) tty_att.o admin.o chg_dir.o curses.o d_delete.o \ XX d_lib.o d_manual.o d_menu.o d_print.o d_prompt.o d_revise.o \ XX data_log.o di_delay.o di_win.o dial.o e_lib.o expand.o help.o \ XX info.o init.o list_dir.o ls_menu.o m_lib.o macro.o main.o \ XX n_shell.o p_lib.o passthru.o pexit.o port.o redial.o s_axfer.o \ XX s_extrnl.o s_gen.o s_menu.o s_modem.o s_prompt.o s_term.o \ XX s_tty.o screen.o script.o st_line.o strings.o terminal.o x_ascii.o \ XX x_batch.o x_extrnl.o x_menu.o x_rcv.o x_send.o x_win.o xmodem.o XX XXINPUT = $(OTHERS) input.o vcs.o XX XXall: pcomm pcomm_input waitfor matches modem_break XX XXpcomm: $(PCOMM) $(SHAREDLIB) XX $(LD) $(PCOMM) $(CURSES) /lib/crt0s.o $(SHAREDLIB) -o pcomm XX XXpcomm_input: $(INPUT) $(SHAREDLIB) XX $(LD) $(INPUT) $(CURSES) /lib/crt0s.o $(SHAREDLIB) -o pcomm_input XX XXwaitfor: waitfor.o XX $(LD) waitfor.o /lib/crt0s.o /lib/shlib.ifile -o waitfor XX XXmatches: matches.o XX $(LD) matches.o /lib/crt0s.o /lib/shlib.ifile -o matches XX XXmodem_break: modem_break.o XX $(LD) modem_break.o /lib/crt0s.o /lib/shlib.ifile -o modem_break 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) shlib_c.ifile XX XXinstall: XX cp pcomm $(BIN) XX cp pcomm_input $(BIN) XX cp waitfor $(BIN) XX cp matches $(BIN) XX cp modem_break $(BIN) XX# rm pcomm XX# rm pcomm_input XX# rm waitfor XX# rm matches XX# rm modem_break XX XXlint: XX lint -p -Dlint admin.c chg_dir.c curses.c d_delete.c d_lib.c \ XX d_manual.c d_menu.c d_print.c d_prompt.c d_revise.c data_log.c \ XX di_delay.c di_win.c dial.c e_lib.c expand.c getcwd.c getopt.c \ XX help.c info.c init.c list_dir.c ls_menu.c m_lib.c macro.c main.c \ XX n_shell.c p_lib.c passthru.c pexit.c port.c redial.c s_axfer.c \ XX s_extrnl.c s_gen.c s_menu.c s_modem.c s_prompt.c s_term.c s_tty.c \ XX screen.c script.c st_line.c strings.c terminal.c tty_att.c \ XX x_ascii.c x_batch.c x_extrnl.c x_menu.c x_rcv.c x_send.c x_win.c \ XX xmodem.c XX lint -p -Dlint input.c vcs.c XX lint -p -Dlint waitfor.c XX lint -p -Dlint matches.c XX lint -p -Dlint modem_break.c XX XXshar: XX $(SHAR) Doc > pcomm_sh.1 XX $(SHAR) Makefile Matches.1 Modem_break.1 Pcomm.1 Pcomm.dial_dir \ XX Pcomm.extrnl Pcomm.modem Pcomm.param Readme Release.notes Sample \ XX Unixpc.shar Waitfor.1 > pcomm_sh.2 XX $(SHAR) admin.c chg_dir.c config.h curses.c d_delete.c d_lib.c \ XX d_manual.c d_menu.c d_print.c d_prompt.c d_revise.c data_log.c \ XX di_delay.c > pcomm_sh.3 XX $(SHAR) di_win.c dial.c dial_dir.h e_lib.c expand.c extrnl.h \ XX getcwd.c getopt.c help.c info.c init.c input.c list_dir.c \ XX ls_menu.c > pcomm_sh.4 XX $(SHAR) m_lib.c macro.c main.c matches.c misc.h modem.h \ XX modem_break.c n_shell.c p_lib.c param.h passthru.c pexit.c \ XX port.c > pcomm_sh.5 XX $(SHAR) redial.c s_axfer.c s_extrnl.c s_gen.c s_menu.c s_modem.c \ XX s_prompt.c s_term.c s_tty.c screen.c script.c st_line.c status.h \ XX strings.c > pcomm_sh.6 XX $(SHAR) terminal.c tty_att.c tty_ucb.c vcs.c vcs.h waitfor.c \ XX x_ascii.c x_batch.c x_extrnl.c > pcomm_sh.7 XX $(SHAR) x_menu.c x_rcv.c x_send.c x_win.c xmodem.c xmodem.h \ XX > pcomm_sh.8 XX XXadmin.o: config.h dial_dir.h param.h XXchg_dir.o: config.h misc.h XXcurses.o: config.h misc.h XXd_delete.o: config.h dial_dir.h misc.h param.h XXd_lib.o: dial_dir.h param.h XXd_manual.o: config.h dial_dir.h misc.h XXd_menu.o: config.h dial_dir.h misc.h param.h XXd_print.o: config.h dial_dir.h misc.h XXd_prompt.o: config.h dial_dir.h misc.h XXd_revise.o: config.h dial_dir.h misc.h param.h XXdata_log.o: config.h misc.h param.h status.h XXdi_delay.o: config.h misc.h param.h XXdi_win.o: config.h dial_dir.h misc.h modem.h param.h XXdial.o: config.h dial_dir.h misc.h modem.h param.h XXe_lib.o: extrnl.h XXexpand.o: config.h XXhelp.o: config.h misc.h XXinit.o: config.h misc.h status.h XXinput.o: config.h misc.h status.h vcs.h XXls_menu.o: config.h dial_dir.h misc.h param.h XXm_lib.o: modem.h XXmacro.o: config.h misc.h param.h XXmain.o: config.h dial_dir.h extrnl.h misc.h modem.h param.h status.h XXn_shell.o: config.h XXp_lib.o: param.h XXpassthru.o: config.h misc.h XXpexit.o: config.h dial_dir.h misc.h param.h status.h XXport.o: config.h dial_dir.h modem.h XXredial.o: config.h dial_dir.h misc.h XXs_axfer.o: config.h misc.h param.h XXs_extrnl.o: config.h extrnl.h misc.h XXs_gen.o: config.h misc.h param.h XXs_menu.o: config.h misc.h XXs_modem.o: config.h misc.h modem.h XXs_prompt.o: config.h misc.h XXs_term.o: config.h misc.h param.h status.h XXs_tty.o: config.h misc.h modem.h XXscreen.o: config.h param.h status.h XXscript.o: config.h dial_dir.h status.h XXst_line.o: config.h dial_dir.h misc.h modem.h param.h status.h XXstrings.o: config.h XXterminal.o: config.h dial_dir.h misc.h modem.h param.h status.h xmodem.h XXtty_att.o: dial_dir.h param.h XXtty_ucb.o: dial_dir.h param.h XXvcs.o: config.h vcs.h XXx_ascii.o: config.h misc.h param.h XXx_batch.o: config.h misc.h xmodem.h XXx_extrnl.o: config.h XXx_menu.o: config.h extrnl.h misc.h xmodem.h XXx_rcv.o: config.h dial_dir.h misc.h xmodem.h XXx_send.o: config.h dial_dir.h misc.h xmodem.h XXx_win.o: config.h dial_dir.h misc.h xmodem.h XXxmodem.o: config.h misc.h param.h xmodem.h XSHAR_EOF Xif test 5239 -ne "`wc -c < 'Makefile'`" Xthen X echo shar: "error transmitting 'Makefile'" '(should have been 5239 characters)' Xfi Xfi Xecho shar: "extracting 'Pcomm.modem'" '(151 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;0 XXTTY_2=tty000;DIRECT;0 XXMODEM_1a=OBM;;%;@; XXMODEM_1b=N;CONNECT;CONNECT;;;; XXMODEM_1c=;;; XXMODEM_2a=DIRECT;;;; XXMODEM_2b=N;;;;;; XXMODEM_2c=;;; XSHAR_EOF Xif test 151 -ne "`wc -c < 'Pcomm.modem'`" Xthen X echo shar: "error transmitting 'Pcomm.modem'" '(should have been 151 characters)' Xfi Xfi Xecho shar: "extracting 'Readme.7300'" '(5740 characters)' Xif test -f 'Readme.7300' Xthen X echo shar: "will not over-write existing file 'Readme.7300'" Xelse Xsed 's/^X//' << \SHAR_EOF > 'Readme.7300' XX Pcomm v1.2 XX Additional Notes for users of XX AT&T Unix PC 7300/3b1 XX XX 1) The shared libraries on your system contain Terminal Access XX Method (TAM) routines in lieu of curses(3) routines. However, XX many of the routines have the same names! This means that XX curses library is not compatible with the shared library. So, XX to circumvent the problem, an alternate shared library "link XX directive file" is needed. XX XX The Ifile.sh file (or Ifile30.sh file if using the 3.0 version XX of Unix) is a shell script that is run by the Makefile to create XX this alternate file. The alternate file has the references to XX the TAM routines removed (actually, they just have an "x" placed XX in the names). The actual shared library binaries are NOT XX altered. We just fool the linker into believing that the TAM XX routines aren't there. XX XX 2) Before Pcomm can be compiled, the curses library routines XX must be installed on your system. The diskette labeled XX "Curses/Terminfo Programmer's Package" is a part of the "Unix XX Development Set". Likewise, before Pcomm can be used, the XX terminfo database must be installed. The diskettes labeled XX "Curses/Terminfo End User Package" and "Terminfo Database" are XX a part of the "Unix Foundation Set" XX XX 3) If you are running Unix version 3.0 or older, you must edit XX the "config.h" file to change the OLDCURSES definition from XX "#undef" to "#define". Also, you must edit the Makefile on XX the following lines: XX XX #for Unix 3.0 XX OTHERS = doprnt.o XX IFILE = Ifile30.sh XX #OTHERS = setvbuf.o doprnt.o XX #IFILE = Ifile.sh XX XX 4) Did you know that your system can use DEC vt100 style line XX drawing character? Curses automatically uses the "alternate" XX character set (if found) to draw the boxes and lines rather than XX using the "-" and "|" characters. To allow your system to use XX this feature, there are two things you must do: XX XX 1) Load the line drawing font in slot 1 prior to running XX a program requiring them. This can be done by typing: XX XX setf /usr/lib/wfont/BLD.ft 1 XX XX ...or permanently install this font in slot 1 by adding XX the following two lines to the end of the /etc/rc file: XX XX sfont /usr/lib/wfont/BLD.ft 1 XX setf /usr/lib/wfont/BLD.ft 1 XX XX 2) Tell curses(3) about the alternate character set by XX editing the terminfo database. XX XX To get a copy of the terminfo entry to play with, XX you type: XX XX infocmp -I s4 > s4.ti XX XX now add the following line (with a leading tab) to the XX "s4.ti" file: XX XX acsc=+h\,g.e-fjjkkllmmnnqqttuuvvwwxx, XX XX recompile the new entry: XX XX tic s4.ti XX XX There is one disadvantage... Sometimes line noise will switch XX you to the line drawing character set while you're communicating XX with a remote! XX XX 5) The "tset" command is broken on every version of Unix this XX box has ever seen (it is commented out of /etc/profile for a XX good reason). One of tset's functions was to send a string to XX initialize the settings of the terminal and to set the tab XX stops. The fact that this program isn't used is often XX overlooked because the console (as well as a lot of other XX terminals) doesn't require any initialization. However, if you XX call into your system from a remote terminal that *does* require XX initialization, you've got trouble. XX XX For example, curses(3) looks at the terminfo database to see if XX your terminal has "hardware tabs", if so, it expects the tab XX stops to be set. Ignoring tabs by using "stty -tabs" (to XX convert tabs to spaces) won't work, in fact, curses(3) RESETS XX things as if you had typed "stty tabs"! XX XX Likewise, my terminfo entry for PCPLUS v1.1's emulation of a XX vt102 has "^[)0" in the initialization string to load the line XX drawing character set. It needs to be sent to the terminal XX before running Pcomm. XX XX Some versions of Unix have a "init" option to the "tput" command XX to perform all the initialization. If so, you should edit the XX /etc/profile to add the following commands at the bottom: XX XX tput init XX tabs XX XX If your version of tput doesn't recognize the "init" option, a XX somewhat longer solution is to edit /etc/profile and add the XX following commands at the bottom: XX XX eval `tput iprog` XX tput is1 XX tput is2 XX if [ -n "`tput hts`" ] ;then XX stty tabs XX else XX stty -tabs XX fi XX tabs XX cat -s "`tput if`" XX tput is3 XX echo "\r\c" XX XX XX 6) Pcomm makes (an arrogant) assumption that the phone line for XX the OBM is already configured in the DATA mode. Users with only XX one phone line attached to ph0 will have to manually switch the XX line to the DATA mode before using Pcomm and then switch it back XX to VOICE afterwards. To aid in this task, the following shell XX script could be used: XX XX phtoggle XX sleep 1 XX /usr/local/bin/pcomm $* XX phtoggle XX XX Users with one phone line attached to ph0 will have to change XX the TTY setup since the default Pcomm.modem file assumes that XX ph1 is being used. XX XX If you only have one phone line but *always* use it in the DATA XX mode, there is another solution. Did you know that you can fool XX your machine into having a one-line system in the DATA mode? XX All you have to do is re-configure the Telephone Setup and tell XX the machine that you've got two lines (one line to be shared XX between VOICE and DATA on ph0, and one line to be DATA only on XX ph1). Then you just never plug the phone line into ph0, you use XX ph1 instead. The Telephone Setup menu is reached through the XX Office of install, Administration, Hardware Setup menues. XX XX 7. The SETUID_BROKE pre-processor variable was designed to take XX care of systems that aren't able to switch back and forth XX between the real and effective user id. On the Unix PC, this XX problem only exists if the program is set-group-id. So, if XX you're running HDB UUCP and have Pcomm set-user-id to uucp, you XX don't need to have SETUID_BROKE defined. XSHAR_EOF Xif test 5740 -ne "`wc -c < 'Readme.7300'`" Xthen X echo shar: "error transmitting 'Readme.7300'" '(should have been 5740 characters)' Xfi Xfi Xecho shar: "extracting 'config.h'" '(2273 characters)' Xif test -f 'config.h' Xthen X echo shar: "will not over-write existing file 'config.h'" Xelse Xsed 's/^X//' << \SHAR_EOF > 'config.h' XX/* XX * Various tunable parameters. This should appear before any other local XX * header file. XX */ XX XX/* Are you using a Berkeley flavor of Unix? */ XX#undef BSD XX XX/* Use the dialing routines specific to the AT&T Unix PC 7300/3b1 */ XX#define UNIXPC XX XX/* Older versions of curses(3) use termcap in lieu of terminfo */ XX#undef OLDCURSES XX XX/* Use shared memory in lieu of a file for the virtual screen */ XX#define SHAREDMEM XX XX/* Should a missing video attribute be promoted to standout? */ XX#define NOPROMOTE XX XX/* Use extra precautions if Pcomm is set-user-id or set-group-id */ XX#undef SETUGID XX XX/* Should Pcomm make a log of all phone calls? */ XX#define LOG_CALLS XX XX/* The name of the log file (if used). */ XX#define LOGFILE "/usr/adm/phone.calls" XX XX/* Should long distance (toll) calls be limited to a specific group? */ XX#undef LIMIT_LD XX XX/* The name of the privileged group for limiting long distance calls */ XX#define GROUP_NAME "uucp" XX XX/* The path to the line printer program */ XX#define LPR "/usr/bin/lp" XX XX/* The path to the "pretty" printer program (if none, use same as LPR) */ XX#define LPRINT "/usr/bin/lp" XX XX/* The path to the default directory containing the Pcomm support files */ XX#define DEFAULT_DIR "/usr/local/lib/pcomm" XX XX/* The path to the directory where UUCP locks are found */ XX#define LOCK_DIR "/usr/spool/uucp" XX XX/* Do the lock files use ASCII encoded PID's? */ XX#undef ASCII_PID XX XX/* Fold the last character of the lock file to lower case? */ XX#undef XENIX_LOCKS XX XX/* Should Pcomm optimize redialing by keeping the TTY port open */ XX#define KEEP_PORT XX XX/* Does the status line scroll up on "magic cookie" terminals? */ XX#define XMC_BROKE XX XX/* Does the alarm() system call work correctly with the wgetch() function? */ XX#undef WGETCH_BROKE XX XX/* The size of the serial port character buffer */ XX#define CLIST_SIZ 64 XX XX/* The size of the input buffer (should be about the same as CLIST_SIZ) */ XX#define INPUT_BUF 16 XX XX/* The size of the output buffer (should be about one half INPUT_BUF) */ XX#define OUTPUT_BUF 1 XX XX/* Does memmove() exist or is memcpy() well behaved when overlapping? */ XX#define MEMMOVE memcpy XX XX/* Does your Unix allow flip-flop between real and effective user IDs? */ XX#define SETUID_BROKE XX XXtypedef int SIG_TYPE; XX XX#ifdef OLDCURSES XX#define fixterm xfixterm XX#endif /* OLDCURSES */ XSHAR_EOF Xif test 2273 -ne "`wc -c < 'config.h'`" Xthen X echo shar: "error transmitting 'config.h'" '(should have been 2273 characters)' Xfi Xfi Xexit 0 X# End of shell archive SHAR_EOF if test 17190 -ne "`wc -c < 'Unixpc.shar'`" then echo shar: "error transmitting 'Unixpc.shar'" '(should have been 17190 characters)' fi fi echo shar: "extracting 'Waitfor.1'" '(871 characters)' if test -f 'Waitfor.1' then echo shar: "will not over-write existing file 'Waitfor.1'" else sed 's/^X//' << \SHAR_EOF > 'Waitfor.1' X.TH WAITFOR 1 local X.SH NAME Xwaitfor \- wait for a string to appear on the stdin X.SH SYNOPSIS X.B waitfor X[ X.B \-n X] X.B string X.SH DESCRIPTION X.I Waitfor Xreads the standard input and returns a 0 if the string argument is Xfound, returns a 1 if the strings did not appear within the allotted Xtime, or returns a \-1 on error. If the string is found, X.I waitfor Xreturns immediately. X.PP X.I Waitfor Xis designed to be used by X.I Pcomm Xin a shell script for automatically logging a user onto a remote system. X.PP XThe X.I \-n Xoption is used to specify the length of time in seconds to wait. The Xdefault is 10 seconds. X.SH EXAMPLE X.nf X # wait 5 seconds for the login prompt X waitfor \-5 login: X # test the exit code of the waitfor command X if [ $? \-eq 0 ] X then X # send my user ID X echo egray X fi X.fi X.SH "SEE ALSO" Xpcomm(1), matches(1), modem_break(1), Pcomm Reference Manual SHAR_EOF if test 871 -ne "`wc -c < 'Waitfor.1'`" then echo shar: "error transmitting 'Waitfor.1'" '(should have been 871 characters)' fi fi exit 0 # End of shell archive
egray@fthood.UUCP (02/04/89)
This is part 3 (of 8) to the Pcomm v1.2 distribution package. Emmet P. Gray US Army, HQ III Corps & Fort Hood ...!uunet!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: # admin.c # chg_dir.c # config.h # curses.c # d_delete.c # d_lib.c # d_manual.c # d_menu.c # d_print.c # d_prompt.c # d_revise.c # data_log.c # di_delay.c # This archive created: Fri Feb 3 07:35:21 1989 export PATH; PATH=/bin:/usr/bin:$PATH echo shar: "extracting 'admin.c'" '(2941 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#include <stdio.h> X#include <grp.h> X#include "config.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 X/* ARGSUSED */ Xvoid Xlog_calls(i) Xint i; X{ X#ifdef LOG_CALLS X FILE *fp; X char *number, *build_num(), *date, *ctime(), *getlogin(), buf[80]; 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] = '\0'; X date[16] = '\0'; X X if (!(fp = fopen(LOGFILE, "a+"))) { X /* fatal! (to prevent hanky panky) */ X sprintf(buf, "Can't open log file \"%s\"", LOGFILE); X error_win(1, buf, "Contact your system administrator"); X } 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; 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 X/* ARGSUSED */ 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(GROUP_NAME); X if (grpbuf == NULL || *grpbuf->gr_mem == '\0') X return(0); X /* are you in the group? */ X name = getlogin(); X for (; *grpbuf->gr_mem!='\0'; 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", ""); X return(1); X } X X if (*number == '\0') { 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#if defined(LOG_CALLS) || defined(LIMIT_LD) X/* X * Put together the complete phone number but strip out the extraneous X * characters. X */ X Xstatic char * Xbuild_num(i) Xint i; X{ X int j; X char *t, temp[80], *strcpy(), *strcat(); X static char ans[80]; X X temp[0] = '\0'; 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] = '\0'; X X return(ans); X} X#endif /* LOG_CALLS || LIMIT_LD */ SHAR_EOF if test 2941 -ne "`wc -c < 'admin.c'`" then echo shar: "error transmitting 'admin.c'" '(should have been 2941 characters)' fi fi echo shar: "extracting 'chg_dir.c'" '(1514 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 you have X * search permission. X */ X X#include <curses.h> X#include "config.h" X#include "misc.h" X Xvoid Xchg_dir() X{ X extern int fd; X WINDOW *ch_win, *newwin(); X char *ans, *dir, *expand(), *cwd, *getcwd(), cwdbuf[200]; X char *get_str(); 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, VERT, HORZ); 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 while ((ans = get_str(ch_win, 80, "", " \t\n")) != NULL) { X /* a CR means no change */ X if (*ans == '\0') X break; X /* expand the input */ X dir = expand(ans); X /* if you have search permission */ X if (!access(dir, 1)) { X if (!chdir(dir)) 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 /* clean up the mess */ X clear_line(ch_win, 3, 19, TRUE); X clear_line(ch_win, 4, 14, TRUE); X wmove(ch_win, 3, 19); X wrefresh(ch_win); X } X if (fd == -1) { X werase(ch_win); X wrefresh(ch_win); X } X delwin(ch_win); X return; X} X X#ifdef BSD X/* X * Get the current working directory, AT&T style. Well... not really, it X * doesn't handle a NULL pointer for the buffer. X */ X X/* ARGSUSED */ Xchar * Xgetcwd(buf, len) Xchar *buf; Xint len; X{ X char *getwd(); X X return(getwd(buf)); X} X#endif /* BSD */ SHAR_EOF if test 1514 -ne "`wc -c < 'chg_dir.c'`" then echo shar: "error transmitting 'chg_dir.c'" '(should have been 1514 characters)' fi fi echo shar: "extracting 'config.h'" '(2286 characters)' if test -f 'config.h' then echo shar: "will not over-write existing file 'config.h'" else sed 's/^X//' << \SHAR_EOF > 'config.h' X/* X * Various tunable parameters. This should appear before any other local X * header file. X */ X X/* Are you using a Berkeley flavor of Unix? */ X#undef BSD X X/* Use the dialing routines specific to the AT&T Unix PC 7300/3b1 */ X#undef UNIXPC X X/* Older versions of curses(3) use termcap in lieu of terminfo */ X#undef OLDCURSES X X/* Use shared memory in lieu of a file for the virtual screen */ X#define SHAREDMEM X X/* Should a missing video attribute be promoted to standout? */ X#define NOPROMOTE X X/* Use extra precautions if Pcomm is set-user-id or set-group-id */ X#undef SETUGID X X/* Should Pcomm make a log of all phone calls? */ X#undef LOG_CALLS X X/* The name of the log file (if used). */ X#define LOGFILE "/usr/adm/phone.calls" X X/* Should long distance (toll) calls be limited to a specific group? */ X#undef LIMIT_LD X X/* The name of the privileged group for limiting long distance calls */ X#define GROUP_NAME "uucp" X X/* The path to the line printer program */ X#define LPR "lp" X X/* The path to the "pretty" printer program (if none, use "pr | lp") */ X#define LPRINT "pr | lp" X X/* The path to the default directory containing the Pcomm support files */ X#define DEFAULT_DIR "/usr/local/lib/pcomm" X X/* The path to the directory where UUCP locks are found */ X#define LOCK_DIR "/usr/spool/uucp" X X/* Do the lock files use ASCII encoded PID's? */ X#undef ASCII_PID X X/* Fold the last character of the lock to lower case? */ X#undef XENIX_LOCKS X X/* Should Pcomm optimize redialing by keeping the TTY port open */ X#define KEEP_PORT X X/* Does the status line scroll up on "magic cookie" terminals? */ X#undef XMC_BROKE X X/* Does the alarm() system call work correctly with the wgetch() function? */ X#undef WGETCH_BROKE X X/* The size of the serial port character buffer */ X#define CLIST_SIZ 64 X X/* The size of the input buffer (should be about the same as CLIST_SIZ) */ X#define INPUT_BUF 64 X X/* The size of the output buffer (should be about one half INPUT_BUF) */ X#define OUTPUT_BUF 32 X X/* Does memmove() exist or is memcpy() well behaved when overlapping? */ X#define MEMMOVE memcpy X X/* Does your Unix allow flip-flop between real and effective user IDs? */ X#undef SETUID_BROKE X Xtypedef void SIG_TYPE; X/* typedef int SIG_TYPE; */ X X#ifdef BSD X#define strchr index X#define strrchr rindex X#endif /* BSD */ SHAR_EOF if test 2286 -ne "`wc -c < 'config.h'`" then echo shar: "error transmitting 'config.h'" '(should have been 2286 characters)' fi fi echo shar: "extracting 'curses.c'" '(9053 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(3) routines. X */ X X#define STR_WIDTH 256 X#define NUM_WIDTH 16 X X#include <stdio.h> X#include <curses.h> X#include <signal.h> X#include "config.h" X#include "misc.h" X X#ifdef BSD X#include <setjmp.h> Xjmp_buf wk_buf; X#endif /* BSD */ X X#ifndef OLDCURSES X#include <term.h> X#else /* OLDCURSES */ X#ifdef UNIXPC X#include <sgtty.h> X#endif /* UNIXPC */ X#endif /* OLDCURSES */ X X/* X * Get a string from a window. Similar to wgetstr(), except we limit X * the length, return a NULL (not pointer to NULL) on <ESC> key, beep X * at any character in "disallow" string, and beep at any character not X * in "allow". (It doesn't make sense to use both "allow" and "disallow" X * at the same time). Returns a pointer to a static area. X */ X Xchar * Xget_str(win, num, allow, disallow) XWINDOW *win; Xint num; Xchar *allow, *disallow; X{ X int count, x, y; X char ans, *strchr(); X static char buf[STR_WIDTH]; X X count = 0; X while ((ans = wgetch(win)) != '\r') { X /* do our own backspace */ X if (ans == BS || ans == DEL) { X if (!count) { X beep(); X continue; X } X count--; X buf[count] = '\0'; X getyx(win, y, x); X x--; X wmove(win, y, x); X waddch(win, (chtype) ' '); X wmove(win, y, x); X wrefresh(win); X continue; X } X /* an <ESC> anywhere in the string */ X if (ans == ESC) X return(NULL); X X /* illegal character? */ X if (*disallow != '\0' && strchr(disallow, ans)) { X beep(); X continue; X } X if (*allow != '\0' && !strchr(allow, ans)) { X beep(); X continue; X } X /* exceeded the max? */ X if (count >= num || count >= STR_WIDTH) { X beep(); X continue; X } X X buf[count] = ans; X waddch(win, (chtype) ans); X wrefresh(win); X count++; X } X buf[count] = '\0'; X return(buf); X} X X/* X * Get a number from a window. We limit the length and return a -1 X * on <ESC> key. X */ X Xint Xget_num(win, num) XWINDOW *win; Xint num; X{ X int count, x, y, number; X char ans, buf[NUM_WIDTH]; X X count = 0; X while ((ans = wgetch(win)) != '\r') { X /* do our own backspace */ X if (ans == BS || ans == DEL) { X if (!count) { X beep(); X continue; X } X count--; X buf[count] = '\0'; X getyx(win, y, x); X x--; X wmove(win, y, x); X waddch(win, (chtype) ' '); X wmove(win, y, x); X wrefresh(win); X continue; X } X /* an <ESC> anywhere in the string */ X if (ans == ESC) X return(-1); X /* only digits are allowed */ X if (ans < '0' || ans > '9') { X beep(); X continue; X } X /* exceeded the max? */ X if (count >= num || count >= NUM_WIDTH) { X beep(); X continue; X } X X buf[count] = ans; X waddch(win, (chtype) ans); X wrefresh(win); X count++; X } X buf[count] = '\0'; X number = atoi(buf); X return(number); X} X X/* X * Change video attributes while printing a string. The use of the X * pre-processor definition NOPROMOTE (located in config.h) means that X * strings will be printed without any special video attribute if the X * requested capability doesn't exist. X */ X Xwattrstr(win, attr, str) XWINDOW *win; Xchtype attr; Xchar *str; X{ X int do_it; X /* if nothing, do nothing */ X if (str == NULL || *str == '\0') X return(0); X X#ifdef OLDCURSES X if (attr) X wstandout(win); X waddstr(win, str); X if (attr) X wstandend(win); X#else /* OLDCURSES */ X X#ifdef NOPROMOTE X /* does the capability exist? */ X do_it = 0; X if ((attr & A_STANDOUT) && enter_standout_mode) X do_it++; X if ((attr & A_UNDERLINE) && enter_underline_mode) X do_it++; X if ((attr & A_REVERSE) && (enter_reverse_mode || enter_standout_mode)) X do_it++; X if ((attr & A_BLINK) && enter_blink_mode) X do_it++; X if ((attr & A_BOLD) && enter_bold_mode) X do_it++; X if ((attr & A_DIM) && enter_dim_mode) X do_it++; X#else /* NOPROMOTE */ X do_it = 1; X#endif /* NOPROMOTE */ X X if (do_it) X wattron(win, attr); X /* print the string */ X waddstr(win, str); X if (do_it) X wattroff(win, attr); X#endif /* OLDCURSES */ X return(0); X} X X/* X * Change video attributes while printing a character. X */ X Xwattrch(win, attr, c) XWINDOW *win; Xchtype attr; Xchar c; X{ X int do_it; X X if (c == '\0') X return(0); X#ifdef OLDCURSES X if (attr) X wstandout(win); X waddch(win, (chtype) c); X if (attr) X wstandend(win); X#else /* OLDCURSES */ X X#ifdef NOPROMOTE X /* does the capability exist? */ X do_it = 0; X if ((attr & A_STANDOUT) && enter_standout_mode) X do_it++; X if ((attr & A_UNDERLINE) && enter_underline_mode) X do_it++; X if ((attr & A_REVERSE) && (enter_reverse_mode || enter_standout_mode)) X do_it++; X if ((attr & A_BLINK) && enter_blink_mode) X do_it++; X if ((attr & A_BOLD) && enter_bold_mode) X do_it++; X if ((attr & A_DIM) && enter_dim_mode) X do_it++; X#else /* NOPROMOTE */ X do_it = 1; X#endif /* NOPROMOTE */ X X if (do_it) X wattron(win, attr); X /* print the character */ X waddch(win, (chtype) c); X if (do_it) X wattroff(win, attr); X#endif /* OLDCURSES */ X return(0); X} X X X/* X * Change video attributes while printing a number. X */ X Xwattrnum(win, attr, num) XWINDOW *win; Xchtype attr; Xint num; X{ X int do_it; X char buf[40]; X X sprintf(buf, "%d", num); X X#ifdef OLDCURSES X if (attr) X wstandout(win); X waddstr(win, buf); X if (attr) X wstandend(win); X#else /* OLDCURSES */ X X#ifdef NOPROMOTE X /* does the capability exist? */ X do_it = 0; X if ((attr & A_STANDOUT) && enter_standout_mode) X do_it++; X if ((attr & A_UNDERLINE) && enter_underline_mode) X do_it++; X if ((attr & A_REVERSE) && (enter_reverse_mode || enter_standout_mode)) X do_it++; X if ((attr & A_BLINK) && enter_blink_mode) X do_it++; X if ((attr & A_BOLD) && enter_bold_mode) X do_it++; X if ((attr & A_DIM) && enter_dim_mode) X do_it++; X#else /* NOPROMOTE */ X do_it = 1; X#endif /* NOPROMOTE */ X X if (do_it) X wattron(win, attr); X /* print the character */ X waddstr(win, buf); X if (do_it) X wattroff(win, attr); X#endif /* OLDCURSES */ X return(0); X} X X/* X * Prompt for a Yes or No answer. Echo the single key input as words. X * Handle the funny cursor movement problems with magic cookie terminals. X * Returns a 1 on yes. X */ X Xint Xyes_prompt(win, y, x, attr, str) XWINDOW *win; Xint y, x; Xchtype attr; Xchar *str; X{ X int ret_code; X char new_str[80], *strcpy(), *strcat(); X /* sanity checking */ X if (strlen(str) > 71) X *(str+71) = '\0'; X /* build and display the prompt */ X strcpy(new_str, str); X strcat(new_str, "? (y/n):"); X mvwattrstr(win, y, x, attr, new_str); X wmove(win, y, strlen(new_str)+x+2); X wrefresh(win); X X ret_code = -1; X while (ret_code == -1) { X switch (wgetch(win)) { X case 'y': X case 'Y': X waddstr(win, "Yes"); X ret_code = 1; X break; X case 'n': X case 'N': X case ESC: X waddstr(win, "No"); X ret_code = 0; X break; X default: X beep(); X X } X } X wrefresh(win); X return(ret_code); X} X X/* X * Handy routine for clear-to-end-of-line. Fixes up the box if requested. X */ X Xint Xclear_line(win, y, x, re_box) XWINDOW *win; Xint y, x, re_box; X{ X if (wmove(win, y, x) == ERR) X return(ERR); X X wclrtoeol(win); X X if (re_box) { X mvwaddch(win, y, win->_maxx-1, (chtype) ACS_VLINE); X wmove(win, y, x); X } X return(0); X} X X/* X * Routine to make a horizontal line. Does NOT do a wrefresh(). X */ X Xint Xhorizontal(win, x, y, len) XWINDOW *win; Xint x, y, len; X{ X wmove(win, x, y); X X while (len--) X waddch(win, ACS_HLINE); X X return(0); X} X X/* X * Wait for a key or time out. Returns a -1 on timeout. This is similar X * to the half-delay mode in the newer versions of curses(3). X */ X Xstatic int wk_flag; X X/* ARGSUSED */ Xint Xwait_key(win, sec) XWINDOW *win; Xunsigned int sec; X{ X int key, wk_force(); X unsigned int alarm(); X char c; X X signal(SIGALRM, wk_force); X wk_flag = 0; X X alarm(sec); X X#ifdef BSD X if (setjmp(wk_buf)) X return(-1); X#endif /* BSD */ X X#ifdef WGETCH_BROKE X read(0, &c, 1); X key = c & 0x7f; X#else /* WGETCH_BROKE */ X key = wgetch(win); X#endif /* WGETCH_BROKE */ X X if (wk_flag) X return(-1); X alarm(0); X return(key); X} X X/* ARGSUSED */ Xstatic int Xwk_force(dummy) Xint dummy; X{ X#ifdef BSD X longjmp(wk_buf, 1); X#else /* BSD */ X signal(SIGALRM, wk_force); X wk_flag = 1; X#endif /* BSD */ X} X X/* X * Here are some routines that are probably missing from the older X * flavors of curses(3). X */ X X#ifdef OLDCURSES X/* X * Make the terminal bell go off X */ X Xint Xbeep() X{ X fputc(BEL, stderr); X return(0); X} X X/* X * 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 X/* ARGSUSED */ Xint Xnodelay(win, on) XWINDOW *win; Xint on; X{ X if (on) X tty_noblock(0, TRUE); X else X tty_noblock(0, FALSE); X return(0); X} X X/* X * Take the terminal out of the "curses mode". The t_mode structure was X * captured before we initialized the curses mode. X */ X Xint Xresetterm() X{ X extern char _putchar(); X extern struct sgttyb t_mode; X X ioctl(0, TIOCSETP, &t_mode); X tputs(TE, 1, _putchar); X tputs(VE, 1, _putchar); X return(0); X} X X/* X * Put the terminal back into the "curses mode". The c_mode structure was X * captured after we initialized the curses mode. X */ X Xint Xfixterm() X{ X extern char _putchar(); X extern struct sgttyb c_mode; X X ioctl(0, TIOCSETP, &c_mode); X tputs(TI, 1, _putchar); X tputs(VS, 1, _putchar); X return(0); X} X#endif /* OLDCURSES */ SHAR_EOF if test 9053 -ne "`wc -c < 'curses.c'`" then echo shar: "error transmitting 'curses.c'" '(should have been 9053 characters)' fi fi echo shar: "extracting 'd_delete.c'" '(2015 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 non-zero return code means that entries were deleted. X */ X X#include <stdio.h> X#include <curses.h> X#include "config.h" X#include "dial_dir.h" X#include "misc.h" X#include "param.h" X Xint Xdelete() X{ X extern char *null_ptr; X WINDOW *d_win, *newwin(); X int i, first, last; X void free_ptr(); X X d_win = newwin(6, 32, 10, 15); X X mvwaddstr(d_win, 2, 2, "Delete entry: thru:"); X box(d_win, VERT, HORZ); 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->script[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->script[i] = null_ptr; X } X delwin(d_win); X return(1); X } X delwin(d_win); X return(0); X} SHAR_EOF if test 2015 -ne "`wc -c < 'd_delete.c'`" then echo shar: "error transmitting 'd_delete.c'" '(should have been 2015 characters)' fi fi echo shar: "extracting 'd_lib.c'" '(6921 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 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 * regardless 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(extra) Xchar *extra; X{ X extern char *null_ptr; X FILE *fp, *my_fopen(); X int i, line, oops; X char *str_dup(), buf[200], *temp_token, *str, *str_tok(), token[20]; X char message[80], *sep, *findfile(); X static struct DIAL_DIR d; X void error_win(); X X if ((d.d_path = findfile(extra, "pcomm.dial_dir")) == NULL) X error_win(1, "Support file \"pcomm.dial_dir\" is missing", "or no read permission"); X X if (!(fp = my_fopen(d.d_path, "r"))) { X sprintf(buf, "\"%s\" for read", d.d_path); X error_win(1, "Can't open dialing directory file", buf); X } X X sep = ";;---;;\n"; X line = 0; X oops = 0; X while (fgets(buf, 200, fp) != NULL) { X line++; X if (line > 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", line); X oops++; X break; X } X /* X * Parse the rest of the line. This is similar to using X * the "real" strtok() function, but this version returns X * a pointer to NULL if the token is missing. Note the use X * of the array of field separators. X */ X for (i=0; i<8; i++) { X if (!(str = str_tok((char *) NULL, 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 d.name[line] = str_dup(str); X break; X case 1: X d.number[line] = str_dup(str); X break; X case 2: X d.baud[line] = atoi(str); X break; X case 3: X d.parity[line] = *str; X break; X case 4: X d.dbits[line] = atoi(str); X break; X case 5: X d.sbits[line] = atoi(str); X break; X case 6: X d.duplex[line] = *str; X break; X case 7: X d.script[line] = str_dup(str); X break; X } X } X if (oops) X break; X /* sanity checking */ X sprintf(token, "DIR_%d", line); X if (strcmp(temp_token, token)) { X sprintf(message, "is corrupted at line %d", line); X oops++; X break; X } X } X fclose(fp); X X if (oops) { X sprintf(buf, "Dialing directory file \"%s\"", d.d_path); X error_win(1, buf, message); X } X d.d_entries = line; X /* if empty database */ X if (!line) { X sprintf(buf, "Dialing directory file \"%s\"", d.d_path); X error_win(0, buf, "has no data"); X } X /* fill in the rest with defaults */ X for (i=line+1; 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.script[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.script[0] = null_ptr; X /* create an empty queue */ X for (i=0; i<NUM_QUEUE; i++) { X d.q_ld[i] = '\0'; X d.q_num[i] = -1; X } X /* the start up 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 non-zero return code means a non-fatal error. X */ X Xint Xup_dir(entry) Xint entry; X{ X FILE *fp_in, *fp_out, *my_fopen(); X int i; X char *temp[NUM_DIR+1], buf[200], *str_dup(), *str_rep(); X void error_win(), free_ptr(); X X /* open for read */ X if (!(fp_in = my_fopen(dir->d_path, "r"))) { X sprintf(buf, "\"%s\" for read", dir->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, 200, fp_in) != NULL) X temp[++i] = str_dup(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->script[entry]); X X if (entry <= dir->d_entries) X free_ptr(temp[entry]); X temp[entry] = str_dup(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] = str_rep(temp[i], buf); X } X } X /* update "dir->d_entries" */ X if (entry > dir->d_entries) X dir->d_entries = entry; X X /* open for write */ X if (!(fp_out = my_fopen(dir->d_path, "w"))) { X for (i=1; i<=dir->d_entries; i++) X free_ptr(temp[i]); X sprintf(buf, "\"%s\"", dir->d_path); X error_win(0, "No write permission on dialing 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 non-zero X * return code means a non-fatal error. X */ X Xint Xdel_dir(first, last) Xint first, last; X{ X FILE *fp_in, *fp_out, *my_fopen(); X int i; X char *temp[NUM_DIR+1], buf[200], *str_dup(), *str_rep(); 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 = my_fopen(dir->d_path, "r"))) { X sprintf(buf, "\"%s\" for read", dir->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, 200, fp_in) != NULL) X temp[++i] = str_dup(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 temp[i] = str_rep(temp[i], 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 = my_fopen(dir->d_path, "w"))) { X for (i=1; i<=dir->d_entries; i++) X free_ptr(temp[i]); X sprintf(buf, "\"%s\"", dir->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 6921 -ne "`wc -c < 'd_lib.c'`" then echo shar: "error transmitting 'd_lib.c'" '(should have been 6921 characters)' fi fi echo shar: "extracting 'd_manual.c'" '(1944 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 non-zero return code X * 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 "config.h" X#include "dial_dir.h" X#include "misc.h" X Xint Xmanual() X{ X extern int xmc; X extern char *null_ptr; X WINDOW *m_win, *newwin(); X char *number, *str_rep(), *get_str(), ld_code, *strchr(); X void fix_xmc(), free_ptr(); X X m_win = newwin(5, 50, 0, 20); X X box(m_win, VERT, HORZ); 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, "", "\n")) == 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 = '\0'; 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 dir->name[0] = str_rep(dir->name[0], number); X /* if space, change to null_ptr */ X if (!strcmp(number, " ")) { X free_ptr(dir->number[0]); X dir->number[0] = null_ptr; X } X else X dir->number[0] = str_rep(dir->number[0], 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 Xstatic void 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 1944 -ne "`wc -c < 'd_manual.c'`" then echo shar: "error transmitting 'd_manual.c'" '(should have been 1944 characters)' fi fi echo shar: "extracting 'd_menu.c'" '(6993 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 "config.h" X#include "dial_dir.h" X#include "misc.h" X#include "param.h" X Xstatic int current = 1; X/* X * Display the dialing directory and prompt for options. A non-zero return X * code means we're ready to dial. X */ X Xint Xdial_menu() X{ X extern int xmc; X WINDOW *dm_win, *newwin(); X char buf[5], ld_code; X int ans, start, needs_repair, count, x, y, i, ret_code; X void dir_scroll(), active_ld(), disp_ld(), print_dir(), st_line(); X X touchwin(stdscr); X refresh(); X st_line(""); 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 horizontal(dm_win, 2, 0, 78); X mvwattrstr(dm_win, 3, 0, A_STANDOUT, " Name Number Baud P D S Dpx Script/TTY "); X /* show 10 entries */ X dir_scroll(dm_win, current); 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, 34, 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, 34, 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>/<down>"); X waddstr(dm_win, " Page"); X mvwattrch(dm_win, 17, 34, 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, VERT, HORZ); X y = 15; X x = 8; X wmove(dm_win, 15, 8); X wrefresh(dm_win); X X#ifndef OLDCURSES X keypad(dm_win, TRUE); X#endif /* OLDCURSES */ X /* prompt for options */ X count = 0; X ld_code = '\0'; 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, (chtype) ans); X wrefresh(dm_win); X count++; X continue; X } X switch (ans) { X case DEL: X case BS: /* do our own backspace */ X if (!count) { X beep(); X break; X } X count--; X if (!count) X ld_code = '\0'; X buf[count] = '\0'; X getyx(dm_win, y, x); X x--; X wmove(dm_win, y, x); X waddch(dm_win, (chtype) ' '); 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 dir_scroll(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 dir_scroll(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 dir_scroll(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] = '\0'; 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++; X break; X } X break; X case 'r': X case 'R': /* revise */ X if (revise()) { X active_ld(dm_win); X dir_scroll(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++; X break; X case 'd': X case 'D': /* delete a range of entries */ X if (delete()) X dir_scroll(dm_win, current); X touchwin(dm_win); X break; X case 'm': X case 'M': /* manual dial */ X if (manual()) { X ret_code++; X break; X } X touchwin(dm_win); X needs_repair++; X break; X case 'l': X case 'L': /* print the entries */ X print_dir(); X touchwin(dm_win); X needs_repair++; X break; X case '+': /* LD codes */ X case '-': X case '@': X case '#': X waddch(dm_win, (chtype) ans); X wrefresh(dm_win); X ld_code = ans; X continue; X case ESC: /* <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, FALSE); X clear_line(dm_win, 3, 0, FALSE); 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 Script/TTY "); X box(dm_win, VERT, HORZ); X } X wmove(dm_win, y, x); X wrefresh(dm_win); X } while (ans != ESC); X X werase(dm_win); X wrefresh(dm_win); X delwin(dm_win); X if (ret_code) { X touchwin(stdscr); X refresh(); X } 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 Xstatic void Xdir_scroll(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->script[i]); X box(win, VERT, HORZ); X return; X} X X/* X * Display the Long Distance codes. Press any key to continue. X */ X Xstatic void 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 horizontal(ld_win, 2, 0, 30); 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, VERT, HORZ); 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 Xstatic void Xactive_ld(win) XWINDOW *win; X{ X mvwaddstr(win, 19, 21, " "); X wmove(win, 19, 21); X /* a NULL means it's not active */ X if (*param->ld_plus != '\0') X waddstr(win, "+ "); X if (*param->ld_minus != '\0') X waddstr(win, "- "); X if (*param->ld_at != '\0') X waddstr(win, "@ "); X if (*param->ld_pound != '\0') X waddstr(win, "# "); X return; X} SHAR_EOF if test 6993 -ne "`wc -c < 'd_menu.c'`" then echo shar: "error transmitting 'd_menu.c'" '(should have been 6993 characters)' fi fi echo shar: "extracting 'd_print.c'" '(3958 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 MAX_STRING 80 X X#include <stdio.h> X#include <curses.h> X#include "config.h" X#include "dial_dir.h" X#include "misc.h" X Xvoid Xprint_dir() X{ X FILE *fp, *popen(), *my_fopen(); X WINDOW *p_win, *newwin(); X char *ans, *file, *e_get_str(), buf[100], *expand(); X int is_printer, i; 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, VERT, HORZ); 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 ((ans = e_get_str(p_win, 80)) == NULL) { X /* erase because it overlaps dm_win */ X werase(p_win); X wrefresh(p_win); X delwin(p_win); X return; X } X file = expand(ans); X is_printer = 0; X /* the default (printer) */ X if (*file == '\0') { X if (!(fp = popen(LPRINT, "w"))) { X sprintf(buf, "\"%s\"", LPRINT); X error_win(0, "Can't open printer program", buf); X werase(p_win); X wrefresh(p_win); X delwin(p_win); X return; X } X is_printer++; X } X /* the requested file */ X else { X /* X * Check to see if the file already exists (and if you X * have write permission too). Currently only allows X * you to bail out or overwrite the file (no append). X */ X switch(can_write(file)) { X case DENIED: 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 case OK_BUT_EXISTS: X werase(p_win); X mvwprintw(p_win, 2, 3, "File \"%s\" already exists!", file); X beep(); X box(p_win, VERT, HORZ); 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 /* fall thru */ X case WRITE_OK: X if (!(fp = my_fopen(file, "w"))) { X sprintf(buf, "\"%s\"", file); X error_win(0, "Can't open file", buf); X werase(p_win); X wrefresh(p_win); X delwin(p_win); X return; X } X break; X } X } X X werase(p_win); X mvwaddstr(p_win, 2, 13, "Printing Pcomm directory"); X box(p_win, VERT, HORZ); 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->script[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 Xstatic char * Xe_get_str(win, num) XWINDOW *win; Xint num; X{ X int count, x, y, done_it; X char ans; X static char buf[MAX_STRING]; X X done_it = 0; X count = 0; X while ((ans = wgetch(win)) != '\r') { X /* do our own backspace */ X if (ans == BS || ans == DEL) { X if (!count) { X beep(); X continue; X } X count--; X buf[count] = '\0'; X getyx(win, y, x); X x--; X wmove(win, y, x); X waddch(win, (chtype) ' '); X wmove(win, y, x); X wrefresh(win); X continue; X } X /* exceeded the max? */ X if (count >= num || count >= MAX_STRING) { X beep(); X continue; X } X /* illegal character? */ X if (ans == '\n') { X beep(); X continue; X } X /* an <ESC> anywhere in the string */ X if (ans == ESC) 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++; X } X X buf[count] = ans; X waddch(win, (chtype) ans); X wrefresh(win); X count++; X } X buf[count] = '\0'; X return(buf); X} SHAR_EOF if test 3958 -ne "`wc -c < 'd_print.c'`" then echo shar: "error transmitting 'd_print.c'" '(should have been 3958 characters)' fi fi echo shar: "extracting 'd_prompt.c'" '(6130 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 non-zero return code means X * the entry was changed. X */ X X#include <stdio.h> X#include <curses.h> X#include "config.h" X#include "dial_dir.h" X#include "misc.h" X Xint Xprompt_lib(win, i) XWINDOW *win; Xint i; X{ X extern int xmc; X extern char *null_ptr; 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[40], number[40], script[40]; X char parity, duplex, *str_rep(), *strcpy(), buf[40]; X void free_ptr(); X /* make copies */ X strcpy(name, dir->name[i]); X strcpy(number, 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 strcpy(script, dir->script[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->script[i]); X box(win, VERT, HORZ); X X /* prompt for name */ X mvwaddstr(win, 4, 4, "Name: "); X wrefresh(win); X X if ((ans = get_str(win, 20, "", ";\n")) == NULL) X return(0); X if (*ans != '\0') { X strcpy(name, 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, TRUE); X waddstr(win, "Number: "); X wrefresh(win); X X if ((ans = get_str(win, 18, "", ";\n")) == NULL) X return(0); X if (*ans != '\0') { X strcpy(number, ans); X mvwaddstr(win, 2, 26, " "); X wrefresh(win); X /* X * Should be right justified, but we don't wanna 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, TRUE); 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 <CR> to accept the currently showing value X * or any other key to see the next choice. The first value X * 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 == ESC) 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 == ESC) 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 == ESC) 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 == ESC) 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 == ESC) 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 script or TTY */ X clear_line(win, 4, 4, TRUE); X waddstr(win, "Script name (or TTY): "); X wrefresh(win); X X if ((ans = get_str(win, 14, "", ";\n")) == NULL) X return(0); X X if (*ans != '\0') { X strcpy(script, ans); X mvwaddstr(win, 2, 62, " "); X wrefresh(win); X mvwattrstr(win, 2, 62, A_BOLD, script); X } X /* store 'em for real */ X X if (!strcmp(name, " ")) { X free_ptr(dir->name[i]); X dir->name[i] = null_ptr; X } X else X dir->name[i] = str_rep(dir->name[i], name); X X if (!strcmp(number, " ")) { X free_ptr(dir->number[i]); X dir->number[i] = null_ptr; X } X else X dir->number[i] = str_rep(dir->number[i], number); X 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 X if (!strcmp(script, " ")) { X free_ptr(dir->script[i]); X dir->script[i] = null_ptr; X } X else X dir->script[i] = str_rep(dir->script[i], script); X X return(1); X} SHAR_EOF if test 6130 -ne "`wc -c < 'd_prompt.c'`" then echo shar: "error transmitting 'd_prompt.c'" '(should have been 6130 characters)' fi fi echo shar: "extracting 'd_revise.c'" '(4009 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 non-zero return code X * means that something was updated. Prompts for saving changes to disk. X */ X X#include <stdio.h> X#include <curses.h> X#include "config.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, *ld_prompt(), *str_rep(); 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, VERT, HORZ); 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)) != ESC) { X if (ans >= '0' && ans <= '9') { X if (count == 3) { X beep(); X continue; X } X buf[count] = ans; X waddch(r_win, (chtype) 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] = '\0'; 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 == BS || ans == DEL) { X if (!count) { X beep(); X continue; X } X count--; X buf[count] = '\0'; X getyx(r_win, y, x); X x--; X wmove(r_win, y, x); X waddch(r_win, (chtype) ' '); 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 = ld_prompt(r_win, param->ld_plus, ans)) != NULL) { X param->ld_plus = str_rep(param->ld_plus, ld); X param_flag++; X } X break; X case '-': X if ((ld = ld_prompt(r_win, param->ld_minus, ans)) != NULL) { X param->ld_minus = str_rep(param->ld_minus, ld); X param_flag++; X } X break; X case '@': X if ((ld = ld_prompt(r_win, param->ld_at, ans)) != NULL) { X param->ld_at = str_rep(param->ld_at, ld); X param_flag++; X } X break; X case '#': X if ((ld = ld_prompt(r_win, param->ld_pound, ans)) != NULL) { X param->ld_pound = str_rep(param->ld_pound, 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, TRUE); 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 (up_dir(num)) { X touchwin(r_win); X wrefresh(r_win); X } X } X if (save && param_flag) { X if (up_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 null_ptr. Returns NULL on escape. Since it uses X * get_str(), the return value is a pointer to a static area. X */ X Xstatic char * Xld_prompt(win, current_ld, name) XWINDOW *win; Xchar *current_ld, name; X{ X extern char *null_ptr; X char *ans, *get_str(); 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, VERT, HORZ); X wrefresh(win); X X if ((ans = get_str(win, 20, "", "\n")) == NULL) X return(NULL); X /* if space, change to null_ptr */ X if (!strcmp(ans, " ")) X ans = null_ptr; X /* display new value */ X clear_line(win, 2, 4, TRUE); X wattrstr(win, A_BOLD, ans); X X return(ans); X} SHAR_EOF if test 4009 -ne "`wc -c < 'd_revise.c'`" then echo shar: "error transmitting 'd_revise.c'" '(should have been 4009 characters)' fi fi echo shar: "extracting 'data_log.c'" '(1726 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. Also turns on the data logging. A non-zero return code means X * we need to restart the input routine. X */ X X#include <stdio.h> X#include <curses.h> X#include "config.h" X#include "misc.h" X#include "param.h" X#include "status.h" X Xint Xdata_logging() X{ X extern int fd; X int ret_code; X WINDOW *dl_win, *newwin(); X char *ans, *path, *expand(), *get_str(), *strcpy(); X void input_off(); 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, VERT, HORZ); 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 while ((ans = get_str(dl_win, PATH, "", " \t\n")) != NULL) { X /* give 'em the default */ X if (*ans == '\0') X path = 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 /* clean up the mess */ X clear_line(dl_win, 3, 18, TRUE); X clear_line(dl_win, 4, 24, TRUE); X wmove(dl_win, 3, 18); X wrefresh(dl_win); X } X if (ret_code) { X strcpy(status->log_path, path); X status->log = 1; X /* X * Without shared memory, killing and restarting the input X * routine is the only way to change the name of the file X * that the input routines uses. X */ X#ifdef SHAREDMEM X ret_code = 0; X#else /* SHAREDMEM */ X input_off(); X#endif /* SHAREDMEM */ X } X if (fd == -1) { X werase(dl_win); X wrefresh(dl_win); X } X delwin(dl_win); X X return(ret_code); X} SHAR_EOF if test 1726 -ne "`wc -c < 'data_log.c'`" then echo shar: "error transmitting 'data_log.c'" '(should have been 1726 characters)' fi fi echo shar: "extracting 'di_delay.c'" '(1978 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 "config.h" X#include "misc.h" X#include "param.h" X Xvoid Xdelay_times() X{ X WINDOW *dt_win, *newwin(); X int cdelay, rdelay; X X dt_win = newwin(9, 45, 7, 15); X X mvwprintw(dt_win, 2, 4, "Current connect delay time: %d", param->c_delay); X mvwprintw(dt_win, 3, 4, "Current redial delay time: %d", param->r_delay); X mvwaddstr(dt_win, 5, 4, "New connect delay: "); X mvwaddstr(dt_win, 6, 4, "New redial delay: "); X box(dt_win, VERT, HORZ); 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->c_delay; 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 rdelay number */ X wmove(dt_win, 6, 20); X wrefresh(dt_win); X if ((rdelay = get_num(dt_win, 3)) == -1) { X delwin(dt_win); X return; X } X /* give 'em the current settings */ X if (!rdelay) { X rdelay = param->r_delay; X wprintw(dt_win, "%-3d", rdelay); X } X else { X /* some reasonable limit */ X if (rdelay > MAX_PAUSE || rdelay < MIN_PAUSE) { X beep(); X if (rdelay > MAX_PAUSE) X rdelay = MAX_PAUSE; X else X rdelay = MIN_PAUSE; X mvwprintw(dt_win, 6, 22, "%-3d", rdelay); X } X } X /* set 'em */ X param->c_delay = cdelay; X param->r_delay = rdelay; X /* save 'em to disk? */ X if (yes_prompt(dt_win, 7, 12, A_BOLD, "Save to disk")) { X if (up_param()) { X touchwin(dt_win); X wrefresh(dt_win); X } X } X X delwin(dt_win); X return; X} SHAR_EOF if test 1978 -ne "`wc -c < 'di_delay.c'`" then echo shar: "error transmitting 'di_delay.c'" '(should have been 1978 characters)' fi fi exit 0 # End of shell archive
egray@fthood.UUCP (02/04/89)
This is part 4 (of 8) to the Pcomm v1.2 distribution package. Emmet P. Gray US Army, HQ III Corps & Fort Hood ...!uunet!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: # di_win.c # dial.c # dial_dir.h # e_lib.c # expand.c # extrnl.h # getcwd.c # getopt.c # help.c # info.c # init.c # input.c # list_dir.c # ls_menu.c # This archive created: Fri Feb 3 07:35:25 1989 export PATH; PATH=/bin:/usr/bin:$PATH echo shar: "extracting 'di_win.c'" '(9205 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 "config.h" X#include "dial_dir.h" X#include "misc.h" X#include "modem.h" X#include "param.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 non-zero return code X * means we're ready to fire up the input routine. X */ X Xint Xdial_win() X{ X extern int rc_index, fd; X WINDOW *di_win, *newwin(); X int i, j, key, want_out, pass, tic, baud; X long now, time(); X char *tbuf, *ctime(), *str, cr=13, *read_codes(); X void disp_queue(), dial_it(), delay_times(), input_off(); X void error_win(), line_set(), hang_up(), zap_vs(), log_calls(); X void st_line(); X unsigned int sleep(); X /* are we already talking? */ X input_off(); X hang_up(VERBOSE); X X touchwin(stdscr); X refresh(); X X if (get_port()) X return(0); X /* X * If the phone number points to NULL, then either you're on a X * direct line, or you want to do the dialing yourself. X */ X if (*dir->number[dir->q_num[0]] == '\0') { 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 On Board Modem directly", X "You must use the automatic dialing feature"); X return(0); X } X X zap_vs(); X touchwin(stdscr); X clear(); X printw("Connected to /dev/%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 horizontal(di_win, 2, 0, 70); 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, 17, "Redial delay time:"); X mvwaddstr(di_win, 11, 24, "Script/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, 22, "<DEL>: Remove from queue"); X mvwaddstr(di_win, 14, 49, "E: Change delays"); X X /* the start time */ X time(&now); X tbuf = ctime(&now); X tbuf[19] = '\0'; X mvwaddstr(di_win, 7, 36, &tbuf[11]); X X mvwprintw(di_win, 9, 36, "%-4d", param->c_delay); X mvwprintw(di_win, 10, 36, "%-4d", param->r_delay); X X box(di_win, VERT, HORZ); X mvwaddstr(di_win, 16, 24, " Press <ESC> to abort "); X X pass = 0; X i = 0; X want_out = 0; X while (!want_out && pass <= MAX_PASS) { X key = -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 want_out++; X break; X } X /* get a port */ X if (get_port()) { X want_out++; X break; X } 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 tty_flush(fd, 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->c_delay) { X if ((str = read_codes()) == NULL) { 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, TRUE); 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 (dir->baud[dir->d_cur] != baud) { X if (can_sync(baud)) { X dir->baud[dir->d_cur] = baud; X line_set(); X } X } X X zap_vs(); 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->c_delay) X break; X /* ok... try the keyboard */ X if ((key = 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(QUIET); X else X write(fd, &cr, 1); X sleep(1); X } X /* if we get here, no key was pressed */ X if (key == -1) { X clear_line(di_win, 6, 14, TRUE); X mvwaddstr(di_win, 6, 27, "Pausing:"); X /* no return code? */ X if (str == NULL) { X clear_line(di_win, 12, 36, TRUE); X waddstr(di_win, "TIMED OUT"); X wmove(di_win, 12, 36); X } X /* do the pause */ X tic = 0; X while (tic < param->r_delay) { X if ((key = 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, TRUE); X waddstr(di_win, "Elapse time this try:"); X } X mvwaddstr(di_win, 6, 36, "0 "); X /* Process the keystroke */ X switch (key) { X case ' ': /* next in the queue */ X clear_line(di_win, 12, 36, TRUE); 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 DEL: /* <DEL> key, remove from queue */ X if (dir->q_num[1] == -1) { X beep(); X clear_line(di_win, 12, 36, TRUE); 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, TRUE); 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->c_delay); X mvwprintw(di_win, 10, 36, "%-4d", param->r_delay); X break; X case ESC: /* <ESC> key */ X beep(); X clear_line(di_win, 12, 36, TRUE); 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", ""); X return(0); X} X X/* X * Display what info we know at this time. X */ X Xstatic void Xdisp_queue(win, entry, pass) XWINDOW *win; Xint entry, pass; X{ X long now, time(); X char *tbuf, *ctime(); X void st_line(); X /* redo the status line */ X st_line(""); X /* system name */ X clear_line(win, 4, 36, TRUE); 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] = '\0'; X mvwaddstr(win, 8, 36, &tbuf[11]); X /* the script field */ X clear_line(win, 11, 36, TRUE); X waddstr(win, dir->script[entry]); X X wmove(win, 12, 36); X wrefresh(win); X return; X} X X/* X * Determine if the modem can detect the synchronization of the connected X * baud rate. We check the modem database and see if the connect string X * is unique. A non-zero return code means the modem can sync. X */ X Xstatic int Xcan_sync(baud) Xint baud; X{ X int i; X char *str; X /* feature disabled? */ X if (modem->auto_baud[modem->m_cur] != 'Y') X return(0); X /* re-construct the string */ X switch (baud) { X case 300: X str = modem->con_3[modem->m_cur]; X break; X case 1200: X str = modem->con_12[modem->m_cur]; X break; X case 2400: X str = modem->con_24[modem->m_cur]; X break; X case 4800: X str = modem->con_48[modem->m_cur]; X break; X case 9600: X str = modem->con_96[modem->m_cur]; X break; X case 19200: X str = modem->con_192[modem->m_cur]; X break; X default: X return(0); X } X X if (*str == '\0') X return(0); X /* test "str" against all others */ X i = 0; X if (!strcmp(str, modem->con_3[modem->m_cur])) X i++; X if (!strcmp(str, modem->con_12[modem->m_cur])) X i++; X if (!strcmp(str, modem->con_24[modem->m_cur])) X i++; X if (!strcmp(str, modem->con_48[modem->m_cur])) X i++; X if (!strcmp(str, modem->con_96[modem->m_cur])) X i++; X if (!strcmp(str, modem->con_192[modem->m_cur])) X i++; X /* should match only itself */ X if (i == 1) X return(1); X return(0); X} SHAR_EOF if test 9205 -ne "`wc -c < 'di_win.c'`" then echo shar: "error transmitting 'di_win.c'" '(should have been 9205 characters)' fi fi echo shar: "extracting 'dial.c'" '(7970 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#define HZ 60 X X#include <stdio.h> X#include <sys/types.h> X#include <sys/times.h> X#include "config.h" X#include "dial_dir.h" X#include "misc.h" X#include "modem.h" X#include "param.h" X X#ifdef UNIXPC X#include <sys/phone.h> X#endif /* UNIXPC */ 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 extern int fd; X int i, skip; 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] = '\0'; X strcpy(s, modem->dial[modem->m_cur]); X X switch (dir->q_ld[num]) { X case 0: /* no ld code requested */ X break; X case '+': X strcat(s, param->ld_plus); X break; X case '-': X strcat(s, param->ld_minus); X break; X case '@': X strcat(s, param->ld_at); X break; X case '#': X strcat(s, param->ld_pound); X break; X } X /* X * Purify the phone number by removing all the pretty characters X * that don't need to be sent to the modem. Typically the "-", X * "(", ")", and space characters are just for looks. To prevent X * this action, prepend a "\" to the character. X */ X i = 0; X skip = 0; X n = dir->number[dir->q_num[num]]; X while (*n) { X if (*n == '\\' && !skip) { X skip++; X n++; X continue; X } X if (!strchr("-() ", *n) || skip) X number[i++] = *n; X n++; X skip = 0; X } X number[i] = '\0'; X /* add it to the string */ X strcat(s, number); X strcat(s, modem->suffix[modem->m_cur]); X#ifdef DEBUG X fprintf(stderr, "raw dial string: \"%s\"\n", s); X#endif /* DEBUG */ X X#ifdef UNIXPC X /* special case for OBM */ X if (!strcmp(modem->mname[modem->m_cur], "OBM")) { X /* prepare the modem */ X pbuf.c_lineparam = DATA|DTMF; X pbuf.c_waitdialtone = 5; X pbuf.c_linestatus = 0; X pbuf.c_feedback = SPEAKERON|NORMSPK; X pbuf.c_waitflash = 500; X ioctl(fd, PIOCSETP, &pbuf); X sleep(1); X /* connect the dialer */ X ioctl(fd, PIOCRECONN); X sleep(1); X /* dial each digit */ X n = s; X while (*n) { X /* switch tone/pulse dialing? */ X switch (*n) { X case '^': X pbuf.c_lineparam = DATA|PULSE; X ioctl(fd, PIOCSETP, &pbuf); X break; X case '%': X pbuf.c_lineparam = DATA|DTMF; X ioctl(fd, PIOCSETP, &pbuf); X break; X default: X ioctl(fd, PIOCDIAL, n); X break; X } X n++; X } X return; X } X#endif /* UNIXPC */ X X send_str(s, SLOW); X return; X} X X/* X * Send a string to the modem. Performs all the character synonym X * translations. X */ X Xvoid Xsend_str(s, slow) Xchar *s; Xint slow; X{ X extern int fd; X int skip, has_pause; X char *strchr(); X unsigned int sleep(); X void do_pause(); X /* empty string? */ X if (s == NULL || *s == '\0') X return; X X /* contains a pause? */ X has_pause = 0; X if (strchr(s, '~')) X has_pause++; X X tty_flush(fd, 1); X /* X * Change the character synonyms to their real values. Writes X * the characters to the modem. To remove the special meaning X * of one of the characters, prepend a "\" to it. X */ X skip = 0; X while (*s) { X /* send the literal character */ X if (skip) { X skip = 0; X write(fd, s, 1); X if (has_pause || slow) X tty_drain(fd); X if (slow) X do_pause(); X#ifdef DEBUG X fprintf(stderr, "send_str: \"%c\", %02x, %03o, %d\n", *s, *s, *s, *s); X#endif /* DEBUG */ X s++; X continue; X } X /* turn off the special meaning */ X if (*s == '\\') { X skip++; X s++; X continue; X } X /* pause synonym */ X if (*s == param->pause_char) { X sleep(1); X s++; X continue; X } X /* carriage return synonym */ X if (*s == param->cr_char) X *s = '\r'; X /* 2 character control sequence */ X if (*s == param->ctrl_char) { X s++; X /* premature EOF? */ X if (*s == '\0') X break; X /* upper and lower case */ X if (*s > '_') X *s -= 96; X else X *s -= 64; X } X /* escape synonym */ X if (*s == param->esc_char) X *s = ESC; X /* modem break synonym */ X if (*s == param->brk_char) { X tty_break(fd); X sleep(1); X s++; X continue; X } X X write(fd, s, 1); X#ifdef DEBUG X fprintf(stderr, "send_str: \"%c\", %02x, %03o, %d\n", *s, *s, *s, *s); X#endif /* DEBUG */ X /* X * Because the pause char makes the timing critical, we X * wait until the buffer is clear before we continue. X */ X if (has_pause || slow) X tty_drain(fd); X if (slow) X do_pause(); X s++; X } X return; X} X X/* X * Read the result codes coming back from the modem. Test for the 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 extern int fd; X int i; 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(fd, PIOCGETP, &pbuf); X X /* X * The OBM doesn't use a return message to announce the X * connection to a remote, so we fake one. The 1200 X * is quite arbitrary... it is not an indicator of the X * connected baud rate. X */ X if (pbuf.c_linestatus & MODEMCONNECTED) X return("1200"); X X sleep(1); X return(NULL); X } X#endif /* UNIXPC */ X /* search for key words */ X for (; rc_index<511; rc_index++) { X if ((i = getc_line(1)) <= 0) X return(NULL); X X c = i & 0x7f; X#ifdef DEBUG X fprintf(stderr, "read_codes: \"%c\", %02x, %03o, %d\n", c, c, c, c); X#endif /* DEBUG */ X /* no NULLs please */ X if (c == '\0') { X if (rc_index) X rc_index--; X continue; X } X rc_buf[rc_index] = c; X rc_buf[rc_index+1] = '\0'; X /* the connect strings */ X if (match(rc_buf, modem->con_3[modem->m_cur])) X return("300"); X X if (match(rc_buf, modem->con_12[modem->m_cur])) X return("1200"); X X if (match(rc_buf, modem->con_24[modem->m_cur])) X return("2400"); X X if (match(rc_buf, modem->con_48[modem->m_cur])) X return("4800"); X X if (match(rc_buf, modem->con_96[modem->m_cur])) X return("9600"); X X if (match(rc_buf, modem->con_192[modem->m_cur])) X return("19200"); X X /* 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 non-zero return code X * means that s2 was found at the end of s1. X */ X Xstatic int Xmatch(s1, s2) Xchar *s1, *s2; X{ X register int i; X int skip, diff; X char new[40]; X /* if no string to match */ X if (*s2 == '\0') X return(0); X /* translate synonyms */ X i = 0; X skip = 0; X while (*s2) { X /* literal character */ X if (skip) { X skip = 0; X new[i++] = *s2; X s2++; X continue; X } X /* turn off the special meaning */ X if (*s2 == '\\') { X skip++; X s2++; X continue; X } X /* carriage return synonym */ X if (*s2 == param->cr_char) X *s2 = '\r'; X X /* 2 character control sequence */ X if (*s2 == param->ctrl_char) { X s2++; X if (*s2 == '\0') X break; X if (*s2 > '_') X *s2 -= 96; X else X *s2 -= 64; X } X /* escape synonym */ X if (*s2 == param->esc_char) X *s2 = ESC; X X new[i++] = *s2; X s2++; X } X new[i] = '\0'; X X diff = strlen(s1) - strlen(new); X /* is it possible? */ X if (diff < 0) X return(0); X /* test it out */ X if (!strcmp(&s1[diff], new)) X return(1); X return(0); X} X X/* X * Apparently some modems can't take input at the rated speed while X * in the command mode. Therefore, a 0.10 sec pause a required between X * characters. X */ X Xvoid Xdo_pause() X{ X struct tms t; X long t1; X X t1 = times(&t); X while ((times(&t) - t1) < HZ/10) X ; X return; X} SHAR_EOF if test 7970 -ne "`wc -c < 'dial.c'`" then echo shar: "error transmitting 'dial.c'" '(should have been 7970 characters)' fi fi echo shar: "extracting 'dial_dir.h'" '(932 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#define FAST 0 X#define SLOW 1 X#define QUIET 0 X#define VERBOSE 1 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 *script[NUM_DIR+1]; /* script name (or TTY) */ X X int q_num[NUM_QUEUE]; /* entry numbers in the queue */ X char q_ld[NUM_QUEUE]; /* LD codes in the queue */ X X int d_entries; /* number of entries in the file */ X int d_cur; /* the current entry */ X X char *d_path; /* path to the pcomm.dial_dir file */ X}; X X#ifndef MAIN Xextern struct DIAL_DIR *dir; X#endif /* MAIN */ SHAR_EOF if test 932 -ne "`wc -c < 'dial_dir.h'`" then echo shar: "error transmitting 'dial_dir.h'" '(should have been 932 characters)' fi fi echo shar: "extracting 'e_lib.c'" '(3624 characters)' if test -f 'e_lib.c' then echo shar: "will not over-write existing file 'e_lib.c'" else sed 's/^X//' << \SHAR_EOF > 'e_lib.c' X/* X * Routines to manipulate the pcomm.extrnl file X */ X X#include <stdio.h> X#include "extrnl.h" X X/* X * Read the external file transfer program database. Returns a pointer X * to a static area containing the EXTRNL structure. This support file is X * optional. X */ X Xstruct EXTRNL * Xread_extrnl(extra) Xchar *extra; X{ X extern char *null_ptr; X FILE *fp, *my_fopen(); X int i, line, up, entry, oops; X char *str_dup(), buf[200], message[80], token[40], *str_tok(), *str; X char *sep, *temp_token, *findfile(); X static struct EXTRNL e; X void error_win(); X X if ((e.e_path = findfile(extra, "pcomm.extrnl")) == NULL) { X /* not required to exist */ X for (i=0; i<3; i++) { X e.name[0][i] = null_ptr; X e.command[0][i] = null_ptr; X e.prompt[0][i] = 'N'; X e.name[1][i] = null_ptr; X e.command[1][i] = null_ptr; X e.prompt[1][i] = 'N'; X } X e.up_entries = 0; X e.dn_entries = 0; X X return(&e); X } X X if (!(fp = my_fopen(e.e_path, "r"))) { X sprintf(buf, "\"%s\" for read", e.e_path); X error_win(1, "Can't open external program file", buf); X } X X sep = ";;\n"; X line = 0; X up = 1; X oops = 0; X while (fgets(buf, 200, fp) != NULL) { X line++; X if (line <= 3) X entry = line-1; X else { X up = 0; X entry = line-4; X } 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 /* X * Parse the rest of the line. This is similar to using X * the "real" strtok() function, but this version returns X * a pointer to NULL if the token is missing. Note the X * use of the array of separators. X */ X for (i=0; i<3; i++) { X if (!(str = str_tok((char *) NULL, 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 e.name[up][entry] = str_dup(str); X break; X case 1: X e.command[up][entry] = str_dup(str); X break; X case 2: X e.prompt[up][entry] = *str; X break; X } X } X if (oops) X break; X X /* sanity checking */ X if (up) X sprintf(token, "SEND_%d", entry+1); X else X sprintf(token, "RCV_%d", entry+1); X X if (strcmp(temp_token, token)) { X sprintf(message, "is corrupted at line %d", line); X oops++; X break; X } X } X fclose(fp); X X if (oops) { X sprintf(buf, "External program file \"%s\"", e.e_path); X error_win(1, buf, message); X } X /* find number of upload entries */ X for (i=0; i<3; i++) { X if (e.name[1][i] == null_ptr) X break; X } X e.up_entries = i; X /* find number of download entries */ X for (i=0; i<3; i++) { X if (e.name[0][i] == null_ptr) X break; X } X e.dn_entries = i; X /* if empty database */ X if (!e.up_entries || !e.dn_entries) { X sprintf(buf, "External program file \"%s\"", e.e_path); X error_win(0, buf, "has no data"); X } X X return(&e); X} X X/* X * Update the external file transfer program database. A non-zero return X * code means a non-fatal error. X */ X Xint Xup_extrnl() X{ X FILE *fp, *my_fopen(); X int i, up, entry; X char buf[200]; X void error_win(); X /* open for write */ X if (!(fp = my_fopen(extrnl->e_path, "w"))) { X sprintf(buf, "\"%s\"", extrnl->e_path); X error_win(0, "No write permission on externl program file", buf); X return(1); X } X /* put 'em back */ X up = 1; X for (i=0; i<6; i++) { X if (i < 3) X entry = i; X else { X up = 0; X entry = i-3; X } X if (up) X fprintf(fp, "SEND_%d=%s;%s;%c\n", entry+1, extrnl->name[up][entry], extrnl->command[up][entry], extrnl->prompt[up][entry]); X else X fprintf(fp, "RCV_%d=%s;%s;%c\n", entry+1, extrnl->name[up][entry], extrnl->command[up][entry], extrnl->prompt[up][entry]); X } X X fclose(fp); X return(0); X} SHAR_EOF if test 3624 -ne "`wc -c < 'e_lib.c'`" then echo shar: "error transmitting 'e_lib.c'" '(should have been 3624 characters)' fi fi echo shar: "extracting 'expand.c'" '(2873 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. Returns a pointer to X * a static area. X */ X X#define EXPAND_BUF 2048 X X#include <stdio.h> X#include <signal.h> X#include <fcntl.h> X#include "config.h" X Xchar * Xexpand(input) Xchar *input; X{ X extern char *null_ptr; X FILE *pfp, *n_popen(); X int last; X char buf[1024], *strpbrk(), *strcpy(); X static char ans[EXPAND_BUF]; X X /* same rules as str_dup() */ X if (input == NULL) X return(NULL); X if (*input == '\0') X return(null_ptr); X /* any thing to expand? */ X if (!strpbrk(input, "$*{}[]\\?~")) { X strcpy(ans, input); X return(ans); X } X /* popen an echo */ X sprintf(buf, "echo %s", input); X X pfp = n_popen(buf, "r"); X fgets(ans, EXPAND_BUF, pfp); X n_pclose(pfp); X X if (!strlen(ans)) { X strcpy(ans, input); X return(ans); X } X /* X * A horrible kludge... if the last character is not a line X * feed, then the csh has returned an error message. Otherwise X * zap the line feed. X */ X last = strlen(ans) -1; X if (ans[last] != '\n') { X strcpy(ans, input); X return(ans); X } X else X ans[last] = '\0'; X 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 * Xn_popen(cmd, mode) Xchar *cmd, *mode; X{ X int myside, hisside, ppid, 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 || *shellpath == '\0') X shellpath = "/bin/sh"; X X if (shell = strrchr(shellpath, '/')) X shell++; X else { X shellpath = "/bin/sh"; X shell = "sh"; X } X /* fix up the flags */ X if (!strcmp(shell, "csh")) X flags = "-fc"; X else X flags = "-c"; /* Korn shell too */ X X if (!(ppid = fork())) { X int stdio; X /* no error messages please */ X close(2); X open("/dev/null", O_WRONLY); X#ifdef SETUGID X setgid(getgid()); X setuid(getuid()); X#endif /* SETUGID */ X stdio = tst(0, 1); X close(myside); X close(stdio); X fcntl(hisside, F_DUPFD, stdio); X close(hisside); X execl(shellpath, shell, flags, cmd, (char *) 0); X _exit(1); X } X if (ppid == -1) { X close(myside); X close(hisside); X return NULL; X } X X popen_pid[myside] = ppid; X X close(hisside); X return(fdopen(myside, mode)); X} X Xn_pclose(ptr) XFILE *ptr; X{ X SIG_TYPE (*hstat)(), (*istat)(), (*qstat)(); X int f, r, sig_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(&sig_status)) != popen_pid[f] && r != -1) X ; X X if (r == -1) X sig_status = -1; X X signal(SIGINT, istat); X signal(SIGQUIT, qstat); X signal(SIGHUP, hstat); X return(sig_status); X} SHAR_EOF if test 2873 -ne "`wc -c < 'expand.c'`" then echo shar: "error transmitting 'expand.c'" '(should have been 2873 characters)' fi fi echo shar: "extracting 'extrnl.h'" '(623 characters)' if test -f 'extrnl.h' then echo shar: "will not over-write existing file 'extrnl.h'" else sed 's/^X//' << \SHAR_EOF > 'extrnl.h' X/* X * The external file transfer program database. The list is limited to X * 3 uploads and 3 downloads because the xfer_menu() routine uses single X * character input (and these selections become 7, 8, and 9). X */ X Xstruct EXTRNL { X char *name[2][3]; /* program name (for display only) */ X char *command[2][3]; /* the command line */ X char prompt[2][3]; /* need to prompt for names? */ X X int up_entries; /* number of up entries in the file */ X int dn_entries; /* number of down entries in the file */ X X char *e_path; /* path to the pcomm.extrnl file */ X}; X X#ifndef MAIN Xextern struct EXTRNL *extrnl; X#endif /* MAIN */ SHAR_EOF if test 623 -ne "`wc -c < 'extrnl.h'`" then echo shar: "error transmitting 'extrnl.h'" '(should have been 623 characters)' fi fi echo shar: "extracting 'getcwd.c'" '(387 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 new line */ X buf[strlen(buf)-1] = '\0'; X return(buf); X} SHAR_EOF if test 387 -ne "`wc -c < 'getcwd.c'`" then echo shar: "error transmitting 'getcwd.c'" '(should have been 387 characters)' fi fi echo shar: "extracting 'getopt.c'" '(1035 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], "--") == 0) { 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 1035 -ne "`wc -c < 'getopt.c'`" then echo shar: "error transmitting 'getopt.c'" '(should have been 1035 characters)' fi fi echo shar: "extracting 'help.c'" '(1779 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 full page descriptions of each X * command. X */ X X#include <stdio.h> X#include <curses.h> X#include "config.h" X#include "misc.h" X Xvoid Xhelp_screen(hot) Xchar *hot; X{ X extern int fd; 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 horizontal(h_win, 2, 0, 80); X mvwattrstr(h_win, 4, 0, A_BOLD, " Major Functions Utility Functions File Functions\n\n"); X mvwprintw(h_win, 6, 2, "Dialing Directory.%4.4s-D Program Info ....%4.4s-I Send Files ....%4.4s-<up>", hot, hot, hot); X mvwprintw(h_win, 7, 2, "Auto Redial ......%4.4s-R Setup Screen ....%4.4s-S Receive Files .%4.4s-<down>", hot, hot, hot); X mvwprintw(h_win, 8, 2, "Keyboard Macros ..%4.4s-M Change Directory.%4.4s-B Pass Thru Mode.%4.4s-T", hot, hot, hot); X mvwprintw(h_win, 9, 2, "Line Settings ....%4.4s-P Clear Screen ....%4.4s-C Directory .....%4.4s-F", hot, hot, hot); X mvwprintw(h_win, 10, 2, "Exit Pcomm .......%4.4s-X Toggle Duplex ...%4.4s-E Screen Dump ...%4.4s-G", hot, hot, hot); X mvwprintw(h_win, 11, 2, "Unix Gateway .....%4.4s-4 Hang Up Phone ...%4.4s-H Start Data Log.%4.4s-1", hot, hot, hot); X mvwprintw(h_win, 12, 28, "Printer On/Off ..%4.4s-L Toggle Log ....%4.4s-2", hot, hot); X mvwprintw(h_win, 13, 28, "Toggle CR-CR/LF .%4.4s-3", hot); X mvwprintw(h_win, 14, 28, "Break Key .......%4.4s-7", hot); X X box(h_win, VERT, HORZ); X mvwaddstr(h_win, 16, 26, " Press any key to continue "); 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 1779 -ne "`wc -c < 'help.c'`" then echo shar: "error transmitting 'help.c'" '(should have been 1779 characters)' fi fi echo shar: "extracting 'info.c'" '(1548 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#define VERSION "1.2.0" X#define DATE "4 Feb 89" X X#include <stdio.h> X#include <curses.h> X Xvoid Xinfo(auto_clear) Xint auto_clear; X{ X extern int fd; X WINDOW *w_win, *newwin(); X char buf[80]; X /* display the welcome screen */ X w_win = newwin(23, 80, 0, 0); X mvwaddstr(w_win, 3, 18, "PPPPPP CCCC OOOO MM MM MM MM"); X mvwaddstr(w_win, 4, 18, "P P C O O M M M M M M M M"); X mvwaddstr(w_win, 5, 18, "PPPPPP C O O M M M M M M"); X mvwaddstr(w_win, 6, 18, "P C O O M M M M"); X mvwaddstr(w_win, 7, 18, "P CCCC OOOO M M M M"); X X sprintf(buf, ">>> Pcomm Version %s <<<", VERSION); X mvwaddstr(w_win, 10, (80-strlen(buf))/2, buf); X sprintf(buf, "Release date: %s", DATE); X mvwaddstr(w_win, 11, (80-strlen(buf))/2, buf); X X mvwaddstr(w_win, 13, 8, "Pcomm is a public domain telecommunication program for Unix that"); X mvwaddstr(w_win, 14, 8, "is designed to operate similar to the MSDOS program, ProComm."); X mvwaddstr(w_win, 15, 8, "ProComm (TM) is copyrighted by Datastorm Technologies, Inc."); X mvwaddstr(w_win, 19, 45, "Emmet P. Gray"); X mvwaddstr(w_win, 20, 45, "...!uunet!uiucuxc!fthood!egray"); X wmove(w_win, 22, 79); X wrefresh(w_win); X /* delay so you can read the herald */ X if (auto_clear) X wait_key(w_win, 5); X else X wgetch(w_win); X X if (fd == -1) { X werase(w_win); X wrefresh(w_win); X } X delwin(w_win); X return; X} SHAR_EOF if test 1548 -ne "`wc -c < 'info.c'`" then echo shar: "error transmitting 'info.c'" '(should have been 1548 characters)' fi fi echo shar: "extracting 'init.c'" '(3065 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 support files. Returns a X * pointer to a static area (or shared memory) containing the STATUS X * structure. All errors are fatal. X */ X X#define TMP_FILE "/tmp/pcommXXXXXX" X X#include <stdio.h> X#include <curses.h> X#include "config.h" X#include "misc.h" X#include "status.h" X X#ifdef SHAREDMEM X#include <sys/types.h> X#include <sys/ipc.h> X#include <sys/shm.h> X#endif /* SHAREDMEM */ X Xstruct STATUS * Xinit(short_cut) Xchar *short_cut; X{ X char *strcpy(); X struct STATUS *s_ptr; X void info(); X#ifdef SHAREDMEM X int mode; X extern int shm_id; X char *shmat(), *memset(); X void perror(), exit(); X X /* X * Since the "pcomm_input" program does not run set-user/group-id X * the mode must be set so the effective ID can read/write to the X * shared memory segment. Kinda strange... real ID's aren't used. X */ X#ifdef SETUGID X mode = 0666; X#else /* SETUGID */ X mode = 0600; X#endif /* SETUGID */ X /* create a shared memory segment */ X shm_id = shmget(IPC_PRIVATE, sizeof (struct STATUS), mode|IPC_CREAT|IPC_EXCL|IPC_NOWAIT); X if (shm_id < 0) { X endwin(); X perror("shmget"); X exit(1); X } X s_ptr = (struct STATUS *) shmat(shm_id, (char *) 0, 0); X if ((int) s_ptr == -1) { X endwin(); X perror("shmat"); X exit(1); X } X#else /* SHAREDMEM */ X char *mktemp(), tempfile[sizeof(TMP_FILE)]; X static struct STATUS s; X s_ptr = &s; X#endif /* SHAREDMEM */ X /* some defaults */ X s_ptr->fd = -1; X s_ptr->dup_fd = -1; X s_ptr->add_lf = 0; X s_ptr->log = 0; X s_ptr->print = 0; X strcpy(s_ptr->log_path, "NOT_DEFINED"); X X#ifdef SHAREDMEM X s_ptr->clr = 0; X s_ptr->row = 0; X s_ptr->col = 0; X memset(s_ptr->vs, '\0', MAX_ROW * MAX_COL); X#else /* SHAREDMEM */ X strcpy(tempfile, TMP_FILE); X strcpy(s_ptr->vs_path, mktemp(tempfile)); X#endif /* SHAREDMEM */ X /* display herald if no short-cut */ X if (short_cut == NULL) X info(AUTO_CLEAR); X X erase(); X refresh(); X return(s_ptr); 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 working X * directory, and lastly, the default directory. X */ X Xchar * Xfindfile(extra, name) Xchar *extra, *name; X{ X int i; X char *pcomm, *getenv(), *path, pbuf[200], *getcwd(), *str_dup(); X char temp[200]; X X /* see if PCOMM variable is set */ X pcomm = getenv("PCOMM"); X if (pcomm == NULL || *pcomm == '\0') X pcomm = NULL; X else { X /* zap the trailing separator */ X if (pcomm[strlen(pcomm)-1] == '/') X pcomm[strlen(pcomm)-1] = '\0'; X } X X for (i=0; i<4; i++) { X /* directory search order */ X switch (i) { X case 0: /* extra directory from command line */ X path = extra; X break; X case 1: /* PCOMM environmental variable */ X path = pcomm; X break; X case 2: /* current working directory */ X path = getcwd(pbuf, 200); X break; X case 3: /* Pcomm's default directory */ X path = DEFAULT_DIR; X break; X } X if (path == NULL) X continue; X X sprintf(temp, "%s/%s", path, name); X /* read permission checked */ X if (!access(temp, 4)) X return(str_dup(temp)); X } X return(NULL); X} SHAR_EOF if test 3065 -ne "`wc -c < 'init.c'`" then echo shar: "error transmitting 'init.c'" '(should have been 3065 characters)' fi fi echo shar: "extracting 'input.c'" '(10960 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. This program runs as a child process to the X * Pcomm program. X */ X X#include <stdio.h> X#include <signal.h> X#include <setjmp.h> X#define MAIN X#include "config.h" X#include "misc.h" X#include "status.h" X#include "vcs.h" X X#ifdef SHAREDMEM X#include <sys/types.h> X#include <sys/ipc.h> X#include <sys/shm.h> X#endif /* SHAREDMEM */ X Xjmp_buf i_jmp; Xint vcs_param[NUM_VCS][5]; /* positional parameters */ Xint vcs_opt[NUM_VCS][10]; /* options unique to each VCS */ Xint vcs_codes[NUM_VCS][VCS_SIZE]; /* the VCS codes */ Xint vcs_leadin[NUM_VCS]; /* unique list of lead-in characters */ Xint num_leadin; /* length of lead-in list */ Xint hold, max_row, max_col, skip_row; XFILE *logfp, *lprfp; Xstruct STATUS *status; X X#ifdef SHAREDMEM X#define VROW status->row X#define VCOL status->col X#define VS status->vs X#else /* SHAREDMEM */ Xint VROW, VCOL; Xchar VS[MAX_ROW][MAX_COL]; Xstruct STATUS s; X#endif /* SHAREDMEM */ 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 */ X Xmain(argc, argv) Xint argc; Xchar *argv[]; X{ X FILE *popen(); X register int in_cnt, out_cnt; X int got_sig(); X char c, *strcpy(), *bufp, in_buf[INPUT_BUF], out_buf[INPUT_BUF*2]; X void _exit(), exit(), vcs_table(), setbuf(), vs_putchar(), vs_clear(); X#ifdef SHAREDMEM X int shm_id; X char *shmat(); X void perror(); X#endif /* SHAREDMEM */ X /* set the trap for the signals */ X signal(SIGALRM, SIG_IGN); X signal(SIGHUP, SIG_IGN); X signal(SIGQUIT, SIG_IGN); X signal(SIGUSR1, got_sig); X signal(SIGUSR2, got_sig); X signal(SIGINT, got_sig); X signal(SIGTERM, got_sig); X X setbuf(stdout, (char *) NULL); X /* for the curious... */ X if (argc == 1) { X fprintf(stderr, "This is the input routine for the Pcomm program\n"); X fprintf(stderr, "It is not designed to be run as a separate program\n"); X exit(1); X } X X#ifdef SHAREDMEM X shm_id = atoi(argv[1]); X status = (struct STATUS *) shmat(shm_id, (char *) 0, 0); X if ((int) status == -1) { X perror("shmat"); X _exit(1); X } X#else /* SHAREDMEM */ X status = &s; X#endif /* SHAREDMEM */ X /* load the VCS table */ X vcs_table(); X if (max_row > MAX_ROW) X max_row = MAX_ROW; X if (max_col > MAX_COL-1) X max_col = MAX_COL-1; X /* parse the command line */ X#ifndef SHAREDMEM X status->fd = atoi(argv[1]); X status->dup_fd = atoi(argv[2]); X status->add_lf = atoi(argv[3]); X status->log = atoi(argv[4]); X status->print = atoi(argv[5]); X strcpy(status->log_path, argv[6]); X strcpy(status->vs_path, argv[7]); X#endif /* SHAREDMEM */ X X skip_row = 0; X X#ifdef SHAREDMEM X if (status->clr) X skip_row = 1; X#else /* SHAREDMEM */ X /* read previous screen */ X if (!access(status->vs_path, 0)) X read_vs(); X else X skip_row = 1; X#endif /* SHAREDMEM */ X X hold = 0; X /* start up file pointers */ X lprfp = (FILE *) NULL; X logfp = (FILE *) NULL; X X switch (setjmp(i_jmp)) { X case 0: /* no signal */ X break; X case 1: /* toggle the data logging */ X status->log = status->log ? 0 : 1; X break; X case 2: /* toggle the printer */ X status->print = status->print ? 0 : 1; X break; X case 3: /* suspend the input */ X hold = hold ? 0 : 1; X#ifndef SHAREDMEM X if (hold) X write_vs(); X#endif /* SHAREDMEM */ X break; X case 4: /* clean up and go home */ X if (status->log) X fclose(logfp); X if (status->print) { X putc('\f', lprfp); X pclose(lprfp); X } X#ifdef SHAREDMEM X /* detach shared memory */ X shmdt((char *) status); X#endif /* SHAREDMEM */ X _exit(0); X break; X } X /* any signal will awaken pause() */ X if (hold) X#ifdef BSD X sigpause(0); X#else /* BSD */ X pause(); X#endif /* BSD */ X /* open or close the printer */ X if (status->print && lprfp == NULL) X lprfp = popen(LPR, "w"); X X if (!status->print && lprfp != NULL) { X putc('\f', lprfp); X pclose(lprfp); X lprfp = (FILE *) NULL; X } X /* open or close the log file */ X if (status->log && logfp == NULL) { X if (strcmp(status->log_path, "NOT_DEFINED")) { X if (!(logfp = fopen(status->log_path, "a"))) X status->log = 0; X } X else X status->log = 0; X } X if (!status->log && logfp != NULL) { X fclose(logfp); X logfp = (FILE *) NULL; X } X X#ifdef SHAREDMEM X if (status->clr) { X status->clr = 0; X vs_clear(); X } X#else /* SHAREDMEM */ X /* clear if vs_path doesn't exist */ X if (access(status->vs_path, 0)) X vs_clear(); X#endif /* SHAREDMEM */ X 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 VROW = 1; X } X /* here we go... */ X while (1) { X if ((in_cnt = read(status->fd, in_buf, INPUT_BUF)) <= 0) X continue; X /* send a duplicate to Pcomm */ X if (status->dup_fd != -1) X write(status->dup_fd, in_buf, in_cnt); X X /* "peel" the buffer one at a time */ X out_cnt = 0; X bufp = in_buf; X while (--in_cnt >= 0) { X c = *bufp++ & 0xff; X /* send to logfile */ X if (status->log) { X if (c == '\r' && status->add_lf) X putc('\n', logfp); X /* no carriage returns in logfile */ X if (c != '\r') X putc(c, logfp); X } X /* send to printer too? */ X if (status->print) X putc(c, lprfp); X X /* put a char in virtual screen */ X vs_putchar(c); X X /* build the output buffer */ X out_buf[out_cnt++] = c; X if (c == '\r' && status->add_lf) X out_buf[out_cnt++] = '\n'; X X /* output in smaller chunks */ X if (out_cnt >= OUTPUT_BUF) { X fwrite(out_buf, sizeof(char), out_cnt, stdout); X out_cnt = 0; X } X } X if (out_cnt) X fwrite(out_buf, sizeof(char), out_cnt, stdout); 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 switch (sig) { X case SIGUSR1: X signal(SIGUSR1, got_sig); X longjmp(i_jmp, 1); X case SIGUSR2: X signal(SIGUSR2, got_sig); X longjmp(i_jmp, 2); X case SIGINT: X signal(SIGINT, got_sig); X longjmp(i_jmp, 3); X case SIGTERM: X signal(SIGTERM, got_sig); X longjmp(i_jmp, 4); X } X} X X/* X * Put a character in the virtual screen. This routine saves incoming X * characters in a two dimensional buffer designed to mimic the real X * screen. X */ X Xvoid Xvs_putchar(c) Xchar c; X{ X register int i; X char *memset(); X int tab_stop; X void vs_scroll(); X X switch (vcs_filter(c)) { X case MAYBE: /* wait and see... */ X break; X case 256+HOME: /* home virtual screen "cursor" */ X VROW = 0; X VCOL = 0; X break; X case 256+CLR_EOL: /* clear to end of line */ X memset(&VS[VROW][VCOL], ' ', max_col - VCOL); X VCOL = max_col -1; X break; X case 256+CLR_EOS: /* clear to end of screen */ X memset(&VS[VROW][VCOL], ' ', max_col - VCOL); X for (i=VROW+1; i<max_row; i++) X memset(VS[i], ' ', max_col); X VROW = max_row -1; X VCOL = max_col -1; X break; X case 256+CLEAR: /* clear all and home "cursor" */ X for (i=0; i<max_row; i++) X memset(VS[i], ' ', max_col); X VROW = 0; X VCOL = 0; X break; X case 256+MV_UP: /* move "cursor" up */ X VROW--; X if (VROW < 0) X VROW = 0; X break; X case 256+MV_DOWN: /* move "cursor" down */ X VROW++; X if (VROW >= max_row) X VROW = max_row -1; X break; X case 256+MV_RIGHT: /* move "cursor" right */ X VCOL++; X if (VCOL >= max_col) X VCOL = max_col -1; X break; X case 256+MV_LEFT: /* move "cursor" left */ X case BS: /* non destructive back space */ X VCOL--; X if (VCOL < 0) X VCOL = 0; X break; X case 256+MV_DIRECT: /* direct cursor movement */ X VROW = vcs_param[MV_DIRECT][0]; X VCOL = vcs_param[MV_DIRECT][1]; X X /* if "add one" and "decimal" */ X if (vcs_opt[MV_DIRECT][0] && vcs_opt[MV_DIRECT][1]) { X VROW--; X VCOL--; X } X /* if "character" */ X if (vcs_opt[MV_DIRECT][2]) { X /* if "add offset" */ X if (vcs_opt[MV_DIRECT][3]) { X VROW -= vcs_opt[MV_DIRECT][5]; X VCOL -= vcs_opt[MV_DIRECT][5]; X } X /* if "subtract offset" */ X if (vcs_opt[MV_DIRECT][4]) { X VROW += vcs_opt[MV_DIRECT][5]; X VCOL += vcs_opt[MV_DIRECT][5]; X } X VROW--; X VCOL--; X } X break; X case 0: X case 7: /* skip NULL and "bell" character */ X break; X case '\t': /* tab character */ X tab_stop = VCOL + 8 - (VCOL % 8); X /* if wrap around */ X if (tab_stop >= max_col) { X /* spaces up to eol */ X memset(&VS[VROW][VCOL], ' ', max_col - VCOL); X VROW++; X if (VROW >= max_row) X vs_scroll(); X X /* the remainder of the tab */ X VCOL = tab_stop - max_col; X } X else { X memset(&VS[VROW][VCOL], ' ', tab_stop - VCOL); X VCOL = tab_stop; X } X break; X case '\r': /* carriage return */ X VCOL = 0; X if (!status->add_lf) X break; X /* fall thru...*/ X case '\n': /* line feed */ X VROW++; X if (VROW >= max_row) X vs_scroll(); X break; X default: /* a normal character */ X VS[VROW][VCOL] = c; X VCOL++; X /* wrap around */ X if (VCOL >= max_col) { X VCOL = 0; X VROW++; X if (VROW >= max_row) X vs_scroll(); X } X break; X } X return; X} X X#ifndef SHAREDMEM X/* X * Save the virtual screen to a file. X */ X Xint Xwrite_vs() X{ X FILE *fp; X register int i; X X if (!(fp = fopen(status->vs_path, "w"))) X return(1); X /* current x y coordinates */ X fprintf(fp, "%d,%d\n", VROW, VCOL); X X for (i=0; i<max_row; i++) { X VS[i][max_col] = '\0'; 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() X{ X FILE *fp; X register int i; X char buf[10]; X /* in case the fopen fails... */ X VROW = 0; X VCOL = 0; X /* not guaranteed to exist yet */ X if (!(fp = fopen(status->vs_path, "r"))) X return(1); X /* get the x, y coordinates */ X fgets(buf, 10, fp); X sscanf(buf, "%d,%d\n", &VROW, &VCOL); X X /* read the file into the vs array */ X for (i=0; i<max_row; i++) { X fgets(VS[i], MAX_COL, fp); X VS[i][max_col] = '\0'; X } X fclose(fp); X return(0); X} X#endif /* SHAREDMEM */ X X/* X * If the user clears the screen with the ^A-C command, the input X * has to be in sync. X */ X Xvoid Xvs_clear() X{ X register int i; X char *memset(); X X for (i=0; i<max_row; i++) X memset(VS[i], ' ', max_col); X /* home the "cursor" */ X VROW = 0; X VCOL = 0; X return; X} X X/* X * Do a software scroll on the virtual screen. Does not alter the X * "col" variable. X */ X Xvoid Xvs_scroll() X{ X char *strcpy(), *memset(); X /* move 'em up 1 line */ X#ifdef MEMMOVE X char *MEMMOVE(); X X MEMMOVE(VS[0], VS[1], (max_row -1) * MAX_COL); X#else /* MEMMOVE */ X register int i; X X for (i=0; i<max_row-1; i++) X strcpy(VS[i], VS[i+1]); X#endif /* MEMMOVE */ X /* clear the bottom line */ X memset(VS[max_row-1], ' ', max_col); X X VROW = max_row -1; X return; X} X X#ifdef BSD X/* X * Copies the character c, n times to string str X */ X Xchar * Xmemset(str, c, n) Xchar *str, c; Xint n; X{ X char *s1 = str; X X while (n > 0) { X --n; X *s1++ = c; X } X return(str); X} X#endif /* BSD */ SHAR_EOF if test 10960 -ne "`wc -c < 'input.c'`" then echo shar: "error transmitting 'input.c'" '(should have been 10960 characters)' fi fi echo shar: "extracting 'list_dir.c'" '(1635 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 the "ls" command. Additional command line options X * are allowed at run time. X */ X X#define LS_CMD "ls -aC" X X#include <stdio.h> X#include <curses.h> X#include "config.h" X#include "misc.h" X Xvoid Xlist_dir() X{ X extern int fd; X WINDOW *ls_win, *newwin(); X FILE *pfp, *n_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, VERT, HORZ); 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, 80, "", "\n")) == 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, "%s %s", LS_CMD, ans); X pfp = n_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 touchwin(ls_win); X /* a crude kind of paging */ 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) == ESC) { X oops++; X break; X } X werase(ls_win); X wrefresh(ls_win); X } X } X n_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 1635 -ne "`wc -c < 'list_dir.c'`" then echo shar: "error transmitting 'list_dir.c'" '(should have been 1635 characters)' fi fi echo shar: "extracting 'ls_menu.c'" '(4816 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 "config.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 non-zero X * return code means settings were changed. X */ X Xint Xls_menu() X{ X extern int fd; 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 horizontal(l_win, 2, 0, 47); 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, VERT, HORZ); X X mvwaddstr(l_win, 19, 13, " 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 (up_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 Xstatic void Xdisp_settings(win) XWINDOW *win; X{ X extern int xmc; X char buf[40]; 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, TRUE); X wrefresh(win); X } X mvwattrstr(win, 4, 8, A_BOLD, buf); X return; X} SHAR_EOF if test 4816 -ne "`wc -c < 'ls_menu.c'`" then echo shar: "error transmitting 'ls_menu.c'" '(should have been 4816 characters)' fi fi exit 0 # End of shell archive
egray@fthood.UUCP (02/05/89)
This is part 5 (of 8) to the Pcomm v1.2 distribution package. Emmet P. Gray US Army, HQ III Corps & Fort Hood ...!uunet!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: # m_lib.c # macro.c # main.c # matches.c # misc.h # modem.h # modem_break.c # n_shell.c # p_lib.c # param.h # passthru.c # pexit.c # port.c # This archive created: Fri Feb 3 07:35:28 1989 export PATH; PATH=/bin:/usr/bin:$PATH echo shar: "extracting 'm_lib.c'" '(9951 characters)' if test -f 'm_lib.c' then echo shar: "will not over-write existing file 'm_lib.c'" else sed 's/^X//' << \SHAR_EOF > 'm_lib.c' X/* X * Routines to manipulate the pcomm.modem file X */ X X#include <stdio.h> X#include "modem.h" X X/* X * Read the modem/TTY database file. Returns a pointer to a static area X * containing the MODEM structure. All modem entries and all TTY entries X * are created regardless of the number of physical entries in the file. X */ X Xstruct MODEM * Xread_modem(extra) Xchar *extra; X{ X extern char *null_ptr; X FILE *fp, *my_fopen(); X int i, tty, mod, line, oops, m_line, start, stop; X char *str_dup(), buf[200], message[80], token[40], *str_tok(), *str; X char *temp_token, *t_sep, *m_sep, *m_letter, *findfile(); X static struct MODEM m; X void error_win(); X X if ((m.m_path = findfile(extra, "pcomm.modem")) == NULL) X error_win(1, "Support file \"pcomm.modem\" is missing", "or no read permission"); X X if (!(fp = my_fopen(m.m_path, "r"))) { X sprintf(buf, "\"%s\" for read", m.m_path); X error_win(1, "Can't open modem/TTY 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 pointer to NULL on a missing X * token. 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] = str_dup(str); X break; X case 1: X m.tname[tty] = str_dup(str); X break; X case 2: X m.init_sp[tty] = atoi(str); X break; X } X } X if (oops) X break; X /* sanity checking */ X sprintf(token, "TTY_%d", tty+1); X if (strcmp(token, temp_token)) { X sprintf(message, "is corrupted at line %d", line); X oops++; X break; X } X tty++; X continue; X } X /* the modem database */ X else { X sprintf(token, "MODEM_%d%c", mod+1, m_letter[m_line]); X if (strcmp(token, temp_token)) { X sprintf(message, "is corrupted at line %d", line); X oops++; X break; X } X /* X * There are three lines to the modem database. They X * are distinguished by the letters a, b, and, c X * appended to the entry number. X */ X switch (m_line) { X case 0: X start = 0; X stop = 5; X break; X case 1: X start = 5; X stop = 12; X break; X case 2: X start = 12; X stop = 16; X break; X } X for (i=start; i<stop; i++) { X if (!(str = str_tok((char *) NULL, m_sep[i]))) { X sprintf(message, "is missing a parameter at line %d", line); X oops++; X break; X } X switch (i) { X case 0: X m.mname[mod] = str_dup(str); X break; X case 1: X m.init[mod] = str_dup(str); X break; X case 2: X m.dial[mod] = str_dup(str); X break; X case 3: X m.suffix[mod] = str_dup(str); X break; X case 4: X m.hang_up[mod] = str_dup(str); X break; X case 5: X m.auto_baud[mod] = *str; X break; X case 6: X m.con_3[mod] = str_dup(str); X break; X case 7: X m.con_12[mod] = str_dup(str); X break; X case 8: X m.con_24[mod] = str_dup(str); X break; X case 9: X m.con_48[mod] = str_dup(str); X break; X case 10: X m.con_96[mod] = str_dup(str); X break; X case 11: X m.con_192[mod] = str_dup(str); X break; X case 12: X m.no_con1[mod] = str_dup(str); X break; X case 13: X m.no_con2[mod] = str_dup(str); X break; X case 14: X m.no_con3[mod] = str_dup(str); X break; X case 15: X m.no_con4[mod] = str_dup(str); X break; X } X } X if (oops) X break; X m_line++; X if (m_line >= 3) { X m_line = 0; X mod++; X } X } X } X fclose(fp); X X if (oops) { X sprintf(buf, "Modem/TTY database file \"%s\"", m.m_path); X error_win(1, buf, message); X } X m.t_entries = tty; X m.m_entries = mod; X m.t_cur = -1; X m.m_cur = -1; X /* if empty database */ X if (!tty) { X sprintf(buf, "Modem/TTY database file \"%s\"", m.m_path); X error_win(0, buf, "has no TTY data"); X } X if (!mod) { X sprintf(buf, "Modem/TTY database file \"%s\"", m.m_path); X error_win(0, buf, "has no modem data"); X } X /* fill in the rest */ X for (; tty<NUM_TTY; tty++) { X m.tty[tty] = null_ptr; X m.tname[tty] = null_ptr; X m.init_sp[tty] = 0; X } X for (; mod<NUM_MODEM; mod++) { X m.mname[mod] = null_ptr; X m.init[mod] = null_ptr; X m.dial[mod] = null_ptr; X m.suffix[mod] = null_ptr; X m.hang_up[mod] = null_ptr; X X m.auto_baud[mod] = 'Y'; X m.con_3[mod] = null_ptr; X m.con_12[mod] = null_ptr; X m.con_24[mod] = null_ptr; X m.con_48[mod] = null_ptr; X m.con_96[mod] = null_ptr; X m.con_192[mod] = null_ptr; X X m.no_con1[mod] = null_ptr; X m.no_con2[mod] = null_ptr; X m.no_con3[mod] = null_ptr; X m.no_con4[mod] = null_ptr; X } X return(&m); X} X X/* X * Update the modem database. Other routines actually do the changes X * or deletions in memory. A non-zero return code means non-fatal error. X */ X Xint Xup_modem() X{ X FILE *fp, *my_fopen(); X char buf[80]; X int i; X void error_win(); X X /* open for write */ X if (!(fp = my_fopen(modem->m_path, "w"))) { X sprintf(buf, "\"%s\"", modem->m_path); X error_win(0, "No write permission on modem/TTY database file", buf); X return(1); X } X /* put back the TTY entries */ X for (i=0; i<modem->t_entries; i++) X fprintf(fp, "TTY_%d=%s;%s;%d\n", i+1, modem->tty[i], X modem->tname[i], modem->init_sp[i]); X X /* put back the modem entries */ X for (i=0; i<modem->m_entries; i++) { X fprintf(fp, "MODEM_%da=%s;%s;%s;%s;%s\n", i+1, modem->mname[i], X modem->init[i], modem->dial[i], modem->suffix[i], X modem->hang_up[i]); X X fprintf(fp, "MODEM_%db=%c;%s;%s;%s;%s;%s;%s\n", i+1, X modem->auto_baud[i], modem->con_3[i], modem->con_12[i], X modem->con_24[i], modem->con_48[i], modem->con_96[i], X modem->con_192[i]); X X fprintf(fp, "MODEM_%dc=%s;%s;%s;%s\n", i+1, modem->no_con1[i], X modem->no_con2[i], modem->no_con3[i], modem->no_con4[i]); X } X X fclose(fp); X return(0); X} X X/* X * See if the new modem is already in the database. If it's not, create X * a slot for it and update the modem->m_cur variable. X */ X Xvoid Xcreate_modem(str) Xchar *str; X{ X int i; X char *str_rep(), buf[80]; X void error_win(); X /* modem entry already exists? */ X for (i=0; i<modem->m_entries; i++) { X if (!strcmp(str, modem->mname[i])) X return; X } X /* empty slot available? */ X if (modem->m_entries == NUM_MODEM) { X sprintf(buf, "\"%s\"", modem->m_path); X error_win(0, "No empty modem slots in", buf); X return; X } X /* create a new entry */ X i = modem->m_entries; X modem->mname[i] = str_rep(modem->mname[i], str); X X /* update number of entries */ X modem->m_entries++; X return; X} X X/* X * See if the modem names in the list still need to be in the database. X * If you find a "lost" entry, delete it and collapse the list. X */ X Xvoid Xdel_modem() X{ X extern char *null_ptr; X int i, j, match; X char *str_rep(); X void free_ptr(); X X for (i=0; i<modem->m_entries; i++) { X match = 0; X for (j=0; j<modem->t_entries; j++) { X if (!strcmp(modem->mname[i], modem->tname[j])) { X match++; X break; X } X } X /* found a "lost" modem name */ X if (!match) { X for (j=i; j<modem->m_entries-1; j++) { X /* copy the info */ X modem->mname[j] = str_rep(modem->mname[j], modem->mname[j+1]); X modem->init[j] = str_rep(modem->init[j], modem->init[j+1]); X modem->dial[j] = str_rep(modem->dial[j], modem->dial[j+1]); X modem->suffix[j] = str_rep(modem->suffix[j], modem->suffix[j+1]); X modem->hang_up[j] = str_rep(modem->hang_up[j], modem->hang_up[j+1]); X X modem->auto_baud[j] = modem->auto_baud[j+1]; X modem->con_3[j] = str_rep(modem->con_3[j], modem->con_3[j+1]); X modem->con_12[j] = str_rep(modem->con_12[j], modem->con_12[j+1]); X modem->con_24[j] = str_rep(modem->con_24[j], modem->con_24[j+1]); X modem->con_48[j] = str_rep(modem->con_48[j], modem->con_48[j+1]); X modem->con_96[j] = str_rep(modem->con_96[j], modem->con_96[j+1]); X modem->con_192[j] = str_rep(modem->con_192[j], modem->con_192[j+1]); X X modem->no_con1[j] = str_rep(modem->no_con1[j], modem->no_con1[j+1]); X modem->no_con2[j] = str_rep(modem->no_con2[j], modem->no_con2[j+1]); X modem->no_con3[j] = str_rep(modem->no_con3[j], modem->no_con3[j+1]); X modem->no_con4[j] = str_rep(modem->no_con4[j], modem->no_con4[j+1]); X } X j = modem->m_entries -1; X X free_ptr(modem->mname[j]); X free_ptr(modem->init[j]); X free_ptr(modem->dial[j]); X free_ptr(modem->suffix[j]); X free_ptr(modem->hang_up[j]); X X free_ptr(modem->con_3[j]); X free_ptr(modem->con_12[j]); X free_ptr(modem->con_24[j]); X free_ptr(modem->con_48[j]); X free_ptr(modem->con_96[j]); X free_ptr(modem->con_192[j]); X X free_ptr(modem->no_con1[j]); X free_ptr(modem->no_con2[j]); X free_ptr(modem->no_con3[j]); X free_ptr(modem->no_con4[j]); X X /* create an empty entry */ X modem->mname[j] = null_ptr; X modem->init[j] = null_ptr; X modem->dial[j] = null_ptr; X modem->suffix[j] = null_ptr; X modem->hang_up[j] = null_ptr; X X modem->auto_baud[j] = 'Y'; X modem->con_3[j] = null_ptr; X modem->con_12[j] = null_ptr; X modem->con_24[j] = null_ptr; X modem->con_48[j] = null_ptr; X modem->con_96[j] = null_ptr; X modem->con_192[j] = null_ptr; X X modem->no_con1[j] = null_ptr; X modem->no_con2[j] = null_ptr; X modem->no_con3[j] = null_ptr; X modem->no_con4[j] = null_ptr; X X /* update the counts */ X modem->m_entries--; X if (modem->m_cur >= modem->m_entries) X modem->m_cur = -1; X return; X } X } X return; X} SHAR_EOF if test 9951 -ne "`wc -c < 'm_lib.c'`" then echo shar: "error transmitting 'm_lib.c'" '(should have been 9951 characters)' fi fi echo shar: "extracting 'macro.c'" '(5246 characters)' if test -f 'macro.c' then echo shar: "will not over-write existing file 'macro.c'" else sed 's/^X//' << \SHAR_EOF > 'macro.c' X/* X * The keyboard macro feature. Displays (and prompts for editing) the X * macros assigned to the shifted number keys. Prompts for saving X * changes to disk. X */ X X#include <stdio.h> X#include <curses.h> X#include "config.h" X#include "misc.h" X#include "param.h" X Xvoid Xmacro() X{ X extern int fd; X WINDOW *ma_win, *newwin(); X int ans, changed; X char *mac, *str_rep(), *mac_prompt(); X X ma_win = newwin(18, 65, 2, 15); X mvwattrstr(ma_win, 1, 25, A_BOLD, "Keyboard Macros"); X horizontal(ma_win, 2, 0, 65); X mvwprintw(ma_win, 4, 0, " %4.4s-! %-50.50s\n", param->ascii_hot, param->mac_1); X wprintw(ma_win, " %4.4s-@ %-50.50s\n", param->ascii_hot, param->mac_2); X wprintw(ma_win, " %4.4s-# %-50.50s\n", param->ascii_hot, param->mac_3); X wprintw(ma_win, " %4.4s-$ %-50.50s\n", param->ascii_hot, param->mac_4); X wprintw(ma_win, " %4.4s-%% %-50.50s\n", param->ascii_hot, param->mac_5); X wprintw(ma_win, " %4.4s-^ %-50.50s\n", param->ascii_hot, param->mac_6); X wprintw(ma_win, " %4.4s-& %-50.50s\n", param->ascii_hot, param->mac_7); X wprintw(ma_win, " %4.4s-* %-50.50s\n", param->ascii_hot, param->mac_8); X wprintw(ma_win, " %4.4s-( %-50.50s\n", param->ascii_hot, param->mac_9); X wprintw(ma_win, " %4.4s-) %-50.50s\n", param->ascii_hot, param->mac_0); X mvwaddstr(ma_win, 15, 5, "Macro key to revise:"); X box(ma_win, VERT, HORZ); X /* on the bottom line */ X mvwaddstr(ma_win, 17, 21, " Press <ESC> to continue "); X wmove(ma_win, 15, 26); X wrefresh(ma_win); X X changed = 0; X X while ((ans = wgetch(ma_win)) != ESC) { X switch (ans) { X case '!': /* shifted 1 */ X if ((mac = mac_prompt(ans, param->mac_1)) != NULL) { X param->mac_1 = str_rep(param->mac_1, mac); X clear_line(ma_win, 4, 9, TRUE); X mvwattrstr(ma_win, 4, 9, A_BOLD, mac); X changed++; X } X break; X case '@': /* shifted 2 */ X if ((mac = mac_prompt(ans, param->mac_2)) != NULL) { X param->mac_2 = str_rep(param->mac_2, mac); X clear_line(ma_win, 5, 9, TRUE); X mvwattrstr(ma_win, 5, 9, A_BOLD, mac); X changed++; X } X break; X case '#': /* shifted 3 */ X if ((mac = mac_prompt(ans, param->mac_3)) != NULL) { X param->mac_3 = str_rep(param->mac_3, mac); X clear_line(ma_win, 6, 9, TRUE); X mvwattrstr(ma_win, 6, 9, A_BOLD, mac); X changed++; X } X break; X case '$': /* shifted 4 */ X if ((mac = mac_prompt(ans, param->mac_4)) != NULL) { X param->mac_4 = str_rep(param->mac_4, mac); X clear_line(ma_win, 7, 9, TRUE); X mvwattrstr(ma_win, 7, 9, A_BOLD, mac); X changed++; X } X break; X case '%': /* shifted 5 */ X if ((mac = mac_prompt(ans, param->mac_5)) != NULL) { X param->mac_5 = str_rep(param->mac_5, mac); X clear_line(ma_win, 8, 9, TRUE); X mvwattrstr(ma_win, 8, 9, A_BOLD, mac); X changed++; X } X break; X case '^': /* shifted 6 */ X if ((mac = mac_prompt(ans, param->mac_6)) != NULL) { X param->mac_6 = str_rep(param->mac_6, mac); X clear_line(ma_win, 9, 9, TRUE); X mvwattrstr(ma_win, 9, 9, A_BOLD, mac); X changed++; X } X break; X case '&': /* shifted 7 */ X if ((mac = mac_prompt(ans, param->mac_7)) != NULL) { X param->mac_7 = str_rep(param->mac_7, mac); X clear_line(ma_win, 10, 9, TRUE); X mvwattrstr(ma_win, 10, 9, A_BOLD, mac); X changed++; X } X break; X case '*': /* shifted 8 */ X if ((mac = mac_prompt(ans, param->mac_8)) != NULL) { X param->mac_8 = str_rep(param->mac_8, mac); X clear_line(ma_win, 11, 9, TRUE); X mvwattrstr(ma_win, 11, 9, A_BOLD, mac); X changed++; X } X break; X case '(': /* shifted 9 */ X if ((mac = mac_prompt(ans, param->mac_9)) != NULL) { X param->mac_9 = str_rep(param->mac_9, mac); X clear_line(ma_win, 12, 9, TRUE); X mvwattrstr(ma_win, 12, 9, A_BOLD, mac); X changed++; X } X break; X case ')': /* shifted 0 */ X if ((mac = mac_prompt(ans, param->mac_0)) != NULL) { X param->mac_0 = str_rep(param->mac_0, mac); X clear_line(ma_win, 13, 9, TRUE); X mvwattrstr(ma_win, 13, 9, A_BOLD, mac); X changed++; X } X break; X default: X beep(); X break; X } X touchwin(ma_win); X wmove(ma_win, 15, 26); X wrefresh(ma_win); X } X /* if something changed */ X if (changed) { X /* save to disk? */ X if (yes_prompt(ma_win, 15, 30, A_BOLD, "Save to disk")) { X if (up_param()) { X touchwin(ma_win); X wrefresh(ma_win); X } X } X } X if (fd == -1) { X werase(ma_win); X wrefresh(ma_win); X } X delwin(ma_win); X return; X} X X/* X * Sounds like McDonalds doesn't it? Actually, it opens a new window X * and prompts for the new macro. Returns a pointer to the new string. X * Since it uses get_str(), the return value points to a static area. X */ X Xstatic char * Xmac_prompt(key, string) Xchar key, *string; X{ X extern char *null_ptr; X WINDOW *mp_win, *newwin(); X char *new, *get_str(); X X mp_win = newwin(6, 65, 8, 0); X mvwprintw(mp_win, 2, 3, "%4.4s-%c %-50.50s", param->ascii_hot, key, string); X mvwaddstr(mp_win, 3, 5, "New : "); X box(mp_win, VERT, HORZ); X wrefresh(mp_win); X X if ((new = get_str(mp_win, 50, "", "\n")) != NULL) { X /* if CR, return NULL */ X if (*new == '\0') X new = NULL; X /* if space, change to null_ptr */ X if (!strcmp(new, " ")) X new = null_ptr; X } X X werase(mp_win); X wrefresh(mp_win); X delwin(mp_win); X return(new); X} SHAR_EOF if test 5246 -ne "`wc -c < 'macro.c'`" then echo shar: "error transmitting 'macro.c'" '(should have been 5246 characters)' fi fi echo shar: "extracting 'main.c'" '(7580 characters)' if test -f 'main.c' then echo shar: "will not over-write existing file 'main.c'" else sed 's/^X//' << \SHAR_EOF > 'main.c' X/* X * Pcomm is a public domain telecommunication program for Unix that X * is designed to operate similar to the MSDOS program, ProComm. X * ProComm (TM) is copyrighted by Datastorm Technologies, Inc. X * X * Emmet P. Gray US Army, HQ III Corps & Fort Hood X * ...!uunet!uiucuxc!fthood!egray Attn: AFZF-DE-ENV X * Directorate of Engineering & Housing X * Environmental Management Office X * Fort Hood, TX 76544-5057 X * X * Release v1.0 12 Mar 88 X * Release v1.1 21 Aug 88 X * Release v1.2.0 4 Feb 89 X */ X X#include <stdio.h> X#include <ctype.h> X#include <signal.h> X#include <curses.h> X#include <sys/types.h> X#include <sys/stat.h> X#define MAIN X#include "config.h" X#include "dial_dir.h" X#include "extrnl.h" X#include "misc.h" X#include "modem.h" X#include "param.h" X#include "status.h" X X#ifndef OLDCURSES X#include <term.h> X#else /* OLDCURSES */ X#ifdef UNIXPC X#include <sgtty.h> X#endif /* UNIXPC */ Xchar tcbuf[1024]; Xstruct sgttyb t_mode, c_mode; X#define cbreak crmode X#endif /* OLDCURSES */ X X#ifdef SHAREDMEM Xint shm_id; X#endif /* SHAREDMEM */ X Xstruct DIAL_DIR *dir; Xstruct EXTRNL *extrnl; Xstruct MODEM *modem; Xstruct PARAM *param; Xstruct STATUS *status; X Xint fd = -1; /* file descriptor for port */ Xint xmc; /* magic cookie terminal */ Xint msg_status; /* read/write permissions on TTY */ Xchar *null_ptr = ""; /* generic null pointer */ X Xmain(argc, argv) Xint argc; Xchar *argv[]; X{ X extern char *optarg; X int c, i, code, quit(); X char *mytty, *ttyname(), *term, *getenv(), *sys_name, *str_dup(); X char *extra_dir, buf[80], message[80]; X struct DIAL_DIR *read_dir(); X struct EXTRNL *read_extrnl(); X struct MODEM *read_modem(); X struct PARAM *read_param(); X struct STATUS *init(); X struct stat stbuf; X void exit(), error_win(), free_ptr(); X#ifdef OLDCURSES X char *tgetstr(), *t, tb[1024]; X t = tcbuf; X#endif /* OLDCURSES */ X X signal(SIGINT, SIG_IGN); X signal(SIGQUIT, SIG_IGN); X signal(SIGTERM, quit); X signal(SIGHUP, quit); X X sys_name = 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 = str_dup(optarg); X break; X case 'f': /* the short cut into the dialing dir */ X sys_name = str_dup(optarg); X break; X case '?': /* default */ X fprintf(stderr, "Usage: pcomm [-d directory] [-f system name]\n"); X exit(1); X break; X } X } X /* get terminal type */ X term = getenv("TERM"); X if (term == NULL || *term == '\0') { X fprintf(stderr, "Windows not supported (TERM not defined)\n"); X exit(1); X } X /* see if terminfo entry exists */ X#ifdef OLDCURSES X i = tgetent(tb, term); X#else /* OLDCURSES */ X setupterm(term, 1, &i); X#endif /* OLDCURSES */ X X if (i != 1) { X fprintf(stderr, "Windows not supported (no terminfo data for \"%s\")\n", term); X exit(1); X } X /* minimum screen size */ X#ifdef OLDCURSES X if (tgetnum("co") < 80 || tgetnum("li") < 24) { X#else /* OLDCURSES */ X if (columns < 80 || lines < 24) { X#endif /* OLDCURSES */ X fprintf(stderr, "Windows not supported (minimum 80x24 screen required)\n"); X exit(1); X } X /* must have cursor movement */ X#ifdef OLDCURSES X if (tgetstr("cm", &t) == NULL) { X#else /* OLDCURSES */ X if (cursor_address == NULL) { X#endif /* OLDCURSES */ X fprintf(stderr, "Windows not supported (terminal too dumb)\n"); X exit(1); X } X /* load magic cookie variable */ X#ifdef OLDCURSES X xmc = tgetnum("sg"); X#else /* OLDCURSES */ X xmc = magic_cookie_glitch; X#endif /* OLDCURSES */ X /* ok... now let's go! */ X#ifdef OLDCURSES X ioctl(0, TIOCGETP, &t_mode); X#endif /* OLDCURSES */ X X initscr(); X nonl(); X cbreak(); X noecho(); X X#ifdef OLDCURSES X ioctl(0, TIOCGETP, &c_mode); X#endif /* OLDCURSES */ X X dir = (struct DIAL_DIR *) NULL; X extrnl = (struct EXTRNL *) NULL; X param = (struct PARAM *) NULL; X modem = (struct MODEM *) NULL; X /* show the herald, return status */ X status = init(sys_name); X /* get "msgs" status */ X mytty = ttyname(0); X stat(mytty, &stbuf); X msg_status = stbuf.st_mode & 0777; X chmod(mytty, 0600); X X mvaddstr(12, 31, "Initializing..."); X refresh(); X /* read the support files */ X param = read_param(extra_dir); X dir = read_dir(extra_dir); X extrnl = read_extrnl(extra_dir); X modem = read_modem(extra_dir); X X /* warning about screen size */ X if (LINES > MAX_ROW || COLS > MAX_COL-1) X error_win(0, "Your screen size exceeds an internal Pcomm limit", X "The edges of the screen may contain garbage"); X X /* short-cut to dialing window? */ X code = 0; X if (sys_name != NULL) { X for (i=1; i<dir->d_entries+1; i++) { X if (match_ci(dir->name[i], sys_name)) { 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 match \"%s\" in dialing directory", sys_name); X sprintf(message, "file \"%s\"", dir->d_path); X error_win(0, buf, message); X } X free_ptr(sys_name); X } X /* start terminal dialogue */ X terminal(extra_dir, code); X exit(0); X} X X/* X * Something dreadful happened... Clean up the mess we made with the X * TTY driver and release the phone line. X */ X Xint Xquit() X{ X void cleanup(); X X cleanup(1); X /* never returns... */ X return(0); X} X X/* X * Check write permission with the real UID and GID. Returns a 0 on X * permission denied, 1 on OK, and 2 on OK-but the file already exists. X */ X Xint Xcan_write(file) Xchar *file; X{ X char *p, path[256], *strcpy(), *strrchr(); X X strcpy(path, file); X /* dissect the path component */ X if (p = strrchr(path, '/')) X *p = '\0'; X else X strcpy(path, "."); X /* if it already exists */ X if (!access(file, 0)) { X if (!access(file, 2)) X return(OK_BUT_EXISTS); X return(DENIED); X } X /* if path is writable */ X if (!access(path, 2)) X return(WRITE_OK); X return(DENIED); X} X X/* X * Check the read and write permissions before opening a file. This X * is a horrible kludge to work around the fact that a lot of systems X * that claim to be SVID compatible don't treat setuid(2) and setgid(2) X * properly. For example, on a Masscomp, you can't flip-flop back and X * forth between the real and effective UID/GID. X */ X XFILE * Xmy_fopen(file, mode) Xchar *file, *mode; X{ X FILE *fp; X X#ifdef SETUGID X#ifdef SETUID_BROKE X switch (*mode) { X case 'a': X case 'w': X switch(can_write(file)) { X case DENIED: X fp = (FILE *) NULL; X break; X case OK_BUT_EXISTS: X fp = fopen(file, mode); X break; X case WRITE_OK: X fp = fopen(file, mode); X chown(file, getuid(), getgid()); X break; X } X break; X case 'r': X if (access(file, 4)) X fp = (FILE *) NULL; X else X fp = fopen(file, mode); X break; X } X#else /* SETUID_BROKE */ X int euid, egid; X X euid = geteuid(); X egid = getegid(); X /* abdicate the throne */ X setuid(getuid()); X setgid(getgid()); X X fp = fopen(file, mode); X /* put things back */ X setuid(euid); X setgid(egid); X#endif /* SETUID_BROKE */ X return(fp); X#else /* SETUGID */ X return(fopen(file, mode)); X#endif /* SETUGID */ X} X X/* X * See if s2 in contained in s1 (case insensitive). Returns a 1 on yes, X * and a 0 on no. X */ X Xmatch_ci(s1, s2) Xchar *s1, *s2; X{ X int i; X char str1[128], str2[128], *strstr(); X X /* copy the strings to lower case */ X i = 0; X while(*s1) { X if (isupper(*s1)) X str1[i++] = tolower(*s1); X else X str1[i++] = *s1; X X if (i >= 127) X break; X s1++; X } X str1[i] = '\0'; X X i = 0; X while(*s2) { X if (isupper(*s2)) X str2[i++] = tolower(*s2); X else X str2[i++] = *s2; X X if (i >= 127) X break; X s2++; X } X str2[i] = '\0'; X /* do they match? */ X if (strstr(str1, str2)) X return(1); X return(0); X} SHAR_EOF if test 7580 -ne "`wc -c < 'main.c'`" then echo shar: "error transmitting 'main.c'" '(should have been 7580 characters)' fi fi echo shar: "extracting 'matches.c'" '(754 characters)' if test -f 'matches.c' then echo shar: "will not over-write existing file 'matches.c'" else sed 's/^X//' << \SHAR_EOF > 'matches.c' X/* X * See if two strings match. Returns a 0 on success, and a 1 on failure. X * This is an external program to be used in shell scripts. X */ X X#define STRSTR X X#include <stdio.h> X Xmain(argc, argv) Xint argc; Xchar *argv[]; X{ X char *strstr(); X void exit(); X X if (argc != 3) { X fprintf(stderr, "Usage: matches string1 string2\n"); X exit(-1); X } X X if (strstr(argv[1], argv[2])) X exit(0); X exit(1); X} X X#ifdef STRSTR X/* X * Return a pointer to the first occurance of string str2 in str1. X * Returns a NULL if str2 is not in str1. X */ X Xchar * Xstrstr(str1, str2) Xchar *str1, *str2; X{ X int len; X X len = strlen(str2); X while (*str1) { X if (*str2 == *str1) { X if (!strncmp(str2, str1, len)) X return(str1); X } X str1++; X } X return(NULL); X} X#endif /* STRSTR */ SHAR_EOF if test 754 -ne "`wc -c < 'matches.c'`" then echo shar: "error transmitting 'matches.c'" '(should have been 754 characters)' fi fi echo shar: "extracting 'misc.h'" '(1549 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(3) functions and to make X * the old curses(3) routines happy. ("config.h" must be included first). X */ 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 */ X X#ifdef OLDCURSES Xtypedef char chtype; X#endif /* OLDCURSES */ X X#ifdef ACS_HLINE X#define VERT (chtype)0 X#define HORZ (chtype)0 X#else /* ACS_HLINE */ X#define VERT (chtype)'|' X#define HORZ (chtype)'-' X#define ACS_VLINE (chtype)'|' X#define ACS_HLINE (chtype)'-' X#endif /* ACS_HLINE */ X X/* X * Other miscellaneous stuff X */ X X#define BEL 7 X#define BS 8 X#define ESC 27 X#define DEL 127 X X#define MANUAL_CLEAR 0 X#define AUTO_CLEAR 1 X X#define DENIED 0 X#define WRITE_OK 1 X#define OK_BUT_EXISTS 2 SHAR_EOF if test 1549 -ne "`wc -c < 'misc.h'`" then echo shar: "error transmitting 'misc.h'" '(should have been 1549 characters)' fi fi echo shar: "extracting 'modem.h'" '(1538 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 16 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 init_sp[NUM_TTY]; /* initialization 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 *hang_up[NUM_MODEM]; /* hang up the modem */ X char auto_baud[NUM_MODEM]; /* should we sync baud rates? */ 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 char *m_path; /* path to the pcomm.modem file */ X}; X X#ifndef MAIN Xextern struct MODEM *modem; X#endif /* MAIN */ SHAR_EOF if test 1538 -ne "`wc -c < 'modem.h'`" then echo shar: "error transmitting 'modem.h'" '(should have been 1538 characters)' fi fi echo shar: "extracting 'modem_break.c'" '(407 characters)' if test -f 'modem_break.c' then echo shar: "will not over-write existing file 'modem_break.c'" else sed 's/^X//' << \SHAR_EOF > 'modem_break.c' X/* X * Send a modem break. This is an external program to be used in shell X * scripts. X */ X X#include <stdio.h> X#ifdef BSD X#include <sgtty.h> X#else /* BSD */ X#include <termio.h> X#endif /* BSD */ X Xmain() X{ X unsigned int sleep(); X X#ifdef BSD X ioctl(1, TIOCSBRK, (struct sgttyb *) 0); X sleep(1); X return(ioctl(1, TIOCCBRK, (struct sgttyb *) 0)); X#else /* BSD */ X return(ioctl(1, TCSBRK, 0)); X#endif /* BSD */ X} SHAR_EOF if test 407 -ne "`wc -c < 'modem_break.c'`" then echo shar: "error transmitting 'modem_break.c'" '(should have been 407 characters)' fi fi echo shar: "extracting 'n_shell.c'" '(1336 characters)' if test -f 'n_shell.c' then echo shar: "will not over-write existing file 'n_shell.c'" else sed 's/^X//' << \SHAR_EOF > 'n_shell.c' X/* X * Spawn a "native" shell. Native means the shell found in the SHELL X * environmental variable. X */ X X#include <stdio.h> X#include <signal.h> X#include <curses.h> X#include "config.h" X Xvoid Xn_shell() X{ X WINDOW *sh_win, *newwin(); X SIG_TYPE (*istat)(), (*qstat)(); X int sig_status, spid, w; X char *shell, *shellpath, *getenv(), *strrchr(); X unsigned int sleep(); X void _exit(); X /* a full window */ X sh_win = newwin(LINES, COLS, 0, 0); X X touchwin(sh_win); X waddstr(sh_win, "Pcomm <=> Unix gateway, use ^D or 'exit' to return\n"); X wrefresh(sh_win); X /* out of curses mode */ X resetterm(); X X shellpath = getenv("SHELL"); X if (shellpath == NULL || *shellpath == '\0') X shellpath = "/bin/sh"; X X if (shell = strrchr(shellpath, '/')) X shell++; X else { X shellpath = "/bin/sh"; X shell = "sh"; X } X X if (!(spid = fork())) { X signal(SIGINT, SIG_DFL); X signal(SIGQUIT, SIG_DFL); X#ifdef SETUGID X setgid(getgid()); X setuid(getuid()); X#endif /* SETUGID */ X execl(shellpath, shell, "-i", (char *) 0); X _exit(1); X } X istat = signal(SIGINT, SIG_IGN); X qstat = signal(SIGQUIT, SIG_IGN); X X while ((w = wait(&sig_status)) != spid && w != -1) X ; X X signal(SIGINT, istat); X signal(SIGQUIT, qstat); X /* back to curses mode */ X sleep(1); X fixterm(); X X clearok(curscr, TRUE); X werase(sh_win); X wrefresh(sh_win); X delwin(sh_win); X return; X} SHAR_EOF if test 1336 -ne "`wc -c < 'n_shell.c'`" then echo shar: "error transmitting 'n_shell.c'" '(should have been 1336 characters)' fi fi echo shar: "extracting 'p_lib.c'" '(7337 characters)' if test -f 'p_lib.c' then echo shar: "will not over-write existing file 'p_lib.c'" else sed 's/^X//' << \SHAR_EOF > 'p_lib.c' X/* X * Routines to manipulate the pcomm.param file. X */ X X#include <stdio.h> X#include "param.h" X X/* X * Read the parameter structure from the pcomm.param file. Returns a X * pointer to a static area containing the PARAM structure. All errors X * are fatal. X */ X Xstruct PARAM * Xread_param(extra) Xchar *extra; X{ X FILE *fp, *my_fopen(); X int i, line, oops; X char buf[200], *temp_token, *str, *str_dup(), *findfile(); X char message[80], *str_tok(); X static char *token[NUM_PARAM] = {"D_BAUD", "D_PARITY", "D_DBITS", X "D_SBITS", "HOT", "ASCII_HOT", "D_DUPLEX", "FLOW", "CR_IN", "CR_OUT", X "LOGFILE", "DUMPFILE", "STRIP", "PAUSE_CHAR", "CR_CHAR", "CTRL_CHAR", X "ESC_CHAR", "BRK_CHAR", "ABORT", "C_DELAY", "R_DELAY", "LECHO", X "EXPAND", "CR_DELAY", "PACE", "CR_UP", "LF_UP", "TIMER", "CR_DN", X "LF_DN", "LD_PLUS", "LD_MINUS", "LD_AT", "LD_POUND", "MAC_1", X "MAC_2", "MAC_3", "MAC_4", "MAC_5", "MAC_6", "MAC_7", "MAC_8", X "MAC_9", "MAC_0"}; X static struct PARAM p; X void error_win(); X X if ((p.p_path = findfile(extra, "pcomm.param")) == NULL) X error_win(1, "Support file \"pcomm.param\" is missing", "or no read permission"); X X if (!(fp = my_fopen(p.p_path, "r"))) { X sprintf(buf, "\"%s\" for read", p.p_path); X error_win(1, "Can't open parameter file", buf); X } X X oops = 0; X line = 0; X for (i=0; i<NUM_PARAM; i++) { X line++; X if (fgets(buf, 200, fp) == NULL) { X sprintf(message, "is truncated at line %d", line); X oops++; X break; X } X /* parse the input line */ X if (!(temp_token = str_tok(buf, '='))) { X sprintf(message, "is missing a token at line %d", line); X oops++; X break; X } X if (!(str = str_tok((char *) NULL, '\n'))) { X sprintf(message, "is missing a parameter at line %d", line); X oops++; X break; X } X /* sanity checking */ X if (strcmp(temp_token, token[i])) { X sprintf(message, "is corrupted at line %d", line); X oops++; X break; X } X X switch (i) { X /* used in ls_menu() */ X case LINE_SET: X p.d_baud = 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 = str_dup(str); X break; X case TERM_SETUP+2: X p.d_duplex = str_dup(str); X break; X case TERM_SETUP+3: X p.flow = str_dup(str); X break; X case TERM_SETUP+4: X p.cr_in = str_dup(str); X break; X case TERM_SETUP+5: X p.cr_out = str_dup(str); X break; X X /* used in gen_setup() */ X case GEN_SETUP: X p.logfile = str_dup(str); X break; X case GEN_SETUP+1: X p.dumpfile = str_dup(str); X break; X case GEN_SETUP+2: X p.strip = str_dup(str); X break; X case GEN_SETUP+3: X p.pause_char = *str; X break; X case GEN_SETUP+4: X p.cr_char = *str; X break; X case GEN_SETUP+5: X p.ctrl_char = *str; X break; X case GEN_SETUP+6: X p.esc_char = *str; X break; X case GEN_SETUP+7: X p.brk_char = *str; X break; X case GEN_SETUP+8: X p.abort = str_dup(str); X break; X X /* used in gen_setup() delay_times() */ X case DELAY_TIMES: X p.c_delay = atoi(str); X break; X case DELAY_TIMES+1: X p.r_delay = atoi(str); X break; X X /* used in axfer_setup() */ X case ASCII_SETUP: X p.lecho = str_dup(str); X break; X case ASCII_SETUP+1: X p.expand = str_dup(str); X break; X case ASCII_SETUP+2: X p.cr_delay = atoi(str); X break; X case ASCII_SETUP+3: X p.pace = str_dup(str); X break; X case ASCII_SETUP+4: X p.cr_up = str_dup(str); X break; X case ASCII_SETUP+5: X p.lf_up = str_dup(str); X break; X case ASCII_SETUP+6: X p.timer = atoi(str); X break; X case ASCII_SETUP+7: X p.cr_dn = str_dup(str); X break; X case ASCII_SETUP+8: X p.lf_dn = str_dup(str); X break; X X /* used in d_revise() */ X case LD_CODES: X p.ld_plus = str_dup(str); X break; X case LD_CODES+1: X p.ld_minus = str_dup(str); X break; X case LD_CODES+2: X p.ld_at = str_dup(str); X break; X case LD_CODES+3: X p.ld_pound = str_dup(str); X break; X X /* used in macro() */ X case MACROS: X p.mac_1 = str_dup(str); X break; X case MACROS+1: X p.mac_2 = str_dup(str); X break; X case MACROS+2: X p.mac_3 = str_dup(str); X break; X case MACROS+3: X p.mac_4 = str_dup(str); X break; X case MACROS+4: X p.mac_5 = str_dup(str); X break; X case MACROS+5: X p.mac_6 = str_dup(str); X break; X case MACROS+6: X p.mac_7 = str_dup(str); X break; X case MACROS+7: X p.mac_8 = str_dup(str); X break; X case MACROS+8: X p.mac_9 = str_dup(str); X break; X case MACROS+9: X p.mac_0 = str_dup(str); X break; X } X } X fclose(fp); X if (oops) { X sprintf(buf, "Parameter file \"%s\"", p.p_path); X error_win(1, buf, message); X } X return(&p); X} X X/* X * Write the updated param structure to disk. The values in memory should X * have already been "purified". Later, we'll update only the entries that X * have been explicitly asked for. A non-zero return code means non-fatal X * error. X */ X Xint Xup_param() X{ X FILE *fp, *my_fopen(); X char buf[80]; X void error_win(); X /* open for write */ X if (!(fp = my_fopen(param->p_path, "w"))) { X sprintf(buf, "\"%s\"", param->p_path); X error_win(0, "No write permission on parameter file", buf); X return(1); X } X X fprintf(fp, "D_BAUD=%d\n", param->d_baud); X fprintf(fp, "D_PARITY=%c\n", param->d_parity); X fprintf(fp, "D_DBITS=%d\n", param->d_dbits); X fprintf(fp, "D_SBITS=%d\n", param->d_sbits); X fprintf(fp, "HOT=%d\n", param->hot); X fprintf(fp, "ASCII_HOT=%s\n", param->ascii_hot); X fprintf(fp, "D_DUPLEX=%s\n", param->d_duplex); X fprintf(fp, "FLOW=%s\n", param->flow); X fprintf(fp, "CR_IN=%s\n", param->cr_in); X fprintf(fp, "CR_OUT=%s\n", param->cr_out); X fprintf(fp, "LOGFILE=%s\n", param->logfile); X fprintf(fp, "DUMPFILE=%s\n", param->dumpfile); X fprintf(fp, "STRIP=%s\n", param->strip); X fprintf(fp, "PAUSE_CHAR=%c\n", param->pause_char); X fprintf(fp, "CR_CHAR=%c\n", param->cr_char); X fprintf(fp, "CTRL_CHAR=%c\n", param->ctrl_char); X fprintf(fp, "ESC_CHAR=%c\n", param->esc_char); X fprintf(fp, "BRK_CHAR=%c\n", param->brk_char); X fprintf(fp, "ABORT=%s\n", param->abort); X fprintf(fp, "C_DELAY=%d\n", param->c_delay); X fprintf(fp, "R_DELAY=%d\n", param->r_delay); X fprintf(fp, "LECHO=%s\n", param->lecho); X fprintf(fp, "EXPAND=%s\n", param->expand); X fprintf(fp, "CR_DELAY=%d\n", param->cr_delay); X fprintf(fp, "PACE=%s\n", param->pace); X fprintf(fp, "CR_UP=%s\n", param->cr_up); X fprintf(fp, "LF_UP=%s\n", param->lf_up); X fprintf(fp, "TIMER=%d\n", param->timer); X fprintf(fp, "CR_DN=%s\n", param->cr_dn); X fprintf(fp, "LF_DN=%s\n", param->lf_dn); X fprintf(fp, "LD_PLUS=%s\n", param->ld_plus); X fprintf(fp, "LD_MINUS=%s\n", param->ld_minus); X fprintf(fp, "LD_AT=%s\n", param->ld_at); X fprintf(fp, "LD_POUND=%s\n", param->ld_pound); X fprintf(fp, "MAC_1=%s\n", param->mac_1); X fprintf(fp, "MAC_2=%s\n", param->mac_2); X fprintf(fp, "MAC_3=%s\n", param->mac_3); X fprintf(fp, "MAC_4=%s\n", param->mac_4); X fprintf(fp, "MAC_5=%s\n", param->mac_5); X fprintf(fp, "MAC_6=%s\n", param->mac_6); X fprintf(fp, "MAC_7=%s\n", param->mac_7); X fprintf(fp, "MAC_8=%s\n", param->mac_8); X fprintf(fp, "MAC_9=%s\n", param->mac_9); X fprintf(fp, "MAC_0=%s\n", param->mac_0); X X fclose(fp); X return(0); X} SHAR_EOF if test 7337 -ne "`wc -c < 'p_lib.c'`" then echo shar: "error transmitting 'p_lib.c'" '(should have been 7337 characters)' fi fi echo shar: "extracting 'param.h'" '(2757 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 44 X#define LINE_SET 0 X#define TERM_SETUP 4 X#define GEN_SETUP 10 X#define DELAY_TIMES 19 X#define ASCII_SETUP 21 X#define LD_CODES 30 X#define MACROS 34 X Xstruct PARAM { X /* 0-3 used in ls_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-18 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 brk_char; /* modem break synonym */ X char *abort; /* destination of aborted downloads */ X X /* 19-20 used in gen_setup() & delay_times() */ X int c_delay; /* connect delay time */ X int r_delay; /* redial delay time */ X X /* 21-29 used in axfer_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 /* 30-33 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 /* 34-43 used in macro() */ X char *mac_1; /* shifted 1 macro */ X char *mac_2; /* shifted 2 macro */ X char *mac_3; /* shifted 3 macro */ X char *mac_4; /* shifted 4 macro */ X char *mac_5; /* shifted 5 macro */ X char *mac_6; /* shifted 6 macro */ X char *mac_7; /* shifted 7 macro */ X char *mac_8; /* shifted 8 macro */ X char *mac_9; /* shifted 9 macro */ X char *mac_0; /* shifted 0 macro */ X X char *p_path; /* path to the pcomm.param file */ X}; X X#ifndef MAIN Xextern struct PARAM *param; X#endif /* MAIN */ SHAR_EOF if test 2757 -ne "`wc -c < 'param.h'`" then echo shar: "error transmitting 'param.h'" '(should have been 2757 characters)' fi fi echo shar: "extracting 'passthru.c'" '(2489 characters)' if test -f 'passthru.c' then echo shar: "will not over-write existing file 'passthru.c'" else sed 's/^X//' << \SHAR_EOF > 'passthru.c' X/* X * A transparent "pass-thru" mode, designed to allow binary transfers X * between 3 machines (with the middle machine in the pass-thru mode). X * A non-zero return code means the input routine should be restarted. X */ X X#include <stdio.h> X#include <signal.h> X#include <curses.h> X#include "config.h" X#include "misc.h" X X#ifdef BSD X#include <setjmp.h> Xjmp_buf cp_buf; X#endif /* BSD */ X Xint Xpass_thru() X{ X extern int fd; X WINDOW *pt_win, *newwin(); X int num; X void cpio(), error_win(); X X pt_win = newwin(5, 70, 5, 5); X X mvwaddstr(pt_win, 2, 4, "Enter the expiration time (5-60 sec): "); X box(pt_win, VERT, HORZ); X X mvwattrstr(pt_win, 0, 3, A_BOLD, " Pass Through Mode "); X wmove(pt_win, 2, 43); X wrefresh(pt_win); X /* get the answer */ X while ((num = get_num(pt_win, 2)) != -1) { X /* out of bounds */ X if (num < 5 || num > 60) { X beep(); X clear_line(pt_win, 2, 43, TRUE); X wmove(pt_win, 2, 43); X wrefresh(pt_win); X } X else { X werase(pt_win); X wrefresh(pt_win); X delwin(pt_win); X X if (fd == -1) { X error_win(0, "Not currently connected to any host", ""); X return(0); X } X X touchwin(stdscr); X refresh(); X X cpio((unsigned int) num); X return(1); X } X } X if (fd == -1) { X werase(pt_win); X wrefresh(pt_win); X } X delwin(pt_win); X return(0); X} X X/* X * Copy the stdin to the TTYout and copy the TTYin to the stdout. Uses X * multi character reads. I'm not too concerned about the excess baggage X * caused by the entire image being forked... this feature won't be used X * that often. X */ X Xstatic int cp_flag; X Xstatic void Xcpio(num) Xunsigned int num; X{ X extern int fd; X int cpid, n, cp_force(); X char buf[CLIST_SIZ]; X unsigned int alarm(), sleep(); X void line_set(), xmodem_mode(), input_off(); X X /* out of curses mode */ X resetterm(); X X input_off(); X xmodem_mode(0); X xmodem_mode(fd); X X /* copy the TTYin to stdout */ X if (!(cpid = fork())) { X while (1) { X n = read(fd, buf, CLIST_SIZ); X write(1, buf, n); X } X } X X cp_flag = 0; X signal(SIGALRM, cp_force); X /* copy the stdin to TTYout */ X while (1) { X alarm(num); X#ifdef BSD X if (setjmp(cp_buf)) X break; X#endif /* BSD */ X n = read(0, buf, CLIST_SIZ); X if (cp_flag) X break; X write(fd, buf, n); X } X kill(cpid, SIGKILL); X /* back to curses mode */ X sleep(1); X fixterm(); X beep(); X line_set(); X clearok(curscr, TRUE); X return; X} X X/* ARGSUSED */ Xstatic int Xcp_force(dummy) X{ X#ifdef BSD X longjmp(cp_buf, 1); X#else /* BSD */ X signal(SIGALRM, cp_force); X cp_flag = 1; X#endif /* BSD */ X} SHAR_EOF if test 2489 -ne "`wc -c < 'passthru.c'`" then echo shar: "error transmitting 'passthru.c'" '(should have been 2489 characters)' fi fi echo shar: "extracting 'pexit.c'" '(2579 characters)' if test -f 'pexit.c' then echo shar: "will not over-write existing file 'pexit.c'" else sed 's/^X//' << \SHAR_EOF > 'pexit.c' X/* X * Exit Pcomm. A user requested abort. There are a lot of things to do X * before we exit! X */ X X#include <stdio.h> X#include <curses.h> X#include "config.h" X#include "dial_dir.h" X#include "misc.h" X#include "param.h" X#include "status.h" X X#ifdef SHAREDMEM X#include <sys/types.h> X#include <sys/ipc.h> X#include <sys/shm.h> X#endif /* SHAREDMEM */ X Xvoid Xpexit() X{ X extern int fd; X WINDOW *ex_win, *newwin(); X void cleanup(), st_line(); X X ex_win = newwin(5, 33, 3, 7); X X box(ex_win, VERT, HORZ); X mvwattrstr(ex_win, 0, 3, A_BOLD, " Exit "); X if (yes_prompt(ex_win, 2, 4, A_BLINK, "Exit to Unix")) { X st_line(" exiting"); X cleanup(0); X } X if (fd == -1) { X werase(ex_win); X wrefresh(ex_win); X } X delwin(ex_win); X return; X} X X/* X * Do the clean up detail before we exit. Only the status structure X * is guaranteed to exit. X */ X Xvoid Xcleanup(val) Xint val; X{ X extern int msg_status; X void release_port(), input_off(), exit(); X char *ttyname(); X#ifdef SHAREDMEM X extern int shm_id; X void perror(); X#endif /* SHAREDMEM */ X /* kill the input routine */ X input_off(); X /* release the port */ X release_port(QUIET); X /* zap the virtual screen */ X#ifdef SHAREDMEM X if (shmdt((char *) status) < 0) X perror("shmdt"); X if (shmctl(shm_id, IPC_RMID, (struct shmid_ds *) NULL) < 0) X perror("shmctl"); X#else /* SHAREDMEM */ X unlink(status->vs_path); X#endif /* SHAREDMEM */ X X /* X * If we die an un-natural death (such as a SIGHUP on the loss of X * the controlling terminal) we won't have a terminal to mess with. X */ X if (isatty(0)) { X touchwin(stdscr); X clear(); X refresh(); X endwin(); X /* return the TTY chmod */ X chmod(ttyname(0), msg_status); X } X exit(val); X} X X/* X * Open a window to display an error message. Handles both fatal and X * non-fatal errors X */ X Xvoid Xerror_win(code, line_one, line_two) Xint code; Xchar *line_one, *line_two; X{ X WINDOW *e_win, *newwin(); X void cleanup(), st_line(); X X /* make sure we're in curses mode */ X fixterm(); X e_win = newwin(7, 70, 9, 5); X /* display the nasty note */ X mvwaddstr(e_win, 2, 4, line_one); X mvwaddstr(e_win, 3, 4, line_two); X box(e_win, VERT, HORZ); X X if (code) { X mvwattrstr(e_win, 0, 4, A_BOLD, " Error "); X mvwattrstr(e_win, 5, 24, A_BLINK, "Press any key to exit"); X wmove(e_win, 5, 46); X } X else { X mvwattrstr(e_win, 0, 4, A_BOLD, " Warning "); X mvwattrstr(e_win, 5, 22, A_BLINK, "Press any key to continue"); X wmove(e_win, 5, 48); X } X beep(); X wrefresh(e_win); X X wgetch(e_win); X werase(e_win); X wrefresh(e_win); X delwin(e_win); X X if (code) { X st_line(" exiting"); X cleanup(code); X } X return; X} SHAR_EOF if test 2579 -ne "`wc -c < 'pexit.c'`" then echo shar: "error transmitting 'pexit.c'" '(should have been 2579 characters)' fi fi echo shar: "extracting 'port.c'" '(10197 characters)' if test -f 'port.c' then echo shar: "will not over-write existing file 'port.c'" else sed 's/^X//' << \SHAR_EOF > 'port.c' X/* X * Routines to get or release a TTY port. X */ X X#define MAX_PID 30000 X#define TRUE 1 X#define FALSE 0 X X#include <stdio.h> X#include <fcntl.h> X#include <errno.h> X#include "config.h" X#include "dial_dir.h" X#include "modem.h" X X#ifdef BSD X#include <sys/file.h> X#endif /* BSD */ X X#ifdef UNIXPC X#include <sys/phone.h> X#endif /* UNIXPC */ X X#ifdef XENIX_LOCKS X#include <ctype.h> X#endif /* XENIX_LOCKS */ X Xstatic int getty_status = 0; Xstatic char *lock_path = NULL; X/* X * Finds a free (or requested) serial port. Creates a lock file to hold X * for our use. Loads the modem database. A non-zero return code means X * all ports (or the requested port) are busy. X */ X Xint Xget_port() X{ X extern int fd; X register int i; X int j, k, lfd, list[NUM_TTY], cmask, tbaud, is_dev, progpid; X char file[80], buf[80], message[80], *str_rep(), *last_c; X unsigned int sleep(); X void error_win(), line_set(), release_port(), send_str(); X X is_dev = chk_script(dir->script[dir->d_cur]); X /* X * If you already have a port, see if it is good enough for the X * current request. X */ X#ifdef KEEP_PORT X if (fd != -1) { X if (!strcmp(dir->script[dir->d_cur], modem->tty[modem->t_cur]) X || (!is_dev && ck_speed(modem->t_cur, dir->baud[dir->d_cur]))){ X /* X * Reset the line because the baud rate (or other X * parameters) may have changed. X */ X line_set(); X return(0); X } X } X#endif /* KEEP_PORT */ X X release_port(VERBOSE); X X list[0] = -1; X /* X * See if you want a specific TTY port. If the script field in the X * dialing directory is a valid device name, then use that TTY. X */ X if (is_dev) { X for (i=0; i<modem->t_entries; i++) { X /* and it exists in modem database */ X if (!strcmp(dir->script[dir->d_cur], modem->tty[i])) { X list[0] = i; X list[1] = -1; X break; X } X } X /* oops... we don't know that port */ X if (list[0] == -1) { X sprintf(message, "Device \"%s\" in the script field doesn't exist in", dir->script[dir->d_cur]); X sprintf(buf, "modem/TTY database \"%s\"", modem->m_path); X error_win(0, message, buf); X } X } X X /* X * Create a list of acceptable TTYs. It searches the modem database X * for the requested baud rate. X */ X k = 0; X if (list[0] == -1) { X for (i=0; i<modem->t_entries; i++) { X /* skip ports with no modems */ X if (!strcmp(modem->tname[i], "DIRECT")) X continue; X X /* can handle requested baud rate? */ X if (ck_speed(i, dir->baud[dir->d_cur])) X list[k++] = i; X } X /* the end of list marker */ X list[k] = -1; X } X /* empty list? */ X if (list[0] == -1) { X sprintf(message, "No modem at a %d baud rating exists in the", dir->baud[dir->d_cur]); X sprintf(buf, "modem database \"%s\"", modem->m_path); X error_win(0, message, buf); X return(1); X } X /* check the list for a free port */ X i = 0; X while (list[i] != -1) { X /* create a lock file name */ X sprintf(file, "%s/LCK..%s", LOCK_DIR, modem->tty[list[i]]); X X#ifdef XENIX_LOCKS X last_c = file + strlen(file)-1; X if (isuuper(*last_c)) X *last_c = tolower(*last_c); X#endif /* XENIX_LOCKS */ X X#ifdef DEBUG X fprintf(stderr, "get_port: checking '/dev/%s'\n", modem->tty[list[i]]); X#endif /* DEBUG */ X X /* no lock exists or it is dead */ X if (checklock(file)) { X getty_status = set_getty(modem->tty[list[i]], FALSE); X X cmask = umask(0); X if ((lfd = open(file, O_CREAT|O_EXCL|O_WRONLY, 0666)) < 0) { X if (getty_status) X set_getty(modem->tty[list[i]], TRUE); X sprintf(buf, "\"%s\"", file); X error_win(1, "Can't create the lockfile", buf); X } X umask(cmask); X#ifdef ASCII_PID X sprintf(buf, "%10d\n", getpid()); X write(lfd, buf, 11); X#else /* ASCII_PID */ X progpid = getpid(); X write(lfd, (char *) &progpid, sizeof(int)); X#endif /* ASCII_PID */ X close(lfd); X /* store the new values */ X lock_path = str_rep(lock_path, file); X modem->t_cur = list[i]; X X /* open the device (ignore DCD) */ X sprintf(buf, "/dev/%s", modem->tty[modem->t_cur]); X if ((fd = open(buf, O_RDWR|O_NDELAY)) < 0) { X if (getty_status) X set_getty(modem->tty[modem->t_cur], TRUE); X sprintf(file, "Can't open port \"%s\" for read and write", buf); X error_win(1, file, ""); X } X /* change line settings */ X line_set(); X /* ...just to be sure */ X close(open(buf, O_RDWR)); X X /* turn off the O_NDELAY setting */ X tty_noblock(fd, FALSE); X X /* load the modem data base */ X modem->m_cur = -1; X for (j=0; j<modem->m_entries; j++) { X if (!strcmp(modem->tname[modem->t_cur], modem->mname[j])) { X modem->m_cur = j; X break; X } X } X if (modem->m_cur == -1) { X sprintf(buf, "Modem name \"%s\" in TTY database", X modem->tname[modem->t_cur]); X error_win(1, buf, "does not exist in modem database"); X } X /* initialize the modem */ X if (modem->init_sp[modem->t_cur]) { X tbaud = dir->baud[dir->d_cur]; X dir->baud[dir->d_cur] = modem->init_sp[modem->t_cur]; X line_set(); X send_str(modem->init[modem->m_cur], SLOW); X dir->baud[dir->d_cur] = tbaud; X } X else X send_str(modem->init[modem->m_cur], SLOW); X sleep(1); X return(0); X } X i++; X } X error_win(0, "All ports are busy now, try again later", ""); X return(1); X} X X/* X * Release the port. Closes the file descriptor and removes the X * lock file X */ X Xvoid Xrelease_port(verbose) Xint verbose; X{ X extern int fd; X extern char *null_ptr; X char buf[80]; X void free_ptr(), hang_up(); X X /* X * The modem structure can't be guaranteed to exist yet. For example, X * an error in reading one of the other support files would cause X * this routine to be used before the MODEM structure gets allocated. X */ X if (modem == NULL) X return; X /* close the port */ X if (fd != -1) { X tty_flush(fd, 2); X /* X * Since HUPCL is set, the close() should drop the DTR and X * hang up the modem (provided you've got the modem to X * respond to DTR). Since this is not guaranteed, we send X * the hang_up string first. X */ X hang_up(verbose); X close(fd); X } X /* remove the lock */ X if (lock_path != NULL && *lock_path != '\0') { X if (unlink(lock_path)) { X sprintf(buf, "\"%s\"", lock_path); X error_win(0, "Can't remove the lock file", buf); X } X free_ptr(lock_path); X lock_path = null_ptr; X } X /* turn the getty back on? */ X if (getty_status && modem->t_cur != -1) X set_getty(modem->tty[modem->t_cur], TRUE); X /* clean up the structure */ X fd = -1; X modem->m_cur = -1; X modem->t_cur = -1; X return; X} X X/* X * Turn the /etc/getty on or off for the specified port. A non-zero return X * code means that the getty was on. Systems with uugetty() or dedicated X * dialout ports won't need this routine. X */ X X/* ARGSUSED */ Xstatic int Xset_getty(tty, on) Xchar *tty; Xint on; X{ X#ifdef UNIXPC X int i, ret_code; X char buf[40]; X unsigned int sleep(); X /* the last three characters */ X i = strlen(tty) -3; X X ret_code = 0; X if (on) { X sprintf(buf, "setgetty %s 1", tty+i); X system(buf); X } X else { X sprintf(buf, "setgetty %s 0", tty+i); X if (system(buf) == 512) X ret_code++; X sleep(1); X } X return(ret_code); X#else /* UNIXPC */ X /* X * If you don't have one of these cute little routines, you X * might wanna write one. It should check for an existing lock X * file, edit the /etc/inittab file, and issue an init -q. X * The return code should tell if there was a getty or not. X * Obviously the program would be suid to root. X */ X return(0); X#endif /* UNIXPC */ X} X X/* X * Check the lock file for a valid pid value. Error conditions such X * as not being able to open the lock file or not being able to interpret X * the contents of the lock file cause the code to assume that the lock X * file is valid. Let the user worry about weird special cases. A X * non-zero return code means the lock is dead or doesn't exist. X */ X Xstatic int Xchecklock(lockfile) Xchar *lockfile; X{ X extern int errno; X int lfd, lckpid, n; X char buf[40]; X /* doesn't exist */ X if (access(lockfile, 0)) X return(1); X /* can't open the lock file */ X if ((lfd = open(lockfile, 0)) < 0) X return(0); X X#ifdef ASCII_PID X if ((n = read(lfd, buf, 40)) <= 0) { X close(lfd); X return(0); X } X close(lfd); X buf[n--] = '\0'; X lckpid = atoi(buf); X#else /* ASCII_PID */ X if (read(lfd, (char *) &lckpid, sizeof(int)) != sizeof(int)) { X close(lfd); X return(0); X } X close(lfd); X#endif /* ASCII_PID */ X /* invalid pid? */ X if (lckpid <= 0 || lckpid > MAX_PID) X return(0); X X if ((kill(lckpid, 0) == -1) && (errno == ESRCH)) { X /* X * If the kill was unsuccessful due to an ESRCH error, X * that means the process is no longer active and the X * lock file can be safely removed. X */ X unlink(lockfile); X sleep(1); X return(1); X } X /* X * If the kill() was successful, that means the process must X * still be active. X */ X return(0); X} X X/* X * Check to see if the desired baud rate can be handled by the modem. X * Uses the connect strings to make this determination. The first X * argument is the index into the TTY database. A non-zero return code X * means "yes it can". X */ X Xstatic int Xck_speed(tty, baud) Xint tty, baud; X{ X int i, mod; X char buf[60]; X /* find the modem database */ X mod = -1; X for (i=0; i<modem->m_entries; i++) { X if (!strcmp(modem->mname[i], modem->tname[tty])) { X mod = i; X break; X } X } X if (mod == -1) { X sprintf(buf, "Modem name \"%s\" in TTY database", modem->tname[tty]); X error_win(1, buf, "does not exist in modem database"); X } X X#ifdef DEBUG X fprintf(stderr, "ck_speed: checking modem \"%s\" for %d baud\n", modem->mname[mod], baud); X#endif /* DEBUG */ X X switch (baud) { X case 300: X if (*modem->con_3[mod] != '\0') X return(1); X break; X case 1200: X if (*modem->con_12[mod] != '\0') X return(1); X break; X case 2400: X if (*modem->con_24[mod] != '\0') X return(1); X break; X case 4800: X if (*modem->con_48[mod] != '\0') X return(1); X break; X case 9600: X if (*modem->con_96[mod] != '\0') X return(1); X break; X case 19200: X if (*modem->con_192[mod] != '\0') X return(1); X break; X } X return(0); X} X X/* X * Check to see if the script field is a valid device name. X */ X Xchk_script(script) Xchar *script; X{ X char buf[80], *strcpy(), *strcat(); X X if (*script == '\0') X return(0); X X strcpy(buf, "/dev/"); X strcat(buf, script); X X if (!access(buf, 0)) X return(1); X return(0); X} SHAR_EOF if test 10197 -ne "`wc -c < 'port.c'`" then echo shar: "error transmitting 'port.c'" '(should have been 10197 characters)' fi fi exit 0 # End of shell archive
egray@fthood.UUCP (02/05/89)
This is part 6 (of 8) to the Pcomm v1.2 distribution package. Emmet P. Gray US Army, HQ III Corps & Fort Hood ...!uunet!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: # redial.c # s_axfer.c # s_extrnl.c # s_gen.c # s_menu.c # s_modem.c # s_prompt.c # s_term.c # s_tty.c # screen.c # script.c # st_line.c # status.h # strings.c # This archive created: Fri Feb 3 07:35:32 1989 export PATH; PATH=/bin:/usr/bin:$PATH echo shar: "extracting 'redial.c'" '(2253 characters)' if test -f 'redial.c' then echo shar: "will not over-write existing file 'redial.c'" else sed 's/^X//' << \SHAR_EOF > 'redial.c' X/* X * The redial option (actually a misnomer, it's really a queuing system). X * We expect a space-separated list of dialing directory entries (although X * new users always try to put in a phone number). A non-zero return code X * means we're ready to dial. X */ X X#include <stdio.h> X#include <curses.h> X#include "config.h" X#include "dial_dir.h" X#include "misc.h" X Xint Xredial() X{ X extern int fd; X WINDOW *rd_win, *newwin(); X char *ans, *entry, *get_str(), *strchr(), *strtok(); X int i, oops, number, ret_code; X X rd_win = newwin(6, 70, 5, 5); X X mvwaddstr(rd_win, 4, 23, "(<CR> for previous numbers)"); X mvwaddstr(rd_win, 2, 4, "Directory Entry Number(s): "); X box(rd_win, VERT, HORZ); X X mvwattrstr(rd_win, 0, 3, A_BOLD, " Redial Queue "); X wmove(rd_win, 2, 31); X wrefresh(rd_win); X /* get the string of numbers */ X ret_code = 0; X while ((ans = get_str(rd_win, 35, "0123456789+-@# ", "")) != NULL) { X oops = 0; X if (*ans == '\0') { X /* use previous queue */ X if (dir->q_num[0] != -1) { X ret_code++; X break; X } X /* there is no previous queue */ X beep(); X mvwattrstr(rd_win, 3, 4, A_BOLD, "No previous numbers"); X wrefresh(rd_win); X wait_key(rd_win, 3); X clear_line(rd_win, 3, 4, TRUE); X wmove(rd_win, 2, 31); X wrefresh(rd_win); X continue; X } X /* parse the queue values */ X entry = strtok(ans, " \t"); X for (i=0; i<NUM_QUEUE; i++) { X if (*entry == '\0') { X dir->q_num[i] = -1; X continue; X } X /* is there a LD code? */ X dir->q_ld[i] = '\0'; 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, TRUE); X clear_line(rd_win, 2, 31, TRUE); 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, " \t"); X } X if (oops) X continue; X ret_code++; X break; X } X if (fd == -1) { X werase(rd_win); X wrefresh(rd_win); X } X delwin(rd_win); X return(ret_code); X} SHAR_EOF if test 2253 -ne "`wc -c < 'redial.c'`" then echo shar: "error transmitting 'redial.c'" '(should have been 2253 characters)' fi fi echo shar: "extracting 's_axfer.c'" '(3835 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 non-zero return X * code means something was changed. X */ X X#include <stdio.h> X#include <curses.h> X#include "config.h" X#include "misc.h" X#include "param.h" X Xint Xaxfer_setup() X{ X extern char *v_yes[]; X WINDOW *x_win, *newwin(); X int i, ret_code, num; X char *ans, *menu_prompt(), *str_rep(); X static char *v_cr[4] = {"NONE", "STRIP", "ADD LF", NULL}; X static char *v_lf[4] = {"NONE", "STRIP", "ADD CR", NULL}; X static char *v_delay[4] = {"0", "100", "150", NULL}; X X x_win = newwin(23, 80, 0, 0); X X horizontal(x_win, 0, 0, 28); X mvwattrstr(x_win, 0, 29, A_BOLD, "ASCII Transfer Setup"); X horizontal(x_win, 0, 50, 29); X mvwaddstr(x_win, 3, 33, "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 (sec) . %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 horizontal(x_win, 19, 0, 80); X mvwattrstr(x_win, 20, 0, A_BOLD, "OPTION ==> "); X mvwaddstr(x_win, 20, 58, "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 param->lecho = str_rep(param->lecho, 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 param->expand = str_rep(param->expand, 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 param->pace = str_rep(param->pace, 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 param->cr_up = str_rep(param->cr_up, 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 param->lf_up = str_rep(param->lf_up, ans); X ret_code++; X } X break; X case 7: X if ((num = num_prompt(x_win, 14, 50, "Transfer timeout", "(in seconds)")) != -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 param->cr_dn = str_rep(param->cr_dn, 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 param->lf_dn = str_rep(param->lf_dn, ans); X ret_code++; X } X break; X default: X beep(); X } X mvwaddch(x_win, 20, 12, (chtype) ' '); X clear_line(x_win, 21, 0, FALSE); X clear_line(x_win, 22, 0, FALSE); X wmove(x_win, 20, 12); X wrefresh(x_win); X } X delwin(x_win); X return(ret_code); X} SHAR_EOF if test 3835 -ne "`wc -c < 's_axfer.c'`" then echo shar: "error transmitting 's_axfer.c'" '(should have been 3835 characters)' fi fi echo shar: "extracting 's_extrnl.c'" '(4086 characters)' if test -f 's_extrnl.c' then echo shar: "will not over-write existing file 's_extrnl.c'" else sed 's/^X//' << \SHAR_EOF > 's_extrnl.c' X/* X * Display the external protocol setup, query for changes. A non-zero X * return code means something was changed. X */ X X#include <stdio.h> X#include <curses.h> X#include "config.h" X#include "extrnl.h" X#include "misc.h" X Xint Xext_setup() X{ X extern char *null_ptr; X WINDOW *ext_win, *newwin(); X int i, ret_code; X char *str, *get_str(); X void disp_ext(); X X ext_win = newwin(23, 80, 0, 0); X X horizontal(ext_win, 0, 0, 27); X mvwattrstr(ext_win, 0, 28, A_BOLD, "External Protocol Setup"); X horizontal(ext_win, 0, 52, 27); X mvwaddstr(ext_win, 3, 36, "UPLOAD"); X mvwaddstr(ext_win, 5, 8, "Name"); X mvwaddstr(ext_win, 5, 21, "Command line"); X mvwaddstr(ext_win, 5, 54, "Requires file list?"); X mvwaddstr(ext_win, 10, 35, "DOWNLOAD"); X mvwaddstr(ext_win, 12, 8, "Name"); X mvwaddstr(ext_win, 12, 21, "Command line"); X mvwaddstr(ext_win, 12, 54, "Requires file list?"); X /* display the current list */ X disp_ext(ext_win); X X horizontal(ext_win, 19, 0, 80); X mvwattrstr(ext_win, 20, 0, A_BOLD, "OPTION ==> "); X mvwaddstr(ext_win, 20, 58, "Press <ESC> to return"); X wmove(ext_win, 20, 12); X touchwin(ext_win); X wrefresh(ext_win); X /* get the option */ X ret_code = 0; X while ((str = get_str(ext_win, 1, "1234356", "")) != NULL) { X switch(*str) { X case '1': X if (ext_prompt(ext_win, 1, 0, 6)) X ret_code++; X break; X case '2': X if (ext_prompt(ext_win, 1, 1, 7)) X ret_code++; X break; X case '3': X if (ext_prompt(ext_win, 1, 2, 8)) X ret_code++; X break; X case '4': X if (ext_prompt(ext_win, 0, 0, 13)) X ret_code++; X break; X case '5': X if (ext_prompt(ext_win, 0, 1, 14)) X ret_code++; X break; X case '6': X if (ext_prompt(ext_win, 0, 2, 15)) X ret_code++; X break; X } X mvwaddstr(ext_win, 20, 12, " "); X clear_line(ext_win, 21, 0, FALSE); X clear_line(ext_win, 22, 0, FALSE); X wmove(ext_win, 20, 12); X wrefresh(ext_win); X } X /* X * Recalculate the number of entries. Please notice that if you X * create an empty entry (a hole), all entries after that are ignored. X * The software doesn't compact the holes out.. you're on your own. X */ X if (ret_code) { X for (i=0; i<3; i++) { X if (extrnl->name[1][i] == null_ptr) X break; X } X extrnl->up_entries = i; X X for (i=0; i<3; i++) { X if (extrnl->name[0][i] == null_ptr) X break; X } X extrnl->dn_entries = i; X } X delwin(ext_win); X return(ret_code); X} X X/* X * Display the current list of external file transfer programs. X */ X Xstatic void Xdisp_ext(win) XWINDOW *win; X{ X int i, up, entry, line; X X up = 1; X line = 6; X for (i=0; i<6; i++) { X if (i < 3) X entry = i; X else { X up = 0; X entry = i-3; X line = 10; X } X mvwprintw(win, i+line, 5, "%d) %-12.12s %-40.40s %c\n", X i+1, extrnl->name[up][entry], extrnl->command[up][entry], X extrnl->prompt[up][entry]); X } X return; X} X X/* X * Prompt for the info in the database. A non-zero return code means X * that something was changed. To delete the line, you enter a single X * space character at the first prompt. X */ X Xstatic int Xext_prompt(win, up, entry, line) XWINDOW *win; Xint up, entry, line; X{ X extern char *v_yn[], *null_ptr; X char *ans, t_name[80], t_command[80], *str_prompt(), *str_rep(); X char *strcpy(), *menu_prompt(); X X /* get temp name */ X if ((ans = str_prompt(win, line, 8, "Protocol name", "")) == NULL) X return(0); X X strcpy(t_name, ans); X clear_line(win, 21, 0, FALSE); X /* are we zapping the line */ X if (ans == null_ptr) { X extrnl->name[up][entry] = null_ptr; X extrnl->command[up][entry] = null_ptr; X extrnl->prompt[up][entry] = 'N'; X return(1); X } X /* get temp command */ X if ((ans = str_prompt(win, line, 21, "Command line", "")) == NULL) X return(0); X X strcpy(t_command, ans); X clear_line(win, 21, 0, FALSE); X X /* get temp prompt */ X if ((ans = menu_prompt(win, line, 63, "Does it require a file list", v_yn)) == NULL) X return(0); X X wrefresh(win); X /* store 'em for real */ X extrnl->name[up][entry] = str_rep(extrnl->name[up][entry], t_name); X extrnl->command[up][entry] = str_rep(extrnl->command[up][entry], t_command); X extrnl->prompt[up][entry] = *ans; X X return(1); X} SHAR_EOF if test 4086 -ne "`wc -c < 's_extrnl.c'`" then echo shar: "error transmitting 's_extrnl.c'" '(should have been 4086 characters)' fi fi echo shar: "extracting 's_gen.c'" '(4402 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 non-zero return code X * means something was changed. X */ X X#include <stdio.h> X#include <curses.h> X#include "config.h" X#include "misc.h" X#include "param.h" X Xint Xgen_setup() X{ X extern char *v_yes[]; X WINDOW *g_win, *newwin(); X int i, num, ret_code; X char c, *ans, *str_prompt(), *menu_prompt(), chr_prompt(); X char *str_rep(); X void line_set(); X static char *v_abort[3] = {"KEEP", "DELETE", NULL}; X X g_win = newwin(23, 80, 0, 0); X X horizontal(g_win, 0, 0, 32); X mvwattrstr(g_win, 0, 33, A_BOLD, "General Setup"); X horizontal(g_win, 0, 47, 32); 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, 12, 22, "8) Break character ........ %c", param->brk_char); X mvwprintw(g_win, 14, 22, "9) Aborted downloads ...... %s", param->abort); X mvwprintw(g_win, 16, 21, "10) Connect delay (sec) .... %d", param->c_delay); X mvwprintw(g_win, 17, 21, "11) Redial delay (sec) ..... %d", param->r_delay); X horizontal(g_win, 19, 0, 80); X mvwattrstr(g_win, 20, 0, A_BOLD, "OPTION ==> "); X mvwaddstr(g_win, 20, 58, "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) { X param->logfile = str_rep(param->logfile, ans); X ret_code++; X } X break; X case 2: X if ((ans = str_prompt(g_win, 4, 50, "Default screen dump file", "")) != NULL) { X param->dumpfile = str_rep(param->dumpfile, 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 param->strip = str_rep(param->strip, ans); X line_set(); X ret_code++; X } X break; X case 4: X if ((c = chr_prompt(g_win, 8, 50, "Pause character", "1 second")) != '\0') { 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)")) != '\0') { 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)")) != '\0') { 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)")) != '\0') { X param->esc_char = c; X ret_code++; X } X break; X case 8: X if ((c = chr_prompt(g_win, 12, 50, "Break character", "")) != '\0') { X param->brk_char = c; X ret_code++; X } X case 9: X if ((ans = menu_prompt(g_win, 14, 50, "Aborted downloads", v_abort)) != NULL) { X param->abort = str_rep(param->abort, ans); X ret_code++; X } X break; X case 10: X if ((num = num_prompt(g_win, 16, 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, 16, 50, " "); X wrefresh(g_win); X mvwattrnum(g_win, 16, 50, A_BOLD, num); X wrefresh(g_win); X } X param->c_delay = num; X ret_code++; X } X break; X case 11: X if ((num = num_prompt(g_win, 17, 50, "Redial delay time", "(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, 17, 50, " "); X wrefresh(g_win); X mvwattrnum(g_win, 17, 50, A_BOLD, num); X wrefresh(g_win); X } X param->r_delay = 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, FALSE); X clear_line(g_win, 22, 0, FALSE); X wmove(g_win, 20, 12); X wrefresh(g_win); X } X delwin(g_win); X return(ret_code); X} SHAR_EOF if test 4402 -ne "`wc -c < 's_gen.c'`" then echo shar: "error transmitting 's_gen.c'" '(should have been 4402 characters)' fi fi echo shar: "extracting 's_menu.c'" '(3200 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. A non-zero X * return code means we have to restart the input routine. X */ X X#include <stdio.h> X#include <curses.h> X#include "config.h" X#include "misc.h" X Xint Xsetup_menu() X{ X extern int fd, xmc; X WINDOW *s_win, *newwin(); X char *ans, *get_str(); X int param_flag, modem_flag, ext_flag, ret_code; X void top_line(); X X s_win = newwin(23, 80, 0, 0); X X top_line(s_win); X mvwaddstr(s_win, 3, 29, "1) TTY Setup"); X mvwaddstr(s_win, 5, 29, "2) Modem Setup"); X mvwaddstr(s_win, 7, 29, "3) Terminal Setup"); X mvwaddstr(s_win, 9, 29, "4) General Setup"); X mvwaddstr(s_win, 11, 29, "5) ASCII Transfer Setup"); X mvwaddstr(s_win, 13, 29, "6) External Protocol Setup"); X mvwaddstr(s_win, 15, 29, "S) Save setup to disk"); X horizontal(s_win, 19, 0, 80); X mvwattrstr(s_win, 20, 0, A_BOLD, "OPTION ==> "); X mvwaddstr(s_win, 20, 58, " Press <ESC> to exit"); X wmove(s_win, 20, 12); X touchwin(s_win); X wrefresh(s_win); X X param_flag = 0; X modem_flag = 0; X ext_flag = 0; X ret_code = 0; X /* get the options */ X while ((ans = get_str(s_win, 1, "123456Ss", "")) != NULL) { X if (xmc > 0) { X clear_line(s_win, 0, 0, FALSE); X wrefresh(s_win); X } X switch (*ans) { X case '1': X if (tty_setup()) X modem_flag++; X break; X case '2': X if (modem_setup()) X modem_flag++; X break; X case '3': X /* X * term_setup() returns a 1 if something was X * changed, and a 2 if the change requires X * the input routine to be restarted. X */ X if (ret_code = term_setup()) { X ret_code--; X param_flag++; X } X break; X case '4': X if (gen_setup()) X param_flag++; X break; X case '5': X if (axfer_setup()) X param_flag++; X break; X case '6': X if (ext_setup()) X ext_flag++; X break; X case 's': X case 'S': X if (xmc > 0) X top_line(s_win); X /* X * Writes to disk are not critical, since X * the changes are made in memory. X */ X if (param_flag) { X mvwattrstr(s_win, 22, 27, A_BLINK, "Updating Parameter File"); X wrefresh(s_win); X wait_key(s_win, 3); X if (up_param()) { X touchwin(s_win); X wrefresh(s_win); X } X } X if (modem_flag) { X mvwattrstr(s_win, 22, 27, A_BLINK, "Updating Modem Database"); X wrefresh(s_win); X wait_key(s_win, 3); X if (up_modem()) { X touchwin(s_win); X wrefresh(s_win); X } X } X if (ext_flag) { X mvwattrstr(s_win, 22, 25, A_BLINK, "Updating External Protocols"); X wrefresh(s_win); X wait_key(s_win, 3); X if (up_extrnl()) { X touchwin(s_win); X wrefresh(s_win); X } X } X clear_line(s_win, 22, 25, FALSE); X wrefresh(s_win); 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, (chtype) ' '); 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(ret_code); 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, FALSE); X wrefresh(win); X horizontal(win, 0, 0, 33); X mvwattrstr(win, 0, 34, A_BOLD, "Setup Menu"); X horizontal(win, 0, 45, 34); X wrefresh(win); X return; X} SHAR_EOF if test 3200 -ne "`wc -c < 's_menu.c'`" then echo shar: "error transmitting 's_menu.c'" '(should have been 3200 characters)' fi fi echo shar: "extracting 's_modem.c'" '(6656 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 non-zero return code X * means something was changed. X */ X X#include <stdio.h> X#include <curses.h> X#include "config.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, mod_prompt(); X char *ans, *str_rep(), *str_prompt(), *menu_prompt(); X void disp_modem(); X extern char *v_yn[]; 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 horizontal(mo_win, 0, 0, 33); X mvwattrstr(mo_win, 0, 34, A_BOLD, "Modem Setup"); X horizontal(mo_win, 0, 46, 34); X /* display the current settings */ X disp_modem(mo_win, j); X horizontal(mo_win, 19, 0, 80); X mvwattrstr(mo_win, 20, 0, A_BOLD, "OPTION ==> "); X mvwaddstr(mo_win, 20, 58, "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 = mod_prompt(mo_win); X break; X case 2: X if ((ans = str_prompt(mo_win, 3, 39, "Modem init string", "sent to the modem once")) != NULL) { X modem->init[j] = str_rep(modem->init[j], ans); X ret_code++; X } X break; X case 3: X if ((ans = str_prompt(mo_win, 4, 39, "Dialing command", "")) != NULL) { X modem->dial[j] = str_rep(modem->dial[j], ans); X ret_code++; X } X break; X case 4: X if ((ans = str_prompt(mo_win, 5, 39, "Dialing cmd suffix", "typically the <CR> character")) != NULL) { X modem->suffix[j] = str_rep(modem->suffix[j], ans); X ret_code++; X } X break; X case 5: X if ((ans = str_prompt(mo_win, 6, 39, "Hang up string", "")) != NULL) { X modem->hang_up[j] = str_rep(modem->hang_up[j], ans); X ret_code++; X } X break; X case 6: X if ((ans = menu_prompt(mo_win, 7, 39, "Auto Baud detect", v_yn)) != NULL) { X modem->auto_baud[j] = *ans; X ret_code++; X } X break; X case 7: X if ((ans = str_prompt(mo_win, 8, 39, "300 baud connect string", "")) != NULL) { X modem->con_3[j] = str_rep(modem->con_3[j], ans); X ret_code++; X } X break; X case 8: X if ((ans = str_prompt(mo_win, 9, 39, "1200 baud connect string", "")) != NULL) { X modem->con_12[j] = str_rep(modem->con_12[j], ans); X ret_code++; X } X break; X case 9: X if ((ans = str_prompt(mo_win, 10, 39, "2400 baud connect string", "")) != NULL) { X modem->con_24[j] = str_rep(modem->con_24[j], ans); X ret_code++; X } X break; X case 10: X if ((ans = str_prompt(mo_win, 11, 39, "4800 baud connect string", "")) != NULL) { X modem->con_48[j] = str_rep(modem->con_48[j], ans); X ret_code++; X } X break; X case 11: X if ((ans = str_prompt(mo_win, 12, 39, "9600 baud connect string", "")) != NULL) { X modem->con_96[j] = str_rep(modem->con_96[j], ans); X ret_code++; X } X break; X case 12: X if ((ans = str_prompt(mo_win, 13, 39, "19200 baud connect string", "")) != NULL) { X modem->con_192[j] = str_rep(modem->con_192[j], ans); X ret_code++; X } X break; X case 13: X if ((ans = str_prompt(mo_win, 14, 39, "No connect string 1", "")) != NULL) { X modem->no_con1[j] = str_rep(modem->no_con1[j], ans); X ret_code++; X } X break; X case 14: X if ((ans = str_prompt(mo_win, 15, 39, "No connect string 2", "")) != NULL) { X modem->no_con2[j] = str_rep(modem->no_con2[j], ans); X ret_code++; X } X break; X case 15: X if ((ans = str_prompt(mo_win, 16, 39, "No connect string 3", "")) != NULL) { X modem->no_con3[j] = str_rep(modem->no_con3[j], ans); X ret_code++; X } X break; X case 16: X if ((ans = str_prompt(mo_win, 17, 39, "No connect string 4", "")) != NULL) { X modem->no_con4[j] = str_rep(modem->no_con4[j], 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, FALSE); X clear_line(mo_win, 22, 0, FALSE); 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 Xstatic int Xmod_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] == '\0') X i = 0; X if (ans == ESC) 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, 39, FALSE); X wrefresh(win); X mvwattrstr(win, 2, 39, A_BOLD, modem->mname[i]); X mvwprintw(win, 2, 25, "(%d of %d) ", i+1, modem->m_entries); X X return(i); X} X X/* X * Show the current settings for the given modem entry number. X */ X Xstatic void Xdisp_modem(w, i) XWINDOW *w; Xint i; X{ X mvwprintw(w, 2, 11, "1) Modem name ............. %-39.39s", modem->mname[i]); X mvwprintw(w, 2, 25, "(%d of %d) ", i+1, modem->m_entries); X mvwprintw(w, 3, 11, "2) Modem init string ...... %-39.39s", modem->init[i]); X mvwprintw(w, 4, 11, "3) Dialing command ........ %-39.39s", modem->dial[i]); X mvwprintw(w, 5, 11, "4) Dialing cmd suffix ..... %-39.39s", modem->suffix[i]); X mvwprintw(w, 6, 11, "5) Hang up string ......... %-39.39s", modem->hang_up[i]); X mvwprintw(w, 7, 11, "6) Auto baud detect ....... %c", modem->auto_baud[i]); X mvwprintw(w, 8, 11, "7) 300 baud connect ....... %-39.39s", modem->con_3[i]); X mvwprintw(w, 9, 11, "8) 1200 baud connect ...... %-39.39s", modem->con_12[i]); X mvwprintw(w, 10, 11, "9) 2400 baud connect ...... %-39.39s", modem->con_24[i]); X mvwprintw(w, 11, 10, "10) 4800 baud connect ...... %-39.39s", modem->con_48[i]); X mvwprintw(w, 12, 10, "11) 9600 baud connect ...... %-39.39s", modem->con_96[i]); X mvwprintw(w, 13, 10, "12) 19200 baud connect ..... %-39.39s", modem->con_192[i]); X mvwprintw(w, 14, 10, "13) No connect string 1 .... %-39.39s", modem->no_con1[i]); X mvwprintw(w, 15, 10, "14) No connect string 2 .... %-39.39s", modem->no_con2[i]); X mvwprintw(w, 16, 10, "15) No connect string 3 .... %-39.39s", modem->no_con3[i]); X mvwprintw(w, 17, 10, "16) No connect string 4 .... %-39.39s", modem->no_con4[i]); X return; X} SHAR_EOF if test 6656 -ne "`wc -c < 's_modem.c'`" then echo shar: "error transmitting 's_modem.c'" '(should have been 6656 characters)' fi fi echo shar: "extracting 's_prompt.c'" '(3089 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 "config.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. Since X * it uses get_str(), the return value points to a static area. X */ X Xchar * Xstr_prompt(win, y, x, p1, p2) XWINDOW *win; Xint y, x; Xchar *p1, *p2; X{ X extern char *null_ptr; 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, 80, "", "\n")) == 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, FALSE); 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, "", "\n")) == NULL) X return('\0'); 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; 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_yn[3] = {"Y", "N", 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 == ESC) 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, FALSE); X wattrstr(win, A_BOLD, menu[i]); X /* return the value */ X return(menu[i]); X} SHAR_EOF if test 3089 -ne "`wc -c < 's_prompt.c'`" then echo shar: "error transmitting 's_prompt.c'" '(should have been 3089 characters)' fi fi echo shar: "extracting 's_term.c'" '(3046 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, 2 means we have to kill and restart X * the input routine. X */ X X#include <stdio.h> X#include <curses.h> X#include "config.h" X#include "misc.h" X#include "param.h" X#include "status.h" X Xint Xterm_setup() X{ X WINDOW *t_win, *newwin(); X int i, num, ret_code; X char *ans, *str_rep(), *str_prompt(), *menu_prompt(); X void input_off(), line_set(); X static char *v_crio[3] = {"CR", "CR/LF", NULL}; X static char *v_duplex[3] = {"FULL", "HALF", NULL}; X static char *v_flow[3] = {"NONE", "XON/XOFF", NULL}; X X t_win = newwin(23, 80, 0, 0); X X horizontal(t_win, 0, 0, 32); X mvwattrstr(t_win, 0, 33, A_BOLD, "Terminal Setup"); X horizontal(t_win, 0, 48, 32); X mvwprintw(t_win, 4, 22, "1) Hot key (decimal) ...... %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 horizontal(t_win, 19, 0, 80); X mvwattrstr(t_win, 20, 0, A_BOLD, "OPTION ==> "); X mvwaddstr(t_win, 20, 58, "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 param->ascii_hot = str_rep(param->ascii_hot, 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 param->d_duplex = str_rep(param->d_duplex, 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 param->flow = str_rep(param->flow, ans); X line_set(); 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 X /* X * the "add lf to cr" function is X * performed by the input routine X */ X param->cr_in = str_rep(param->cr_in, ans); X status->add_lf = !strcmp(ans, "CR/LF"); X#ifdef SHAREDMEM X ret_code = 1; X#else /* SHAREDMEM */ X input_off(); X ret_code = 2; X#endif /* SHAREDMEM */ X } X break; X case 6: X if ((ans = menu_prompt(t_win, 15, 50, "CR translation (out)", v_crio)) != NULL) { X param->cr_out = str_rep(param->cr_out, ans); X ret_code = 1; X } X break; X default: X beep(); X } X mvwaddch(t_win, 20, 12, (chtype) ' '); X clear_line(t_win, 21, 0, FALSE); X clear_line(t_win, 22, 0, FALSE); X wmove(t_win, 20, 12); X wrefresh(t_win); X } X delwin(t_win); X return(ret_code); X} SHAR_EOF if test 3046 -ne "`wc -c < 's_term.c'`" then echo shar: "error transmitting 's_term.c'" '(should have been 3046 characters)' fi fi echo shar: "extracting 's_tty.c'" '(4903 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 non-zero return code X * means something was changed. X */ X X#include <stdio.h> X#include <curses.h> X#include "config.h" X#include "misc.h" X#include "modem.h" X Xint Xtty_setup() X{ X WINDOW *tt_win, *newwin(); X char message[80], *str, *get_str(); X int num, i, j, ret_code; X void disp_tty(), create_modem(), del_modem(), error_win(); X void del_tty(); X X tt_win = newwin(23, 80, 0, 0); X X horizontal(tt_win, 0, 0, 34); X mvwattrstr(tt_win, 0, 35, A_BOLD, "TTY Setup"); X horizontal(tt_win, 0, 45, 34); X mvwaddstr(tt_win, 2, 22, "TTY name"); X mvwaddstr(tt_win, 2, 37, "Modem name"); X mvwaddstr(tt_win, 2, 51, "Init speed"); X /* display the current TTY list */ X disp_tty(tt_win); X /* prompt for options */ X mvwaddstr(tt_win, 15, 20, "A) Add a TTY entry"); X mvwaddstr(tt_win, 16, 20, "D) Delete a TTY entry"); X horizontal(tt_win, 19, 0, 80); X mvwattrstr(tt_win, 20, 0, A_BOLD, "OPTION ==> "); X mvwaddstr(tt_win, 20, 58, "Press <ESC> to return"); X wmove(tt_win, 20, 12); X touchwin(tt_win); X wrefresh(tt_win); X /* get the option */ X ret_code = 0; X while ((str = get_str(tt_win, 2, "01234356789AaDd", "")) != NULL) { X switch(*str) { X case '0': X case '1': X case '2': X case '3': X case '4': X case '5': X case '6': X case '7': X case '8': X case '9': X i = atoi(str); X /* if beyond t_entries */ X if (i > modem->t_entries) { X beep(); X break; X } X X /* change the entry */ X if (tty_prompt(tt_win, i-1)) { X X /* requires modem update? */ X create_modem(modem->tname[i-1]); X del_modem(); X ret_code++; X } X break; X case 'a': X case 'A': /* add an entry */ X if (modem->t_entries == NUM_TTY) { X sprintf(message, "\"%s\"", modem->m_path); X error_win(0, "No empty TTY slots in modem/TTY database", message); X break; X } X /* prompt for info */ X j = modem->t_entries; X if (tty_prompt(tt_win, j)) { X X /* add modem entry? */ X modem->t_entries++; X create_modem(modem->tname[j]); X ret_code++; X } X break; X case 'd': X case 'D': /* delete an entry */ 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 wmove(tt_win, 21, 24); X wrefresh(tt_win); X continue; X } X del_tty(num-1); X del_modem(); X X /* show the new list */ X disp_tty(tt_win); X ret_code++; X break; X } X break; X default: X beep(); X break; X } X mvwaddstr(tt_win, 20, 12, " "); X clear_line(tt_win, 21, 0, FALSE); X clear_line(tt_win, 22, 0, FALSE); 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 Xstatic void 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->init_sp[i]); X return; X} X X/* X * Prompt the user for the TTY database info. A non-zero return code means X * something was changed. The second argument is the zero based index. X */ X Xstatic int Xtty_prompt(win, i) XWINDOW *win; Xint i; X{ X char *ans, t_tty[80], t_tname[80], *str_prompt(), *menu_prompt(); X char *str_rep(), *strcpy(); X static char *v_baud[8] = {"0", "300", "1200", "2400", "4800", "9600", X "19200", NULL}; X /* get temp TTY */ X if ((ans = str_prompt(win, i+4, 24, "TTY name", "")) == NULL) X return(0); X X strcpy(t_tty, ans); X clear_line(win, 21, 0, FALSE); X X /* get temp tname */ X if ((ans = str_prompt(win, i+4, 39, "Modem name", "")) == NULL) X return(0); X X strcpy(t_tname, ans); X clear_line(win, 21, 0, FALSE); X X /* get maximum baud */ X if ((ans = menu_prompt(win, i+4, 55, "Init speed", v_baud)) == NULL) X return(0); X X wrefresh(win); X /* store 'em for real */ X modem->tty[i] = str_rep(modem->tty[i], t_tty); X modem->tname[i] = str_rep(modem->tname[i], t_tname); X modem->init_sp[i] = atoi(ans); X X return(1); 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 Xstatic void Xdel_tty(i) Xint i; X{ X extern char *null_ptr; X int j; X char *str_rep(); X void free_ptr(); X /* collapse the list */ X for (j=i; j<modem->t_entries-1; j++) { X modem->tty[j] = str_rep(modem->tty[j], modem->tty[j+1]); X modem->tname[j] = str_rep(modem->tname[j], modem->tname[j+1]); X modem->init_sp[j] = modem->init_sp[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->init_sp[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 4903 -ne "`wc -c < 's_tty.c'`" then echo shar: "error transmitting 's_tty.c'" '(should have been 4903 characters)' fi fi echo shar: "extracting 'screen.c'" '(2024 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#include <stdio.h> X#include <curses.h> X#include "config.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, *my_fopen(); X char buf[MAX_COL]; X void error_win(); X int i; X /* open for append */ X if (!(fp_out = my_fopen(param->dumpfile, "a"))) { X sprintf(buf, "\"%s\" for write", param->dumpfile); X error_win(0, "Can't open screen dump file", buf); X return; X } X#ifdef SHAREDMEM X for (i=0; i<LINES; i++) X fprintf(fp_out, "%s\n", status->vs[i]); X X#else /* SHAREDMEM */ X /* not guaranteed to exist yet */ X if (!(fp_in = my_fopen(status->vs_path, "r"))) { X fclose(fp_in); X return; X } X /* skip the x, y coordinates */ X fgets(buf, 10, fp_in); X X while (fgets(buf, MAX_COL, fp_in) != NULL) X fputs(buf, fp_out); X X fclose(fp_in); X#endif /* SHAREDMEM */ X X fclose(fp_out); X X return; X} X X/* X * Read the virtual screen and paint its contents to the stdscr using X * curses(3). Move the cursor where it belongs. X */ X Xvoid Xload_vs() X{ X register int i; X FILE *fp, *my_fopen(); X int row, col, max_col; X char buf[MAX_COL]; X X clearok(curscr, TRUE); X erase(); X X#ifdef SHAREDMEM X for (i=0; i<LINES; i++) X mvaddstr(i, 0, status->vs[i]); X X move(status->row, status->col); X#else /* SHAREDMEM */ X /* not guaranteed to exist yet */ X if (!(fp = my_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 i = 0; X max_col = (COLS > MAX_COL-1) ? MAX_COL-1 : COLS; X while (fgets(buf, MAX_COL, fp) != NULL) { X /* zap the line feed */ X buf[max_col] = '\0'; X mvaddstr(i++, 0, buf); X } X fclose(fp); X move(row, col); X#endif /* SHAREDMEM */ X X refresh(); X return; X} X X/* X * Zap the virtual screen file (or clear it). X */ X Xvoid Xzap_vs() X{ X#ifdef SHAREDMEM X status->clr = 1; X#else /* SHAREDMEM */ X unlink(status->vs_path); X#endif /* SHAREDMEM */ X return; X} SHAR_EOF if test 2024 -ne "`wc -c < 'screen.c'`" then echo shar: "error transmitting 'screen.c'" '(should have been 2024 characters)' fi fi echo shar: "extracting 'script.c'" '(3790 characters)' if test -f 'script.c' then echo shar: "will not over-write existing file 'script.c'" else sed 's/^X//' << \SHAR_EOF > 'script.c' X/* X * Spawn a shell with file descriptors that look like this: X * X * +---------+ X * TTYin ---> | input | ---> screen (& virtual screen) X * | program | X * +---------+ X * | +---------+ X * pipe ----------> stdin | | X * | shell | X * TTYout <---------------------- stdout | | X * +---------+ X * X * The input program has a routine that duplicates the TTYin and sends it X * down a pipe. The other end of the pipe is the stdin to the shell script. X * This allows the characters to appear on the screen *and* be interpreted X * by the shell script. X */ X X#include <stdio.h> X#include <signal.h> X#include <curses.h> X#include <errno.h> X#include "config.h" X#include "dial_dir.h" X#include "status.h" X X#ifdef BSD X#include <sys/file.h> X#else /* BSD */ X#include <fcntl.h> X#endif /* BSD */ X Xvoid Xdo_script(extra) Xchar *extra; X{ X extern int fd, errno; X SIG_TYPE (*istat)(), (*qstat)(); X int epid, dup_pipe[2], want_out, sig_status; X char buf[80], *ttyname(), *strcpy(), *path, *findfile(); X void _exit(), error_win(), input_off(), do_input(); X unsigned int sleep(); X X /* if empty */ X if (*dir->script[dir->d_cur] == '\0') X return; X /* if a device */ X if (chk_script(dir->script[dir->d_cur])) X return; X /* find the script file */ X if ((path = findfile(extra, dir->script[dir->d_cur])) == NULL) { X sprintf(buf, "Can't locate script \"%s\"", dir->script[dir->d_cur]); X error_win(0, buf, ""); X return; X } X /* execute permission ? */ X if (access(path, 1)) { X sprintf(buf, "\"%s\"", path); X error_win(0, "No execute permission on script file", buf); X return; X } X /* create a fd for duplicating input */ X if (pipe(dup_pipe) < 0) X return; X X status->dup_fd = dup_pipe[1]; X /* start input duplication */ X do_input(); X X if (!(epid = fork())) { X /* create a new process group ID */ X#ifdef BSD X setpgrp(0, getpid()); X#else /* BSD */ X setpgrp(); X#endif /* BSD */ X /* recreate the device name */ X strcpy(buf, ttyname(fd)); X close(fd); X /* swap the stdin */ X close(0); X dup(dup_pipe[0]); X /* swap the stdout */ X close(1); X#ifdef UNIXPC X/* X * Some strange things here... The OBM uses the second parameter of X * open() to determine if the the port should be in the DATA mode or X * the VOICE mode. Therefore, we must always open with read and write. X */ X if (!strncmp(buf, "/dev/ph", 7)) X open(buf, O_RDWR); X else X#endif /* UNIXPC */ X X open(buf, O_WRONLY); X#ifdef SETUGID X setgid(getgid()); X setuid(getuid()); X#endif /* SETUGID */ X X execl("/bin/sh", "sh", "-c", path, (char *) 0); X _exit(1); X } X istat = signal(SIGINT, SIG_IGN); X qstat = signal(SIGQUIT, SIG_IGN); X X /* X * Check the keyboard while the script is being "played". If the X * user hits the <ESC> key, then kill the entire process group X * associated with the new shell. X */ X want_out = 0; X while(1) { X switch(wait_key(stdscr, 1)) { X case -1: /* timed out */ X break; X case 27: /* a user abort */ X#ifdef BSD X killpg(epid, SIGKILL); X#else /* BSD */ X kill(-epid, SIGKILL); X#endif /* BSD */ X want_out++; X break; X default: X beep(); X break; X } X if (want_out) X break; X /* see if the process it still active */ X#ifdef BSD X if ((kill(epid, 0) == -1) && errno == ESRCH) X#else /* BSD */ X if ((kill(-epid, 0) == -1) && errno == ESRCH) X#endif /* BSD */ X break; X } X /* wait for the zombie process */ X wait(&sig_status); X X signal(SIGINT, istat); X signal(SIGQUIT, qstat); X /* shut down the duplication of input */ X status->dup_fd = -1; X X#ifndef SHAREDMEM X input_off(); X#endif /* SHAREDMEM */ X X close(dup_pipe[0]); X close(dup_pipe[1]); X sleep(1); X beep(); X return; X} SHAR_EOF if test 3790 -ne "`wc -c < 'script.c'`" then echo shar: "error transmitting 'script.c'" '(should have been 3790 characters)' fi fi echo shar: "extracting 'st_line.c'" '(2103 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 "config.h" X#include "dial_dir.h" X#include "misc.h" X#include "modem.h" X#include "param.h" X#include "status.h" X Xvoid Xst_line(message) Xchar *message; X{ X extern int xmc; 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 X /* is anybody missing? */ X if (dir == NULL || modem == NULL || param == NULL) X return; X /* remember where we parked the car.. */ X getyx(stdscr, y, x); 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++; 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 == '\0') X sprintf(field_one, " %4.4s-0 HELP ", param->ascii_hot); X else X sprintf(field_one, " %-13.13s", message); X X#ifdef XMC_BROKE X if (xmc > 0) 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 else X#endif /* XMC_BROKE */ 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 2103 -ne "`wc -c < 'st_line.c'`" then echo shar: "error transmitting 'st_line.c'" '(should have been 2103 characters)' fi fi echo shar: "extracting 'status.h'" '(808 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 status flags, and other various changeable things. Obviously X * the "config.h" file must appear before this file. X */ X X#define MAX_ROW 64 X#define MAX_COL 133 X#define PATH 128 X Xstruct STATUS { X int fd; /* file descriptor for TTY */ X int dup_fd; /* for duplicating input */ X int add_lf; /* add <CR> to <LF>? */ X int log; /* status of log option */ X int print; /* status of print option */ X char log_path[PATH]; /* data logging file */ X#ifdef SHAREDMEM X int clr; /* flag to clear the screen */ X int row; /* cursor row position */ X int col; /* cursor column position */ X char vs[MAX_ROW][MAX_COL]; /* the virtual screen */ X#else /* SHAREDMEM */ X char vs_path[PATH]; /* virtual screen file */ X#endif /* SHAREDMEM */ X}; X X#ifndef MAIN Xextern struct STATUS *status; X#endif /* MAIN */ SHAR_EOF if test 808 -ne "`wc -c < 'status.h'`" then echo shar: "error transmitting 'status.h'" '(should have been 808 characters)' fi fi echo shar: "extracting 'strings.c'" '(4200 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#define STRSTR X X#include <stdio.h> X#include "config.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 X * memory first. X */ X Xchar * Xstr_dup(str) Xchar *str; X{ X extern char *null_ptr; X char *ret, *malloc(), *strcpy(); X void error_win(); X X if (str == NULL) X return(NULL); X /* if pointer to null */ X if (*str == '\0') X return(null_ptr); X X if (!(ret = malloc((unsigned int) strlen(str)+1))) X error_win(1, "Out of memory", ""); X 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 && str != null_ptr) X free(str); X return; X} X X/* X * Replace a string. Follows the same convention as str_dup(), except X * that realloc() is used instead of malloc(). Returns a pointer to X * the new string (which may have moved). X */ X Xchar * Xstr_rep(s1, s2) Xchar *s1, *s2; X{ X extern char *null_ptr; X void free_ptr(), error_win(); X char *s, *malloc(), *realloc(), *strcpy(); X X /* copy null pointer ? */ X if (s2 == NULL) { X free_ptr(s1); X return(NULL); X } X if (s2 == '\0') { X free_ptr(s1); X return(null_ptr); X } X /* use realloc()? */ X if (s1 == NULL || s1 == null_ptr) { X if (!(s = malloc((unsigned int) strlen(s2)+1))) X error_win(1, "Out of memory", ""); X } X else { X if (!(s = realloc(s1, (unsigned int) strlen(s2)+1))) X error_win(1, "Out of memory", ""); X } X X strcpy(s, s2); X return(s); X} X X/* X * This routine is similar to strtok(3). But this version handles missing X * tokens by returning a pointer to null. Also it takes a single separator X * character as an argument. 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 /* start at beginning */ X if (str != NULL) X ptr = str; X else X ptr = sep; X /* at the end? */ X if (*ptr == '\0') X return(NULL); X /* no separator? */ X if (!(sep = strchr(ptr, c))) X return(NULL); X /* zap the sep, move past it */ X *sep = '\0'; X sep++; X X return(ptr); X} X X#ifdef STRSTR X/* X * Return a pointer to the first occurance of string str2 in str1. X * Returns a NULL if str2 is not in str1. X */ X Xchar * Xstrstr(str1, str2) Xchar *str1, *str2; X{ X int len; X X len = strlen(str2); X while (*str1) { X if (*str2 == *str1) { X if (!strncmp(str2, str1, len)) X return(str1); X } X str1++; X } X return(NULL); X} X#endif /* STRSTR */ X X#ifdef BSD X/* X * Returns the length of the initial segment of string which consists X * entirely of characters from charset. X */ X Xint Xstrspn(string, charset) Xchar *string; Xregister char *charset; X{ X register char *p, *q; X X for(q=string; *q != '\0'; ++q) { X for(p=charset; *p != '\0' && *p != *q; ++p) X ; X if(*p == '\0') X break; X } X return(q-string); X} X X/* X * Strtok considers string to consist of a sequence of zero or more X * text tokens separated by spans of one or more characters from sepset. X */ X Xchar * Xstrtok(string, sepset) Xchar *string, *sepset; X{ X register char *p, *q, *r; X static char *savept; X char *strpbrk(); X X /*first or subsequent call*/ X p = (string == NULL)? savept: string; X X if(p == 0) /* return if no tokens remaining */ X return(NULL); X X q = p + strspn(p, sepset); /* skip leading separators */ X X if(*q == '\0') /* return if no tokens remaining */ X return(NULL); X X if((r = strpbrk(q, sepset)) == NULL) /* move past token */ X savept = 0; /* indicate this is last token */ X else { X *r = '\0'; X savept = ++r; X } X return(q); X} X X/* X * Return ptr to first occurrence of any character from `brkset' X * in the character string `string'; NULL if none exists. X */ X Xchar * Xstrpbrk(string, brkset) Xregister char *string, *brkset; X{ X register char *p; X X if(!string || !brkset) X return(0); X do { X for(p=brkset; *p != '\0' && *p != *string; ++p) X ; X if(*p != '\0') X return(string); X } X while(*string++); X return(0); X} X X/* X * Copies the character c, n times to string s X */ X Xchar * Xmemset(s, c, n) Xchar *s, c; Xint n; X{ X char *s1 = s; X X while (n > 0) { X --n; X *s++ = c; X } X return(s1); X} X#endif /* BSD */ SHAR_EOF if test 4200 -ne "`wc -c < 'strings.c'`" then echo shar: "error transmitting 'strings.c'" '(should have been 4200 characters)' fi fi exit 0 # End of shell archive
egray@fthood.UUCP (02/05/89)
This is part 7 (of 8) to the Pcomm v1.2 distribution package. Emmet P. Gray US Army, HQ III Corps & Fort Hood ...!uunet!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: # terminal.c # tty_att.c # tty_ucb.c # vcs.c # vcs.h # waitfor.c # x_ascii.c # x_batch.c # x_extrnl.c # This archive created: Fri Feb 3 07:35:35 1989 export PATH; PATH=/bin:/usr/bin:$PATH echo shar: "extracting 'terminal.c'" '(9863 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#include "config.h" X#include "dial_dir.h" X#include "misc.h" X#include "modem.h" X#include "param.h" X#include "status.h" X#include "xmodem.h" X X#ifdef UNIXPC X#include <sys/phone.h> X#include <fcntl.h> X#endif /* UNIXPC */ X Xstatic int pid = -1; X Xterminal(extra_dir, input_status) Xchar *extra_dir; Xint input_status; X{ X extern int fd; X int i, j, k, cr_lf, script; X char c, lf=10, *str_rep(), *keymac, *memset(); X void help_screen(), line_set(), n_shell(), load_vs(), send_str(); X void release_port(), do_input(), list_dir(), pexit(), zap_vs(); X void st_line(), chg_dir(), screen_dump(), input_off(), suspend(); X void info(), term_mode(), macro(), do_script(); X X /* if starting out in command mode */ X if (!input_status) { X erase(); X refresh(); X st_line(""); X } X /* put stdin/stdout in terminal mode */ X resetterm(); X term_mode(); X cr_lf = !strcmp(param->cr_out, "CR/LF"); X X if (input_status) { X do_script(extra_dir); X do_input(); X } X X while (1) { X read(0, &c, 1); X c &= 0x7f; X /* is it the hot key? */ X if (c == param->hot) { X /* suspend input */ X input_status = 0; X suspend(TRUE); X script = 0; X X /* X * Put the terminal in the curses mode, load the X * virtual screen and add the status line at the bottom. X */ X fixterm(); X load_vs(); X st_line(""); X#ifndef OLDCURSES X keypad(stdscr, TRUE); X#endif /* OLDCURSES */ X i = wgetch(stdscr); X /* map an additional hot key to -1 */ X if (i == param->hot) X i = -1; X X keymac = ""; X /* look for options */ X k = -1; X switch (i) { X case -1: /* 2 "hots" means send 1 */ X k = param->hot; X break; X case '0': /* help screen */ X help_screen(param->ascii_hot); X break; X case 'd': X case 'D': /* dialing directory */ X if (dial_menu()) X input_status = dial_win(); X script = input_status; X break; X case 'r': X case 'R': /* redial */ X if (redial()) X input_status = dial_win(); X script = input_status; X break; X case 'm': X case 'M': /* keyboard macros */ X macro(); X break; X case 'p': X case 'P': /* line settings */ X if (ls_menu()) X line_set(); X break; X case 'x': X case 'X': /* exit */ X pexit(); X break; X case '4': /* Unix gateway */ X n_shell(); X break; X case 'i': X case 'I': /* program info screen */ X info(MANUAL_CLEAR); X break; X case 's': /* setup menu */ X case 'S': X input_status = setup_menu(); X break; X case 'c': /* clear the screen */ X case 'C': X zap_vs(); X erase(); X#ifdef SHAREDMEM X if (pid == -1) { X for (j=0; j<LINES; j++) X memset(status->vs[j], ' ', COLS); X } X#endif /* SHAREDMEM */ X break; X case 'b': X case 'B': /* change directory */ X chg_dir(); X break; X case 'e': X case 'E': /* toggle duplex */ X if (dir->duplex[dir->d_cur] == 'F') X dir->duplex[dir->d_cur] = 'H'; X else X dir->duplex[dir->d_cur] = 'F'; X X /* show changes */ X st_line(""); X k = wait_key(stdscr, 2); X break; X case 'h': X case 'H': /* hang up phone */ X release_port(VERBOSE); X input_off(); X break; X case 'l': X case 'L': /* toggle printer */ X status->print = status->print ? 0 : 1; X#ifndef SHAREDMEM X if (pid != -1) X kill(pid, SIGUSR2); X#endif /* SHAREDMEM */ X /* show changes */ X st_line(""); X k = wait_key(stdscr, 2); X break; X case '3': /* toggle CR - CR/LF */ X if (!strcmp(param->cr_in, "CR")) { X param->cr_in = str_rep(param->cr_in, "CR/LF"); X status->add_lf = 1; X } X else { X param->cr_in = str_rep(param->cr_in, "CR"); X status->add_lf = 0; X } X#ifndef SHAREDMEM X input_off(); X input_status++; X#endif /* SHAREDMEM */ X /* show changes */ X st_line(""); X k = wait_key(stdscr, 2); X break; X case '7': /* break key */ X if (fd != -1) X tty_break(fd); X X st_line(" break"); X break; X#ifndef OLDCURSES X case KEY_UP: X#endif /* OLDCURSES */ X case 'u': X case 'U': /* send files */ X input_status = xfer_menu(UP_LOAD); X break; X#ifndef OLDCURSES X case KEY_DOWN: X case '\n': X#endif /* OLDCURSES */ X case 'n': X case 'N': /* receive files */ X input_status = xfer_menu(DOWN_LOAD); X break; X case 't': X case 'T': X input_status = pass_thru(); X break; X case 'f': X case 'F': /* list directory */ X list_dir(); X break; X case 'g': /* screen dump */ X case 'G': X screen_dump(); X st_line(" screen dump"); X k = wait_key(stdscr, 2); X break; X case '1': /* data logging */ X input_status = data_logging(); X break; X case '2': /* toggle log */ X if (!strcmp(status->log_path, "NOT_DEFINED")) { X beep(); X st_line(" no log file"); X k = wait_key(stdscr, 2); X break; X } X status->log = status->log ? 0 : 1; X#ifndef SHAREDMEM X if (pid != -1) X kill(pid, SIGUSR1); X#endif /* SHAREDMEM */ X /* show changes */ X st_line(""); X k = wait_key(stdscr, 2); X break; X /* X * The following are the keyboard macros X * corresponding to the shifted number keys. X * (Too many keys... [control] [A] [shift] [1] X * is hardly a shortcut!) X */ X case '!': X keymac = param->mac_1; X break; X case '@': X keymac = param->mac_2; X break; X case '#': X keymac = param->mac_3; X break; X case '$': X keymac = param->mac_4; X break; X case '%': X keymac = param->mac_5; X break; X case '^': X keymac = param->mac_6; X break; X case '&': X keymac = param->mac_7; X break; X case '*': X keymac = param->mac_8; X break; X case '(': X keymac = param->mac_9; X break; X case ')': X keymac = param->mac_0; X break; X default: X fputc(BEL, stderr); X break; X } X X /* X * Repaint the stdscr (if we are already talking), X * get the stdin/stdout out of the curses mode and X * into the terminal mode. X */ X if (fd != -1) { X touchwin(stdscr); X refresh(); X } X resetterm(); X term_mode(); X X /* X * Some of the output processing options have to be X * faked... Unfortunately, adding a LF to CR on X * output is one of them. X */ X cr_lf = !strcmp(param->cr_out, "CR/LF"); X X /* run the auto-login script */ X if (script) X do_script(extra_dir); X X /* re-start input routine */ X if (input_status) X do_input(); X else X suspend(FALSE); X X /* send the macro */ X if (*keymac != '\0') X send_str(keymac, FAST); 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 /* ignore errors if fd == -1 */ X write(fd, &c, 1); X /* map cr to cr_lf? */ X if (c == '\r' && cr_lf) X write(fd, &lf, 1); X } X} X X/* X * Fire up the input routine... X */ X Xvoid Xdo_input() X{ X extern int fd; X void error_win(); X char first[(sizeof(int)*8)+1]; X#ifdef SHAREDMEM X extern int shm_id; X#else /* SHAREDMEM */ X char add_lf[2], log[2], print[2], dup_fd[3]; X#endif /* SHAREDMEM */ X /* if no TTY, or already on */ X if (pid != -1 || fd == -1) X return; X X status->fd = fd; X status->add_lf = !strcmp(param->cr_in, "CR/LF"); X X#ifdef SHAREDMEM X sprintf(first, "%d", shm_id); X#else /* SHAREDMEM */ X sprintf(first, "%d", status->fd); X sprintf(dup_fd, "%d", status->dup_fd); X sprintf(add_lf, "%d", status->add_lf); X sprintf(log, "%d", status->log); X sprintf(print, "%d", status->print); X#endif /* SHAREDMEM */ X X /* fork the input routine */ X if (!(pid = fork())) { X#ifdef BSD X setpgrp(0, getpid()); X#else /* BSD */ X setpgrp(); X#endif /* BSD */ X X#ifdef SETUGID X setuid(getuid()); X setgid(getgid()); X#endif /* SETUGID */ X X#ifdef SHAREDMEM X execlp("pcomm_input", "pcomm_input", first, (char *) 0); X#else /* SHAREDMEM */ X execlp("pcomm_input", "pcomm_input", first, dup_fd, add_lf, X log, print, status->log_path, status->vs_path, (char *) 0); X#endif /* SHAREDMEM */ X error_win(1, "Cannot find (or execute) the 'pcomm_input' program", ""); X } X X return; X} X X/* X * shut it down... X */ X Xvoid Xinput_off() X{ X if (pid != -1) { X kill(pid, SIGTERM); X pid = -1; X } X return; X} X X/* X * Hang up the phone but remain in the Pcomm command state. Uses the X * hang_up string only, does *not* drop the DTR! X */ X Xvoid Xhang_up(verbose) Xint verbose; X{ X extern int fd; X void send_str(), st_line(), line_set(); X char buf[80], *strcpy(), *ttyname(); X /* sanity checking */ X if (modem == NULL) X return; X /* anything to hang up? */ X if (modem->m_cur == -1 || fd == -1) X return; X X if (verbose) X st_line("disconnecting"); X /* special case for OBM */ X#ifdef UNIXPC X if (!strcmp(modem->mname[modem->m_cur], "OBM")) { X ioctl(fd, PIOCDISC); X /* X * The PIOCDISC ioctl screws up the file descriptor!!! X * No other phone(7) ioctl can fix it. Whatever it does, X * it seems to escape detection with PIOCGETA and TCGETA. X * The best I can do is close the port and start over. X */ X strcpy(buf, ttyname(fd)); X close(fd); X fd = open(buf, O_RDWR|O_NDELAY); X line_set(); X fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NDELAY); X } X else X#endif /* UNIXPC */ X send_str(modem->hang_up[modem->m_cur], SLOW); X X if (verbose) X st_line(""); X return; X} X X/* X * Suspend or un-suspend the input routine. The argument is used in X * non-shared memory configurations to give the vs_path file a fighting X * chance of being written to disk before load_vs() reads it. X */ X X/* ARGSUSED */ Xvoid Xsuspend(on) Xint on; X{ X unsigned int sleep(); X X if (pid == -1) X return; X kill(pid, SIGINT); X X#ifndef SHAREDMEM X if (on) X sleep(1); X#endif /* SHAREDMEM */ X X return; X} SHAR_EOF if test 9863 -ne "`wc -c < 'terminal.c'`" then echo shar: "error transmitting 'terminal.c'" '(should have been 9863 characters)' fi fi echo shar: "extracting 'tty_att.c'" '(4795 characters)' if test -f 'tty_att.c' then echo shar: "will not over-write existing file 'tty_att.c'" else sed 's/^X//' << \SHAR_EOF > 'tty_att.c' X/* X * System V specific routines for manipulating the TTY X */ X X#include <stdio.h> X#include <termio.h> X#include <fcntl.h> X#include "dial_dir.h" X#include "param.h" X X/* X * Change the communication line settings to the new values. X */ X Xvoid Xline_set() X{ X extern int fd; 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 (fd == -1) X return; X /* get the current settings */ X ioctl(fd, TCGETA, &tbuf); X /* set some beginning values */ X tbuf.c_cc[4] = 1; /* VMIN */ X tbuf.c_cc[5] = 0; /* VTIME */ X tbuf.c_oflag = 0; X tbuf.c_iflag = 0; X tbuf.c_cflag = (CREAD|HUPCL|CLOCAL); X tbuf.c_lflag = 0; X X if (*param->flow == 'X') X tbuf.c_iflag |= (IXON|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#ifdef B19200 X tbuf.c_cflag |= B19200; X#else /* B19200 */ X#ifdef EXTA X tbuf.c_cflag |= EXTA; X#endif /* EXTA */ X#endif /* 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(fd, TCSETAF, &tbuf); X return; X} X X/* X * Put the stdin/stdout in terminal mode. We've divided up the X * responsibility for the line settings options between the serial port X * and the stdin and stdout. X */ X Xvoid Xterm_mode() X{ 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 /* duplex */ X if (dir->duplex[dir->d_cur] == 'H') X tbuf.c_lflag = ECHO; X X ioctl(0, TCSETAF, &tbuf); X return; X} X X/* X * Put the TTY driver in the mode suitable for xmodem transfers. X */ X Xvoid Xxmodem_mode(fds) Xint fds; X{ X struct termio tbuf; X X ioctl(fds, TCGETA, &tbuf); X /* X * Turn off the XON/XOFF flow control, turn off echoing, and X * switch to 8 bit no parity. 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|CSIZE);/* no parity */ X tbuf.c_cflag |= CS8; /* 8 bit */ X X ioctl(fds, TCSETAF, &tbuf); 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. X */ X Xvoid Xascii_mode(up) Xint up; X{ X extern int fd; X struct termio tbuf; X X ioctl(fd, TCGETA, &tbuf); X tbuf.c_oflag = 0; X /* flow control & 8th bit stripping */ X if (up) { X tbuf.c_iflag = (ISTRIP|IXON); X X /* if no CR's, use NL delays */ 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 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 X ioctl(fd, TCSETAF, &tbuf); X return; X} X X/* X * Flush the file descriptor X */ X Xint Xtty_flush(fds, mode) Xint fds, mode; X{ X return(ioctl(fds, TCFLSH, mode)); X} X X/* X * Wait for the output to drain X */ X Xint Xtty_drain(fds) Xint fds; X{ X return(ioctl(fds, TCSBRK, 1)); X} X X/* X * Send a modem break X */ X Xint Xtty_break(fds) Xint fds; X{ X return(ioctl(fds, TCSBRK, 0)); X} X X/* X * Fix the file descriptor so that a read is satisfied immediately. When X * read() is called it returns the character in the queue, or an error if X * no key was pressed. X */ X Xint Xtty_noblock(fds, on) Xint fds, on; X{ X int current; X X current = fcntl(fds, F_GETFL, 0); X if (on) X return(fcntl(fds, F_SETFL, current | O_NDELAY)); X else X return(fcntl(fds, F_SETFL, current & ~O_NDELAY)); X} X X/* X * Get the current baud rate of the terminal X */ X Xint Xmy_speed() X{ X static int speed[15] = {0, 50, 75, 110, 134, 150, 200, 300, 600, X 1200, 1800, 2400, 4800, 9600, 19200}; X struct termio tbuf; X X ioctl(0, TCGETA, &tbuf); X return(speed[tbuf.c_cflag & CBAUD]); X} SHAR_EOF if test 4795 -ne "`wc -c < 'tty_att.c'`" then echo shar: "error transmitting 'tty_att.c'" '(should have been 4795 characters)' fi fi echo shar: "extracting 'tty_ucb.c'" '(4666 characters)' if test -f 'tty_ucb.c' then echo shar: "will not over-write existing file 'tty_ucb.c'" else sed 's/^X//' << \SHAR_EOF > 'tty_ucb.c' X/* X * Berkeley specific routines for manipulating the TTY X */ X X#include <stdio.h> X#include <sgtty.h> X#include <fcntl.h> X#include "dial_dir.h" X#include "param.h" X X/* X * Change the communication line settings to the new values. X */ X Xvoid Xline_set() X{ X extern int fd; X struct sgttyb 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 (fd == -1) X return; X /* get the current settings */ X ioctl(fd, TIOCGETP, &tbuf); X /* set some beginning values */ X tbuf.sg_flags = CBREAK; X X if (*param->flow == 'X') X tbuf.sg_flags |= TANDEM; X /* the baud rate */ X switch (dir->baud[dir->d_cur]) { X case 300: X tbuf.sg_ispeed = B300; X tbuf.sg_ospeed = B300; X break; X case 1200: X tbuf.sg_ispeed = B1200; X tbuf.sg_ospeed = B1200; X break; X case 2400: X tbuf.sg_ispeed = B2400; X tbuf.sg_ospeed = B2400; X break; X case 4800: X tbuf.sg_ispeed = B4800; X tbuf.sg_ospeed = B4800; X break; X case 9600: X tbuf.sg_ispeed = B9600; X tbuf.sg_ospeed = B9600; X break; X case 19200: X#ifdef B19200 X tbuf.sg_ispeed = B19200; X tbuf.sg_ospeed = B19200; X#else /* B19200 */ X#ifdef EXTA X tbuf.sg_ispeed = EXTA; X tbuf.sg_ospeed = EXTA; X#endif /* EXTA */ X#endif /* B19200 */ X break; X } X /* the parity */ X switch (dir->parity[dir->d_cur]) { X case 'N': X tbuf.sg_flags |= ANYP; X break; X case 'O': X tbuf.sg_flags |= ODDP; X break; X case 'E': X tbuf.sg_flags |= EVENP; X break; X } X /* now set 'em! */ X ioctl(fd, TIOCSETP, &tbuf); X return; X} X X/* X * Put the stdin/stdout in terminal mode. We've divided up the X * responsibility for the line settings options between the serial port X * and the stdin and stdout. X */ X Xvoid Xterm_mode() X{ X struct sgttyb tbuf; X X ioctl(0, TIOCGETP, &tbuf); X X tbuf.sg_flags |= CBREAK; X tbuf.sg_flags &= ~(RAW|CRMOD|ECHO); X X if (dir->duplex[dir->d_cur] == 'H') X tbuf.sg_flags |= ECHO; X X ioctl(0, TIOCSETP, &tbuf); X return; X} X X/* X * Put the TTY driver in the mode suitable for xmodem transfers. X */ X Xvoid Xxmodem_mode(fds) Xint fds; X{ X struct sgttyb tbuf; X X ioctl(fds, TIOCGETP, &tbuf); X /* X * Turn off the XON/XOFF flow control, turn off echoing, and X * switch to 8 bit no parity. X */ X tbuf.sg_flags |= (RAW|ANYP); X tbuf.sg_flags &= ~ECHO; X ioctl(fds, TIOCSETP, &tbuf); X return; X} X X/* X * Put the TTY line in a mode suitable for the ASCII transfer. X */ X Xvoid Xascii_mode(up) Xint up; X{ X extern int fd; X struct sgttyb tbuf; X X ioctl(fd, TIOCGETP, &tbuf); X X tbuf.sg_flags |= (CBREAK|TANDEM); X tbuf.sg_flags &= ~(RAW|CRMOD|ECHO|CRDELAY); X X if (up) { X /* CR delay times */ X switch (param->cr_delay) { X case 0: X break; X case 100: X tbuf.sg_flags |= CR1; X break; X case 150: X tbuf.sg_flags |= CR2; X break; X } X } X X ioctl(fd, TIOCSETP, &tbuf); X return; X} X X/* X * Flush the file descriptor. Very messy... flushing the input causes a X * wait for the ouput to drain, and there is no output flushing. X */ X Xint Xtty_flush(fds, mode) Xint fds, mode; X{ X int ret_code = 0; X struct sgttyb tbuf; X X switch(mode) { X case 0: /* flush input queue */ X ioctl(fds, TIOCGETP, &tbuf); X ioctl(fds, TIOCSETP, &tbuf); X break; X case 1: /* flush output queue */ X /* sorry! */ X break; X case 2: /* flush both input and output */ X ioctl(fds, TIOCFLUSH, 0); X break; X default: X ret_code++; X break; X } X return(ret_code); X} X X/* X * Wait for the output to drain X */ X Xint Xtty_drain(fds) Xint fds; X{ X struct sgttyb tbuf; X /* this flushes the input too */ X ioctl(fds, TIOCGETP, &tbuf); X return(ioctl(fds, TIOCSETP, &tbuf)); X} X X/* X * Send a modem break X */ X Xint Xtty_break(fds) Xint fds; X{ X unsigned int sleep(); X X ioctl(fds, TIOCSBRK, (struct sgttyb *) 0); X sleep(1); X return(ioctl(fds, TIOCCBRK, (struct sgttyb *) 0)); X} X X/* X * Fix the file descriptor so that a read is satisfied immediately. When X * read() is called it returns the character in the queue, or an error if X * no key was pressed. X */ X Xint Xtty_noblock(fds, on) Xint fds, on; X{ X int current; X X current = fcntl(fds, F_GETFL, 0); X if (on) X return(fcntl(fds, F_SETFL, current | FNDELAY)); X else X return(fcntl(fds, F_SETFL, current & ~FNDELAY)); X} X X/* X * Get the current baud rate of the terminal X */ X Xint Xmy_speed() X{ X static int speed[15] = {0, 50, 75, 110, 134, 150, 200, 300, 600, X 1200, 1800, 2400, 4800, 9600, 19200}; X struct sgttyb tbuf; X X ioctl(0, TIOCGETP, &tbuf); X return(speed[tbuf.sg_ispeed]); X} SHAR_EOF if test 4666 -ne "`wc -c < 'tty_ucb.c'`" then echo shar: "error transmitting 'tty_ucb.c'" '(should have been 4666 characters)' fi fi echo shar: "extracting 'vcs.c'" '(10939 characters)' if test -f 'vcs.c' then echo shar: "will not over-write existing file 'vcs.c'" else sed 's/^X//' << \SHAR_EOF > 'vcs.c' X/* X * Routines for VCS detection. X */ X X#include <stdio.h> X#include "config.h" X#include "vcs.h" X X#ifndef OLDCURSES X#include <curses.h> X#include <term.h> X#endif /* OLDCURSES */ X Xstatic int putc_cnt; Xstatic char putc_buf[VCS_SIZE]; X X/* X * Test for possible VCS (video command sequence). A character return X * code means no match. An return code greater than 255 means a VCS X * was found. X */ X Xint Xvcs_filter(c) Xchar c; X{ X extern int vcs_codes[NUM_VCS][VCS_SIZE], vcs_leadin[NUM_VCS]; X extern int num_leadin; X static int vcs_buf[VCS_SIZE]; X static int ptr = 0; X register int i; X int maybe, possible; X X /* see if possible */ X possible = 0; X if (ptr == 0) { X /* X * This is kinda crude... I'm checking to see if the X * lead-in character is greater than the space character. X * If so, it most probably is NOT a VCS. X */ X if (c >= ' ') X return(c & 0xff); X /* check the list */ X for (i=0; i<num_leadin; i++) { X if (c == vcs_leadin[i]) { X possible++; X break; X } X } X if (!possible) X return(c & 0xff); X } X X /* build the string */ X vcs_buf[ptr++] = c; X vcs_buf[ptr] = -1; X /* test for match */ X maybe = 0; X for (i=0; i<NUM_VCS; i++) { X switch (match_codes(vcs_buf, vcs_codes[i], i)) { X case YES: X ptr = 0; X return(i+256); X case NO: X break; X case MAYBE: X maybe++; X break; X } X } X /* abandon what you've got */ X if (maybe && ptr == VCS_SIZE-1) { X ptr = 0; X return(c & 0xff); X } X /* hang on, wait and see */ X if (maybe) X return(MAYBE); X /* a clean miss */ X ptr = 0; X return(c & 0xff); X} X X/* X * See if the two integer arrays "match". Character parameters are X * designated by codes > 1000 and ASCII digit parameters are designated X * by codes > 2000. Uses a simple linear search, so if NUM_VCS grows X * this routine will have to mature a bit. X */ X Xstatic int Xmatch_codes(test, code, k) Xint test[], code[], k; X{ X extern int vcs_param[NUM_VCS][5]; X register int i, j; X int pos, done; X /* doesn't exist */ X if (code[0] == -1) X return(NO); X X i = 0; X j = 0; X while (i<VCS_SIZE && j<VCS_SIZE) { X /* at the end (a match) */ X if (test[i] == -1 && code[j] == -1) X return(YES); X /* ran out of input */ X if (test[i] == -1) X break; X /* X * The char parameter (code 1000) always matches the X * next character. X */ X if (code[j] >= 1000 && code[j] < 2000) { X pos = code[j] -1000; X vcs_param[k][pos] = test[i]; X i++; X j++; X continue; X } X /* X * The digit parameter (code 2000) tries to match as many X * ASCII digits as it can. X */ X if (code[j] >= 2000) { X pos = code[j] -2000; X /* done with this number? */ X if (vcs_param[k][pos]) X done = 1; X else X done = 0; X /* only digits */ X while (test[i] >= 48 && test[i] <= 57) { X if (!done) X vcs_param[k][pos] = (vcs_param[k][pos] * 10) + test[i] -48; X i++; X } X /* ended in a digit */ X if (test[i] == -1 && code[j+1] != -1) { X vcs_param[k][pos] = 0; X break; X } X j++; X continue; X } X /* a clean miss */ X if (test[i] != code[j]) { X for (j=0; j<5; j++) X vcs_param[k][j] = 0; X return(NO); X } X i++; X j++; X } X /* a maybe */ X return(MAYBE); X} X X/* X * Build the table of VCS codes. Actually we cheat... We tell curses(3) X * to build the strings to perform the function, and then we decipher X * what it did. X * X * For example: On a vt100 the cursor motion string in terminfo is: X * cup=\E[%i%p1%d;%p2%dH$<5> X * X * This gets translated to the integer array vcs_code[] as: X * \E [ %p1%d ; %p2%d H X * 27, 91, 2000, 59, 2001, 72 X * X * Notice that the "%p1" and "%p2" parameters get translated to 2000 and X * 2001. This is to signify that the parameters are multiple digit ASCII X * encoded numbers. The "%i" and "%d" codes are imbedded into the vcs_opt[] X * array in somewhat of a loose manner. In other words, there is no set X * format for the vcs_opt[] array. The padding info "$<5>" is ignored. X */ X Xvoid Xvcs_table() X{ X extern int vcs_codes[NUM_VCS][VCS_SIZE], vcs_opt[NUM_VCS][10]; X extern int vcs_leadin[NUM_VCS], num_leadin, max_row, max_col; X int i, j, k, match, temp[VCS_SIZE]; X char *p, *strcpy(), buf[VCS_SIZE], *getenv(), *tparm(); X void fake_it(); X X#ifdef OLDCURSES X char tcbuf[1024], tb[1024], *t, *cursor_home, *clr_eol, *clr_eos; X char *clear_screen, *cursor_up, *cursor_down, *cursor_right; X char *cursor_left, *cursor_address, *getenv(), *tgetstr(), *tgoto(); X X tgetent(tb, getenv("TERM")); X t = tcbuf; X X cursor_home = tgetstr("ho", &t); X clr_eol = tgetstr("ce", &t); X clr_eos = tgetstr("cd", &t); X clear_screen = tgetstr("cl", &t); X cursor_up = tgetstr("up", &t); X cursor_down = tgetstr("do", &t); X cursor_right = tgetstr("nd", &t); X cursor_left = tgetstr("le", &t); X cursor_address = tgetstr("cm", &t); X max_row = tgetnum("li"); X max_col = tgetnum("co"); X#else /* OLDCURSES */ X setupterm(getenv("TERM"), 1, &i); X max_row = lines; X max_col = columns; X#endif /* OLDCURSES */ X X /* X * Do the easy ones first. These don't take positional parameters, X * so all we have to do is strip the padding info. X */ X for (i=0; i<NUM_VCS; i++) { X switch (i) { X case HOME: X p = cursor_home; X break; X case CLR_EOL: X p = clr_eol; X break; X case CLR_EOS: X p = clr_eos; X break; X case CLEAR: X p = clear_screen; X break; X case MV_UP: X p = cursor_up; X break; X case MV_DOWN: X p = cursor_down; X break; X case MV_RIGHT: X p = cursor_right; X break; X case MV_LEFT: X p = cursor_left; X break; X default: X p = ""; X break; X } X /* X * Either the capability doesn't exist, or we're gonna X * do this one by hand (i.e.: ones with positional parameters) X */ X if (!p) { X vcs_codes[i][0] = -1; X continue; X } X /* fake an "output" */ X fake_it(p); X /* copy what it did */ X j = 0; X while (putc_buf[j]) { X vcs_codes[i][j] = putc_buf[j]; X j++; X if (j == VCS_SIZE-1) X break; X } X vcs_codes[i][j] = -1; X } X X /* X * And now for the difficult ones. The way it's done is: load the X * string with a few known parameters and then find where the X * parameters end up. The vcs_opt[][] array is "free-flowing" X * and means something only to the routine being used. X */ X /* add one to the param */ X if (substr(cursor_address, "%i") > 0) X vcs_opt[MV_DIRECT][0] = 1; X /* decimal codes used */ X if (substr(cursor_address, "%d") > 0) X vcs_opt[MV_DIRECT][1] = 1; X /* character codes used */ X if (substr(cursor_address, "%c") > 0) X vcs_opt[MV_DIRECT][2] = 1; X /* add an offset */ X if (substr(cursor_address, "%+") > 0) X vcs_opt[MV_DIRECT][3] = 1; X /* subtract an offset */ X if (substr(cursor_address, "%-") > 0) X vcs_opt[MV_DIRECT][4] = 1; X /* load with parameters 12 & 34 */ X#ifdef OLDCURSES X fake_it(tgoto(cursor_address, 12, 34)); X#else /* OLDCURSES */ X fake_it(tparm(cursor_address, 12, 34)); X#endif /* OLDCURSES */ X X j = 0; X while (putc_buf[j]) { X temp[j] = putc_buf[j]; X j++; X if (j == VCS_SIZE-1) X break; X } X temp[j] = -1; X /* if decimal parameters */ X if (vcs_opt[MV_DIRECT][1]) { X /* if add one */ X if (vcs_opt[MV_DIRECT][0]) X strcpy(buf, "13"); X else X strcpy(buf, "12"); X /* where is the 12 (or 13)? */ X if ((i = substr(putc_buf, buf)) > 0) { X temp[i] = 2000; X temp[i+1] = -2; X } X else X temp[0] = -1; X /* if add one */ X if (vcs_opt[MV_DIRECT][0]) X strcpy(buf, "35"); X else X strcpy(buf, "34"); X /* where is the 34 (or 35)? */ X if ((i = substr(putc_buf, buf)) > 0) { X temp[i] = 2001; X temp[i+1] = -2; X } X else X temp[0] = -1; X } X /* if character parameters */ X if (vcs_opt[MV_DIRECT][2]) { X /* original with 12 and 34 */ X strcpy(buf, putc_buf); X /* change 12 to 13 */ X#ifdef OLDCURSES X fake_it(tgoto(cursor_address, 13, 34)); X#else /* OLDCURSES */ X fake_it(tparm(cursor_address, 13, 34)); X#endif /* OLDCURSES */ X /* where are they different */ X i = 0; X while (buf[i] != '\0') { X if (buf[i] != putc_buf[i]) X break; X i++; X } X /* sanity checking */ X if (buf[i] == '\0') X temp[0] = -1; X /* if add, what is offset? */ X if (vcs_opt[MV_DIRECT][3]) X vcs_opt[MV_DIRECT][5] = temp[i] - 13; X X /* if subtract, what is offset? */ X if (vcs_opt[MV_DIRECT][4]) X vcs_opt[MV_DIRECT][5] = 13 - temp[i]; X X temp[i] = 1000; X /* change 34 to 35 */ X#ifdef OLDCURSES X fake_it(tgoto(cursor_address, 12, 35)); X#else /* OLDCURSES */ X fake_it(tparm(cursor_address, 12, 35)); X#endif /* OLDCURSES */ X /* where are they different */ X i = 0; X while (buf[i] != '\0') { X if (buf[i] != putc_buf[i]) X break; X i++; X } X temp[i] = 1001; X if (buf[i] == '\0') X temp[0] = -1; X } X /* strip the -2's out, if any */ X i = 0; X j = 0; X while (temp[i] != -1) { X if (temp[i] != -2) X vcs_codes[MV_DIRECT][j++] = temp[i]; X i++; X } X vcs_codes[MV_DIRECT][j] = -1; X X /* X * Simplify the list. Some codes are already handled by the X * virtual screen routines... no need to duplicate them. X */ X if (vcs_codes[MV_DOWN][0] == '\n') X vcs_codes[MV_DOWN][0] = -1; X X if (vcs_codes[MV_LEFT][0] == 8) X vcs_codes[MV_LEFT][0] = -1; X X /* X * Often the "clear screen" sequence will contain the "home" X * sequence... if so, don't duplicate the "home" portion. X */ X fake_it(cursor_home); X strcpy(buf, putc_buf); X X fake_it(clear_screen); X /* if "home" inside "clear screen" */ X if ((k = substr(putc_buf, buf)) >= 0) { X /* if at the beginning */ X if (k == 0) { X i = 0; X for (j=strlen(buf); j<VCS_SIZE; j++) X vcs_codes[CLEAR][i++] = putc_buf[j]; X vcs_codes[CLEAR][i] = -1; X } X /* if at the end */ X else if (strlen(buf)+k == strlen(putc_buf)) X vcs_codes[CLEAR][k] = -1; X } X /* is "clear screen" still unique */ X k = 0; X for (i=0; i<NUM_VCS; i++) { X if (vcs_codes[CLEAR][i] == -1 || vcs_codes[CLR_EOS][i] == -1) X break; X if (vcs_codes[CLEAR][i] != vcs_codes[CLR_EOS][i]) { X k++; X break; X } X } X if (k == 0) X vcs_codes[CLEAR][0] = -1; X X /* X * Make a list of unique lead-in characters to be used as a X * simple hash table. X */ X num_leadin = 0; X for (i=0; i<NUM_VCS; i++) { X if (vcs_codes[i][0] == -1) X continue; X /* add any new lead-in character */ X match = 0; X for (j=0; j<num_leadin; j++) { X if (vcs_leadin[j] == vcs_codes[i][0]) X match++; X } X if (!match) X vcs_leadin[num_leadin++] = vcs_codes[i][0]; X } X return; X} X X/* X * The routine that fakes curses(3) into outputting the string info with X * the padding removed. X */ Xstatic void Xfake_it(s) Xchar *s; X{ X int fake_putc(); X X putc_cnt = 0; X putc_buf[0] = '\0'; X tputs(s, 1, fake_putc); X putc_buf[putc_cnt] = '\0'; X return; X} Xstatic int Xfake_putc(c) Xchar c; X{ X if (c != '\0') X putc_buf[putc_cnt++] = c; X return(c); X} X X/* X * Is string2 contained in string1? If so, return the offset, otherwise X * return a -1. X */ X Xstatic int Xsubstr(s1, s2) Xchar *s1, *s2; X{ X int i, len; X X len = strlen(s2); X /* not possible */ X if (len > strlen(s1)) X return(-1); X X i = 0; X while (*s1) { X if (!strncmp(s1, s2, len)) X return(i); X s1++; X i++; X } X return(-1); X} SHAR_EOF if test 10939 -ne "`wc -c < 'vcs.c'`" then echo shar: "error transmitting 'vcs.c'" '(should have been 10939 characters)' fi fi echo shar: "extracting 'vcs.h'" '(330 characters)' if test -f 'vcs.h' then echo shar: "will not over-write existing file 'vcs.h'" else sed 's/^X//' << \SHAR_EOF > 'vcs.h' X/* X * Definitions to support the detection of video command sequences X */ X X#define VCS_SIZE 25 X#define NUM_VCS 9 X X#define HOME 0 X#define CLR_EOL 1 X#define CLR_EOS 2 X#define CLEAR 3 X#define MV_UP 4 X#define MV_DOWN 5 X#define MV_RIGHT 6 X#define MV_LEFT 7 X#define MV_DIRECT 8 X X#define YES 1 X#define NO 0 X#define MAYBE (-1) SHAR_EOF if test 330 -ne "`wc -c < 'vcs.h'`" then echo shar: "error transmitting 'vcs.h'" '(should have been 330 characters)' fi fi echo shar: "extracting 'waitfor.c'" '(2108 characters)' if test -f 'waitfor.c' then echo shar: "will not over-write existing file 'waitfor.c'" else sed 's/^X//' << \SHAR_EOF > 'waitfor.c' X/* X * Wait for a string on the stdin. Returns a 0 on success, 1 on failure X * and -1 on error. This is an external program designed to be used in X * shell scripts. X */ X X#define TIMEOUT 10 X#define BUF_SIZ 1024 X#define HZ 60 X#define STRSTR X Xint wf_flag; X X#include <stdio.h> X#include <signal.h> X#include <sys/types.h> X#include <sys/times.h> X X#ifdef BSD X#include <setjmp.h> Xjmp_buf wf_buf; X#endif /* BSD */ X Xmain(argc, argv) Xint argc; Xchar *argv[]; X{ X int i, j, timeout; X char c, buf[BUF_SIZ], *string, *strstr(); X struct tms t; X long t1; X void exit(); X X if (argc < 2 || argc > 3) { X fprintf(stderr, "Usage: waitfor -n string\n"); X exit(-1); X } X X if (argv[1][0] == '-') { X timeout = atoi(&argv[1][1]); X if (argc != 3) { X fprintf(stderr, "Usage: waitfor -n string\n"); X exit(-1); X } X string = argv[2]; X } X else { X timeout = TIMEOUT; X string = argv[1]; X } X /* here we go.. */ X i = 0; X t1 = times(&t); X while ((times(&t) - t1) < (HZ * timeout)) { X if ((j = getc_line()) != -1) { X c = j & 0x7f; X /* no NULLs please */ X if (c != '\0') { X buf[i++] = c; X buf[i] = '\0'; X } X X if (i >= BUF_SIZ) { X fprintf(stderr, "waitfor: buffer overflow\n"); X exit(-1); X } X /* yea.. we found it! */ X if (strstr(buf, string)) X exit(0); X } X } X exit(1); X} X Xint Xgetc_line() X{ X int wf_force(); X char c; X unsigned int alarm(); X X signal(SIGALRM, wf_force); X wf_flag = 0; X X alarm(1); X X#ifdef BSD X if (setjmp(wf_buf)) X return(-1); X#endif /* BSD */ X X if (read(0, &c, 1) <= 0) { X alarm(0); X return(-1); X } X if (wf_flag) X return(-1); X alarm(0); X return(c & 0xff); X} X X/* ARGSUSED */ Xstatic int Xwf_force(dummy) Xint dummy; X{ X#ifdef BSD X longjmp(wf_buf, 1); X#else /* BSD */ X signal(SIGALRM, wf_force); X wf_flag = 1; X#endif /* BSD */ X} X X#ifdef STRSTR X/* X * Return a pointer to the first occurance of string str2 in str1. X * Returns a NULL if str2 is not in str1. X */ X Xchar * Xstrstr(str1, str2) Xchar *str1, *str2; X{ X int len; X len = strlen(str2); X while (*str1) { X if (*str2 == *str1) { X if (!strncmp(str2, str1, len)) X return(str1); X } X str1++; X } X return(NULL); X} X#endif /* STRSTR */ SHAR_EOF if test 2108 -ne "`wc -c < 'waitfor.c'`" then echo shar: "error transmitting 'waitfor.c'" '(should have been 2108 characters)' fi fi echo shar: "extracting 'x_ascii.c'" '(6450 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 <curses.h> X#include <signal.h> X#include "config.h" X#include "misc.h" X#include "param.h" X X#ifdef BSD X#include <setjmp.h> Xjmp_buf bl_buf; X#endif /* BSD */ 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(), st_line(), suspend(); X void load_vs(), ascii_mode(), input_off(), term_mode(); X unsigned int sleep(); X X touchwin(stdscr); X refresh(); X /* only one file from list */ X file = strtok(list, " \t"); X X cr_lf = !strcmp(param->cr_out, "CR/LF"); X ascii_mode(up); X /* out of curses mode */ X resetterm(); X term_mode(); X tty_noblock(0, TRUE); X X if (up) { X /* un-suspend the input routine */ X suspend(FALSE); X send_ascii(file, cr_lf); X suspend(TRUE); X } X else { X input_off(); X rcv_ascii(file, cr_lf); X } 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 line_set(); X fixterm(); X tty_noblock(0, FALSE); X X /* X * On downloading, the contents of the virtual screen won't contain X * the characters shown during the transfer. Too bad... X */ X load_vs(); X beep(); X st_line("xfer complete"); X X sleep(2); X return; 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 Xstatic void Xsend_ascii(file, cr_lf) Xchar *file; Xint cr_lf; X{ X extern int fd; X FILE *fp, *my_fopen(); X int i, j, strip_cr, strip_lf, add_cr, add_lf, expand, lecho, pace; X char buf[80]; X unsigned char c, last; X unsigned int sleep(); X void error_win(); X /* permission already checked */ X if (!(fp = my_fopen(file, "r"))) { X sprintf(buf, "\"%s\"", file); X error_win(0, "Can't open file for read", buf); X return; X } 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 ESC: /* <ESC> key for abort */ X fclose(fp); X sleep(2); X tty_drain(fd); X return; X default: /* send the char */ X c = j; X putc_line(c); X if (c == '\r' && cr_lf) X putc_line('\n'); X break; X } X c = i & 0x7f; X /* expand blank lines */ X if (expand && last == '\n' && c == '\n') X putc_line(' '); X last = c; X X /* CR translations */ X if (c == '\r' && strip_cr) X continue; X if (c == '\r' && add_lf) { X putc_line(c); X putc_line('\n'); X continue; X } X /* LF translations */ X if (c == '\n' && strip_lf) X continue; X if (c == '\n' && add_cr) { X putc_line('\r'); 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 tty_drain(fd); X if (lecho) { X putchar((char) c); X fflush(stdout); X } X } X fclose(fp); X sleep(2); X tty_drain(fd); 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 bgetc_line() X * and non-blocking input makes it seem like full duplex, but it's not. X * Be aware that while the timer is active the keyboard is deaf. Input is X * NOT loaded into the virtual screen!! X */ X Xstatic void Xrcv_ascii(file, cr_lf) Xchar *file; Xint cr_lf; X{ X FILE *fp, *my_fopen(); X int i, strip_cr, strip_lf, add_cr, add_lf, got_first; X unsigned int delay; X char c, buf[80]; X void error_win(); X /* permission already checked */ X if (!(fp = my_fopen(file, "w"))) { X sprintf(buf, "\"%s\"", file); X error_win(0, "Can't open file for write", buf); X return; X } 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 ESC: /* <ESC> key */ X fclose(fp); X return; X default: /* send it */ X c = i; X putc_line((unsigned char) c); X if (c == '\r' && cr_lf) X putc_line('\n'); X break; X } X /* read a character */ X if ((i = bgetc_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 & 0x7f; X /* display it on the screen */ X putchar(c); X fflush(stdout); X /* CR translations */ X if (c == '\r' && strip_cr) X continue; X if (c == '\r' && add_lf) { X fputc(c, fp); X fputc('\n', fp); X continue; X } X /* LF translations */ X if (c == '\n' && strip_lf) X continue; X if (c == '\n' && add_cr) { X fputc('\r', fp); X fputc(c, fp); X continue; X } X fputc(c, fp); X } X} X X/* X * Get a character from the line (using buffered I/O) with a specified X * time-out period in seconds. If the function times-out, it returns a -1. X */ X Xstatic int bl_flag; X Xstatic int Xbgetc_line(sec) Xunsigned int sec; X{ X int c, bl_force(); X unsigned int alarm(); X X signal(SIGALRM, bl_force); X bl_flag = 0; X X alarm(sec); X X#ifdef BSD X if (setjmp(bl_buf)) X return(-1); X#endif /* BSD */ X X if ((c = buf_read()) < 0) { X alarm(0); X return(-1); X } X if (bl_flag) X return(-1); X alarm(0); X return(c); X} X X/* ARGSUSED */ Xstatic int Xbl_force(dummy) Xint dummy; X{ X#ifdef BSD X longjmp(bl_buf, 1); X#else /* BSD */ X signal(SIGALRM, bl_force); X bl_flag = 1; X#endif /* BSD */ X} X X/* X * Do a single character buffered read from the serial port. X */ X Xstatic int Xbuf_read() X{ X extern int fd; X static char buf[CLIST_SIZ]; X static char *bufp = buf; X static int n = 0; X X if (n <= 0) { X n = read(fd, buf, CLIST_SIZ); X bufp = buf; X } X if (--n >= 0) X return(*bufp++ & 0xff); X return(-1); X} SHAR_EOF if test 6450 -ne "`wc -c < 'x_ascii.c'`" then echo shar: "error transmitting 'x_ascii.c'" '(should have been 6450 characters)' fi fi echo shar: "extracting 'x_batch.c'" '(8686 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 "config.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. Returns zero on success or the standard error codes. X */ X Xint Xsend_modem7(win, name) XWINDOW *win; Xchar *name; X{ X char *new_name, *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 -1: /* timed out */ X clear_line(win, 12, 24, TRUE); X waddstr(win, "NO RESPONSE"); X wrefresh(win); X return(ERROR); X case ACK: /* got it! */ X break; X case CAN: /* cancel transmission */ X if (getc_line(2) == CAN) { X beep(); X clear_line(win, 12, 24, TRUE); X wattrstr(win, A_BOLD, "REMOTE ABORTED"); X wrefresh(win); X return(CANCEL); X } X /* fall thru... */ X default: X clear_line(win, 12, 24, TRUE); X waddstr(win, "NAME FAILED"); X wrefresh(win); X return(ERROR); X } X new_name++; X } X putc_line(CTRLZ); X /* verify the checksum */ X if (getc_line(10) != sum) { X putc_line('u'); X clear_line(win, 12, 24, TRUE); X waddstr(win, "CHECKSUM FAILED"); X wrefresh(win); X return(ERROR); X } X putc_line(ACK); X return(0); X} X X/* X * Receive a modem7 file name. Returns zero on success, the standard error X * codes, or a -1 on the end-of-batch. (Oddly enough, the end-of-batch code X * is the same as the code for a user abort) X */ X Xint Xrcv_modem7(win, default_err) XWINDOW *win; Xint default_err; X{ X extern char file_name[15]; X int i, j, err_method, err_count, got_it; X unsigned char sum, calc_sum(); X char temp_name[13]; X void change_name(), unfix_name(); X X err_method = default_err; X if (default_err == CRC_CHECKSUM) X err_method = CRC; X X err_count = 0; X got_it = 0; X while (err_count < MAX_ERRORS) { X /* switch to checksum? */ X if (default_err == CRC_CHECKSUM && err_count > MAX_ERRORS/2) X err_method = CHECKSUM; X X if (err_method == CRC) X putc_line('C'); X else X putc_line(NAK); X /* what'd we get? */ X switch (getc_line(10)) { X case -1: /* timed out */ X clear_line(win, 12, 24, TRUE); X wattrstr(win, A_BOLD, "NO RESPONSE"); X wrefresh(win); X err_count++; X case ACK: /* ready to go... */ X got_it++; X break; X default: /* huh? */ X clear_line(win, 12, 24, TRUE); X wattrstr(win, A_BOLD, "BAD HEADER"); X wrefresh(win); X err_count++; X } X } X if (!got_it) X return(ERROR); X /* get the name */ X for (i=0; i<12; i++) { X j = getc_line(3); X X switch (j) { X case -1: /* timed out */ X clear_line(win, 12, 24, TRUE); X wattrstr(win, A_BOLD, "NO RESPONSE"); X wrefresh(win); X return(ERROR); X case EOT: /* end of batch? */ X return(-1); X case CAN: /* cancel transmission */ X if (getc_line(2) == CAN) { X beep(); X clear_line(win, 12, 24, TRUE); X wattrstr(win, A_BOLD, "REMOTE ABORTED"); X wrefresh(win); X return(CANCEL); X } X /* fall thru... */ X case 'u': /* bad name character */ X beep(); X clear_line(win, 12, 24, TRUE); X wattrstr(win, A_BOLD, "BAD NAME"); X wrefresh(win); X return(ERROR); X default: /* the name... */ X temp_name[i] = j & 0xff; X if (j != CTRLZ) X putc_line(ACK); X break; X } X } X temp_name[12] = '\0'; X /* send our checksum */ X sum = calc_sum((unsigned char *) temp_name, 12); X putc_line(sum); X /* do they agree? */ X if (getc_line(10) != ACK) { X beep(); X clear_line(win, 12, 24, TRUE); X wattrstr(win, A_BOLD, "BAD NAME"); X wrefresh(win); X return(ERROR); X } X /* load the file_name array */ X unfix_name(temp_name); X /* any name collisions? */ X change_name(win, file_name); X return(0); X} X X/* X * Send the block 0 information for a ymodem batch transfer. Uses only X * the name component of the path and the file size. X */ X Xint Xsend_ymodem(win, file, size) XWINDOW *win; Xchar *file; Xlong size; X{ X unsigned short crc, calc_crc(); X char *strcpy(), *memset(); X unsigned char buf[133]; X /* start with a clean block */ X memset(buf, '\0', 133); X /* the header */ X buf[0] = SOH; X buf[1] = 0; X buf[2] = 255; X X /* X * The block zero consists of the file name (no path component), X * a NULL, and the file length (as a string). The end of batch X * marker is an empty block. X */ X if (*file != '\0') { X strcpy((char *) &buf[3], file); X sprintf((char *) &buf[strlen(file)+4], "%ld", size); X } X /* the crc */ X crc = calc_crc(&buf[3], 128); X buf[131] = crc >> 8; X buf[132] = crc; X /* the block count */ X mvwaddstr(win, 7, 24, "0 "); X X return(send_block(win, buf, 133)); X} X X/* X * Receive the block 0 information for a ymodem batch transfer. We X * only use the file name and the size (if present). Currently doesn't X * support full path names. X */ X Xint Xrcv_ymodem(win) XWINDOW *win; X{ X extern unsigned char buf[1029]; X extern long file_length; X extern char file_name[15]; X int code, length_is_at; X long atol(); X X file_length = 0L; X file_name[0] = '\0'; X /* read the zero block */ X if (code = rcv_block(win, 1, 1024, 0)) X return(code); X /* at end of batch */ X if (buf[3] == '\0') X return(0); X /* get the file name */ X change_name(win, (char *) &buf[3]); X /* any trouble? */ X if (file_name[0] == '\0') { X putc_line(CAN); X return(0); X } X /* X * The file length is placed after the NULL of the file name X * and is terminated by another NULL. If the length is missing, X * atol() will see a NULL and return 0. X */ X length_is_at = strlen((char *) &buf[3]) + 4; X file_length = atol((char *) &buf[length_is_at]); X return(0); X} X X/* X * Handle file name collisions. Prepend an "X" to the name until you find X * a name that doesn't already exist. Creates a NULL name on error. X * Loads the global character array "file_name". X */ X Xvoid Xchange_name(win, str) XWINDOW *win; Xchar *str; X{ X extern char file_name[15]; X register int i; X int modified; X char temp[15], ans[15], *s, *strrchr(), *strcpy(), *strncat(); X unsigned int sleep(); 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] = '\0'; X /* write permission on directory? */ X if (access(".", 2)) { X beep(); X clear_line(win, 12, 24, TRUE); X wattrstr(win, A_BOLD, "NO WRITE ON DIRECTORY"); X wrefresh(win); X return; X } X /* prepend up to 13 "X"s */ X modified = 0; X for (i=1; i<14; i++) { X if (access(ans, 0)) { X if (modified) { X beep(); X clear_line(win, 12, 24, TRUE); X waddstr(win, "NAME COLLISION"); X wrefresh(win); X sleep(1); X } X strcpy(file_name, ans); X return; X } X X modified++; X strcpy(temp, "X"); X strncat(temp, ans, 13); X temp[14] = '\0'; X strcpy(ans, temp); X } X beep(); X clear_line(win, 12, 24, TRUE); X waddstr(win, "BAD NAME"); X wrefresh(win); X return; X} X X/* X * Convert a perfectly good Unix file name to fit the CP/M file name X * rules. Used for the modem7 batch file transfer. Returns a pointer X * to a static area containing the new name. X */ X 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 = ""; X dot = 0; X for (s=name; *s; ++s) { X if (*s == '.' && !dot) { X dot++; X *s = '\0'; X ext = s + 1; X } X if (islower(*s)) X *s = toupper(*s); X } X /* if null name component */ X if (*name == '\0') X name = "X"; X /* if name too long */ X if (strlen(name) > 8) X *(name+8) = '\0'; X /* if extension too long */ X if (strlen(ext) > 3) X *(ext+3) = '\0'; X X sprintf(ans, "%-8.8s%-3.3s%c", temp, ext, CTRLZ); X return(ans); X} X X/* X * Convert a CP/M style filename into a legal Unix file name. Loads the X * global character array "file_name". X */ X Xvoid Xunfix_name(cpm_name) Xchar *cpm_name; X{ X extern char file_name[15]; X register int i, n; X int dot; X char temp[15]; X X file_name[0] = '\0'; X if (*cpm_name == '\0') X return; X X strcpy(temp, cpm_name); X /* 8 character of the name */ X n = 0; X for (i=0; i<8; i++) { X if (temp[i] != ' ') { X if (isupper(temp[i])) X file_name[n++] = tolower(temp[i]); X else X file_name[n++] = temp[i]; X } X } X /* 3 character extension */ X dot = 0; X for (i=8; i<11; i++) { X if (temp[i] != ' ') { X if (!dot) { X dot++; X file_name[n++] = '.'; X } X if (isupper(temp[i])) X file_name[n++] = tolower(temp[i]); X else X file_name[n++] = temp[i]; X } X } X file_name[n] = '\0'; X return; X} SHAR_EOF if test 8686 -ne "`wc -c < 'x_batch.c'`" then echo shar: "error transmitting 'x_batch.c'" '(should have been 8686 characters)' fi fi echo shar: "extracting 'x_extrnl.c'" '(2965 characters)' if test -f 'x_extrnl.c' then echo shar: "will not over-write existing file 'x_extrnl.c'" else sed 's/^X//' << \SHAR_EOF > 'x_extrnl.c' X/* X * Spawn a shell with the stdin and stdout swapped with the remote X * system, ie: X * +----------+ X * TTYin ------------> stdin | | X * | shell | X * TTYout <---------- stdout | | X * +----------+ X * X * An undocumented feature: The external protocol gateway X * can be used to pipe the output of a normal Unix command to the X * remote system. X */ X X#include <stdio.h> X#include <signal.h> X#include <curses.h> X#include <errno.h> X#include "config.h" X X#ifdef BSD X#include <sys/file.h> X#else /* BSD */ X#include <fcntl.h> X#endif /* BSD */ X Xvoid Xdo_extrnl(cmd) Xchar *cmd; X{ X extern int fd, errno; X WINDOW *xt_win, *newwin(); X SIG_TYPE (*istat)(), (*qstat)(); X int epid, want_out, sig_status; X char buf[80], *ttyname(), *strcpy(); X unsigned int sleep(); X void _exit(), input_off(); X X input_off(); X /* a full window */ X xt_win = newwin(LINES, COLS, 0, 0); X touchwin(xt_win); X wrefresh(xt_win); X /* out of curses mode */ X resetterm(); X X if (!(epid = fork())) { X /* create a new process group ID */ X#ifdef BSD X setpgrp(0, getpid()); X#else /* BSD */ X setpgrp(); X#endif /* BSD */ X /* recreate the device name */ X strcpy(buf, ttyname(fd)); X close(fd); X /* swap the stdin */ X close(0); X#ifdef UNIXPC X/* X * Some strange things here... The OBM uses the second parameter of X * open() to determine if the port should be in the DATA mode or X * the VOICE mode. Therefore, we must always open with read and write. X */ X if (!strncmp(buf, "/dev/ph", 7)) X open(buf, O_RDWR); X else X#endif /* UNIXPC */ X open(buf, O_RDONLY); X /* swap the stdout */ X close(1); X#ifdef UNIXPC X if (!strncmp(buf, "/dev/ph", 7)) X open(buf, O_RDWR); X else X#endif /* UNIXPC */ X open(buf, O_WRONLY); X#ifdef SETUGID X setgid(getgid()); X setuid(getuid()); X#endif /* SETUGID */ X execl("/bin/sh", "sh", "-c", cmd, (char *) 0); X _exit(1); X } X istat = signal(SIGINT, SIG_IGN); X qstat = signal(SIGQUIT, SIG_IGN); X X /* X * Check the keyboard while the external program is running. If X * the user hits the <ESC> key, then kill the entire process X * group associated with the new shell. X */ X want_out = 0; X while(1) { X switch(wait_key(stdscr, 1)) { X case -1: /* timed out */ X break; X case 27: /* a user abort */ X#ifdef BSD X killpg(epid, SIGKILL); X#else /* BSD */ X kill(-epid, SIGKILL); X#endif /* BSD */ X want_out++; X break; X default: X beep(); X break; X } X if (want_out) X break; X /* see if the process it still active */ X#ifdef BSD X if ((kill(epid, 0) == -1) && errno == ESRCH) X#else /* BSD */ X if ((kill(-epid, 0) == -1) && errno == ESRCH) X#endif /* BSD */ X break; X } X /* wait for the zombie process */ X wait(&sig_status); X X signal(SIGINT, istat); X signal(SIGQUIT, qstat); X /* back to curses mode */ X sleep(1); X fixterm(); X X clearok(curscr, TRUE); X werase(xt_win); X wrefresh(xt_win); X delwin(xt_win); X return; X} SHAR_EOF if test 2965 -ne "`wc -c < 'x_extrnl.c'`" then echo shar: "error transmitting 'x_extrnl.c'" '(should have been 2965 characters)' fi fi exit 0 # End of shell archive
egray@fthood.UUCP (02/05/89)
This is part 8 (of 8) to the Pcomm v1.2 distribution package. Emmet P. Gray US Army, HQ III Corps & Fort Hood ...!uunet!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_menu.c # x_rcv.c # x_send.c # x_win.c # xmodem.c # xmodem.h # This archive created: Fri Feb 3 07:35:39 1989 export PATH; PATH=/bin:/usr/bin:$PATH echo shar: "extracting 'x_menu.c'" '(7594 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 non-zero return code means turn the X * input routine back on. X */ X X#include <stdio.h> X#include <sys/types.h> X#include <sys/stat.h> X#include <curses.h> X#include "config.h" X#include "extrnl.h" X#include "misc.h" X#include "xmodem.h" X Xint Xxfer_menu(up) Xint up; X{ X extern int fd; X extern char *null_ptr; X WINDOW *xm_win, *newwin(); X char buf[2048], *list, *get_names(), *get_extrnl(), *strcat(); X char *strcpy(); X int type, is_batch, i, ans, num_extrnl, n, ret_code; X void xfer_win(), xfer_ascii(), do_extrnl(), error_win(); X X num_extrnl = (up) ? extrnl->up_entries : extrnl->dn_entries; X xm_win = newwin(14+num_extrnl, 20, 2, 45); X X mvwaddstr(xm_win, 2, 3, "1) xmodem"); X mvwaddstr(xm_win, 3, 3, "2) xmodem-1k"); X mvwaddstr(xm_win, 4, 3, "3) modem7"); X mvwaddstr(xm_win, 5, 3, "4) ymodem"); X mvwaddstr(xm_win, 6, 3, "5) ymodem-g"); X mvwaddstr(xm_win, 7, 3, "6) ASCII"); X X for (i=0; i<num_extrnl; i++) X mvwprintw(xm_win, i+8, 3, "%d) %-12.12s", i+7, extrnl->name[up][i]); X mvwaddstr(xm_win, i+8, 3, "E) (external)"); X mvwaddstr(xm_win, i+10, 3, "<ESC> to Abort"); X mvwaddstr(xm_win, i+11, 3, "Protocol:"); X box(xm_win, VERT, HORZ); X if (up) X mvwattrstr(xm_win, 0, 6, A_BOLD, " Upload "); X else X mvwattrstr(xm_win, 0, 5, A_BOLD, " Download "); X X wmove(xm_win, i+11, 13); X wrefresh(xm_win); X /* get the protocol */ X type = -1; X while ((ans = wgetch(xm_win)) != ESC) { X switch (ans) { X case '1': X type = XMODEM; X break; X case '2': X type = XMODEM_1k; X break; X case '3': X type = MODEM7; X break; X case '4': X type = YMODEM; X break; X case '5': X type = YMODEM_G; X break; X case '6': X type = XASCII; X break; X case '7': X if (num_extrnl >= 1) X type = EXT_1; X else X beep(); X break; X case '8': X if (num_extrnl >= 2) X type = EXT_2; X else X beep(); X break; X case '9': X if (num_extrnl >= 3) X type = EXT_3; X else X beep(); X break; X case 'e': X case 'E': X type = EXT_MANUAL; X break; X default: X beep(); X } X if (type != -1) X break; X } X werase(xm_win); X wrefresh(xm_win); X delwin(xm_win); X /* chicken'd out */ X if (type == -1) X return(0); X X if (fd == -1) { X error_win(0, "Not currently connected to any host", ""); X return(0); X } X /* which protocol? */ X ret_code = 0; X is_batch = 0; X switch(type) { X case MODEM7: X case YMODEM: X case YMODEM_G: /* built-in protocols */ X is_batch++; X /* fall thru */ X case XMODEM: X case XMODEM_1k: /* non-batch built-ins */ X list = null_ptr; X /* X * When receiving in a batch mode, don't prompt X * for file names. X */ X if (up || !is_batch) { X if (!(list = get_names(up, type, is_batch))) X break; X } X xfer_win(list, up, type); X ret_code++; X break; X case XASCII: /* ascii xfer, yuck! */ X if (list = get_names(up, type, FALSE)) { X xfer_ascii(list, up); X if (!up) X ret_code++; X } X break; X case EXT_1: X case EXT_2: X case EXT_3: /* one of the externals */ X n = type -NUM_INTERNAL; X strcpy(buf, extrnl->command[up][n]); X /* see if we need to prompt for files */ X if (extrnl->prompt[up][n] == 'Y') { X if (list = get_names(up, type, TRUE)) { X strcat(buf, " "); X strcat(buf, list); X } X else X break; X } X do_extrnl(buf); X ret_code++; X break; X case EXT_MANUAL: /* the manual external protocol */ X if (list = get_extrnl(up)) { X do_extrnl(list); X ret_code++; X } X break; X } X return(ret_code); X} X Xchar *protocol[NUM_INTERNAL] = {"xmodem", "xmodem-1k", "modem7", "ymodem", X "ymodem-g", "ASCII"}; X X/* X * Prompt for a list of files for the transfer programs. Since expand() X * is used, it returns a pointer to a static area. Returns a NULL if X * you chicken'd out. X */ X Xstatic char * Xget_names(up, type, is_batch) Xint up, type, is_batch; X{ X int got_it; X WINDOW *gn_win, *newwin(); X char *ans, *file, *list, buf[40], *expand(), *get_str(), *strtok(); X void st_line(); X struct stat stbuf; X X touchwin(stdscr); X refresh(); X st_line(""); X X gn_win = newwin(7, 70, 5, 5); X mvwaddstr(gn_win, 3, 4, "Enter filename: "); X box(gn_win, VERT, HORZ); X if (up) { X if (type < NUM_INTERNAL) X sprintf(buf, " Send %s ", protocol[type]); X else X sprintf(buf, " Send %s ", extrnl->name[up][type-NUM_INTERNAL]); X } X else { X if (type < NUM_INTERNAL) X sprintf(buf, " Receive %s ", protocol[type]); X else X sprintf(buf, " Receive %s ", extrnl->name[up][type-NUM_INTERNAL]); X } X mvwattrstr(gn_win, 0, 3, A_BOLD, buf); X X while (1) { X wmove(gn_win, 3, 20); X wrefresh(gn_win); X /* get the answers */ X if (is_batch) X ans = get_str(gn_win, 60, "", "\n"); X else X ans = get_str(gn_win, 60, "", " \t\n"); X X if (ans == NULL || *ans == '\0') { X list = NULL; X break; X } X list = expand(ans); X /* batches are checked on-the-fly */ X if (is_batch) X break; X /* X * Here we have the opportunity to determine the read and X * write permissions before things get started. Much nicer X * than finding out later when there's no way to fix it. X * Only checks the first file. X */ X file = strtok(list, " \t"); X /* sanity checking */ X if (!stat(file, &stbuf)) { X if ((stbuf.st_mode & S_IFREG) != S_IFREG) { X beep(); X clear_line(gn_win, 4, 15, TRUE); X mvwattrstr(gn_win, 4, 15, A_BOLD, "Not a regular file"); X wrefresh(gn_win); X wait_key(gn_win, 3); X clear_line(gn_win, 4, 15, TRUE); X clear_line(gn_win, 3, 20, TRUE); X continue; X } X } X /* check read permission */ X if (up) { X if (access(file, 0)) { X beep(); X mvwattrstr(gn_win, 4, 15, A_BOLD, "Can't find file"); X wrefresh(gn_win); X wait_key(gn_win, 3); X clear_line(gn_win, 4, 15, TRUE); X clear_line(gn_win, 3, 20, TRUE); X continue; X } X if (access(file, 4)) { X beep(); X mvwattrstr(gn_win, 4, 15, A_BOLD, "No read permission"); X wrefresh(gn_win); X wait_key(gn_win, 3); X clear_line(gn_win, 4, 15, TRUE); X clear_line(gn_win, 3, 20, TRUE); X continue; X } X break; X } X /* check write permission */ X got_it = 0; X switch(can_write(file)) { X case DENIED: X beep(); X clear_line(gn_win, 4, 15, TRUE); X mvwattrstr(gn_win, 4, 15, A_BOLD, "No write permission"); X wrefresh(gn_win); X wait_key(gn_win, 3); X clear_line(gn_win, 4, 15, TRUE); X clear_line(gn_win, 3, 20, TRUE); X break; X case OK_BUT_EXISTS: X if (!yes_prompt(gn_win, 4, 15, A_BOLD, "File exists, overwrite")) { X clear_line(gn_win, 4, 15, TRUE); X clear_line(gn_win, 3, 20, TRUE); X break; X } X /* fall thru */ X case WRITE_OK: X got_it++; X break; X } X if (got_it) X break; X } X werase(gn_win); X wrefresh(gn_win); X delwin(gn_win); X X return(list); X} X X/* X * Prompt for the Unix command line to be used as an external file X * transfer program. Since expand() is used, it returns a pointer to X * a static area. X */ X Xstatic char * Xget_extrnl(up) Xint up; X{ X WINDOW *ge_win, *newwin(); X char *ans, *cmd, *get_str(), *expand(); X void st_line(); X X touchwin(stdscr); X refresh(); X st_line(""); X /* prompt for command line */ X ge_win = newwin(7, 70, 5, 5); X mvwaddstr(ge_win, 3, 4, "Enter Unix command: "); X box(ge_win, VERT, HORZ); X X if (up) X mvwattrstr(ge_win, 0, 3, A_BOLD, " Send (external) "); X else X mvwattrstr(ge_win, 0, 3, A_BOLD, " Receive (external) "); X X wmove(ge_win, 3, 24); X wrefresh(ge_win); X /* get the line */ X ans = get_str(ge_win, 60, "", "\n"); X if (ans == NULL || *ans == '\0') X cmd = NULL; X else X cmd = expand(ans); X X werase(ge_win); X wrefresh(ge_win); X delwin(ge_win); X return(cmd); X} SHAR_EOF if test 7594 -ne "`wc -c < 'x_menu.c'`" then echo shar: "error transmitting 'x_menu.c'" '(should have been 7594 characters)' fi fi echo shar: "extracting 'x_rcv.c'" '(12008 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 non-zero return code means the user must acknowledge X * an error condition (a user generated abort returns a 0). Write errors X * are considered fatal. X */ X X#include <stdio.h> X#include <curses.h> X#include "config.h" X#include "dial_dir.h" X#include "misc.h" X#include "xmodem.h" X Xunsigned char buf[1029]; Xchar file_name[15]; Xlong file_length; X Xstatic int err_method, tot_err, block_size; X Xint Xrcv_xmodem(win, list, type, fast) XWINDOW *win; Xchar *list; Xint type, fast; X{ X extern char *protocol[]; X FILE *fp, *my_fopen(); X int i, default_err, is_batch, max_block, code, file_count, got_hdr; X int hours, mins, secs, len; X long block, recv; X float percent, performance; X unsigned char blk; X unsigned int sleep(); X char *file, *name, *strcpy(), *strrchr(), *strtok(); X void cancel_xfer(); X /* which protocol? */ X switch (type) { X case XMODEM: X default_err = CRC_CHECKSUM; X is_batch = 0; X max_block = 128; X break; X case XMODEM_1k: X default_err = CRC_CHECKSUM; X is_batch = 0; X max_block = 1024; X break; X case MODEM7: X default_err = CHECKSUM; X is_batch = 1; X max_block = 128; X break; X case YMODEM: X default_err = CRC; X is_batch = 1; X max_block = 1024; X performance = 1.09; X break; X case YMODEM_G: X default_err = NONE; X is_batch = 1; X max_block = 1024; X performance = 1.02; X break; X default: X return(1); X } X X tot_err = 0; X file_count = 0; X mvwaddstr(win, 2, 24, protocol[type]); X mvwaddstr(win, 11, 24, "0 "); X X while (1) { X file_count++; X file_length = 0L; X /* user supplied name */ X if (!is_batch) { X if (file_count > 1) X break; X X file = strtok(list, " \t"); 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] == '\0') { 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] == '\0') X continue; X X clear_line(win, 3, 24, TRUE); X waddstr(win, file_name); X /* if file length is known */ X if (file_length != 0L) { X mvwprintw(win, 4, 24, "%-10ld", 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 != 0L && 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, TRUE); 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 modem7 X * or ymodem supplied name, the name is unique and the write X * permission on the directory is checked by the change_name() X * routines. However, this is required for systems with X * SETUID_BROKE set. X */ X /* open the file */ X if (!(fp = my_fopen(file, "w"))) { X beep(); X clear_line(win, 12, 24, TRUE); X wattrstr(win, A_BOLD, "CAN'T OPEN FILE"); X wrefresh(win); X cancel_xfer(DOWN_LOAD); 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 return(code +1); X } X /* here we go... */ X clear_line(win, 12, 24, TRUE); X waddstr(win, "NONE"); X wrefresh(win); X blk = 1; X block = 1L; X recv = 0L; 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 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 if (file_length != 0L) { X len = file_length - recv; X if (len > block_size) X len = block_size; X } X else X len = block_size; X X if (fwrite((char *) &buf[3], sizeof(char), len, fp) != len) { X beep(); X clear_line(win, 12, 24, TRUE); X wattrstr(win, A_BOLD, "WRITE ERROR"); X wrefresh(win); X cancel_xfer(DOWN_LOAD); X fclose(fp); X /* fatal */ X return(1); X } X mvwprintw(win, 7, 24, "%-5ld", block); X recv = recv + (unsigned int) len; X if (fast) X mvwprintw(win, 9, 24, "%-10ld", recv); 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 != 0L && 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 != 0L && fast) { X mvwaddstr(win, 8, 24, "100% "); X wrefresh(win); X } X /* X * If the file length is not known, search backwards from X * the end of the file until you find a character that is X * not the ^Z padding character. X */ X if (file_length == 0L) { X for (i=block_size+2; i>2; i--) { X if (buf[i] != CTRLZ) X break; X } X file_length = recv - (unsigned int) block_size + (unsigned int) i -2L; X fclose(fp); X if (fix_length(file, file_length)) { X beep(); X clear_line(win, 12, 24, TRUE); X wattrstr(win, A_BOLD, "TRUNCATE ERROR"); X wrefresh(win); X /* fatal */ X return(1); X } X } X else X fclose(fp); 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 Xstatic int 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 void cancel_xfer(); X /* default error method */ X err_method = default_err; X if (default_err == CRC_CHECKSUM) X err_method = CRC; 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) == ESC) { X beep(); X clear_line(win, 12, 24, TRUE); X waddstr(win, "ABORTED"); X wrefresh(win); X cancel_xfer(DOWN_LOAD); X sleep(3); X return(ABORT); X } X /* switch to checksum? */ X if (default_err == CRC_CHECKSUM && err_count > MAX_ERRORS/2) X err_method = CHECKSUM; X X /* send error method code */ X clear_line(win, 5, 24, TRUE); X switch (err_method) { X case CHECKSUM: X waddstr(win, "CHECKSUM"); X putc_line(NAK); X break; X case CRC: X waddstr(win, "CRC"); X putc_line('C'); X break; X case NONE: 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, TRUE); X waddstr(win, "NO RESPONSE"); X wrefresh(win); X continue; X } X buf[0] = i; X#ifdef DEBUG X fprintf(stderr, "send_first: got header %02x, %03o, %d\n", buf[0], buf[0], buf[0]); X#endif /* DEBUG */ 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, TRUE); X waddstr(win, "BAD HEADER"); X wrefresh(win); X /* read some garbage... */ X while(fread_line(buf, 1028, 1) != -1) X ; X putc_line(NAK); X break; X } X } X beep(); X clear_line(win, 12, 24, TRUE); 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; X unsigned short crc, calc_crc(); X unsigned int packet, sleep(); X unsigned char blk_compliment, calc_sum(), crc_1, crc_2; X void cancel_xfer(); 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) == ESC) { X beep(); X clear_line(win, 12, 24, TRUE); X waddstr(win, "ABORTED"); X wrefresh(win); X cancel_xfer(DOWN_LOAD); 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, TRUE); X waddstr(win, "NO RESPONSE"); X wrefresh(win); X continue; X } X buf[0] = i; X#ifdef DEBUG X fprintf(stderr, "rcv_block: got header %02x, %03o, %d\n", buf[0], buf[0], buf[0]); X#endif /* DEBUG */ X /* what'd we get? */ X switch (buf[0]) { X case EOT: /* we're done! */ X clear_line(win, 12, 24, TRUE); 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, TRUE); X waddstr(win, "BAD HEADER"); X wrefresh(win); X X /* read some garbage... */ X while(fread_line(buf, 1028, 1) != -1) X ; X putc_line(NAK); X continue; X } X } X /* read the rest of the packet */ X packet = block_size + 2 + (err_method == CHECKSUM ? 1 : 2); X if (fread_line(&buf[1], packet, 10) == -1) { X clear_line(win, 12, 24, TRUE); 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 blk_compliment = ~blk; X if (buf[1] != blk || buf[2] != blk_compliment) X out_of_sync++; X X bad_block = 0; X switch (err_method) { X case CHECKSUM: X#ifdef DEBUG X fprintf(stderr, "blk=%d, checksum=%d\n", blk, calc_sum(&buf[3], block_size)); X#endif /* DEBUG */ X if (buf[block_size +3] != calc_sum(&buf[3], block_size)) X bad_block++; X break; X case CRC: X crc = calc_crc(&buf[3], block_size); X crc_1 = crc >> 8; X crc_2 = crc; X#ifdef DEBUG X fprintf(stderr, "blk=%d, crc1=%d, crc2=%d\n", blk, crc_1, crc_2); X#endif /* DEBUG */ X if (buf[block_size +3] != crc_1 || buf[block_size +4] != crc_2) X bad_block++; X break; X case NONE: X return(0); X } X /* handle errors */ X if (bad_block) { X clear_line(win, 12, 24, TRUE); X if (err_method == CRC) 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, TRUE); 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, TRUE); X waddstr(win, "TOO MANY ERRORS"); X wrefresh(win); X cancel_xfer(DOWN_LOAD); X return(ERROR); X} SHAR_EOF if test 12008 -ne "`wc -c < 'x_rcv.c'`" then echo shar: "error transmitting 'x_rcv.c'" '(should have been 12008 characters)' fi fi echo shar: "extracting 'x_send.c'" '(11650 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 (a user generated abort returns a 0). X */ X X#include <stdio.h> X#include <curses.h> X#include <sys/types.h> X#include <sys/stat.h> X#include "config.h" X#include "dial_dir.h" X#include "misc.h" X#include "xmodem.h" X Xstatic int tot_err, err_method; X Xint Xsend_xmodem(win, list, type, fast) XWINDOW *win; Xchar *list; Xint type, fast; X{ X extern char *protocol[]; X FILE *fp, *my_fopen(); X int i, block_size, file_count, secs, mins, hours, big_blocks; X int small_blocks, err_count, got_it, num, is_batch, code; X int max_block, default_err; X long size, block, sent, xmit_size; X char *file, *strtok(), *name, *strrchr(); X unsigned short crc, calc_crc(); X unsigned char buf[1029], blk, calc_sum(); X unsigned int packet, sleep(); X float performance, percent; X struct stat stbuf; X /* which protocol? */ X switch (type) { X case XMODEM: X is_batch = 0; X default_err = CRC_CHECKSUM; X max_block = 128; X performance = 1.36; X break; X case XMODEM_1k: X is_batch = 0; X default_err = CRC_CHECKSUM; X max_block = 1024; X performance = 1.09; X break; X case MODEM7: X is_batch = 1; X default_err = CHECKSUM; X max_block = 128; X performance = 1.36; X break; X case YMODEM: X is_batch = 1; X default_err = CRC; X max_block = 1024; X performance = 1.09; X break; X case YMODEM_G: X is_batch = 1; X default_err = NONE; X max_block = 1024; X performance = 1.02; X break; X default: X return(1); X } X X tot_err = 0; X file_count = 0; X mvwaddstr(win, 2, 24, protocol[type]); X mvwaddstr(win, 11, 24, "0 "); X X /* each one in the list */ X file = strtok(list, " \t"); 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, TRUE); 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, &stbuf) < 0) { X beep(); X clear_line(win, 12, 24, TRUE); X wattrstr(win, A_BOLD, "CAN'T FIND FILE"); X wrefresh(win); X sleep(3); X continue; X } X /* sanity checking */ X if ((stbuf.st_mode & S_IFREG) != S_IFREG) { X beep(); X clear_line(win, 12, 24, TRUE); X wattrstr(win, A_BOLD, "NOT REGULAR FILE"); X wrefresh(win); X sleep(3); X continue; X } X X size = stbuf.st_size; X mvwprintw(win, 4, 24, "%-10ld", size); X clear_line(win, 5, 24, TRUE); X X if (!(fp = my_fopen(file, "r"))) { X beep(); X clear_line(win, 12, 24, TRUE); X wattrstr(win, A_BOLD, "PERMISSION DENIED"); 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 = ((unsigned int) big_blocks * 1024L) + ((unsigned int) small_blocks * 128L); X /* add block 0 to the size */ X if (type == YMODEM || type == YMODEM_G) X xmit_size += 128L; 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, TRUE); 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 -= 128L; 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 clear_line(win, 12, 24, TRUE); X waddstr(win, "NONE"); X wrefresh(win); X sent = 0L; X block = 1L; X blk = 1; X while (num = fread((char *) &buf[3], sizeof(char), 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, "%-5ld", block); X if (fast) { X percent = sent * 100.0 / xmit_size; X mvwprintw(win, 8, 24, "%0.1f%%", percent); X mvwprintw(win, 9, 24, "%-10ld", 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 CHECKSUM: X buf[block_size+3] = calc_sum(&buf[3], block_size); X#ifdef DEBUG X fprintf(stderr, "blk=%d, checksum=%d\n", blk, buf[block_size+3]); X#endif /* DEBUG */ X packet = block_size +4; X break; X case CRC: X crc = calc_crc(&buf[3], block_size); X buf[block_size+3] = crc >> 8; X buf[block_size+4] = crc; X#ifdef DEBUG X fprintf(stderr, "blk=%d, crc1=%d, crc2=%d\n", blk, buf[block_size+3], buf[block_size+4]); X#endif /* DEBUG */ X packet = block_size +5; X break; X case 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 = sent + (unsigned int) 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, "%-10ld", 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, TRUE); 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, " \t")); 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, "", 0L)) 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 Xstatic int Xrcv_first(win, default_err) XWINDOW *win; Xint default_err; X{ X int i, err_count; X unsigned int sleep(); X void cancel_xfer(); X X err_count = 0; X while (err_count < MAX_ERRORS) { X X /* scan the keyboard for abort */ X if (wgetch(win) == ESC) { X beep(); X clear_line(win, 12, 24, TRUE); X waddstr(win, "ABORTED"); X wrefresh(win); X cancel_xfer(UP_LOAD); X sleep(3); X return(ABORT); X } X /* scan the TTY line */ X i = getc_line(10); X#ifdef DEBUG X fprintf(stderr, "rcv_first: got \"%c\", %02x, %03o, %d\n", i, i, i, i); X#endif /* DEBUG */ X switch (i) { X case -1: /* timed out */ X clear_line(win, 12, 24, TRUE); X wattrstr(win, A_BOLD, "NO RESPONSE"); X err_count++; X break; X case NAK: /* checksum marker */ X if (default_err == CHECKSUM || default_err == CRC_CHECKSUM) { X mvwaddstr(win, 5, 24, "CHECKSUM"); X err_method = CHECKSUM; X return(0); X } X err_count++; X break; X case 'C': /* CRC marker */ X if (default_err == CRC_CHECKSUM || default_err == CRC) { X mvwaddstr(win, 5, 24, "CRC"); X err_method = CRC; X return(0); X } X err_count++; X break; X case 'G': /* ymodem-g marker */ X if (default_err == NONE) { X mvwaddstr(win, 5, 24, "NONE"); X err_method = NONE; 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, TRUE); X wattrstr(win, A_BOLD, "REMOTE ABORTED"); X wrefresh(win); X return(CANCEL); X } X err_count++; X break; X default: X clear_line(win, 12, 24, TRUE); X waddstr(win, "BAD HEADER"); X err_count++; X break; X } 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, TRUE); 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 extern int fd; X int i, err_count; X void cancel_xfer(); X X err_count = 0; X mvwaddstr(win, 10, 24, "0 "); X X while (err_count < MAX_ERRORS) { X /* write the block */ X write(fd, (char *) blk, packet); X /* scan the keyboard */ X if (wgetch(win) == ESC) { X beep(); X clear_line(win, 12, 24, TRUE); X waddstr(win, "ABORTED"); X wrefresh(win); X cancel_xfer(UP_LOAD); X sleep(3); X return(ABORT); X } X /* ymodem-g doesn't need ACKs */ X if (err_method == NONE) X return(0); X /* wait for acknowledge */ X i = getc_line(10); X#ifdef DEBUG X fprintf(stderr, "send_block: got \"%c\", %02x, %03o, %d\n", i, i, i, i); X#endif /* DEBUG */ X switch (i) { X case -1: /* timed out */ X clear_line(win, 12, 24, TRUE); X waddstr(win, "NO RESPONSE"); X err_count++; X tot_err++; X break; X case ACK: /* Hooray!! we got it */ X return(0); X case NAK: /* show our disappointment... */ X clear_line(win, 12, 24, TRUE); X if (err_method == CRC) 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, TRUE); 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, TRUE); X waddstr(win, "RESENDING"); X err_count++; X tot_err++; X break; X } X /* flush any pending garbage */ X tty_flush(fd, 0); 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, TRUE); X wattrstr(win, A_BOLD, "TOO MANY ERRORS"); X wrefresh(win); X cancel_xfer(UP_LOAD); X return(ERROR); X} SHAR_EOF if test 11650 -ne "`wc -c < 'x_send.c'`" then echo shar: "error transmitting 'x_send.c'" '(should have been 11650 characters)' fi fi echo shar: "extracting 'x_win.c'" '(2317 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 "config.h" X#include "dial_dir.h" X#include "misc.h" X#include "xmodem.h" X Xvoid Xxfer_win(list, up, type) Xchar *list; Xint up, type; X{ X extern int fd; X WINDOW *xf_win, *newwin(); X int ack_error, fast; X void xmodem_mode(), input_off(), line_set(), st_line(); X X touchwin(stdscr); X refresh(); X st_line(""); 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, TRUE); 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, VERT, HORZ); 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 X mvwaddstr(xf_win, 14, 11, " Press <ESC> to abort "); X wrefresh(xf_win); X /* fix up the terminal mode */ X input_off(); X xmodem_mode(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 fast = 0; X X if (my_speed() >= dir->baud[dir->d_cur]) X fast++; X X if (up) X ack_error = send_xmodem(xf_win, list, type, fast); X else X ack_error = rcv_xmodem(xf_win, list, type, fast); X X nodelay(xf_win, FALSE); X /* prompt for a key on errors */ X if (ack_error) { X beep(); X clear_line(xf_win, 13, 9, TRUE); 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 2317 -ne "`wc -c < 'x_win.c'`" then echo shar: "error transmitting 'x_win.c'" '(should have been 2317 characters)' fi fi echo shar: "extracting 'xmodem.c'" '(6553 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#define TMP_FILE "trunXXXXXX" X X#include <stdio.h> X#include <signal.h> X#include <sys/types.h> X#include <sys/stat.h> X#include "config.h" X#include "misc.h" X#include "param.h" X#include "xmodem.h" X X#ifdef BSD X#include <setjmp.h> Xjmp_buf gl_buf, rl_buf; X#endif /* BSD */ X X/* X * Calculate the CRC for the given buffer X */ X Xunsigned short Xcalc_crc(buf, len) Xunsigned char *buf; Xint len; X{ X register int i; X unsigned short crc; X static unsigned short crctab[256] = { X 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, X 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, X 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, X 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, X 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, X 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, X 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, X 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, X 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, X 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, X 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, X 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, X 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, X 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, X 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, X 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, X 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, X 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, X 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, X 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, X 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, X 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, X 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, X 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, X 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, X 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, X 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, X 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, X 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, X 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, X 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, X 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0}; X X crc = 0; X for (i=0; i<len; i++) X crc = (crc<<8) ^ crctab[(crc>>8) ^ *buf++]; X X return(crc); X} X X/* X * Calculate the checksum for the given buffer. X */ X Xunsigned char Xcalc_sum(buf, len) Xunsigned char *buf; Xint len; X{ X unsigned char sum; X X sum = 0; X while (--len >= 0) X sum += *buf++; X X return(sum); X} X X/* X * Get a single character from the line with a specified time-out period X * in seconds. If the function times-out, it returns a -1. X */ X Xstatic int gl_flag; X Xint Xgetc_line(sec) Xunsigned int sec; X{ X extern int fd; X int gl_force(); X char c; X unsigned int alarm(); X X signal(SIGALRM, gl_force); X gl_flag = 0; X X alarm(sec); X X#ifdef BSD X if (setjmp(gl_buf)) X return(-1); X#endif /* BSD */ X X if (read(fd, &c, 1) <= 0) { X alarm(0); X return(-1); X } X if (gl_flag) X return(-1); X alarm(0); X return(c & 0xff); X} X X/* ARGSUSED */ Xstatic int Xgl_force(dummy) Xint dummy; X{ X#ifdef BSD X longjmp(gl_buf, 1); X#else /* BSD */ X signal(SIGALRM, gl_force); X gl_flag = 1; X#endif /* BSD */ X} X X/* X * Same as above, but reads a bunch of characters. The return code is X * now just a success/fail indicator. X */ X Xstatic int rl_flag; X Xint Xfread_line(buf, len, sec) Xunsigned char *buf; Xunsigned int len, sec; X{ X extern int fd; X int n, rl_force(); X unsigned int try, alarm(); X X signal(SIGALRM, rl_force); X rl_flag = 0; X X alarm(sec); X while (len) { X /* read at most CLIST_SIZ chars */ X try = (len > CLIST_SIZ) ? CLIST_SIZ : len; X#ifdef BSD X if (setjmp(rl_buf)) X return(-1); X#endif /* BSD */ X if ((n = read(fd, (char *) buf, try)) <= 0) { X alarm(0); X return(-1); X } X if (rl_flag) X return(-1); X len -= n; X buf = buf + n; X } X alarm(0); X return(0); X} X X/* ARGSUSED */ Xstatic int Xrl_force(dummy) Xint dummy; X{ X#ifdef BSD X longjmp(rl_buf, 1); X#else /* BSD */ X signal(SIGALRM, rl_force); X rl_flag = 1; X#endif /* BSD */ X} X X/* X * Put a character on the TTY line. This serves no useful purpose other X * than making the code look pretty. X */ X Xint Xputc_line(c) Xunsigned char c; X{ X extern int fd; X X return(write(fd, (char *) &c, 1)); X} X X/* X * Cancel the file transfer. Send several ^X's to the remote, followed X * by an equal number of backspaces (in case they have already aborted and X * we're really at the command line). X */ X Xvoid Xcancel_xfer(up) Xint up; X{ X extern char file_name[15]; X X if (!up && !strcmp(param->abort, "DELETE")) X unlink(file_name); X X putc_line(CAN); X putc_line(CAN); X putc_line(CAN); X putc_line(BS); X putc_line(BS); X putc_line(BS); X return; X} X X/* X * Shorten a file to a predetermined length. Used to remove the ^Z X * padding from the end of files. (Heaven help us, if one day a binary X * file actually has ^Z's as part of the end of the file). X */ X Xint Xfix_length(file, len) Xchar *file; Xlong len; X{ X FILE *fp, *tempfp, *my_fopen(); X register int num; X char *mktemp(), tempfile[128], buf[BUFSIZ], *strcpy(); X char *s, *strrchr(), *strcat(); X struct stat stbuf; X X if (stat(file, &stbuf) < 0) X return(1); X /* see if we have any work to do */ X if (len >= stbuf.st_size) X return(0); X X if (!(fp = my_fopen(file, "r"))) X return(1); X X /* X * The temporary file should be in the same directory as the X * file being received because otherwise we'd have no way of X * guaranteeing they would be in the same file system. (Hard X * links across different file systems aren't allowed). X */ X strcpy(tempfile, file); X if (s = strrchr(tempfile, '/')) X *++s = '\0'; X else X strcpy(tempfile, "./"); X X strcat(tempfile, TMP_FILE); X mktemp(tempfile); X X if (!(tempfp = my_fopen(tempfile, "w"))) { X fclose(fp); X return(1); X } X X while (len != 0L) { X num = (len > BUFSIZ) ? BUFSIZ : len; X fread(buf, sizeof(char), num, fp); X if (fwrite(buf, sizeof(char), num, tempfp) != num) { X fclose(fp); X fclose(tempfp); X return(1); X } X len = len - (unsigned int) 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 6553 -ne "`wc -c < 'xmodem.c'`" then echo shar: "error transmitting 'xmodem.c'" '(should have been 6553 characters)' fi fi echo shar: "extracting 'xmodem.h'" '(561 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 NUM_INTERNAL 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#define EXT_1 6 X#define EXT_2 7 X#define EXT_3 8 X#define EXT_MANUAL 9 X X#define ABORT (-1) X#define ERROR (-2) X#define CANCEL (-3) X X#define CHECKSUM 0 X#define CRC_CHECKSUM 1 X#define CRC 2 X#define NONE 3 X X#define DOWN_LOAD 0 X#define UP_LOAD 1 SHAR_EOF if test 561 -ne "`wc -c < 'xmodem.h'`" then echo shar: "error transmitting 'xmodem.h'" '(should have been 561 characters)' fi fi exit 0 # End of shell archive
ssa@mrsvr.UUCP (Shahrooz S. Alavi) (02/07/89)
From article <6800110@fthood>, by egray@fthood.UUCP: || || This is part 3 (of 8) to the Pcomm v1.2 distribution package. || || Emmet P. Gray US Army, HQ III Corps & Fort Hood || ...!uunet!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: || # admin.c || # chg_dir.c || # config.h || # curses.c || # d_delete.c || # d_lib.c || # d_manual.c || # d_menu.c || # d_print.c || # d_prompt.c || # d_revise.c || # data_log.c || # di_delay.c || # This archive created: Fri Feb 3 07:35:21 1989 We did not get past d_prompt.c here , could someone repost it? Thanks, ======================================================================= / /| | |\ \ | | /__ /_| | |_\ \ | | ...att!uwmcsd1!mrsvr!ssa / / | | | \ \ | | (414) 547-9429 / o / | |__ | \ \| | (414) 521-6607 (work) =======================================================================