egray@killer.DALLAS.TX.US (Emmet Gray) (09/04/88)
Howdy netlanders! Well, here it is... hot off the presses. This is the new release of my Pcomm program. I'm sending out the source in 8 parts over a period of two days. Pcomm is a public domain telecommunication program for Unix designed to operate similar to the MSDOS program, ProComm. ProComm (TM) is copyrighted by Datastorm Technologies, Inc. This is the second release of Pcomm.... the v1.0 release appeared in unix-pc.sources (and in comp.sources.unix as v14i099 thru v14i105) many months ago. There is a file called Release.notes that describes the changes from the first release. Just like before, there is a shell archive called "Unixpc.shar" that contains the files that are specific to the AT&T Unix PC 7300/3b1. By the way... My "normal" machine is down for a few more days, so be careful on the return path for mail to me. This is part 1 (of 8) to the Pcomm v1.1 release package. Emmet P. Gray US Army, HQ III Corps & Fort Hood ..!uunet!uiucuxc!fthood!egray Attn: AFZF-DE-ENV osiris!hood DEH, Environmental Management Office ^temporary path 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: Sat Sep 3 15:46:10 1988 export PATH; PATH=/bin:/usr/bin:$PATH echo shar: "extracting 'Doc'" '(53982 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.1 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 Send files ........... 22 X 3.2 TTY setup ............ 8 6.2 Receive files ........ 23 X 3.3 Modem setup .......... 9 6.3 Pass thru mode ....... 24 X 3.4 Terminal setup ....... 10 6.4 Directory ............ 24 X 3.5 General setup ........ 11 6.5 Screen dump .......... 25 X 3.6 ASCII transfer setup . 12 6.6 Start data logging ... 25 X 6.7 Toggle logging ....... 25 X 4. MAJOR FUNCTIONS ....... 15 X 4.1 Dialing directory .... 15 7. DIALING WINDOW ........ 26 X 4.2 Redial ............... 17 X 4.3 Keyboard macros ...... 17 X 4.4 Line settings ........ 18 X 4.5 Exit Pcomm ........... 19 X 4.6 Unix gateway ......... 19 X X X X X X X Appendix A - Typical Modem Configuration ...... 27 X Appendix B - AT&T Unix PC 7300/3b1 Dial Codes . 28 X Appendix C - Using Telebit Trailblazers ....... 30 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 Automatic redial feature X +o Supports popular file transfer protocols 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 labled "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 three support files, namely: X X pcomm.dial_dir the dialing directory X pcomm.modem the modem/TTY database X pcomm.param the start-up default parameters X X There is a default directory (typically "/usr/local/lib/pcomm") X where the "standard" support files live. Since the average user X 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 The following directories are searched to find the support X files: X X +o directory given with the "-d" option X +o directory in the PCOMM environmental variable X +o the current working directory X +o the 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 index] 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 "index" 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. 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 is typical and shows the sub-menu choices: X X ------------------------ Setup Menu ---------------------------- X X 1) TTY Setup X 2) Modem Setup X 3) Terminal Setup X 4) General Setup X 5) ASCII Transfer Setup X S) Save setup to disk X X ---------------------------------------------------------------- X OPTION ==> _ Press <ESC> to exit X X To select one of the sub-menu choices, you 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 11) Add a TTY entry X 12) Delete a TTY entry X X ---------------------------------------------------------------- X OPTION ==> _ Press <ESC> to return X X You may edit an entry by typing the entry number at the prompt. X To add an entry, you type "11" 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 the screen. (The duplex mode can also be changed X "on 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 only used 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 prompts 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 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 Index/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 crest | X | 5- Last Chance 1 (219) 762-8411 2400-E-7-1 F | X | 6- Killer 1 (214) 827-1994 1200-E-7-1 F | X | 7- System A (direct) 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 Index. The string to be used to select this entry X with the "-f" command line option. This field is also X used to specify a particular TTY for the entry. X X NOTE: On all hard-wired ports, the index field must be set to X the name of the port. For example, if tty12 is a hard-wired X port to "System A", then the dialing directory entry for "System X A" will have "tty12" in the index field. X X The commands at the dialing directory prompt are: X X R) Revise (or add) a dialing directory entry or long 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. 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 phone number prompt of the manual dial X 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 NOTE: While a keyboard macro is being sent to the remote, the X incoming characters are temporarily suspended. This often X results in an awkward visual effect. 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 does not drop the DTR (Data Terminal Ready) during X a hang up. Therefore, this would have no effect on direct X lines. 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 (external) ? ? ? X X Notes: 1 CP/M style file name X 2 MSDOS style file name and file size X 3 Not needed! 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 Chuck X Forsberg's Zmodem (sz/rz/dsz) program. 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 NOTE: The protocols that send file name information, convert the X Unix style file name to fit the MSDOS name restrictions. X X 6.1 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) (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.2 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.3 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 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.4 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 know to the shell are valid. X X NOTE: Since we're really doing a popen() to the "ls" command, X additional command line options are also valid. X X 6.5 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 6.6 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.7 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 | Index/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, then that X number is 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 dailing 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 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: "46 control characters may be missing from 'Doc'" SHAR_EOF if test 53982 -ne "`wc -c < 'Doc'`" then echo shar: "error transmitting 'Doc'" '(should have been 53982 characters)' fi fi exit 0 # End of shell archive
egray@killer.DALLAS.TX.US (Emmet Gray) (09/04/88)
This is part 2 (of 8) to the Pcomm v1.1 release package. Emmet P. Gray US Army, HQ III Corps & Fort Hood ..!uunet!uiucuxc!fthood!egray Attn: AFZF-DE-ENV DEH, Environmental Management Office Fort Hood, TX 76544-5057 ------------------------------------------------------------------------------ #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # Readme # Release.notes # Makefile # Pcomm.1 # Pcomm.dial_dir # Pcomm.modem # Pcomm.param # Unixpc.shar # config.h # dial_dir.h # misc.h # modem.h # param.h # status.h # vcs.h # xmodem.h # This archive created: Sat Sep 3 15:34:53 1988 export PATH; PATH=/bin:/usr/bin:$PATH echo shar: "extracting 'Readme'" '(6391 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 to extract. There is a shell X archive called "Unixpc.shar" that contains additional (and X replacement) 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.modem, X and Pcomm.param to the default directory and rename them to X change the uppercase "P" to a lower case "p". The files should X *not* have write permission to all. X X 4) Copy (and rename as appropriate) the Pcomm.1 nroff manual to X the proper /usr/man 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 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). Some X versions of the AT&T Unix PC 7300/3b1 may X require this. X X SHAREDMEM If defined, keeps the virtual screen area in X shared memory rather than in a file. Some X performance gains are realized if shared memory X is used. 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 tweeking to detect what is X a long distance number. 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 the same as LPR. 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 would X typically be /usr/spool/locks. 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 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 2) Edit the Makefile. There are provisions in the Makefile to X include getcwd() and getopt() routines if they are missing from X your system. You may want to customize the CFLAGS, LDFLAGS, and X BIN assignments to suit your needs. X X 3) Compile pcomm and pcomm_input. Type "make". The Makefile X will attempt to install "pcomm" and "pcomm_input" into the BIN X directory given in the Makefile. However, those sites running X HDB UUCP software may require you to change the mode of "pcomm" X to be set-user-id to uucp. DO NOT CHANGE THE SET-UID/GID BITS X ON THE "pcomm_input" PROGRAM. 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) This program was written with AT&T System V in mind. It X makes use of System V specific routines such as shared memory X and the ioctl() calls of termio(7). There is currently no X port to Berkeley or v7 Unix. X X 2) 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"). Check your terminfo database... X X 3) 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 4) 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 5) Compilers that adhere to the draft ANSI C Standard will bark X at the declartions of signal(), perror(), malloc(), fread(), and X fwrite(). 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 6391 -ne "`wc -c < 'Readme'`" then echo shar: "error transmitting 'Readme'" '(should have been 6391 characters)' fi fi echo shar: "extracting 'Release.notes'" '(5256 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.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 recieve 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 5256 -ne "`wc -c < 'Release.notes'`" then echo shar: "error transmitting 'Release.notes'" '(should have been 5256 characters)' fi fi echo shar: "extracting 'Makefile'" '(3691 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 generic System V Unix X# X# for systems without getcwd(3) or getopt(3) X# X#GETCWD = getcwd.o X#GETOPT = getopt.o X XCFLAGS = -O X#CURSES = -ltermlib -lcurses XCURSES = -lcurses XLDFLAGS = -s XSHAR = shar -a XBIN = /usr/local/bin X XPCOMM = $(GETCWD) $(GETOPT) 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 expand.o help.o info.o \ X init.o line_set.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_gen.o s_menu.o s_modem.o s_prompt.o s_term.o s_tty.o screen.o \ X st_line.o strings.o terminal.o x_ascii.o x_batch.o x_extrnl.o \ X 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 install X Xpcomm: $(PCOMM) X $(CC) $(LDFLAGS) $(PCOMM) -o pcomm $(CURSES) X Xpcomm_input: $(INPUT) X $(CC) $(LDFLAGS) $(INPUT) -o pcomm_input $(CURSES) X Xinstall: X cp pcomm $(BIN) X# rm pcomm X cp pcomm_input $(BIN) X# rm pcomm_input X Xlint: X lint -p -Dlint *.c X Xshar: X cat Doc > pcomm_sh.1 X $(SHAR) Readme Release.notes Makefile Pcomm.1 Pcomm.dial_dir \ X Pcomm.modem Pcomm.param Unixpc.shar config.h dial_dir.h misc.h \ X modem.h param.h status.h vcs.h xmodem.h > pcomm_sh.2 X $(SHAR) admin.c chg_dir.c curses.c d_delete.c d_lib.c d_manual.c \ X d_menu.c d_print.c d_prompt.c d_revise.c data_log.c di_delay.c \ X > pcomm_sh.3 X $(SHAR) di_win.c dial.c expand.c getcwd.c getopt.c help.c info.c \ X init.c input.c line_set.c list_dir.c ls_menu.c > pcomm_sh.4 X $(SHAR) m_lib.c macro.c main.c n_shell.c p_lib.c passthru.c \ X pexit.c port.c redial.c > pcomm_sh.5 X $(SHAR) s_axfer.c s_gen.c s_menu.c s_modem.c s_prompt.c s_term.c \ X s_tty.c screen.c st_line.c strings.c terminal.c > pcomm_sh.6 X $(SHAR) vcs.c x_ascii.c x_batch.c x_extrnl.c x_menu.c x_rcv.c \ X > pcomm_sh.7 X $(SHAR) x_send.c x_win.c xmodem.c > 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 misc.h dial_dir.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 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 Xline_set.o: dial_dir.h param.h Xlist_dir.o: config.h misc.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 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_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 Xst_line.o: config.h dial_dir.h misc.h modem.h param.h status.h Xterminal.o: config.h dial_dir.h misc.h modem.h param.h status.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 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 SHAR_EOF if test 3691 -ne "`wc -c < 'Makefile'`" then echo shar: "error transmitting 'Makefile'" '(should have been 3691 characters)' fi fi echo shar: "extracting 'Pcomm.1'" '(7955 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 Xindex ] 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 "-d" option is used to specify an additional path to search for the XPcomm support files. X.PP XThe "-f" option is used to specify automatic dialing of an entry in the Xdialing directory. The "index" field in the dialing directory is Xchecked against the string given on the command line. If a match is Xfound, that entry is automatically dialed. X.PP XWhenever X.I Pcomm Xis in the command mode, a status line is displayed at the bottom of the Xscreen. The eight fields of the status line are: X.PP X.RS 5 X.nf 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.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 key" Xis control-A. The notatation "^A-X" means control-A followed by the Xletter X. The dash (-) is for clarity, and is not a part of the command Xsequence. 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 select an entry to dial, just enter the entry number at Xthe prompt. The following commands are available from the dialing Xdirectory: 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 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 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 X.fi X.RE X.PP XIn addition, X.I Pcomm Xcan use an external program, such as kermit or the sz/rz/dsz programs, Xto transfer files. 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 three Pcomm support files that contain the default parameters, Xthe modem/tty database, and dialing directory entries. Users may Xmaintain private versions of these files in a directory of their choice. X.I Pcomm Xuses the environmental variable PCOMM to search for these "private" Xversions. The following directories are searched to find the support Xfiles: X.PP X.RS 5 X.nf X+o directory given with the "-d" option X+o directory in the PCOMM environmental variable X+o current directory X+o default directory (compiled into Pcomm) X.fi X.RE X.PP XThe "index" field in the dialing directory serves two purposes. The Xfirst use is to act as a short cut into the dialing directory with Xthe "-f" command line option. The second use is to specify a tty name Xfor a given entry. If the "index" is a valid device name, that device Xis used instead of searching the tty database for a free port. X.SH FILES X.nf Xpcomm.dial_dir the dialing directory Xpcomm.modem the modem/tty database Xpcomm.param the start-up default parameters X.fi X.SH SEE ALSO XPcomm Reference Manual, xmodem(1), mdm(1) echo shar: "12 control characters may be missing from 'Pcomm.1'" SHAR_EOF if test 7955 -ne "`wc -c < 'Pcomm.1'`" then echo shar: "error transmitting 'Pcomm.1'" '(should have been 7955 characters)' fi fi echo shar: "extracting 'Pcomm.dial_dir'" '(320 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;crest XDIR_5=Last Chance;1 (219) 762-8411;2400-E-7-1;F; XDIR_6=Killer;1 (214) 827-1994;1200-E-7-1;F; XDIR_7=System A (direct);;19200-E-7-1;F;tty12 SHAR_EOF if test 320 -ne "`wc -c < 'Pcomm.dial_dir'`" then echo shar: "error transmitting 'Pcomm.dial_dir'" '(should have been 320 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 'Unixpc.shar'" '(12507 characters)' if test -f 'Unixpc.shar' then echo shar: "will not over-write existing file 'Unixpc.shar'" else sed 's/^X//' << \SHAR_EOF > 'Unixpc.shar' X#! /bin/sh X# This is a shell archive, meaning: X# 1. Remove everything above the #! /bin/sh line. X# 2. Save the resulting text in a file. X# 3. Execute the file with /bin/sh (not csh) to create: X# Ifile.sh X# Makefile X# Pcomm.modem X# Readme.7300 X# config.h X# This archive created: Wed Aug 24 22:01:02 1988 Xexport PATH; PATH=/bin:/usr/bin:$PATH Xecho shar: "extracting 'Ifile.sh'" '(705 characters)' Xif test -f 'Ifile.sh' Xthen X echo shar: "will not over-write existing file 'Ifile.sh'" Xelse Xsed 's/^X//' << \SHAR_EOF > 'Ifile.sh' XXex - $1 << EOF XX1,\$s/^PC/xPC/ XX1,\$s/^BC/xBC/ XX1,\$s/^UP/xUP/ XX1,\$s/^ospeed/xospeed/ XX1,\$s/^LINES/xLINES/ XX1,\$s/^COLS/xCOLS/ XX1,\$s/^tgetflag/xtgetflag/ XX1,\$s/^tgetent/xtgetent/ XX1,\$s/^tgetstr/xtgetstr/ XX1,\$s/^tgetnum/xtgetnum/ XX1,\$s/^tgoto/xtgoto/ XX1,\$s/^tputs/xtputs/ XX1,\$s/^wrefresh/xwrefresh/ XX1,\$s/^initscr/xinitscr/ XX1,\$s/^cbreak/xcbreak/ XX1,\$s/^nl/xnl/ XX1,\$s/^flushinp/xflushinp/ XX1,\$s/^noecho/xnoecho/ XX1,\$s/^savetty/xsavetty/ XX1,\$s/^resetty/xresetty/ XX1,\$s/^echo/xecho/ XX1,\$s/^nocbreak/xnocbreak/ XX1,\$s/^nonl/xnonl/ XX1,\$s/^keypad/xkeypad/ XX1,\$s/^endwin/xendwin/ XX1,\$s/^printw/xprintw/ XX1,\$s/^fixterm/xfixterm/ XX1,\$s/^resetterm/xresetterm/ XX1,\$s/^setterm/xsetterm/ XX1,\$s/^baudrate/xbaudrate/ XXw XXq XXEOF XSHAR_EOF Xif test 705 -ne "`wc -c < 'Ifile.sh'`" Xthen X echo shar: "error transmitting 'Ifile.sh'" '(should have been 705 characters)' Xfi Xfi Xecho shar: "extracting 'Makefile'" '(3891 characters)' Xif test -f 'Makefile' Xthen X echo shar: "will not over-write existing file 'Makefile'" Xelse Xsed 's/^X//' << \SHAR_EOF > 'Makefile' XX# Pcomm XX# for AT&T Unix PC 7300/3b1 XX# XX XXCFLAGS = -O XX#CURSES = -lcurses -ltermcap XXCURSES = -lcurses XXLD = ld -s XXSHAR = shar -a XXBIN = /usr/local/bin XX XXSHAREDLIB = shlib_c.ifile XX XXPCOMM = admin.o chg_dir.o curses.o d_delete.o d_lib.o d_manual.o \ XX d_menu.o d_print.o d_prompt.o d_revise.o data_log.o di_delay.o \ XX di_win.o dial.o expand.o help.o info.o init.o line_set.o \ XX list_dir.o ls_menu.o m_lib.o macro.o main.o n_shell.o p_lib.o \ XX passthru.o pexit.o port.o redial.o s_axfer.o s_gen.o s_menu.o \ XX s_modem.o s_prompt.o s_term.o s_tty.o screen.o st_line.o \ XX strings.o terminal.o x_ascii.o x_batch.o x_extrnl.o x_menu.o \ XX x_rcv.o x_send.o x_win.o xmodem.o XX XXINPUT = input.o vcs.o XX XXOTHERS = setvbuf.o doprnt.o XX XXall: pcomm pcomm_input install XX XXpcomm: $(PCOMM) $(OTHERS) $(SHAREDLIB) XX $(LD) $(PCOMM) $(OTHERS) $(CURSES) /lib/crt0s.o $(SHAREDLIB) -o pcomm XX XXpcomm_input: $(INPUT) $(OTHERS) $(SHAREDLIB) XX $(LD) $(INPUT) $(OTHERS) $(CURSES) /lib/crt0s.o $(SHAREDLIB) -o pcomm_input XX XXsetvbuf.o: XX ar x /lib/libc.a setvbuf.o XX XXdoprnt.o: XX ar x /lib/libc.a doprnt.o XX XXshlib_c.ifile: XX cp /lib/shlib.ifile shlib_c.ifile XX sh Ifile.sh shlib_c.ifile XX XXinstall: XX cp pcomm $(BIN) XX# rm pcomm XX cp pcomm_input $(BIN) XX# rm pcomm_input XX XXlint: XX lint -p -Dlint *.c XX XXshar: XX cat Doc > pcomm_sh.1 XX $(SHAR) Readme Release.notes Makefile Pcomm.1 Pcomm.dial_dir \ XX Pcomm.modem Pcomm.param Unixpc.shar config.h dial_dir.h misc.h \ XX modem.h param.h status.h vcs.h xmodem.h > pcomm_sh.2 XX $(SHAR) admin.c chg_dir.c curses.c d_delete.c d_lib.c d_manual.c \ XX d_menu.c d_print.c d_prompt.c d_revise.c data_log.c di_delay.c \ XX > pcomm_sh.3 XX $(SHAR) di_win.c dial.c expand.c getcwd.c getopt.c help.c info.c \ XX init.c input.c line_set.c list_dir.c ls_menu.c > pcomm_sh.4 XX $(SHAR) m_lib.c macro.c main.c n_shell.c p_lib.c passthru.c \ XX pexit.c port.c redial.c > pcomm_sh.5 XX $(SHAR) s_axfer.c s_gen.c s_menu.c s_modem.c s_prompt.c s_term.c \ XX s_tty.c screen.c st_line.c strings.c terminal.c > pcomm_sh.6 XX $(SHAR) vcs.c x_ascii.c x_batch.c x_extrnl.c x_menu.c x_rcv.c \ XX > pcomm_sh.7 XX $(SHAR) x_send.c x_win.c xmodem.c > 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 misc.h dial_dir.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 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 XXline_set.o: dial_dir.h param.h XXlist_dir.o: config.h misc.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 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_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 XXst_line.o: config.h dial_dir.h misc.h modem.h param.h status.h XXterminal.o: config.h dial_dir.h misc.h modem.h param.h status.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 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 3891 -ne "`wc -c < 'Makefile'`" Xthen X echo shar: "error transmitting 'Makefile'" '(should have been 3891 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'" '(3827 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.1 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. The Ifile.sh file is a shell script XX that is run by the Makefile to create this alternate file. The XX alternate file has the references to the TAM routines removed XX (actually, they just have an 'x' placed in the names). The XX actual shared library binaries are NOT altered. We just fool XX the linker into believing that the TAM 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 labled XX "Curses/Terminfo Programmer's Package" is a part of the "Unix XX Developement Set". Likewise, before Pcomm can be used, the XX terminfo database must be installed. The diskettes labled 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". I understand the older version of XX curses(3) is very buggy. 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 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 is to send a string to XX initialize the settings of the terminal and to set the tab XX stops. The fact that this program doesn't work 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 I understand that future version of Unix will have an option to XX the "tput" command to perform all the initialization with only XX one argument. Meanwhile, a somewhat longer solution is to edit XX /etc/profile and add the following commands at the bottom: XX XX eval `tput iprog` XX tput is1 XX tput is2 XX if [ -n "`tput tab`" ] ;then XX stty tabs XX else XX stty -tabs XX fi XX tabs XX cat -s "`tput if`" XX tpuf is3 XX echo "\r\c" XSHAR_EOF Xif test 3827 -ne "`wc -c < 'Readme.7300'`" Xthen X echo shar: "error transmitting 'Readme.7300'" '(should have been 3827 characters)' Xfi Xfi Xecho shar: "extracting 'config.h'" '(1584 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/* 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#undef 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/* 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 XSHAR_EOF Xif test 1584 -ne "`wc -c < 'config.h'`" Xthen X echo shar: "error transmitting 'config.h'" '(should have been 1584 characters)' Xfi Xfi Xexit 0 X# End of shell archive SHAR_EOF if test 12507 -ne "`wc -c < 'Unixpc.shar'`" then echo shar: "error transmitting 'Unixpc.shar'" '(should have been 12507 characters)' fi fi echo shar: "extracting 'config.h'" '(1582 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/* 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 "/usr/bin/lp" X X/* The path to the "pretty" printer program (if none, use same as LPR) */ X#define LPRINT "/usr/bin/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/* 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 SHAR_EOF if test 1582 -ne "`wc -c < 'config.h'`" then echo shar: "error transmitting 'config.h'" '(should have been 1582 characters)' fi fi echo shar: "extracting 'dial_dir.h'" '(870 characters)' if test -f 'dial_dir.h' then echo shar: "will not over-write existing file 'dial_dir.h'" else sed 's/^X//' << \SHAR_EOF > 'dial_dir.h' X/* X * The dialing directory structure. The first eight elements are X * contained in the pcomm.dial_dir file. X */ X X#define NUM_DIR 100 X#define NUM_QUEUE 10 X Xstruct DIAL_DIR { X char *name[NUM_DIR+1]; /* name of system being called */ X char *number[NUM_DIR+1]; /* phone number */ X int baud[NUM_DIR+1]; /* baud rate */ X char parity[NUM_DIR+1]; /* parity */ X int dbits[NUM_DIR+1]; /* data bits */ X int sbits[NUM_DIR+1]; /* stop bits */ X char duplex[NUM_DIR+1]; /* duplex (F = full, H = half) */ X char *index[NUM_DIR+1]; /* command line index (or TTY) */ X X int 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 870 -ne "`wc -c < 'dial_dir.h'`" then echo shar: "error transmitting 'dial_dir.h'" '(should have been 870 characters)' fi fi echo shar: "extracting 'misc.h'" '(1404 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#define BEL 7 X#define BS 8 X#define ESC 27 X#define DEL 127 SHAR_EOF if test 1404 -ne "`wc -c < 'misc.h'`" then echo shar: "error transmitting 'misc.h'" '(should have been 1404 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 '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 'status.h'" '(767 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 128 X#define PATH 128 X Xstruct STATUS { X int fd; /* file descriptor for TTY */ 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+1]; /* 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 767 -ne "`wc -c < 'status.h'`" then echo shar: "error transmitting 'status.h'" '(should have been 767 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 'xmodem.h'" '(464 characters)' if test -f 'xmodem.h' then echo shar: "will not over-write existing file 'xmodem.h'" else sed 's/^X//' << \SHAR_EOF > 'xmodem.h' X/* X * Definitions for the xmodem stuff. X */ X X#define MAX_ERRORS 10 X X#define SOH 1 X#define STX 2 X#define EOT 4 X#define ACK 6 X#define NAK 21 X#define CAN 24 X#define CTRLZ 26 X X#define PROTOCOLS 7 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 EXTRNL 6 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 SHAR_EOF if test 464 -ne "`wc -c < 'xmodem.h'`" then echo shar: "error transmitting 'xmodem.h'" '(should have been 464 characters)' fi fi exit 0 # End of shell archive
egray@killer.DALLAS.TX.US (Emmet Gray) (09/04/88)
This is part 3 (of 8) to the Pcomm v1.1 release package. Emmet P. Gray US Army, HQ III Corps & Fort Hood ..!uunet!uiucuxc!fthood!egray Attn: AFZF-DE-ENV DEH, Environmental Management Office Fort Hood, TX 76544-5057 ------------------------------------------------------------------------------ #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # admin.c # chg_dir.c # 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: Sat Sep 3 15:34:55 1988 export PATH; PATH=/bin:/usr/bin:$PATH echo shar: "extracting 'admin.c'" '(2880 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] = NULL; X date[16] = NULL; X X if (!(fp = fopen(LOGFILE, "a+"))) { 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 || !*grpbuf->gr_mem) X return(0); X /* are you in the group? */ X name = getlogin(); X for (; *grpbuf->gr_mem!=NULL; grpbuf->gr_mem++) { X if (!strcmp(*grpbuf->gr_mem, name)) X return(0); X } X /* numbers only... */ X number = build_num(i); X X /* X * VERY SITE SPECIFIC!!! We use a "9" to get an outside line, X * so any 9 followed by a 1 is a toll call (except for 1-800 X * numbers). X */ X if (!strncmp(number, "91", 2) && strncmp(number, "91800", 5)) { X error_win(0, "You are not authorized to place long distance \(toll\) calls", ""); X return(1); X } X X if (*number == NULL) { X error_win(0, "You are not authorized direct access to the line", "Use the automatic dialing feature"); X return(1); X } X#endif /* LIMIT_LD */ X return(0); X} X X#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[40], *strcpy(), *strcat(); X static char ans[40]; X X temp[0] = NULL; X /* add LD codes? */ X switch (dir->q_ld[i]) { X case 0: X break; X case '+': X strcpy(temp, param->ld_plus); X break; X case '-': X strcpy(temp, param->ld_minus); X break; X case '@': X strcpy(temp, param->ld_at); X break; X case '#': X strcpy(temp, param->ld_pound); X break; X } X /* add the number */ X strcat(temp, dir->number[dir->q_num[i]]); X X /* copy only digits */ X j = 0; X t = temp; X while (*t) { X if (*t >= '0' && *t <= '9') X ans[j++] = *t; X t++; X } X ans[j] = NULL; X X return(ans); X} X#endif /* LOG_CALLS || LIMIT_LD */ SHAR_EOF if test 2880 -ne "`wc -c < 'admin.c'`" then echo shar: "error transmitting 'admin.c'" '(should have been 2880 characters)' fi fi echo shar: "extracting 'chg_dir.c'" '(1305 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 void free_ptr(); X X cwd = getcwd(cwdbuf, 200); X X ch_win = newwin(6, 70, 5, 5); X X mvwprintw(ch_win, 2, 4, "Current directory: %s", cwd); X mvwaddstr(ch_win, 3, 4, "New directory: "); X box(ch_win, 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, 60, "", " ")) != NULL) { X /* a CR means no change */ X if (*ans == NULL) 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 free_ptr(dir); X break; X } 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, 1); X clear_line(ch_win, 4, 14, 1); X wmove(ch_win, 3, 19); X wrefresh(ch_win); X free_ptr(dir); X } X if (fd == -1) { X werase(ch_win); X wrefresh(ch_win); X } X delwin(ch_win); X return; X} SHAR_EOF if test 1305 -ne "`wc -c < 'chg_dir.c'`" then echo shar: "error transmitting 'chg_dir.c'" '(should have been 1305 characters)' fi fi echo shar: "extracting 'curses.c'" '(8404 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#include <stdio.h> X#include <curses.h> X#include <signal.h> X#include "config.h" X#ifdef OLDCURSES X#include <fcntl.h> X#else /* OLDCURSES */ X#include <term.h> X#endif /* OLDCURSES */ X#include "misc.h" X X/* X * Get a string from a window. Similar to wgetstr(), except we limit X * the length, return a NULL (not pointer to NULL) on <ESC> key, beep X * at any character in "disallow" string, and beep at any character not X * in "allow". (It doesn't make sense to use both "allow" and "disallow" X * at the same time) X */ X Xchar * Xget_str(win, num, allow, disallow) XWINDOW *win; Xint num; Xchar *allow, *disallow; X{ X int count, x, y; X char ans, *strchr(); X static char buf[80]; X X count = 0; X while ((ans = wgetch(win)) != '\r') { X /* do our own backspace */ X if (ans == BS) { X if (!count) { X beep(); X continue; X } X count--; X buf[count] = NULL; X getyx(win, y, x); X x--; X wmove(win, y, x); X waddch(win, (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 != NULL && strchr(disallow, ans)) { X beep(); X continue; X } X if (*allow != NULL && !strchr(allow, ans)) { X beep(); X continue; X } X /* exceeded the max? */ X if (count == num) { X beep(); X continue; X } X X buf[count] = ans; X waddch(win, (chtype) ans); X wrefresh(win); X count++; X } X buf[count] = NULL; X return(buf); X} X X/* X * Get a number from a window. We limit the length and return a -1 X * on <ESC> key. X */ X Xint Xget_num(win, num) XWINDOW *win; Xint num; X{ X int count, x, y, number; X char ans, buf[80]; X X count = 0; X while ((ans = wgetch(win)) != '\r') { X /* do our own backspace */ X if (ans == BS) { X if (!count) { X beep(); X continue; X } X count--; X buf[count] = NULL; X getyx(win, y, x); X x--; X wmove(win, y, x); X waddch(win, (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) { X beep(); X continue; X } X X buf[count] = ans; X waddch(win, (chtype) ans); X wrefresh(win); X count++; X } X buf[count] = NULL; X number = atoi(buf); X return(number); X} X X/* X * Change video attributes while printing a string. The use of the X * pre-processor definition NOPROMOTE (located in 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 == NULL) X return(0); X X#ifdef OLDCURSES X if (attr) X wstandout(win); X waddstr(win, str); X if (attr) X wstandend(win); X#else /* OLDCURSES */ X#ifdef NOPROMOTE X /* does the capability exist? */ X do_it = 0; X if ((attr & A_STANDOUT) && enter_standout_mode) X do_it++; X if ((attr & A_UNDERLINE) && enter_underline_mode) X do_it++; X if ((attr & A_REVERSE) && (enter_reverse_mode || enter_standout_mode)) X do_it++; X if ((attr & A_BLINK) && enter_blink_mode) X do_it++; X if ((attr & A_BOLD) && enter_bold_mode) X do_it++; X if ((attr & A_DIM) && enter_dim_mode) X do_it++; X#else /* NOPROMOTE */ X do_it = 1; X#endif /* NOPROMOTE */ X X if (do_it) X wattron(win, attr); X /* print the string */ X waddstr(win, str); X if (do_it) X wattroff(win, attr); X#endif /* OLDCURSES */ X return(0); X} X X/* X * Change video attributes while printing a character. X */ X Xwattrch(win, attr, c) XWINDOW *win; Xchtype attr; Xchar c; X{ X int do_it; X X if (c == NULL) X return(0); X#ifdef OLDCURSES X if (attr) X wstandout(win); X waddch(win, (chtype) c); X if (attr) X wstandend(win); X#else /* OLDCURSES */ X#ifdef NOPROMOTE X /* does the capability exist? */ X do_it = 0; X if ((attr & A_STANDOUT) && enter_standout_mode) X do_it++; X if ((attr & A_UNDERLINE) && enter_underline_mode) X do_it++; X if ((attr & A_REVERSE) && (enter_reverse_mode || enter_standout_mode)) X do_it++; X if ((attr & A_BLINK) && enter_blink_mode) X do_it++; X if ((attr & A_BOLD) && enter_bold_mode) X do_it++; X if ((attr & A_DIM) && enter_dim_mode) X do_it++; X#else /* NOPROMOTE */ X do_it = 1; X#endif /* NOPROMOTE */ X X if (do_it) X wattron(win, attr); X /* print the character */ X waddch(win, (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[20]; X X sprintf(buf, "%d", num); X X#ifdef OLDCURSES X if (attr) X wstandout(win); X waddstr(win, buf); X if (attr) X wstandend(win); X#else /* OLDCURSES */ X#ifdef NOPROMOTE X /* does the capability exist? */ X do_it = 0; X if ((attr & A_STANDOUT) && enter_standout_mode) X do_it++; X if ((attr & A_UNDERLINE) && enter_underline_mode) X do_it++; X if ((attr & A_REVERSE) && (enter_reverse_mode || enter_standout_mode)) X do_it++; X if ((attr & A_BLINK) && enter_blink_mode) X do_it++; X if ((attr & A_BOLD) && enter_bold_mode) X do_it++; X if ((attr & A_DIM) && enter_dim_mode) X do_it++; X#else /* NOPROMOTE */ X do_it = 1; X#endif /* NOPROMOTE */ X X if (do_it) X wattron(win, attr); X /* print the character */ X waddstr(win, buf); X if (do_it) X wattroff(win, attr); X#endif /* OLDCURSES */ X return(0); X} X X/* X * Prompt for a Yes or No answer. Echo the single key input as words. X * Handle the funny cursor movement problems with magic cookie terminals. X * Returns a 1 on yes. X */ X Xint Xyes_prompt(win, y, x, attr, str) XWINDOW *win; Xint y, x; Xchtype attr; Xchar *str; X{ X int save, ret_code; X char new_str[80], *strcpy(), *strcat(); X /* build and display the prompt */ X strcpy(new_str, str); X strcat(new_str, "? (y/n):"); X mvwattrstr(win, y, x, attr, new_str); X wmove(win, y, strlen(new_str)+x+2); X wrefresh(win); X X ret_code = -1; X while (ret_code == -1) { X save = wgetch(win); X switch (save) { 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 Xint Xwait_key(win, sec) XWINDOW *win; Xunsigned int sec; X{ X int key, wk_force(); X unsigned int alarm(); X#ifdef WGETCH_BROKE X char c; X#endif /* WGETCH_BROKE */ X X signal(SIGALRM, wk_force); X wk_flag = 0; X X alarm(sec); X#ifdef WGETCH_BROKE X read(0, &c, 1); X key = c; X#else /* WGETCH_BROKE */ X key = wgetch(win); X#endif /* WGETCH_BROKE */ X if (wk_flag) X return(-1); X alarm(0); X return(key); X} X/*ARGSUSED*/ Xstatic int Xwk_force(dummy) Xint dummy; X{ X wk_flag = 1; X} X X/* X * Here are some routines that are probably missing from the older X * flavors of curses(3). X */ X X#ifdef OLDCURSES X/* X * Make the terminal bell go off X */ X Xint Xbeep() X{ X fputc(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 Xint Xnodelay(win, flag) XWINDOW *win; Xint flag; X{ X if (flag) X fcntl(0, F_SETFL, fcntl(0, F_GETFL, 0) | O_NDELAY); X else X fcntl(0, F_SETFL, fcntl(0, F_GETFL, 0) & ~O_NDELAY); X return(0); X} X X/* X * Take the terminal out of the "curses mode" X */ X Xint Xresetterm() X{ X resetty(); X return(0); X} X X/* X * Put the terminal back into the "curses mode" X */ X Xint Xmyputchar(c) Xchar c; X{ X return(putchar(c)); X} Xint Xfixterm() X{ X int myputchar(); X extern char *TI, *VS; X X tputs(TI, 1, myputchar); X tputs(VS, 1, myputchar); X nonl(); X crmode(); X noecho(); X return(0); X} X#endif /* OLDCURSES */ SHAR_EOF if test 8404 -ne "`wc -c < 'curses.c'`" then echo shar: "error transmitting 'curses.c'" '(should have been 8404 characters)' fi fi echo shar: "extracting 'd_delete.c'" '(2009 characters)' if test -f 'd_delete.c' then echo shar: "will not over-write existing file 'd_delete.c'" else sed 's/^X//' << \SHAR_EOF > 'd_delete.c' X/* X * The delete option of the dialing directory. Prompts for saving X * changes to disk. A return code of 1 means that entries were deleted. X */ X X#include <stdio.h> X#include <curses.h> X#include "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->index[i]); X dir->name[i] = null_ptr; X dir->number[i] = null_ptr; X dir->baud[i] = param->d_baud; X dir->parity[i] = param->d_parity; X dir->dbits[i] = param->d_dbits; X dir->sbits[i] = param->d_sbits; X dir->duplex[i] = *param->d_duplex; X dir->index[i] = null_ptr; X } X delwin(d_win); X return(1); X } X delwin(d_win); X return(0); X} SHAR_EOF if test 2009 -ne "`wc -c < 'd_delete.c'`" then echo shar: "error transmitting 'd_delete.c'" '(should have been 2009 characters)' fi fi echo shar: "extracting 'd_lib.c'" '(6787 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, j, oops; X char *strdup(), buf[80], *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 i = 0; X oops = 0; X while (fgets(buf, 80, fp) != NULL) { X i++; X if (i > NUM_DIR) X break; X /* get the token */ X if (!(temp_token = str_tok(buf, '='))) { X sprintf(message, "is missing a token at line %d", i); X oops++; X break; X } X /* X * Parse the rest of the line. This is similar to using X * the "real" strtok() function, but my version returns X * a null pointer if the parameter is missing. Note the X * array of field separators. X */ X for (j=0; j<8; j++) { X if (!(str = str_tok((char *) NULL, sep[j]))) { X sprintf(message, "is missing a parameter at line %d", i); X oops++; X break; X } X switch (j) { X case 0: X d.name[i] = strdup(str); X break; X case 1: X d.number[i] = strdup(str); X break; X case 2: X d.baud[i] = atoi(str); X break; X case 3: X d.parity[i] = *str; X break; X case 4: X d.dbits[i] = atoi(str); X break; X case 5: X d.sbits[i] = atoi(str); X break; X case 6: X d.duplex[i] = *str; X break; X case 7: X d.index[i] = strdup(str); X break; X } X } X if (oops) X break; X /* sanity checking */ X sprintf(token, "DIR_%d", i); X if (strcmp(temp_token, token)) { X sprintf(message, "is corrupted at line %d", i); X oops++; X break; X } X } X fclose(fp); X X if (oops) { X sprintf(buf, "Dialing directory file '%s'", d.d_path); X error_win(1, buf, message); X } X d.d_entries = i; X /* if empty database */ X if (!i) { 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 i++; X for (; i<=NUM_DIR; i++) { X d.name[i] = null_ptr; X d.number[i] = null_ptr; X d.baud[i] = param->d_baud; X d.parity[i] = param->d_parity; X d.dbits[i] = param->d_dbits; X d.sbits[i] = param->d_sbits; X d.duplex[i] = *param->d_duplex; X d.index[i] = null_ptr; X } X /* create an empty "manual" entry */ X d.name[0] = null_ptr; X d.number[0] = null_ptr; X d.baud[0] = param->d_baud; X d.parity[0] = param->d_parity; X d.dbits[0] = param->d_dbits; X d.sbits[0] = param->d_sbits; X d.duplex[0] = *param->d_duplex; X d.index[0] = null_ptr; X /* create an empty queue */ X for (i=0; i<NUM_QUEUE; i++) { X d.q_ld[i] = NULL; X d.q_num[i] = -1; X } X /* the 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 return code of 1 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[80], *strdup(); 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, 80, fp_in) != NULL) X temp[++i] = strdup(buf); X X fclose(fp_in); X /* alter only 1 entry */ X sprintf(buf, "DIR_%d=%s;%s;%d-%c-%d-%d;%c;%s\n", entry, X dir->name[entry], dir->number[entry], dir->baud[entry], X dir->parity[entry], dir->dbits[entry], dir->sbits[entry], X dir->duplex[entry], dir->index[entry]); X X if (entry <= dir->d_entries) X free_ptr(temp[entry]); X temp[entry] = strdup(buf); X /* fill in holes if beyond end */ X if (entry > dir->d_entries+1) { X for (i=dir->d_entries+1; i<entry; i++) { X sprintf(buf, "DIR_%d=;;%d-%c-%d-%d;%c;\n", i, X param->d_baud, param->d_parity, param->d_dbits, X param->d_sbits, *param->d_duplex); X temp[i] = strdup(buf); X } X } X /* update "dir->d_entries" */ X if (entry > dir->d_entries) X dir->d_entries = entry; X X /* open for 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 return code X * of 1 means a non-fatal error. X */ X Xint Xdel_dir(first, last) Xint first, last; X{ X FILE *fp_in, *fp_out, *my_fopen(); X int i; X char *temp[NUM_DIR+1], buf[80], *strdup(); X void error_win(), free_ptr(); X /* sanity checking */ X if (first > dir->d_entries) X return(0); X if (last > dir->d_entries) X last = dir->d_entries; X X /* open for read */ X if (!(fp_in = 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, 80, fp_in) != NULL) X temp[++i] = strdup(buf); X X fclose(fp_in); X /* delete the range of values */ X for (i=first; i<=last; i++) { X sprintf(buf, "DIR_%d=;;%d-%c-%d-%d;%c;\n", i, param->d_baud, X param->d_parity, param->d_dbits, param->d_sbits, X *param->d_duplex); X free_ptr(temp[i]); X temp[i] = strdup(buf); X } X /* shrink the file? */ X if (last >= dir->d_entries) { X for (i=first; i<=last; i++) X free_ptr(temp[i]); X dir->d_entries = first-1; X } X /* open for write */ X if (!(fp_out = 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 6787 -ne "`wc -c < 'd_lib.c'`" then echo shar: "error transmitting 'd_lib.c'" '(should have been 6787 characters)' fi fi echo shar: "extracting 'd_manual.c'" '(1920 characters)' if test -f 'd_manual.c' then echo shar: "will not over-write existing file 'd_manual.c'" else sed 's/^X//' << \SHAR_EOF > 'd_manual.c' X/* X * The manual dial option of the dialing directory. A return code of X * 1 means we're ready to dial. Dialing directory entry 0 is reserved X * for the manual dial option. No sanity checking is done on the input. X */ X X#include <stdio.h> X#include <curses.h> X#include "config.h" X#include "misc.h" X#include "dial_dir.h" X Xint Xmanual() X{ X extern int xmc; X extern char *null_ptr; X WINDOW *m_win, *newwin(); X char *number, *strdup(), *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, "", "")) == NULL) { X werase(m_win); X wrefresh(m_win); X delwin(m_win); X if (xmc > 0) X fix_xmc(); X return(0); X } X /* is first char an LD code? */ X ld_code = NULL; X if (strchr("+-@#", *number)) { X ld_code = *number; X number++; X } X /* put it in the queue */ X dir->q_ld[0] = ld_code; X dir->q_num[0] = 0; X /* end of queue marker */ X dir->q_num[1] = -1; X dir->d_cur = 0; X /* build the entry zero */ X free_ptr(dir->name[0]); X free_ptr(dir->number[0]); X dir->name[0] = strdup(number); X /* if space, change to null */ X if (!strcmp(number, " ")) X dir->number[0] = null_ptr; X else X dir->number[0] = strdup(number); X /* it overlaps dm_win, so erase it */ X werase(m_win); X wrefresh(m_win); X delwin(m_win); X if (xmc > 0) X fix_xmc(); X return(1); X} X X/* X * Clear the end of the physical screen where the magic cookie got shifted X * Geez, I hate magic cookie terminals... Wyse, are you listening? X */ X 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 1920 -ne "`wc -c < 'd_manual.c'`" then echo shar: "error transmitting 'd_manual.c'" '(should have been 1920 characters)' fi fi echo shar: "extracting 'd_menu.c'" '(6921 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 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, current, 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 Index/TTY "); X /* show the first 10 entries */ X dir_scroll(dm_win, 1); X X mvwaddstr(dm_win, 15, 4, "==>"); X mvwattrch(dm_win, 15, 14, A_BOLD, 'R'); X waddstr(dm_win, " Revise"); X mvwattrch(dm_win, 15, 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#ifndef OLDCURSES X keypad(dm_win, TRUE); X#endif /* OLDCURSES */ X /* prompt for options */ X current = 1; X count = 0; X ld_code = NULL; X ret_code = 0; X do { X needs_repair = 0; X ans = wgetch(dm_win); X /* get an entry number */ X if (ans >= '0' && ans <= '9') { X if (count > 2) { X beep(); X continue; X } X buf[count] = ans; X waddch(dm_win, (chtype) ans); X wrefresh(dm_win); X count++; X continue; X } X switch (ans) { X case BS: /* do our own backspace */ X if (!count) { X beep(); X break; X } X count--; X if (!count) X ld_code = NULL; X buf[count] = NULL; X getyx(dm_win, y, x); X x--; X wmove(dm_win, y, x); X waddch(dm_win, (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] = NULL; X i = atoi(buf); X if (!i || i > NUM_DIR) { X beep(); X mvwaddstr(dm_win, 15, 8, " "); X x = 8; X count = 0; X break; X } X dir->q_ld[0] = ld_code; X dir->q_num[0] = i; X dir->d_cur = i; X X /* end of queue marker */ X dir->q_num[1] = -1; X X ret_code++; 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, 0); X clear_line(dm_win, 3, 0, 0); X wrefresh(dm_win); X mvwattrstr(dm_win, 1, 20, A_BOLD, "D I A L I N G D I R E C T O R Y"); X mvwattrstr(dm_win, 3, 0, A_STANDOUT, " Name Number Baud P D S Dpx Index/TTY "); X box(dm_win, 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 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->index[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 pointer means not active */ X if (*param->ld_plus != NULL) X waddstr(win, "+ "); X if (*param->ld_minus != NULL) X waddstr(win, "- "); X if (*param->ld_at != NULL) X waddstr(win, "@ "); X if (*param->ld_pound != NULL) X waddstr(win, "# "); X return; X} SHAR_EOF if test 6921 -ne "`wc -c < 'd_menu.c'`" then echo shar: "error transmitting 'd_menu.c'" '(should have been 6921 characters)' fi fi echo shar: "extracting 'd_print.c'" '(3496 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#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(); X WINDOW *p_win, *newwin(); X char *file, *e_get_str(), buf[80]; X int is_printer, i, can; X void error_win(); X unsigned int sleep(); X X p_win = newwin(5, 54, 0, 26); X X mvwaddstr(p_win, 2, 3, "Print to: (printer)"); X box(p_win, 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 ((file = e_get_str(p_win, 40)) == NULL) { X /* erase because it overlaps dm_win */ X werase(p_win); X wrefresh(p_win); X delwin(p_win); X return; X } X is_printer = 0; X /* the default (printer) */ X if (*file == NULL) { X if (!(fp = popen(LPRINT, "w"))) { X sprintf(buf, "'%s'", LPRINT); X error_win(0, "Can't open printer 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 we X * have write permission too). Currently only allows X * you to bail out or overwrite the file. X */ X if (!(can = can_write(file))) { X sprintf(buf, "'%s'", file); X error_win(0, "No write permission on file", buf); X werase(p_win); X wrefresh(p_win); X delwin(p_win); X return; X } X if (can == 2) { X werase(p_win); X mvwprintw(p_win, 2, 3, "File '%s' already exists!", file); X beep(); X box(p_win, 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 } X fp = fopen(file, "w"); 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->index[i]); X X if (is_printer) X pclose(fp); X else { X /* a dramatic delay... */ X sleep(1); X fclose(fp); X } X X werase(p_win); X wrefresh(p_win); X delwin(p_win); X return; X} X X/* X * Get a string from a window but erase the line first. X */ X 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[80]; X X done_it = 0; X count = 0; X while ((ans = wgetch(win)) != '\r') { X /* do our own backspace */ X if (ans == BS) { X if (!count) { X beep(); X continue; X } X count--; X buf[count] = NULL; X getyx(win, y, x); X x--; X wmove(win, y, x); X waddch(win, (chtype) ' '); X wmove(win, y, x); X wrefresh(win); X continue; X } X /* exceeded the max? */ X if (count == num) { X beep(); X continue; X } X /* an <ESC> anywhere in the string */ X if (ans == 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] = NULL; X return(buf); X} SHAR_EOF if test 3496 -ne "`wc -c < 'd_print.c'`" then echo shar: "error transmitting 'd_print.c'" '(should have been 3496 characters)' fi fi echo shar: "extracting 'd_prompt.c'" '(6003 characters)' if test -f 'd_prompt.c' then echo shar: "will not over-write existing file 'd_prompt.c'" else sed 's/^X//' << \SHAR_EOF > 'd_prompt.c' X/* X * Prompt for directory entry changes. Copies the original values in X * case you change your mind half way thru. A return code of 1 means X * the entry was changed. X */ X X#include <stdio.h> X#include <curses.h> X#include "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], index[40]; X char parity, duplex, *strdup(), *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(index, dir->index[i]); X /* display original values */ X werase(win); X mvwprintw(win, 2, 5, "%-20.20s %18.18s %5d-%c-%d-%d %c %-14.14s\n", X dir->name[i], dir->number[i], dir->baud[i], dir->parity[i], X dir->dbits[i], dir->sbits[i], dir->duplex[i], dir->index[i]); X box(win, VERT, HORZ); X X /* prompt for name */ X mvwaddstr(win, 4, 4, "Name: "); X wrefresh(win); X X if ((ans = get_str(win, 20, "", ";")) == NULL) X return(0); X if (*ans != NULL) { 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, 1); X waddstr(win, "Number: "); X wrefresh(win); X X if ((ans = get_str(win, 18, "", ";")) == NULL) X return(0); X if (*ans != NULL) { X strcpy(number, ans); X mvwaddstr(win, 2, 26, " "); X wrefresh(win); X /* X * Should be right justified, but we don't wanna to have X * the attribute turned on for blanks. X */ X spot = 26 + 18 - strlen(number); X mvwattrstr(win, 2, spot, A_BOLD, number); X } X /* template for next few */ X clear_line(win, 4, 4, 1); X mvwaddstr(win, 4, 31, "(Any key to change, <CR> to accept)"); X X /* X * These next few prompts display a series of choices and allow X * the user to hit a return to accept the currently showing X * value. The first value displayed is always the current value. X */ X /* choose from baud menu */ X for (n=0; n<6; n++) { X if (valid_baud[n] == baud) X break; X } X mvwprintw(win, 4, 4, "Baud: %-5d", valid_baud[n]); X wmove(win, 4, 10); X wrefresh(win); X X while ((c = wgetch(win)) != '\r') { X if (c == 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 command line index */ X clear_line(win, 4, 4, 1); X waddstr(win, "Command line index (or TTY): "); X wrefresh(win); X X if ((ans = get_str(win, 14, "", ";")) == NULL) X return(0); X if (*ans != NULL) { X strcpy(index, ans); X mvwaddstr(win, 2, 62, " "); X wrefresh(win); X mvwattrstr(win, 2, 62, A_BOLD, index); X } X /* store 'em for real */ X free_ptr(dir->name[i]); X free_ptr(dir->number[i]); X free_ptr(dir->index[i]); X X if (!strcmp(name, " ")) X dir->name[i] = null_ptr; X else X dir->name[i] = strdup(name); X if (!strcmp(number, " ")) X dir->number[i] = null_ptr; X else X dir->number[i] = strdup(number); X dir->baud[i] = baud; X dir->parity[i] = parity; X dir->dbits[i] = dbits; X dir->sbits[i] = sbits; X dir->duplex[i] = duplex; X if (!strcmp(index, " ")) X dir->index[i] = null_ptr; X else X dir->index[i] = strdup(index); X X return(1); X} SHAR_EOF if test 6003 -ne "`wc -c < 'd_prompt.c'`" then echo shar: "error transmitting 'd_prompt.c'" '(should have been 6003 characters)' fi fi echo shar: "extracting 'd_revise.c'" '(4006 characters)' if test -f 'd_revise.c' then echo shar: "will not over-write existing file 'd_revise.c'" else sed 's/^X//' << \SHAR_EOF > 'd_revise.c' X/* X * The revise option of the dialing directory. A return code of 1 means X * that something was updated. Prompts for saving changes to disk. X */ X X#include <stdio.h> X#include <curses.h> X#include "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(), *strdup(); X void free_ptr(); X X r_win = newwin(7, 77, 7, 2); X X mvwaddstr(r_win, 3, 6, "Entry to revise?"); X mvwaddstr(r_win, 3, 35, "(Entry Number, +, -, @, #)"); X box(r_win, 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] = NULL; X num = atoi(buf); X /* valid range of numbers? */ X if (num == 0 || num > NUM_DIR) { X beep(); X mvwaddstr(r_win, 3, 23, " "); X wmove(r_win, 3, 23); X wrefresh(r_win); X count = 0; X continue; X } X /* prompt for that entry */ X if (prompt_lib(r_win, num)) { X dir_flag++; X break; X } X delwin(r_win); X return(0); X } X /* do our own backspace */ X if (ans == BS) { X if (!count) { X beep(); X continue; X } X count--; X buf[count] = NULL; X getyx(r_win, y, x); X x--; X wmove(r_win, y, x); X waddch(r_win, (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 free_ptr(param->ld_plus); X param->ld_plus = strdup(ld); X param_flag++; X } X break; X case '-': X if ((ld = ld_prompt(r_win, param->ld_minus, ans)) != NULL) { X free_ptr(param->ld_minus); X param->ld_minus = strdup(ld); X param_flag++; X } X break; X case '@': X if ((ld = ld_prompt(r_win, param->ld_at, ans)) != NULL) { X free_ptr(param->ld_at); X param->ld_at = strdup(ld); X param_flag++; X } X break; X case '#': X if ((ld = ld_prompt(r_win, param->ld_pound, ans)) != NULL) { X free_ptr(param->ld_pound); X param->ld_pound = strdup(ld); X param_flag++; X } X break; X default: X beep(); X continue; X } X break; X } X /* if nothing changed */ X if (!param_flag && !dir_flag) { X delwin(r_win); X return(0); X } X /* save to disk? */ X clear_line(r_win, 4, 4, 1); X if (dir_flag) { X sprintf(buf, "Save entry %d to disk", num); X save = yes_prompt(r_win, 4, 4, A_BOLD, buf); X } X else X save = yes_prompt(r_win, 4, 4, A_BOLD, "Save to disk"); X X /* update the files */ X if (save && dir_flag) { X if (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 a null pointer. Returns the new value or NULL on escape. 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, "", "")) == NULL) X return(NULL); X /* if space, change to NULL pointer */ X if (!strcmp(ans, " ")) X ans = null_ptr; X /* display new value */ X clear_line(win, 2, 4, 1); X wattrstr(win, A_BOLD, ans); X X return(ans); X} SHAR_EOF if test 4006 -ne "`wc -c < 'd_revise.c'`" then echo shar: "error transmitting 'd_revise.c'" '(should have been 4006 characters)' fi fi echo shar: "extracting 'data_log.c'" '(1801 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 return code of 1 means we X * 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 extern char *null_ptr; X int ret_code; X WINDOW *dl_win, *newwin(); X char *ans, *path, *expand(), *get_str(), *strdup(), *strcpy(); X void input_off(), free_ptr(); X X dl_win = newwin(6, 70, 5, 5); X X mvwprintw(dl_win, 2, 4, "Default log file: %s", param->logfile); X mvwaddstr(dl_win, 3, 4, "New log file: "); X box(dl_win, 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 path = null_ptr; X while ((ans = get_str(dl_win, 60, "", " ")) != NULL) { X /* give 'em the default */ X if (*ans == NULL) X path = strdup(param->logfile); X else X path = expand(ans); X X /* test write permission */ X if (can_write(path)) { X ret_code++; X break; X } X X beep(); X mvwattrstr(dl_win, 4, 24, A_BOLD, "No write permission"); X wrefresh(dl_win); X wait_key(dl_win, 3); X /* clean up the mess */ X clear_line(dl_win, 3, 18, 1); X clear_line(dl_win, 4, 24, 1); X wmove(dl_win, 3, 18); X wrefresh(dl_win); X } X if (ret_code) { X 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 free_ptr(path); X return(ret_code); X} SHAR_EOF if test 1801 -ne "`wc -c < 'data_log.c'`" then echo shar: "error transmitting 'data_log.c'" '(should have been 1801 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, 20, "%-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@killer.DALLAS.TX.US (Emmet Gray) (09/05/88)
This is part 4 (of 8) to the Pcomm v1.1 release package. Emmet P. Gray US Army, HQ III Corps & Fort Hood ..!uunet!uiucuxc!fthood!egray Attn: AFZF-DE-ENV DEH, Environmental Management Office Fort Hood, TX 76544-5057 ------------------------------------------------------------------------------ #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # di_win.c # dial.c # expand.c # getcwd.c # getopt.c # help.c # info.c # init.c # input.c # line_set.c # list_dir.c # ls_menu.c # This archive created: Sat Sep 3 15:34:58 1988 export PATH; PATH=/bin:/usr/bin:$PATH echo shar: "extracting 'di_win.c'" '(9165 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 return code of 1 means X * 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(), send_str(), 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(1); X X touchwin(stdscr); X refresh(); X X if (get_port()) X return(0); X /* X * If the phone number is a NULL, then either we are on a X * direct line, or you want to do the dialing yourself. X */ X if (*dir->number[dir->q_num[0]] == NULL) { X /* check LD permission */ X if (limit_ld(0)) X return(0); X /* can't talk directly to OBM */ X if (!strcmp(modem->mname[modem->m_cur], "OBM")) { X error_win(0, "Can't access the 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, 25, "Index/TTY:"); X mvwaddstr(di_win, 12, 16, "Result of last try:"); X X mvwaddstr(di_win, 14, 3, "<SPACE>: Recycle"); X mvwaddstr(di_win, 14, 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] = NULL; 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 ioctl(fd, TCFLSH, 0); X X /* X * Here we do a time-slice between reading the result codes X * from the modem and reading the keyboard. The one second X * granularity won't be too accurate, but who cares? X */ X tic = 0; X rc_index = 0; X while (tic < param->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, 1); X wattrstr(di_win, A_BLINK, "CONNECTED"); X wmove(di_win, 12, 36); X wrefresh(di_win); X wait_key(di_win, 2); X delwin(di_win); X X /* X * Did the modem sync at a different baud X * rate than what we expected? X */ X if (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(0); 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, 1); X mvwaddstr(di_win, 6, 27, "Pausing:"); X /* no return code? */ X if (str == NULL) { X clear_line(di_win, 12, 36, 1); X waddstr(di_win, "TIMED OUT"); X wmove(di_win, 12, 36); X } X /* do the pause */ X tic = 0; X while (tic < param->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, 1); 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, 1); X waddstr(di_win, "RECYCLED"); X wmove(di_win, 12, 36); X wrefresh(di_win); X /* fall thru... */ X case -1: /* no key was pressed */ X i++; X if (i > NUM_QUEUE) X i = 0; X if (dir->q_num[i] == -1) X i = 0; X break; X case DEL: /* <DEL> key, remove from queue */ X if (dir->q_num[1] == -1) { X beep(); X clear_line(di_win, 12, 36, 1); X waddstr(di_win, "NO MORE ENTRIES"); X wmove(di_win, 12, 36); X wrefresh(di_win); X wait_key(di_win, 3); X break; X } X clear_line(di_win, 12, 36, 1); X waddstr(di_win, "ENTRY DELETED"); X wmove(di_win, 12, 36); X wrefresh(di_win); X wait_key(di_win, 3); X X /* compact the queue */ X for (j=i; j<NUM_QUEUE-1; j++) X dir->q_num[j] = dir->q_num[j+1]; X dir->q_num[NUM_QUEUE-1] = -1; X break; X case 'e': X case 'E': /* change delay time */ X delay_times(); X touchwin(di_win); X mvwprintw(di_win, 9, 36, "%-4d", param->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, 1); X wattrstr(di_win, A_BLINK, "DIAL ABORTED"); X wmove(di_win, 12, 36); X wrefresh(di_win); X wait_key(di_win, 3); X want_out++; X break; X default: X beep(); X break; X } X } X /* clean up and go home */ X werase(di_win); X wrefresh(di_win); X delwin(di_win); X if (!want_out) X error_win(0, "Exceeded the maximum number number of dialing attempts", ""); 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, 1); X waddstr(win, dir->name[entry]); X /* pass number */ X mvwprintw(win, 5, 36, "%-4d", pass); X /* time of this call */ X time(&now); X tbuf = ctime(&now); X tbuf[19] = NULL; X mvwaddstr(win, 8, 36, &tbuf[11]); X /* the index field */ X clear_line(win, 11, 36, 1); X waddstr(win, dir->index[entry]); X X wmove(win, 12, 36); X wrefresh(win); X return; X} X X/* X * 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 return code of 1 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 == NULL) 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 9165 -ne "`wc -c < 'di_win.c'`" then echo shar: "error transmitting 'di_win.c'" '(should have been 9165 characters)' fi fi echo shar: "extracting 'dial.c'" '(7336 characters)' if test -f 'dial.c' then echo shar: "will not over-write existing file 'dial.c'" else sed 's/^X//' << \SHAR_EOF > 'dial.c' X/* X * The routines that dial the modem and listen for the return codes. X */ X X#include <stdio.h> X#include <termio.h> X#include "config.h" X#ifdef UNIXPC X#include <sys/phone.h> X#endif /* UNIXPC */ X#include "dial_dir.h" X#include "misc.h" X#include "modem.h" X#include "param.h" X X/* X * Get the dial string ready, send it to the modem. The parameter is not X * the actual entry number, it is an index into the queue. X */ X Xvoid Xdial_it(num) Xint num; X{ X 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] = NULL; X strcpy(s, modem->dial[modem->m_cur]); X X switch (dir->q_ld[num]) { X case 0: /* no ld code requested */ X break; X case '+': X strcat(s, param->ld_plus); X break; X case '-': X strcat(s, param->ld_minus); X break; X case '@': X strcat(s, param->ld_at); X break; X case '#': X strcat(s, param->ld_pound); X break; X } X /* X * Purify the phone number by removing all the pretty characters X * that don't need to be sent to the modem. Typically the "-", X * "(", ")", and space characters are just for looks. 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] = NULL; 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); X return; X} X X/* X * Send a string to the modem. Performs all the character synonym X * translations. No sanity checking on the "m_cur" value. X */ X Xvoid Xsend_str(s) Xchar *s; X{ X extern int fd; X int skip; X unsigned int sleep(); X /* empty string? */ X if (s == NULL || *s == NULL) X return; X X ioctl(fd, TCFLSH, 1); X /* X * Change the character synonyms to their real values. Writes X * the characters to the modem. To remove the special meaning X * of one of the characters, prepend a "\" to it. X */ X skip = 0; X while (*s) { X /* send the literal character */ X if (skip) { X skip = 0; X write(fd, s, 1); X ioctl(fd, TCSBRK, 1); 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 == NULL) 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 ioctl(fd, TCSBRK, 0); 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 ioctl(fd, TCSBRK, 1); X s++; X } X return; X} X X/* X * Read the result codes coming back from the modem. Test for the 6 X * "connect" strings and the 4 "no connect" strings. Return the connected X * baud rate (as a string) or the error message. X */ X Xchar rc_buf[512]; Xint rc_index; X Xchar * Xread_codes() X{ X extern int fd; 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 ((int) (c = getc_line(1)) <= 0) X return(NULL); X#ifdef DEBUG X fprintf(stderr, "read_codes: '%c', %02x, %03o, %d\n", c, c, c, c); X#endif /* DEBUG */ X X rc_buf[rc_index] = c; X rc_buf[rc_index+1] = NULL; X /* the connect strings */ X if (match(rc_buf, modem->con_3[modem->m_cur])) X return("300"); X X if (match(rc_buf, modem->con_12[modem->m_cur])) X return("1200"); X X if (match(rc_buf, modem->con_24[modem->m_cur])) X return("2400"); X X if (match(rc_buf, modem->con_48[modem->m_cur])) X return("4800"); X X if (match(rc_buf, modem->con_96[modem->m_cur])) X return("9600"); X X if (match(rc_buf, modem->con_192[modem->m_cur])) X return("19200"); X X /* the no connect strings */ X if (match(rc_buf, modem->no_con1[modem->m_cur])) X return(modem->no_con1[modem->m_cur]); X X if (match(rc_buf, modem->no_con2[modem->m_cur])) X return(modem->no_con2[modem->m_cur]); X X if (match(rc_buf, modem->no_con3[modem->m_cur])) X return(modem->no_con3[modem->m_cur]); X X if (match(rc_buf, modem->no_con4[modem->m_cur])) X return(modem->no_con4[modem->m_cur]); X } X /* ran out of buffer? */ X return("ERROR"); X} X X/* X * Test for a match between two character strings. A return code of 1 X * means that s2 was found at the end of s1. X */ X 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 == NULL) 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 == NULL) 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] = NULL; X X diff = strlen(s1) - strlen(new); X /* is it possible? */ X if (diff < 0) X return(0); X /* test it out */ X if (!strcmp(&s1[diff], new)) X return(1); X return(0); X} SHAR_EOF if test 7336 -ne "`wc -c < 'dial.c'`" then echo shar: "error transmitting 'dial.c'" '(should have been 7336 characters)' fi fi echo shar: "extracting 'expand.c'" '(2683 characters)' if test -f 'expand.c' then echo shar: "will not over-write existing file 'expand.c'" else sed 's/^X//' << \SHAR_EOF > 'expand.c' X/* X * Do file name expansion with "native" shell. Using the native shell X * (as described in the SHELL environmental variable) allows for csh or X * ksh abbreviations that sh doesn't recognize. X */ X X#include <stdio.h> X#include <signal.h> X#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 *ans, buf[1024], *strpbrk(), *strdup(); X void free_ptr(); X X /* same rules as strdup() */ X if (input == NULL) X return(NULL); X if (*input == NULL) X return(null_ptr); X /* any thing to expand? */ X ans = strdup(input); X if (!strpbrk(input, "$*{}[]\\?~")) X return(ans); X /* popen an echo */ X sprintf(buf, "echo %s", input); X X pfp = n_popen(buf, "r"); X fgets(buf, 1024, pfp); X n_pclose(pfp); X X if (!strlen(buf)) X return(ans); 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(buf) -1; X if (buf[last] != '\n') X return(ans); X else X buf[last] = NULL; X X free_ptr(ans); X ans = strdup(buf); X return(ans); X} X X#define tst(a,b) (*mode == 'r'? (b) : (a)) X#define RDR 0 X#define WTR 1 Xstatic int popen_pid[20]; X XFILE * 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 == NULL) X shellpath = "/bin/sh"; X X shell = strrchr(shellpath, '/') + 1; X /* fix up the flags */ X if (!strcmp(shell, "csh")) X flags = "-fc"; X else X flags = "-c"; /* Korn shell too */ X X if (!(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 int f, r, (*hstat)(), (*istat)(), (*qstat)(), status; X X f = fileno(ptr); X fclose(ptr); X istat = signal(SIGINT, SIG_IGN); X qstat = signal(SIGQUIT, SIG_IGN); X hstat = signal(SIGHUP, SIG_IGN); X X while ((r = wait(&status)) != popen_pid[f] && r != -1) X ; X X if (r == -1) X status = -1; X X signal(SIGINT, istat); X signal(SIGQUIT, qstat); X signal(SIGHUP, hstat); X return(status); X} SHAR_EOF if test 2683 -ne "`wc -c < 'expand.c'`" then echo shar: "error transmitting 'expand.c'" '(should have been 2683 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] = NULL; 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'" '(1034 characters)' if test -f 'getopt.c' then echo shar: "will not over-write existing file 'getopt.c'" else sed 's/^X//' << \SHAR_EOF > 'getopt.c' X/* X * Parse the command line and return option flags and arguments X */ X X#include <stdio.h> X Xint optind = 1; Xchar *optarg; X Xint Xgetopt(argc, argv, opts) Xint argc; Xchar *argv[]; Xchar *opts; X{ X static int sp = 1; X int c, strcmp(); X char *cp, *strchr(); X X if (sp == 1) { X if (optind >= argc || argv[optind][0] != '-' || argv[optind][1] == '\0') X return(EOF); X else if (strcmp(argv[optind], "--") == NULL) { X optind++; X return(EOF); X } X } X c = argv[optind][sp]; X if (c == ':' || (cp=strchr(opts, c)) == NULL) { X fprintf(stderr, "%s: illegal option '%c'\n", argv[0], c); X if (argv[optind][++sp] == '\0') { X optind++; X sp = 1; X } X return('?'); X } X if (*++cp == ':') { X if (argv[optind][sp+1] != '\0') X optarg = &argv[optind++][sp+1]; X else if (++optind >= argc) { X fprintf(stderr, "%s: option '%c' requires an argument\n", argv[0], c); X sp = 1; X return('?'); X } else X optarg = argv[optind++]; X sp = 1; X } else { X if (argv[optind][++sp] == '\0') { X sp = 1; X optind++; X } X optarg = NULL; X } X return(c); X} SHAR_EOF if test 1034 -ne "`wc -c < 'getopt.c'`" then echo shar: "error transmitting 'getopt.c'" '(should have been 1034 characters)' fi fi echo shar: "extracting 'help.c'" '(1802 characters)' if test -f 'help.c' then echo shar: "will not over-write existing file 'help.c'" else sed 's/^X//' << \SHAR_EOF > 'help.c' X/* X * Display the help screen. Press any key to continue. If the ascii_hot X * string is more than 4 characters wide, this screen will look silly. X * Maybe one day, this will also contain page-full descriptions of each X * command. X */ X X#include <stdio.h> X#include <curses.h> X#include "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 wmove(h_win, 16, 79); X wrefresh(h_win); X X wgetch(h_win); X if (fd == -1) { X werase(h_win); X wrefresh(h_win); X } X delwin(h_win); X return; X} SHAR_EOF if test 1802 -ne "`wc -c < 'help.c'`" then echo shar: "error transmitting 'help.c'" '(should have been 1802 characters)' fi fi echo shar: "extracting 'info.c'" '(1532 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.1" X#define DATE "21 Aug 88" X X#include <stdio.h> X#include <curses.h> X Xvoid Xinfo(delay) Xint delay; 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 (delay) 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 1532 -ne "`wc -c < 'info.c'`" then echo shar: "error transmitting 'info.c'" '(should have been 1532 characters)' fi fi echo shar: "extracting 'init.c'" '(2944 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 the STATUS structure. All errors are fatal. X */ X X#include <stdio.h> X#include <curses.h> X#include "config.h" X#ifdef SHAREDMEM X#include <sys/types.h> X#include <sys/ipc.h> X#include <sys/shm.h> X#endif /* SHAREDMEM */ X#include "misc.h" X#include "status.h" X Xstruct STATUS * Xinit(short_cut) Xchar *short_cut; X{ X char *mktemp(), *strcpy(); X struct STATUS *s_ptr; X void info(); X#ifdef SHAREDMEM X int i, j, mode; X extern int shm_id; X char *shmat(); X void 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 static struct STATUS s; X s_ptr = &s; X#endif /* SHAREDMEM */ X /* some defaults */ X s_ptr->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#ifdef SHAREDMEM X s_ptr->clr = 0; X s_ptr->row = 0; X s_ptr->col = 0; X for (i=0; i<LINES; i++) { X for (j=0; j<COLS; j++) X s_ptr->vs[i][j] = ' '; X s_ptr->vs[i][COLS] = NULL; X } X#else /* SHAREDMEM */ X strcpy(s_ptr->vs_path, mktemp("/tmp/pcommXXXXXX")); X#endif /* SHAREDMEM */ X /* display herald if no short-cut */ X if (short_cut == NULL) X info(1); 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(), *strdup(); X char temp[200]; X X /* see if PCOMM variable is set */ X pcomm = getenv("PCOMM"); X if (pcomm == NULL || *pcomm == NULL) X pcomm = NULL; X else { X /* zap the trailing separator */ X if (pcomm[strlen(pcomm)-1] == '/') X pcomm[strlen(pcomm)-1] = NULL; X } X X for (i=0; i<4; i++) { X /* directory search order */ X switch (i) { X case 0: /* 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(strdup(temp)); X } X return(NULL); X} SHAR_EOF if test 2944 -ne "`wc -c < 'init.c'`" then echo shar: "error transmitting 'init.c'" '(should have been 2944 characters)' fi fi echo shar: "extracting 'input.c'" '(10147 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#define CLIST 64 X X#include <stdio.h> X#include <signal.h> X#include <setjmp.h> X#include "config.h" X#ifdef SHAREDMEM X#include <sys/types.h> X#include <sys/ipc.h> X#include <sys/shm.h> X#endif /* SHAREDMEM */ X#define MAIN X#include "misc.h" X#include "status.h" X#include "vcs.h" 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+2]; 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 int got_sig(); X char c, *strcpy(); X void _exit(), exit(), vcs_table(); X#ifdef SHAREDMEM X int shm_id; X char *shmat(); 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 /* unbuffered output */ 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#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) X max_col = MAX_COL; X /* parse the command line */ X#ifndef SHAREDMEM X status->fd = atoi(argv[1]); X status->add_lf = atoi(argv[2]); X status->log = atoi(argv[3]); X status->print = atoi(argv[4]); X strcpy(status->log_path, argv[5]); X strcpy(status->vs_path, argv[6]); X#endif /* SHAREDMEM */ X X skip_row = 0; 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 pause(); 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 * 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 X while (1) { X if ((int) (c = readbyte()) <= 0) X continue; 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 putchar(c); X /* add LF to CR? */ X if (c == '\r' && status->add_lf) X putchar('\n'); X } X} X X/* X * Figure out which signal we just received, and fix the return code of X * the setjmp function above to the proper value. X */ X Xint Xgot_sig(sig) Xint sig; X{ X void longjmp(); X 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 Xint Xvs_putchar(c) Xchar c; X{ X register int j, i; X int tab_stop; 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 for (i=VCOL; i<max_col; i++) X VS[VROW][i] = ' '; X break; X case 256+CLR_EOS: /* clear to end of screen */ X for (j=VCOL; j<max_col; j++) X VS[VROW][j] = ' '; X for (i=VROW+1; i<max_row; i++) { X for (j=0; j<max_col; j++) X VS[i][j] = ' '; X } X break; X case 256+CLEAR: /* clear all and home "cursor" */ X for (i=0; i<max_row; i++) { X for (j=0; j<max_col; j++) X VS[i][j] = ' '; X } 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 '\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 for (; VCOL<max_col; VCOL++) X VS[VROW][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 for (; VCOL<tab_stop; VCOL++) X VS[VROW][VCOL] = ' '; 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(0); 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] = NULL; X fprintf(fp, "%s\n", VS[i]); X } X fclose(fp); X return(0); X} X X/* X * Get the virtual screen image from the file. Since input() gets X * killed from time to time, the vs_path file is the only way to retain X * the screen image. X */ X Xint Xread_vs() 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 scanf(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+2, fp); X VS[i][max_col] = NULL; 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 Xint Xvs_clear() X{ X register int j, i; X X for (i=0; i<max_row; i++) { X VS[i][max_col] = NULL; X for (j=0; j<max_col; j++) X VS[i][j] = ' '; X } X /* home the "cursor" */ X VROW = 0; X VCOL = 0; X return(0); X} X X/* X * Do a software scroll on the virtual screen. Does not alter the X * "col" variable. X */ X Xint Xvs_scroll() X{ X register int i; X char *strcpy(); X /* move 'em up 1 line */ X for (i=0; i<max_row-1; i++) X strcpy(VS[i], VS[i+1]); X /* clear the bottom line */ X for (i=0; i<max_col; i++) X VS[max_row-1][i] = ' '; X X VROW = max_row -1; X return(0); X} X X/* X * Do a buffered read from the serial port. X */ X Xint Xreadbyte() X{ X static char buf[CLIST]; X static char *bufp = buf; X static int n = 0; X X if (n <= 0) { X if ((n = read(status->fd, buf, CLIST)) <= 0) X return(-1); X bufp = buf; X } X while (--n >= 0) X return(*bufp++ & 0xff); X return(-1); X} SHAR_EOF if test 10147 -ne "`wc -c < 'input.c'`" then echo shar: "error transmitting 'input.c'" '(should have been 10147 characters)' fi fi echo shar: "extracting 'line_set.c'" '(1944 characters)' if test -f 'line_set.c' then echo shar: "will not over-write existing file 'line_set.c'" else sed 's/^X//' << \SHAR_EOF > 'line_set.c' X/* X * Change the communication line settings to the new values. X */ X X#include <stdio.h> X#include <termio.h> X#include "dial_dir.h" X#include "param.h" X 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, TCSETA, &tbuf); X ioctl(fd, TCFLSH, 2); X return; X} SHAR_EOF if test 1944 -ne "`wc -c < 'line_set.c'`" then echo shar: "error transmitting 'line_set.c'" '(should have been 1944 characters)' fi fi echo shar: "extracting 'list_dir.c'" '(1508 characters)' if test -f 'list_dir.c' then echo shar: "will not over-write existing file 'list_dir.c'" else sed 's/^X//' << \SHAR_EOF > 'list_dir.c' X/* X * Do a shell escape with an "ls" command X */ X X#include <stdio.h> X#include <curses.h> X#include "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, 60, "", "")) == NULL) { X if (fd == -1) { X werase(ls_win); X wrefresh(ls_win); X } X delwin(ls_win); X return; X } X /* popen() an ls */ X sprintf(buf, "ls -aC %s", ans); X pfp = 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 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 1508 -ne "`wc -c < 'list_dir.c'`" then echo shar: "error transmitting 'list_dir.c'" '(should have been 1508 characters)' fi fi echo shar: "extracting 'ls_menu.c'" '(4809 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 return X * code of 1 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, 1); X wrefresh(win); X } X mvwattrstr(win, 4, 8, A_BOLD, buf); X return; X} SHAR_EOF if test 4809 -ne "`wc -c < 'ls_menu.c'`" then echo shar: "error transmitting 'ls_menu.c'" '(should have been 4809 characters)' fi fi exit 0 # End of shell archive
egray@killer.DALLAS.TX.US (Emmet Gray) (09/05/88)
This is part 5 (of 8) to the Pcomm v1.1 release package. Emmet P. Gray US Army, HQ III Corps & Fort Hood ..!uunet!uiucuxc!fthood!egray Attn: AFZF-DE-ENV DEH, Environmental Management Office Fort Hood, TX 76544-5057 ------------------------------------------------------------------------------ #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # m_lib.c # macro.c # main.c # n_shell.c # p_lib.c # passthru.c # pexit.c # port.c # redial.c # This archive created: Sat Sep 3 15:35:00 1988 export PATH; PATH=/bin:/usr/bin:$PATH echo shar: "extracting 'm_lib.c'" '(10070 characters)' if test -f 'm_lib.c' then echo shar: "will not over-write existing file 'm_lib.c'" else sed 's/^X//' << \SHAR_EOF > 'm_lib.c' X/* X * Routines to manipulate the pcomm.modem file X */ X X#include <stdio.h> X#include "modem.h" X X/* X * Read the modem/TTY database file. Returns a pointer to a static area X * containing the MODEM structure. All modem entries and all TTY entries X * are created regardless of the number of physical entries in the file. X */ X Xstruct MODEM * Xread_modem(extra) Xchar *extra; X{ X extern char *null_ptr; X FILE *fp, *my_fopen(); X int i, tty, mod, line, oops, m_line, start, stop; X char *strdup(), buf[200], message[80], token[40], *str_tok(), *str; X char *temp_token, *t_sep, *m_sep, *m_letter, *findfile(); X static struct MODEM m; X void error_win(); X X if ((m.m_path = findfile(extra, "pcomm.modem")) == NULL) X error_win(1, "Support file 'pcomm.modem' is missing", "or no read permission"); X /* read permission checked */ X fp = my_fopen(m.m_path, "r"); X X t_sep = ";;\n"; X m_sep = ";;;;\n;;;;;;\n;;;\n"; X m_letter = "abc"; X oops = 0; X tty = 0; X mod = 0; X line = 0; X m_line = 0; X while (fgets(buf, 200, fp) != NULL) { X line++; X if (tty >= NUM_TTY || mod >= NUM_MODEM) X break; X /* get the token */ X if (!(temp_token = str_tok(buf, '='))) { X sprintf(message, "is missing a token at line %d", line); X oops++; X break; X } X if (*temp_token != 'T' && *temp_token != 'M') { X sprintf(message, "is corrupted at line %d", line); X oops++; X break; X } X /* the TTY database */ X if (*temp_token == 'T') { X /* X * This is similar to the "real" strtok() command X * but this one returns a null pointer on a missing X * attribute. Note the use of the field separator X * array. X */ X for (i=0; i<3; i++) { X if (!(str = str_tok((char *) NULL, t_sep[i]))) { X sprintf(message, "is missing a parameter at line %d", line); X oops++; X break; X } X switch (i) { X case 0: X m.tty[tty] = strdup(str); X break; X case 1: X m.tname[tty] = strdup(str); X break; X case 2: X m.init_sp[tty] = atoi(str); X break; X } X } X if (oops) X break; X /* sanity checking */ X sprintf(token, "TTY_%d", tty+1); X if (strcmp(token, temp_token)) { X sprintf(message, "is corrupted at line %d", line); X oops++; X break; X } X tty++; X continue; X } X /* the modem database */ X else { X sprintf(token, "MODEM_%d%c", mod+1, m_letter[m_line]); X if (strcmp(token, temp_token)) { X sprintf(message, "is corrupted at line %d", line); X oops++; X break; X } X /* X * There are three lines to the modem database. They X * are distinguished by the letters a, b, and, c X * appended to the entry number. X */ X switch (m_line) { X case 0: X start = 0; X stop = 5; X break; X case 1: X start = 5; X stop = 12; X break; X case 2: X start = 12; X stop = 16; X break; X } X for (i=start; i<stop; i++) { X if (!(str = str_tok((char *) NULL, m_sep[i]))) { X sprintf(message, "is missing a parameter at line %d", line); X oops++; X break; X } X switch (i) { X case 0: X m.mname[mod] = strdup(str); X break; X case 1: X m.init[mod] = strdup(str); X break; X case 2: X m.dial[mod] = strdup(str); X break; X case 3: X m.suffix[mod] = strdup(str); X break; X case 4: X m.hang_up[mod] = strdup(str); X break; X case 5: X m.auto_baud[mod] = *str; X break; X case 6: X m.con_3[mod] = strdup(str); X break; X case 7: X m.con_12[mod] = strdup(str); X break; X case 8: X m.con_24[mod] = strdup(str); X break; X case 9: X m.con_48[mod] = strdup(str); X break; X case 10: X m.con_96[mod] = strdup(str); X break; X case 11: X m.con_192[mod] = strdup(str); X break; X case 12: X m.no_con1[mod] = strdup(str); X break; X case 13: X m.no_con2[mod] = strdup(str); X break; X case 14: X m.no_con3[mod] = strdup(str); X break; X case 15: X m.no_con4[mod] = strdup(str); X break; X } X } X if (oops) X break; X m_line++; X if (m_line >= 3) { X m_line = 0; X mod++; X } X } X } X fclose(fp); X X if (oops) { X sprintf(buf, "Modem/TTY database file '%s'", m.m_path); X error_win(1, buf, message); X } X m.t_entries = tty; X m.m_entries = mod; X m.t_cur = -1; X m.m_cur = -1; X /* if empty database */ X if (!tty) { X sprintf(buf, "Modem/TTY database file '%s'", m.m_path); X error_win(0, buf, "has no TTY data"); X } X if (!mod) { X sprintf(buf, "Modem/TTY database file '%s'", m.m_path); X error_win(0, buf, "has no modem data"); X } X /* fill in the rest */ X for (; tty<NUM_TTY; tty++) { X m.tty[tty] = null_ptr; X m.tname[tty] = null_ptr; X m.init_sp[tty] = 0; X } X for (; mod<NUM_MODEM; mod++) { X m.mname[mod] = null_ptr; X m.init[mod] = null_ptr; X m.dial[mod] = null_ptr; X m.suffix[mod] = null_ptr; X m.hang_up[mod] = null_ptr; X X m.auto_baud[mod] = 'Y'; X m.con_3[mod] = null_ptr; X m.con_12[mod] = null_ptr; X m.con_24[mod] = null_ptr; X m.con_48[mod] = null_ptr; X m.con_96[mod] = null_ptr; X m.con_192[mod] = null_ptr; X X m.no_con1[mod] = null_ptr; X m.no_con2[mod] = null_ptr; X m.no_con3[mod] = null_ptr; X m.no_con4[mod] = null_ptr; X } X return(&m); X} X X/* X * Update the modem database. Other routines actually do the changes X * or deletions in memory. A return code of 1 means non-fatal error. X */ X Xint Xup_modem() X{ X FILE *fp, *my_fopen(); X char buf[80]; X int i; X void error_win(); X X /* open for write */ X if (!(fp = my_fopen(modem->m_path, "w"))) { X sprintf(buf, "'%s'", modem->m_path); X error_win(0, "No write permission on modem/TTY database file", buf); X return(1); X } X /* put back the TTY entries */ X for (i=0; i<modem->t_entries; i++) X fprintf(fp, "TTY_%d=%s;%s;%d\n", i+1, modem->tty[i], X modem->tname[i], modem->init_sp[i]); X X /* put back the modem entries */ X for (i=0; i<modem->m_entries; i++) { X fprintf(fp, "MODEM_%da=%s;%s;%s;%s;%s\n", i+1, modem->mname[i], X modem->init[i], modem->dial[i], modem->suffix[i], X modem->hang_up[i]); X X fprintf(fp, "MODEM_%db=%c;%s;%s;%s;%s;%s;%s\n", i+1, X modem->auto_baud[i], modem->con_3[i], modem->con_12[i], X modem->con_24[i], modem->con_48[i], modem->con_96[i], X modem->con_192[i]); X X fprintf(fp, "MODEM_%dc=%s;%s;%s;%s\n", i+1, modem->no_con1[i], X modem->no_con2[i], modem->no_con3[i], modem->no_con4[i]); X } X X fclose(fp); X return(0); X} X X/* X * See if the new modem is already in the database. If it's not, create X * a slot for it and update the modem->m_cur variable. X */ X Xvoid Xcreate_modem(str) Xchar *str; X{ X int i; X char *strdup(), buf[80]; X void error_win(), free_ptr(); X /* modem entry already exists? */ X for (i=0; i<modem->m_entries; i++) { X if (!strcmp(str, modem->mname[i])) X return; X } X /* empty slot available? */ X if (modem->m_entries == NUM_MODEM) { X sprintf(buf, "'%s'", modem->m_path); X error_win(0, "No empty modem slots in", buf); X return; X } X /* create a new entry */ X free_ptr(modem->mname[modem->m_entries]); X modem->mname[modem->m_entries] = strdup(str); X X /* update number of entries */ X modem->m_entries++; X return; X} X X/* X * See if the modem names in the list still need to be in the database. X * If you find a "lost" entry, delete it and collapse the list. X */ X Xvoid Xdel_modem() X{ X extern char *null_ptr; X int i, j, match; X char *strdup(); X void free_ptr(); X X for (i=0; i<modem->m_entries; i++) { X match = 0; X for (j=0; j<modem->t_entries; j++) { X if (!strcmp(modem->mname[i], modem->tname[j])) { X match++; X break; X } X } X /* found a "lost" modem name */ X if (!match) { X for (j=i; j<modem->m_entries-1; j++) { X free_ptr(modem->mname[j]); X free_ptr(modem->init[j]); X free_ptr(modem->dial[j]); X free_ptr(modem->suffix[j]); X free_ptr(modem->hang_up[j]); X X free_ptr(modem->con_3[j]); X free_ptr(modem->con_12[j]); X free_ptr(modem->con_24[j]); X free_ptr(modem->con_48[j]); X free_ptr(modem->con_96[j]); X free_ptr(modem->con_192[j]); X X free_ptr(modem->no_con1[j]); X free_ptr(modem->no_con2[j]); X free_ptr(modem->no_con3[j]); X free_ptr(modem->no_con4[j]); X X /* copy the info */ X modem->mname[j] = strdup(modem->mname[j+1]); X modem->init[j] = strdup(modem->init[j+1]); X modem->dial[j] = strdup(modem->dial[j+1]); X modem->suffix[j] = strdup(modem->suffix[j+1]); X modem->hang_up[j] = strdup(modem->hang_up[j+1]); X X modem->auto_baud[j] = modem->auto_baud[j+1]; X modem->con_3[j] = strdup(modem->con_3[j+1]); X modem->con_12[j] = strdup(modem->con_12[j+1]); X modem->con_24[j] = strdup(modem->con_24[j+1]); X modem->con_48[j] = strdup(modem->con_48[j+1]); X modem->con_96[j] = strdup(modem->con_96[j+1]); X modem->con_192[j] = strdup(modem->con_192[j+1]); X X modem->no_con1[j] = strdup(modem->no_con1[j+1]); X modem->no_con2[j] = strdup(modem->no_con2[j+1]); X modem->no_con3[j] = strdup(modem->no_con3[j+1]); X modem->no_con4[j] = strdup(modem->no_con4[j+1]); X } X j = modem->m_entries -1; X X free_ptr(modem->mname[j]); X free_ptr(modem->init[j]); X free_ptr(modem->dial[j]); X free_ptr(modem->suffix[j]); X free_ptr(modem->hang_up[j]); X X free_ptr(modem->con_3[j]); X free_ptr(modem->con_12[j]); X free_ptr(modem->con_24[j]); X free_ptr(modem->con_48[j]); X free_ptr(modem->con_96[j]); X free_ptr(modem->con_192[j]); X X free_ptr(modem->no_con1[j]); X free_ptr(modem->no_con2[j]); X free_ptr(modem->no_con3[j]); X free_ptr(modem->no_con4[j]); X X /* create an empty entry */ X modem->mname[j] = null_ptr; X modem->init[j] = null_ptr; X modem->dial[j] = null_ptr; X modem->suffix[j] = null_ptr; X modem->hang_up[j] = null_ptr; X X modem->auto_baud[j] = 'Y'; X modem->con_3[j] = null_ptr; X modem->con_12[j] = null_ptr; X modem->con_24[j] = null_ptr; X modem->con_48[j] = null_ptr; X modem->con_96[j] = null_ptr; X modem->con_192[j] = null_ptr; X X modem->no_con1[j] = null_ptr; X modem->no_con2[j] = null_ptr; X modem->no_con3[j] = null_ptr; X modem->no_con4[j] = null_ptr; X X /* update the counts */ X modem->m_entries--; X if (modem->m_cur >= modem->m_entries) X modem->m_cur = -1; X return; X } X } X return; X} SHAR_EOF if test 10070 -ne "`wc -c < 'm_lib.c'`" then echo shar: "error transmitting 'm_lib.c'" '(should have been 10070 characters)' fi fi echo shar: "extracting 'macro.c'" '(5243 characters)' if test -f 'macro.c' then echo shar: "will not over-write existing file 'macro.c'" else sed 's/^X//' << \SHAR_EOF > 'macro.c' X/* X * The keyboard macro feature. Displays (and prompts for editing) the X * macros assigned to the shifted number keys. Prompts for saving X * changes to disk. X */ X X#include <stdio.h> X#include <curses.h> X#include "config.h" X#include "misc.h" X#include "param.h" X Xint Xmacro() X{ X extern int fd; X WINDOW *ma_win, *newwin(); X int ans, ret_code; X char *mac, *strdup(), *mac_prompt(); X void free_ptr(); X X ma_win = newwin(18, 65, 2, 15); X mvwattrstr(ma_win, 1, 25, A_BOLD, "Keyboard Macros"); X horizontal(ma_win, 2, 0, 65); X mvwprintw(ma_win, 4, 0, " %4.4s-! %-50.50s\n", param->ascii_hot, param->mac_1); X wprintw(ma_win, " %4.4s-@ %-50.50s\n", param->ascii_hot, param->mac_2); X wprintw(ma_win, " %4.4s-# %-50.50s\n", param->ascii_hot, param->mac_3); X wprintw(ma_win, " %4.4s-$ %-50.50s\n", param->ascii_hot, param->mac_4); X wprintw(ma_win, " %4.4s-%% %-50.50s\n", param->ascii_hot, param->mac_5); X wprintw(ma_win, " %4.4s-^ %-50.50s\n", param->ascii_hot, param->mac_6); X wprintw(ma_win, " %4.4s-& %-50.50s\n", param->ascii_hot, param->mac_7); X wprintw(ma_win, " %4.4s-* %-50.50s\n", param->ascii_hot, param->mac_8); X wprintw(ma_win, " %4.4s-( %-50.50s\n", param->ascii_hot, param->mac_9); X wprintw(ma_win, " %4.4s-) %-50.50s\n", param->ascii_hot, param->mac_0); X mvwaddstr(ma_win, 15, 5, "Macro key to revise:"); X box(ma_win, VERT, HORZ); X /* on the bottom line */ X mvwaddstr(ma_win, 17, 21, " Press <ESC> to continue "); X wmove(ma_win, 15, 26); X wrefresh(ma_win); X X ret_code = 0; X X while ((ans = wgetch(ma_win)) != ESC) { X switch (ans) { X case '!': /* shifted 1 */ X if ((mac = mac_prompt(ans, param->mac_1)) != NULL) { X free_ptr(param->mac_1); X param->mac_1 = strdup(mac); X clear_line(ma_win, 4, 9, 1); X mvwattrstr(ma_win, 4, 9, A_BOLD, mac); X ret_code++; X } X break; X case '@': /* shifted 2 */ X if ((mac = mac_prompt(ans, param->mac_2)) != NULL) { X free_ptr(param->mac_2); X param->mac_2 = strdup(mac); X clear_line(ma_win, 5, 9, 1); X mvwattrstr(ma_win, 5, 9, A_BOLD, mac); X ret_code++; X } X break; X case '#': /* shifted 3 */ X if ((mac = mac_prompt(ans, param->mac_3)) != NULL) { X free_ptr(param->mac_3); X param->mac_3 = strdup(mac); X clear_line(ma_win, 6, 9, 1); X mvwattrstr(ma_win, 6, 9, A_BOLD, mac); X ret_code++; X } X break; X case '$': /* shifted 4 */ X if ((mac = mac_prompt(ans, param->mac_4)) != NULL) { X free_ptr(param->mac_4); X param->mac_4 = strdup(mac); X clear_line(ma_win, 7, 9, 1); X mvwattrstr(ma_win, 7, 9, A_BOLD, mac); X ret_code++; X } X break; X case '%': /* shifted 5 */ X if ((mac = mac_prompt(ans, param->mac_5)) != NULL) { X free_ptr(param->mac_5); X param->mac_5 = strdup(mac); X clear_line(ma_win, 8, 9, 1); X mvwattrstr(ma_win, 8, 9, A_BOLD, mac); X ret_code++; X } X break; X case '^': /* shifted 6 */ X if ((mac = mac_prompt(ans, param->mac_6)) != NULL) { X free_ptr(param->mac_6); X param->mac_6 = strdup(mac); X clear_line(ma_win, 9, 9, 1); X mvwattrstr(ma_win, 9, 9, A_BOLD, mac); X ret_code++; X } X break; X case '&': /* shifted 7 */ X if ((mac = mac_prompt(ans, param->mac_7)) != NULL) { X free_ptr(param->mac_7); X param->mac_7 = strdup(mac); X clear_line(ma_win, 10, 9, 1); X mvwattrstr(ma_win, 10, 9, A_BOLD, mac); X ret_code++; X } X break; X case '*': /* shifted 8 */ X if ((mac = mac_prompt(ans, param->mac_8)) != NULL) { X free_ptr(param->mac_8); X param->mac_8 = strdup(mac); X clear_line(ma_win, 11, 9, 1); X mvwattrstr(ma_win, 11, 9, A_BOLD, mac); X ret_code++; X } X break; X case '(': /* shifted 9 */ X if ((mac = mac_prompt(ans, param->mac_9)) != NULL) { X free_ptr(param->mac_9); X param->mac_9 = strdup(mac); X clear_line(ma_win, 12, 9, 1); X mvwattrstr(ma_win, 12, 9, A_BOLD, mac); X ret_code++; X } X break; X case ')': /* shifted 0 */ X if ((mac = mac_prompt(ans, param->mac_0)) != NULL) { X free_ptr(param->mac_0); X param->mac_0 = strdup(mac); X clear_line(ma_win, 13, 9, 1); X mvwattrstr(ma_win, 13, 9, A_BOLD, mac); X ret_code++; X } X break; X default: X beep(); X break; X } X touchwin(ma_win); X wmove(ma_win, 15, 26); X wrefresh(ma_win); X } X /* if something changed */ X if (ret_code) { X /* save to disk? */ X if (yes_prompt(ma_win, 15, 30, A_BOLD, "Save to disk")) { X if (up_param()) { X touchwin(ma_win); X wrefresh(ma_win); X } X } X } X if (fd == -1) { X werase(ma_win); X wrefresh(ma_win); X } X delwin(ma_win); X return(ret_code); X} X X/* X * Sounds like Mac Donalds doesn't it? Actually, it opens a new window X * and prompts for the new macro. Returns a pointer to the new string. X */ X Xstatic char * Xmac_prompt(key, string) Xchar key, *string; X{ X extern char *null_ptr; X WINDOW *mp_win, *newwin(); X char *new, *get_str(); X X mp_win = newwin(6, 65, 8, 0); X mvwprintw(mp_win, 2, 3, "%4.4s-%c %-50.50s", param->ascii_hot, key, string); X mvwaddstr(mp_win, 3, 5, "New : "); X box(mp_win, VERT, HORZ); X wrefresh(mp_win); X X new = get_str(mp_win, 50, "", ""); X /* if space, change to NULL pointer */ X if (!strcmp(new, " ")) X new = null_ptr; X X werase(mp_win); X wrefresh(mp_win); X delwin(mp_win); X return(new); X} SHAR_EOF if test 5243 -ne "`wc -c < 'macro.c'`" then echo shar: "error transmitting 'macro.c'" '(should have been 5243 characters)' fi fi echo shar: "extracting 'main.c'" '(6133 characters)' if test -f 'main.c' then echo shar: "will not over-write existing file 'main.c'" else sed 's/^X//' << \SHAR_EOF > 'main.c' X/* X * Pcomm is a public domain telecommunication program for Unix that X * is designed to operate similar to the MSDOS program, ProComm. X * ProComm (TM) is copyrighted by Datastorm Technologies, Inc. X * X * Emmet P. Gray US Army, HQ III Corps & Fort Hood X * ...!uunet!uiucuxc!fthood!egray Attn: AFZF-DE-ENV X * Directorate of Engineering & Housing X * Environmental Management Office X * Fort Hood, TX 76544-5057 X * X * Release v1.0 12 Mar 88 X * patch #1 22 Mar 88 X * patch #2 26 Mar 88 X * patch #3 3 Apr 88 X * patch #4 14 Apr 88 X * patch #5 25 May 88 X * Release v1.1 21 Aug 88 X */ X X#include <stdio.h> X#include <signal.h> X#include <curses.h> X#include <sys/types.h> X#include <sys/stat.h> X#include "config.h" X#ifndef OLDCURSES X#include <term.h> X#endif /* OLDCURSES */ X#define MAIN X#include "dial_dir.h" X#include "modem.h" X#include "param.h" X#include "status.h" X X#ifdef OLDCURSES Xchar tcbuf[1024], *TI, *VS; X#define cbreak crmode X#endif /* OLDCURSES */ X X#ifdef SHAREDMEM Xint shm_id; X#endif /* SHAREDMEM */ X Xstruct PARAM *param; Xstruct DIAL_DIR *dir; Xstruct STATUS *status; Xstruct MODEM *modem; X Xint fd = -1; /* file descriptor for port */ Xint xmc; /* magic cookie terminal */ Xint msg_status; /* read/write permissions on TTY */ Xchar *null_ptr = ""; /* generic null pointer */ X Xmain(argc, argv) Xint argc; Xchar *argv[]; X{ X extern char *optarg; X int c, ret_code, i, code, quit(); X char *mytty, *ttyname(), *term, *getenv(), *short_cut, *strdup(); X char *extra_dir, buf[80], message[80]; X struct PARAM *read_param(); X struct DIAL_DIR *read_dir(); X struct STATUS *init(); X struct MODEM *read_modem(); X struct stat stbuf; X void exit(), error_win(), free_ptr(); X#ifdef OLDCURSES X char *tgetstr(), *t, tb[1024]; X t = tcbuf; X#endif /* OLDCURSES */ X X signal(SIGINT, SIG_IGN); X signal(SIGQUIT, SIG_IGN); X signal(SIGTERM, quit); X signal(SIGHUP, quit); X X short_cut = NULL; X extra_dir = NULL; X /* the command line */ X while ((c = getopt(argc, argv, "d:f:")) != EOF) { X switch (c) { X case 'd': /* the extra directory to search */ X extra_dir = strdup(optarg); X break; X case 'f': /* the index into the dialing dir */ X short_cut = strdup(optarg); X break; X case '?': /* default */ X fprintf(stderr, "Usage: pcomm [-d directory] [-f index]\n"); X exit(1); X break; X } X } X /* get terminal type */ X term = getenv("TERM"); X if (term == NULL || *term == NULL) { X fprintf(stderr, "Windows not supported (TERM not defined)\n"); X exit(1); X } X /* see if terminfo entry exists */ X#ifdef OLDCURSES X ret_code = tgetent(tb, term); X#else /* OLDCURSES */ X setupterm(term, 1, &ret_code); X#endif /* OLDCURSES */ X if (ret_code != 1) { X fprintf(stderr, "Windows not supported (no terminfo data for '%s')\n", term); X exit(1); X } X /* minimum screen size */ X#ifdef OLDCURSES X if (tgetnum("co") < 80 || tgetnum("li") < 24) { X#else /* OLDCURSES */ X if (columns < 80 || lines < 24) { X#endif /* OLDCURSES */ X fprintf(stderr, "Windows not supported (minimum 80x24 screen required)\n"); X exit(1); X } X /* must have cursor movement */ X#ifdef OLDCURSES X if (tgetstr("cm", &t) == NULL) { X#else /* OLDCURSES */ X if (cursor_address == NULL) { X#endif /* OLDCURSES */ X fprintf(stderr, "Windows not supported (terminal too dumb)\n"); X exit(1); X } X /* load magic cookie variable */ X#ifdef OLDCURSES X xmc = tgetnum("sg"); X TI = tgetstr("ti", &t); X VS = tgetstr("vs", &t); X#else /* OLDCURSES */ X xmc = magic_cookie_glitch; X#endif /* OLDCURSES */ X /* ok... now lets go! */ X initscr(); X nonl(); X cbreak(); X noecho(); X X param = (struct PARAM *) NULL; X modem = (struct MODEM *) NULL; X dir = (struct DIAL_DIR *) NULL; X /* show the herald, return status */ X status = init(short_cut); X /* get "msgs" status */ X mytty = ttyname(0); X stat(mytty, &stbuf); X chmod(mytty, 0600); X msg_status = stbuf.st_mode & 0777; X /* read the support files */ X param = read_param(extra_dir); X dir = read_dir(extra_dir); X modem = read_modem(extra_dir); X free_ptr(extra_dir); X /* warning about screen size */ X if (LINES > MAX_ROW || COLS > MAX_COL) X error_win(0, "Your screen size exceeds an internal Pcomm limit", X "The edges of the screen may contain garbage"); X X /* short-cut to dialing window? */ X code = 0; X if (short_cut != NULL) { X for (i=1; i<dir->d_entries+1; i++) { X if (!strcmp(dir->index[i], short_cut)) { X dir->q_num[0] = i; X dir->d_cur = i; X break; X } X } X /* if match is found */ X if (dir->q_num[0] != -1) X code = dial_win(); X else { X sprintf(buf, "Can't find index '%s' in dialing directory", short_cut); X sprintf(message, "file '%s'", dir->d_path); X error_win(0, buf, message); X } X free_ptr(short_cut); X } X /* start terminal dialogue */ X terminal(code); X exit(0); X} X X/* X * Something dreadful happened... Clean up the mess we made with the X * TTY driver and release the phone line. X */ X Xint Xquit() X{ X void cleanup(); X X cleanup(1); X /* never returns... */ X return(0); X} X X/* X * Check write permission with the real UID and GID. Returns a 0 on X * permission denied, 1 on OK, and 2 on OK-but the file already exists. X */ X Xint Xcan_write(file) Xchar *file; X{ X char *p, path[200], *strcpy(), *strrchr(); X X p = strcpy(path, file); X /* dissect the path component */ X if (p = strrchr(path, '/')) X *(p++) = NULL; X else X strcpy(path, "."); X /* if it already exists */ X if (!access(file, 0)) { X if (!access(file, 2)) X return(2); X return(0); X } X /* if path is writable */ X if (!access(path, 2)) X return(1); X return(0); X} X X/* X * Check the read and write permissions before opening a file. This X * is a horrible kludge to work around that fact that a lot of systems X * that claim to be SVID compatible don't treat setuid(2) and setgid(2) X * properly. For example, on a Masscomp, you can't flip-flop back and X * forth between the real and effective UID/GID. X */ X XFILE * Xmy_fopen(file, mode) Xchar *file, *mode; X{ X#ifdef SETUGID X switch (*mode) { X case 'a': X case 'w': X if (!can_write(file)) X return(NULL); X break; X case 'r': X if (access(file, 4)) X return(NULL); X break; X } X#endif /* SETUGID */ X return ((FILE *) fopen(file, mode)); X} SHAR_EOF if test 6133 -ne "`wc -c < 'main.c'`" then echo shar: "error transmitting 'main.c'" '(should have been 6133 characters)' fi fi echo shar: "extracting 'n_shell.c'" '(1255 characters)' if test -f 'n_shell.c' then echo shar: "will not over-write existing file 'n_shell.c'" else sed 's/^X//' << \SHAR_EOF > 'n_shell.c' X/* X * Spawn a "native" shell. Native means the shell found in the SHELL X * environmental variable. X */ X X#include <stdio.h> X#include <signal.h> X#include <curses.h> X#include "config.h" X Xvoid Xn_shell() X{ X WINDOW *sh_win, *newwin(); X int (*istat)(), (*qstat)(), status, spid, w; X char *shell, *shellpath, *getenv(), *strrchr(); X unsigned int sleep(); X void _exit(); X /* a full window */ X sh_win = newwin(LINES, COLS, 0, 0); X X touchwin(sh_win); X waddstr(sh_win, "Pcomm <=> Unix gateway, use ^D or 'exit' to return\n"); X wrefresh(sh_win); X /* out of curses mode */ X resetterm(); X X shellpath = getenv("SHELL"); X if (shellpath == NULL || *shellpath == NULL) X shellpath = "/bin/sh"; X X shell = strrchr(shellpath, '/') + 1; X X if (!(spid = fork())) { X signal(SIGINT, SIG_DFL); X signal(SIGQUIT, SIG_DFL); X#ifdef SETUGID X setgid(getgid()); X setuid(getuid()); X#endif /* SETUGID */ X execl(shellpath, shell, "-i", (char *) 0); X _exit(1); X } X istat = signal(SIGINT, SIG_IGN); X qstat = signal(SIGQUIT, SIG_IGN); X X while ((w = wait(&status)) != spid && w != -1) X ; X X signal(SIGINT, istat); X signal(SIGQUIT, qstat); X /* back to curses mode */ X sleep(1); X fixterm(); X X clearok(curscr, TRUE); X werase(sh_win); X wrefresh(sh_win); X delwin(sh_win); X return; X} SHAR_EOF if test 1255 -ne "`wc -c < 'n_shell.c'`" then echo shar: "error transmitting 'n_shell.c'" '(should have been 1255 characters)' fi fi echo shar: "extracting 'p_lib.c'" '(7151 characters)' if test -f 'p_lib.c' then echo shar: "will not over-write existing file 'p_lib.c'" else sed 's/^X//' << \SHAR_EOF > 'p_lib.c' X/* X * Routines to manipulate the pcomm.param file. X */ X X#include <stdio.h> X#include "param.h" X X/* X * Read the parameter structure from the pcomm.param file. Returns a X * pointer to the PARAM structure. All errors are fatal. X */ X Xstruct PARAM * Xread_param(extra) Xchar *extra; X{ X FILE *fp; X int i, oops; X char buf[80], *temp_token, *str, *strdup(), *findfile(); X char message[80], *str_tok(); X static char *token[NUM_PARAM] = {"D_BAUD", "D_PARITY", "D_DBITS", X "D_SBITS", "HOT", "ASCII_HOT", "D_DUPLEX", "FLOW", "CR_IN", "CR_OUT", X "LOGFILE", "DUMPFILE", "STRIP", "PAUSE_CHAR", "CR_CHAR", "CTRL_CHAR", X "ESC_CHAR", "BRK_CHAR", "ABORT", "C_DELAY", "R_DELAY", "LECHO", X "EXPAND", "CR_DELAY", "PACE", "CR_UP", "LF_UP", "TIMER", "CR_DN", X "LF_DN", "LD_PLUS", "LD_MINUS", "LD_AT", "LD_POUND", "MAC_1", X "MAC_2", "MAC_3", "MAC_4", "MAC_5", "MAC_6", "MAC_7", "MAC_8", X "MAC_9", "MAC_0"}; X static struct PARAM p; X void error_win(); X X if ((p.p_path = findfile(extra, "pcomm.param")) == NULL) X error_win(1, "Support file 'pcomm.param' is missing", "or no read permission"); X /* read permission already checked */ X fp = fopen(p.p_path, "r"); X X oops = 0; X for (i=0; i<NUM_PARAM; i++) { X if (fgets(buf, 80, fp) == NULL) { X sprintf(message, "is truncated at line %d", i+1); X oops++; X break; X } X /* parse the input line */ X if (!(temp_token = str_tok(buf, '='))) { X sprintf(message, "is missing a token at line %d", i+1); X oops++; X break; X } X if (!(str = str_tok((char *) NULL, '\n'))) { X sprintf(message, "is missing a parameter at line %d", i+1); X oops++; X break; X } X /* sanity checking */ X if (strcmp(temp_token, token[i])) { X sprintf(message, "is corrupted at line %d", i+1); X oops++; X break; X } X X switch (i) { X /* used in ls_menu() */ X case LINE_SET: X p.d_baud = atoi(str); X break; X case LINE_SET+1: X p.d_parity = *str; X break; X case LINE_SET+2: X p.d_dbits = atoi(str); X break; X case LINE_SET+3: X p.d_sbits = atoi(str); X break; X X /* used in term_setup() */ X case TERM_SETUP: X p.hot = atoi(str); X break; X case TERM_SETUP+1: X p.ascii_hot = strdup(str); X break; X case TERM_SETUP+2: X p.d_duplex = strdup(str); X break; X case TERM_SETUP+3: X p.flow = strdup(str); X break; X case TERM_SETUP+4: X p.cr_in = strdup(str); X break; X case TERM_SETUP+5: X p.cr_out = strdup(str); X break; X X /* used in gen_setup() */ X case GEN_SETUP: X p.logfile = strdup(str); X break; X case GEN_SETUP+1: X p.dumpfile = strdup(str); X break; X case GEN_SETUP+2: X p.strip = strdup(str); X break; X case GEN_SETUP+3: X p.pause_char = *str; X break; X case GEN_SETUP+4: X p.cr_char = *str; X break; X case GEN_SETUP+5: X p.ctrl_char = *str; X break; X case GEN_SETUP+6: X p.esc_char = *str; X break; X case GEN_SETUP+7: X p.brk_char = *str; X break; X case GEN_SETUP+8: X p.abort = strdup(str); X break; X X /* used in gen_setup() delay_times() */ X case DELAY_TIMES: X p.c_delay = atoi(str); X break; X case DELAY_TIMES+1: X p.r_delay = atoi(str); X break; X X /* used in axfer_setup() */ X case ASCII_SETUP: X p.lecho = strdup(str); X break; X case ASCII_SETUP+1: X p.expand = strdup(str); X break; X case ASCII_SETUP+2: X p.cr_delay = atoi(str); X break; X case ASCII_SETUP+3: X p.pace = strdup(str); X break; X case ASCII_SETUP+4: X p.cr_up = strdup(str); X break; X case ASCII_SETUP+5: X p.lf_up = strdup(str); X break; X case ASCII_SETUP+6: X p.timer = atoi(str); X break; X case ASCII_SETUP+7: X p.cr_dn = strdup(str); X break; X case ASCII_SETUP+8: X p.lf_dn = strdup(str); X break; X X /* used in d_revise() */ X case LD_CODES: X p.ld_plus = strdup(str); X break; X case LD_CODES+1: X p.ld_minus = strdup(str); X break; X case LD_CODES+2: X p.ld_at = strdup(str); X break; X case LD_CODES+3: X p.ld_pound = strdup(str); X break; X X /* used in macro() */ X case MACROS: X p.mac_1 = strdup(str); X break; X case MACROS+1: X p.mac_2 = strdup(str); X break; X case MACROS+2: X p.mac_3 = strdup(str); X break; X case MACROS+3: X p.mac_4 = strdup(str); X break; X case MACROS+4: X p.mac_5 = strdup(str); X break; X case MACROS+5: X p.mac_6 = strdup(str); X break; X case MACROS+6: X p.mac_7 = strdup(str); X break; X case MACROS+7: X p.mac_8 = strdup(str); X break; X case MACROS+8: X p.mac_9 = strdup(str); X break; X case MACROS+9: X p.mac_0 = strdup(str); X break; X } X } X fclose(fp); X if (oops) { X sprintf(buf, "Parameter file '%s'", p.p_path); X error_win(1, buf, message); X } X return(&p); X} X X/* X * Write the updated param structure to disk. The values in memory should X * have already been "purified". Later, we'll update only the entries that X * have been explicitly asked for. A return code of 1 means non-fatal error. X */ X Xint Xup_param() X{ X FILE *fp, *my_fopen(); X char buf[80]; X void error_win(); X /* open for write */ X if (!(fp = my_fopen(param->p_path, "w"))) { X sprintf(buf, "'%s'", param->p_path); X error_win(0, "No write permission on parameter file", buf); X return(1); X } X X fprintf(fp, "D_BAUD=%d\n", param->d_baud); X fprintf(fp, "D_PARITY=%c\n", param->d_parity); X fprintf(fp, "D_DBITS=%d\n", param->d_dbits); X fprintf(fp, "D_SBITS=%d\n", param->d_sbits); X fprintf(fp, "HOT=%d\n", param->hot); X fprintf(fp, "ASCII_HOT=%s\n", param->ascii_hot); X fprintf(fp, "D_DUPLEX=%s\n", param->d_duplex); X fprintf(fp, "FLOW=%s\n", param->flow); X fprintf(fp, "CR_IN=%s\n", param->cr_in); X fprintf(fp, "CR_OUT=%s\n", param->cr_out); X fprintf(fp, "LOGFILE=%s\n", param->logfile); X fprintf(fp, "DUMPFILE=%s\n", param->dumpfile); X fprintf(fp, "STRIP=%s\n", param->strip); X fprintf(fp, "PAUSE_CHAR=%c\n", param->pause_char); X fprintf(fp, "CR_CHAR=%c\n", param->cr_char); X fprintf(fp, "CTRL_CHAR=%c\n", param->ctrl_char); X fprintf(fp, "ESC_CHAR=%c\n", param->esc_char); X fprintf(fp, "BRK_CHAR=%c\n", param->brk_char); X fprintf(fp, "ABORT=%s\n", param->abort); X fprintf(fp, "C_DELAY=%d\n", param->c_delay); X fprintf(fp, "R_DELAY=%d\n", param->r_delay); X fprintf(fp, "LECHO=%s\n", param->lecho); X fprintf(fp, "EXPAND=%s\n", param->expand); X fprintf(fp, "CR_DELAY=%d\n", param->cr_delay); X fprintf(fp, "PACE=%s\n", param->pace); X fprintf(fp, "CR_UP=%s\n", param->cr_up); X fprintf(fp, "LF_UP=%s\n", param->lf_up); X fprintf(fp, "TIMER=%d\n", param->timer); X fprintf(fp, "CR_DN=%s\n", param->cr_dn); X fprintf(fp, "LF_DN=%s\n", param->lf_dn); X fprintf(fp, "LD_PLUS=%s\n", param->ld_plus); X fprintf(fp, "LD_MINUS=%s\n", param->ld_minus); X fprintf(fp, "LD_AT=%s\n", param->ld_at); X fprintf(fp, "LD_POUND=%s\n", param->ld_pound); X fprintf(fp, "MAC_1=%s\n", param->mac_1); X fprintf(fp, "MAC_2=%s\n", param->mac_2); X fprintf(fp, "MAC_3=%s\n", param->mac_3); X fprintf(fp, "MAC_4=%s\n", param->mac_4); X fprintf(fp, "MAC_5=%s\n", param->mac_5); X fprintf(fp, "MAC_6=%s\n", param->mac_6); X fprintf(fp, "MAC_7=%s\n", param->mac_7); X fprintf(fp, "MAC_8=%s\n", param->mac_8); X fprintf(fp, "MAC_9=%s\n", param->mac_9); X fprintf(fp, "MAC_0=%s\n", param->mac_0); X X fclose(fp); X return(0); X} SHAR_EOF if test 7151 -ne "`wc -c < 'p_lib.c'`" then echo shar: "error transmitting 'p_lib.c'" '(should have been 7151 characters)' fi fi echo shar: "extracting 'passthru.c'" '(2141 characters)' if test -f 'passthru.c' then echo shar: "will not over-write existing file 'passthru.c'" else sed 's/^X//' << \SHAR_EOF > 'passthru.c' X/* X * A transparent "pass-thru" mode, designed to allow binary transfers X * between 3 machines (with the middle machine in the pass-thru mode). X * A non-zero return code means the input routine should be restarted. X */ X X#include <stdio.h> X#include <signal.h> X#include <curses.h> X#include "config.h" X#include "misc.h" X Xint Xpass_thru() X{ X extern int fd; X WINDOW *pt_win, *newwin(); X int num; X void cpio(); X X pt_win = newwin(5, 70, 5, 5); X X mvwaddstr(pt_win, 2, 4, "Enter the expiration time (5-60 sec): "); X box(pt_win, VERT, HORZ); X X mvwattrstr(pt_win, 0, 3, A_BOLD, " Pass Through Mode "); X wmove(pt_win, 2, 43); X wrefresh(pt_win); X /* get the answer */ X while ((num = get_num(pt_win, 2)) != -1) { X /* out of bounds */ X if (num < 5 || num > 60) { X beep(); X clear_line(pt_win, 2, 43, 1); X wmove(pt_win, 2, 43); X wrefresh(pt_win); X } X else { X werase(pt_win); X wrefresh(pt_win); X delwin(pt_win); X X touchwin(stdscr); X refresh(); X X cpio((unsigned int) num); X return(1); X } X } X if (fd == -1) { X werase(pt_win); X wrefresh(pt_win); X } X delwin(pt_win); X return(0); X} X X/* X * Copy the stdin to the TTYout and copy the TTYin to the stdout. Uses X * multi character reads. I'm not too concerned about the excess bagage X * caused by the entire image being forked... this feature won't be used X * that often. X */ X Xstatic int cp_flag; X Xstatic void Xcpio(num) Xunsigned int num; X{ X extern int fd; X int cpid, n, cp_force(); X char buf[BUFSIZ]; X unsigned int alarm(), sleep(); X void line_set(), xmodem_mode(), input_off(); X X /* out of curses mode */ X resetterm(); X X input_off(); X xmodem_mode(0); X xmodem_mode(fd); X X /* copy the TTYin to stdout */ X if (!(cpid = fork())) { X while (1) { X n = read(fd, buf, BUFSIZ); X write(1, buf, n); X } X } X X cp_flag = 0; X signal(SIGALRM, cp_force); X /* copy the stdin to TTYout */ X while (1) { X alarm(num); X n = read(0, buf, BUFSIZ); X if (cp_flag) X break; X write(fd, buf, n); X } X kill(cpid, SIGKILL); X /* back to curses mode */ X sleep(1); X fixterm(); X beep(); X line_set(); X clearok(curscr, TRUE); X return; X} X/*ARGSUSED*/ Xstatic int Xcp_force(dummy) X{ X cp_flag = 1; X} SHAR_EOF if test 2141 -ne "`wc -c < 'passthru.c'`" then echo shar: "error transmitting 'passthru.c'" '(should have been 2141 characters)' fi fi echo shar: "extracting 'pexit.c'" '(2504 characters)' if test -f 'pexit.c' then echo shar: "will not over-write existing file 'pexit.c'" else sed 's/^X//' << \SHAR_EOF > 'pexit.c' X/* X * Exit Pcomm. A user requested abort. There are a lot of things to do X * before we exit! X */ X X#include <stdio.h> X#include <curses.h> X#include "config.h" X#ifdef SHAREDMEM X#include <sys/types.h> X#include <sys/ipc.h> X#include <sys/shm.h> X#endif /* SHAREDMEM */ X#include "dial_dir.h" X#include "misc.h" X#include "param.h" X#include "status.h" X Xvoid Xpexit() X{ X extern int fd; X WINDOW *ex_win, *newwin(); X void cleanup(), st_line(); X X ex_win = newwin(5, 33, 3, 7); X X box(ex_win, VERT, HORZ); X mvwattrstr(ex_win, 0, 3, A_BOLD, " Exit "); X if (yes_prompt(ex_win, 2, 4, A_BLINK, "Exit to Unix")) { X st_line(" exiting"); X cleanup(0); X } X if (fd == -1) { X werase(ex_win); X wrefresh(ex_win); X } X delwin(ex_win); X return; X} X X/* X * Do the clean up detail before we exit. Only the status structure X * is guaranteed to exit. X */ X Xvoid Xcleanup(val) Xint val; X{ X extern int msg_status; X void release_port(), input_off(), exit(); X char *ttyname(); X#ifdef SHAREDMEM X extern int shm_id; X#endif /* SHAREDMEM */ X /* kill the input routine */ X input_off(); X /* release the port */ X release_port(0); X /* zap the virtual screen */ X#ifdef SHAREDMEM X if (shmdt((char *) status) < 0) X perror("shmdt"); X if (shmctl(shm_id, IPC_RMID, (struct shmid_ds *) NULL) < 0) X perror("shmctl"); X#else /* SHAREDMEM */ X unlink(status->vs_path); X#endif /* SHAREDMEM */ X X /* X * If we die an un-natural death (such as a SIGHUP on the loss of X * the controlling terminal) we won't have a terminal to mess with. X */ X if (isatty(0)) { X touchwin(stdscr); X clear(); X refresh(); X endwin(); X /* return the TTY chmod */ X chmod(ttyname(0), msg_status); X } X exit(val); X} X X/* X * Open a window to display an error message. Handles both fatal and X * non-fatal errors X */ X Xvoid Xerror_win(code, line_one, line_two) Xint code; Xchar *line_one, *line_two; X{ X WINDOW *e_win, *newwin(); X void cleanup(), st_line(); X X e_win = newwin(7, 70, 9, 5); X /* display the nasty note */ X mvwaddstr(e_win, 2, 4, line_one); X mvwaddstr(e_win, 3, 4, line_two); X box(e_win, VERT, HORZ); X X if (code) { X mvwattrstr(e_win, 0, 4, A_BOLD, " Error "); X mvwattrstr(e_win, 5, 24, A_BLINK, "Press any key to exit"); X wmove(e_win, 5, 46); X } X else { X mvwattrstr(e_win, 0, 4, A_BOLD, " Warning "); X mvwattrstr(e_win, 5, 22, A_BLINK, "Press any key to continue"); X wmove(e_win, 5, 48); X } X beep(); X wrefresh(e_win); X X wgetch(e_win); X werase(e_win); X wrefresh(e_win); X delwin(e_win); X X if (code) { X st_line(" exiting"); X cleanup(code); X } X return; X} SHAR_EOF if test 2504 -ne "`wc -c < 'pexit.c'`" then echo shar: "error transmitting 'pexit.c'" '(should have been 2504 characters)' fi fi echo shar: "extracting 'port.c'" '(9459 characters)' if test -f 'port.c' then echo shar: "will not over-write existing file 'port.c'" else sed 's/^X//' << \SHAR_EOF > 'port.c' X/* X * Routines to get or release a TTY port. X */ X X#define MAX_PID 30000 X X#include <stdio.h> X#include <fcntl.h> X#include <termio.h> X#include <errno.h> X#include "config.h" X#ifdef UNIXPC X#include <sys/phone.h> X#endif /* UNIXPC */ X#include "dial_dir.h" X#include "modem.h" X Xstatic int getty_status; Xstatic char *lock_path = NULL; X/* X * Finds a free (or requested) serial port. Creates a lock file to hold X * for our use. Loads the modem database. A return code of 1 means X * all ports (or the requested port) are busy. X */ X Xint Xget_port() X{ X extern int fd; X register int i; X int j, k, lfd, list[NUM_TTY], cmask, tbaud; X char file[80], buf[80], message[80], *strdup(); X unsigned int sleep(); X void error_win(), line_set(), release_port(), send_str(); X void free_ptr(); X#ifndef ASCII_PID X int progpid; X#endif /* ASCII_PID */ X X /* X * If we already have a port, see if it is good enough for the X * current request. X */ X#ifdef KEEP_PORT X if (fd != -1) { X if (!strcmp(dir->index[dir->d_cur], modem->tty[modem->t_cur]) || X ck_speed(modem->t_cur, dir->baud[dir->d_cur])) { X /* X * Reset the line because the baud rate (or other X * parameters) may have changed. X */ X line_set(); X return(0); X } X } X#endif /* KEEP_PORT */ X release_port(1); X X list[0] = -1; X /* X * See if you want a specific TTY port. If the index field in the X * dialing directory is a valid device name, then use that TTY. X */ X if (*dir->index[dir->d_cur] != NULL) { X sprintf(buf, "/dev/%s", dir->index[dir->d_cur]); X /* if index is a valid device */ X if (!access(buf, 0)) { X for (i=0; i<modem->t_entries; i++) { X /* and it exists in modem database */ X if (!strcmp(dir->index[dir->d_cur], modem->tty[i])) { X list[0] = i; X list[1] = -1; X break; X } X } X } X } X X /* X * Create a list of acceptable TTYs. It searches the modem database X * for the requested baud rate. X */ X k = 0; X if (list[0] == -1) { X for (i=0; i<modem->t_entries; i++) { X /* skip ports with no modems */ X if (!strcmp(modem->tname[i], "DIRECT")) X continue; X X /* can handle requested baud rate? */ X if (ck_speed(i, dir->baud[dir->d_cur])) X list[k++] = i; X } X /* the end of list marker */ X list[k] = -1; X } X /* empty list? */ X if (list[0] == -1) { X sprintf(message, "No modem at a %d baud rating exists in the", dir->baud[dir->d_cur]); X sprintf(buf, "modem database '%s'", modem->m_path); X error_win(0, message, buf); X return(1); X } X /* check the list for a free port */ X i = 0; X while (list[i] != -1) { X /* create a lock file name */ X sprintf(file, "%s/LCK..%s", LOCK_DIR, modem->tty[list[i]]); X#ifdef DEBUG X fprintf(stderr, "get_port: checking '/dev/%s'\n", modem->tty[list[i]]); X#endif /* DEBUG */ X X /* does it exist or is it dead? */ X if (checklock(file)) { X getty_status = set_getty(modem->tty[list[i]], 0); X X cmask = umask(0); X if ((lfd = open(file, O_CREAT|O_EXCL|O_WRONLY, 0666)) < 0) { X if (getty_status) X set_getty(modem->tty[list[i]], 1); X sprintf(buf, "'%s'", file); X error_win(1, "Can't create the lockfile", buf); X } X umask(cmask); X#ifdef ASCII_PID X sprintf(buf, "%10d\n", getpid()); X write(lfd, buf, 11); X#else /* ASCII_PID */ X progpid = getpid(); X write(lfd, (char *) &progpid, sizeof(int)); X#endif /* ASCII_PID */ X close(lfd); X /* store the new values */ X free_ptr(lock_path); X lock_path = strdup(file); X modem->t_cur = list[i]; X X /* open the device (ignore DCD) */ X sprintf(buf, "/dev/%s", modem->tty[modem->t_cur]); X if ((fd = open(buf, O_RDWR|O_NDELAY)) < 0) { X if (getty_status) X set_getty(modem->tty[modem->t_cur], 1); X sprintf(file, "Can't open port '%s' for read and write", buf); X error_win(1, file, ""); X } X /* turn off the "no delay" mode */ X fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NDELAY); X /* change line settings */ X line_set(); X /* load the modem data base */ X modem->m_cur = -1; X for (j=0; j<modem->m_entries; j++) { X if (!strcmp(modem->tname[modem->t_cur], modem->mname[j])) { X modem->m_cur = j; X break; X } X } X if (modem->m_cur == -1) { X sprintf(buf, "Modem name '%s' in TTY database", X modem->tname[modem->t_cur]); X error_win(1, buf, "does not exist in modem database"); X } X /* initialize the modem */ X if (modem->init_sp[modem->t_cur]) { X tbaud = dir->baud[dir->d_cur]; X dir->baud[dir->d_cur] = modem->init_sp[modem->t_cur]; X line_set(); X send_str(modem->init[modem->m_cur]); X dir->baud[dir->d_cur] = tbaud; X } X else X send_str(modem->init[modem->m_cur]); X sleep(1); X return(0); X } X i++; X } X error_win(0, "All ports are busy now, try again later", ""); X return(1); X} X X/* X * Release the port. Closes the file descriptor and removes the X * lock file X */ X Xvoid Xrelease_port(verbose) Xint verbose; X{ X extern int fd; X extern char *null_ptr; X char buf[80]; X void free_ptr(), hang_up(); X X /* X * The modem structure can't be guaranteed to exist yet. For example, X * an error in reading one of the other support files would cause X * this routine to be used before the MODEM structure gets allocated. X */ X if (modem == NULL) X return; X /* close the port */ X if (fd != -1) { X ioctl(fd, TCFLSH, 2); X /* X * Since HUPCL is set, the close() should drop the DTR and X * hang up the modem (provided you've got the modem to X * respond to DTR). Since this is not guaranteed, we send X * the hang_up string first. X */ X hang_up(verbose); X close(fd); X } X /* remove the lock */ X if (*lock_path != NULL && lock_path != NULL) { X if (unlink(lock_path)) { X sprintf(buf, "'%s'", lock_path); X error_win(0, "Can't remove the lock file", buf); X } X free_ptr(lock_path); X lock_path = null_ptr; X } X /* turn the getty back on? */ X if (getty_status) X set_getty(modem->tty[modem->t_cur], 1); X /* clean up the structure */ X fd = -1; X modem->m_cur = -1; X modem->t_cur = -1; X return; X} X X/* X * Turn the /etc/getty on or off for the specified port. A return code X * of 1 means that the getty was on. Systems with uugetty() or dedicated X * dialout ports won't need this routine. X */ X X/*ARGSUSED*/ Xstatic int Xset_getty(tty, on) Xchar *tty; Xint on; X{ X#ifdef UNIXPC X int i, ret_code; X char buf[40]; X unsigned int sleep(); X /* the last three characters */ X i = strlen(tty) -3; X X ret_code = 0; X if (on) { X sprintf(buf, "setgetty %s 1", tty+i); X system(buf); X } X else { X sprintf(buf, "setgetty %s 0", tty+i); X if (system(buf) == 512) X ret_code++; X sleep(1); X } X return(ret_code); X#else /* UNIXPC */ X /* X * If you don't have one of these cute little routines, you X * might wanna write one. It should check for an existing lock X * file, edit the /etc/inittab file, and issue an init -q. X * The return code should tell if there was a getty or not. X * Obviously the program would be suid to root. X */ X return(0); X#endif /* UNIXPC */ X} X X/* X * Check the lock file for a valid pid value. Error conditions such X * as not being able to open the lock file or not being able to interpret X * the contents of the lock file cause the code to assume that the lock X * file is valid. Let the user worry about weird special cases. A return X * code of 1 means the lock is dead or doesn't exist. X */ X Xstatic int Xchecklock(lockfile) Xchar *lockfile; X{ X extern int errno; X int lfd, lckpid; X#ifdef ASCII_PID X int n; X char buf[40]; X#endif /* ASCII_PID */ X /* doesn't exist */ X if (access(lockfile, 0)) X return(1); X /* can't open the lock file */ X if ((lfd = open(lockfile, 0)) < 0) X return(0); X X#ifdef ASCII_PID X if ((n = read(lfd, buf, 40)) <= 0) { X close(lfd); X return(0); X } X close(lfd); X buf[n--] = '\0'; X lckpid = atoi(buf); X#else /* ASCII_PID */ X if (read(lfd, (char *) &lckpid, sizeof(int)) != sizeof(int)) { X close(lfd); X return(0); X } X close(lfd); X#endif /* ASCII_PID */ X /* invalid pid? */ X if (lckpid <= 0 || lckpid > MAX_PID) X return(0); X X if ((kill(lckpid, 0) == -1) && (errno == ESRCH)) { X /* X * If the kill was unsuccessful due to an ESRCH error, X * that means the process is no longer active and the X * lock file can be safely removed. X */ X unlink(lockfile); X sleep(1); X return(1); X } X /* X * If the kill() was successful, that means the process must X * still active. X */ X return(0); X} X X/* X * Check to see if the desired baud rate can be handled by the modem. X * Uses the connect strings to make this determination. The first X * argument is the index into the TTY database. A return code of 1 X * means yes. X */ X Xstatic int Xck_speed(tty, baud) Xint tty, baud; X{ X int i, mod; X char buf[60]; X /* find the modem database */ X mod = -1; X for (i=0; i<modem->m_entries; i++) { X if (!strcmp(modem->mname[i], modem->tname[tty])) { X mod = i; X break; X } X } X if (mod == -1) { X sprintf(buf, "Modem name '%s' in TTY database", modem->tname[tty]); X error_win(1, buf, "does not exist in modem database"); X } X#ifdef DEBUG X fprintf(stderr, "ck_speed: checking modem '%s' for %d buad\n", modem->mname[mod], baud); X#endif /* DEBUG */ X X switch (baud) { X case 300: X if (*modem->con_3[mod] != NULL) X return(1); X break; X case 1200: X if (*modem->con_12[mod] != NULL) X return(1); X break; X case 2400: X if (*modem->con_24[mod] != NULL) X return(1); X break; X case 4800: X if (*modem->con_48[mod] != NULL) X return(1); X break; X case 9600: X if (*modem->con_96[mod] != NULL) X return(1); X break; X case 19200: X if (*modem->con_192[mod] != NULL) X return(1); X break; X } X return(0); X} SHAR_EOF if test 9459 -ne "`wc -c < 'port.c'`" then echo shar: "error transmitting 'port.c'" '(should have been 9459 characters)' fi fi echo shar: "extracting 'redial.c'" '(2242 characters)' if test -f 'redial.c' then echo shar: "will not over-write existing file 'redial.c'" else sed 's/^X//' << \SHAR_EOF > 'redial.c' X/* X * The redial option (actually a misnomer, it's really a queuing system). X * We expect a space-separated list of dialing directory entries (although X * new users always try to put in a phone number). A non-zero return code X * means we're ready to dial. X */ X X#include <stdio.h> X#include <curses.h> X#include "config.h" X#include "dial_dir.h" X#include "misc.h" X Xint Xredial() X{ X extern int fd; X WINDOW *rd_win, *newwin(); X char *ans, *entry, *get_str(), *strchr(), *strtok(); X int i, oops, number, ret_code; X X rd_win = newwin(6, 70, 5, 5); X X mvwaddstr(rd_win, 4, 23, "(<CR> for previous numbers)"); X mvwaddstr(rd_win, 2, 4, "Directory Entry Number(s): "); X box(rd_win, VERT, HORZ); X X mvwattrstr(rd_win, 0, 3, A_BOLD, " Redial Queue "); X wmove(rd_win, 2, 31); X wrefresh(rd_win); X /* get the string of numbers */ X ret_code = 0; X while ((ans = get_str(rd_win, 35, "0123456789+-@# ", "")) != NULL) { X oops = 0; X if (*ans == NULL) { X /* use previous queue */ X if (dir->q_num[0] != -1) { X ret_code++; X break; X } X /* there is no previous queue */ X beep(); X mvwattrstr(rd_win, 3, 4, A_BOLD, "No previous numbers"); X wrefresh(rd_win); X wait_key(rd_win, 3); X clear_line(rd_win, 3, 4, 1); X wmove(rd_win, 2, 31); X wrefresh(rd_win); X continue; X } X /* parse the queue values */ X entry = strtok(ans, " "); X for (i=0; i<NUM_QUEUE; i++) { X if (*entry == NULL) { X dir->q_num[i] = -1; X continue; X } X /* is there a LD code? */ X dir->q_ld[i] = NULL; X if (strchr("+-@#", *entry)) { X dir->q_ld[i] = *entry; X entry++; X } X X /* X * Zero is valid here, because it means use X * the current entry information. X */ X number = atoi(entry); X if (number < -1 || number > NUM_DIR) { X beep(); X mvwattrstr(rd_win, 3, 4, A_BOLD, "Invalid directory entry number"); X wrefresh(rd_win); X wait_key(rd_win, 3); X clear_line(rd_win, 3, 4, 1); X clear_line(rd_win, 2, 31, 1); X wrefresh(rd_win); X oops++; X break; X } X /* store the number in the queue */ X dir->q_num[i] = number; X entry = strtok((char *) NULL, " "); X } X if (oops) X continue; X ret_code++; X break; X } X if (fd == -1) { X werase(rd_win); X wrefresh(rd_win); X } X delwin(rd_win); X return(ret_code); X} SHAR_EOF if test 2242 -ne "`wc -c < 'redial.c'`" then echo shar: "error transmitting 'redial.c'" '(should have been 2242 characters)' fi fi exit 0 # End of shell archive
egray@killer.DALLAS.TX.US (Emmet Gray) (09/05/88)
This is part 6 (of 8) to the Pcomm v1.1 release package. Emmet P. Gray US Army, HQ III Corps & Fort Hood ..!uunet!uiucuxc!fthood!egray Attn: AFZF-DE-ENV DEH, Environmental Management Office Fort Hood, TX 76544-5057 ------------------------------------------------------------------------------ #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # s_axfer.c # s_gen.c # s_menu.c # s_modem.c # s_prompt.c # s_term.c # s_tty.c # screen.c # st_line.c # strings.c # terminal.c # This archive created: Sat Sep 3 15:35:04 1988 export PATH; PATH=/bin:/usr/bin:$PATH echo shar: "extracting 's_axfer.c'" '(3938 characters)' if test -f 's_axfer.c' then echo shar: "will not over-write existing file 's_axfer.c'" else sed 's/^X//' << \SHAR_EOF > 's_axfer.c' X/* X * Display the ASCII transfer setup, query for changes. A return code X * of 1 means something was changed. X */ X X#include <stdio.h> X#include <curses.h> X#include "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(), *strdup(); X void free_ptr(); 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, 34, "ASCII UPLOAD"); X mvwprintw(x_win, 5, 22, "1) Echo locally ........... %s", param->lecho); X mvwprintw(x_win, 6, 22, "2) Expand blank lines ..... %s", param->expand); X mvwprintw(x_win, 7, 22, "3) CR delay (ms) .......... %d", param->cr_delay); X mvwprintw(x_win, 8, 22, "4) Pace the output ........ %s", param->pace); X mvwprintw(x_win, 9, 22, "5) CR translation ......... %s", param->cr_up); X mvwprintw(x_win, 10, 22, "6) LF translation ......... %s", param->lf_up); X mvwaddstr(x_win, 12, 32, "ASCII DOWNLOAD"); X mvwprintw(x_win, 14, 22, "7) Transfer timeout (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 free_ptr(param->lecho); X param->lecho = strdup(ans); X ret_code++; X } X break; X case 2: X if ((ans = menu_prompt(x_win, 6, 50, "Expand blank lines", v_yes)) != NULL) { X free_ptr(param->expand); X param->expand = strdup(ans); X ret_code++; X } X break; X case 3: X if ((ans = menu_prompt(x_win, 7, 50, "CR delay (ms)", v_delay)) != NULL) { X param->cr_delay = atoi(ans); X ret_code++; X } X break; X case 4: X if ((ans = menu_prompt(x_win, 8, 50, "Pace the output", v_yes)) != NULL) { X free_ptr(param->pace); X param->pace = strdup(ans); X ret_code++; X } X break; X case 5: X if ((ans = menu_prompt(x_win, 9, 50, "CR translation (upload)", v_cr)) != NULL) { X free_ptr(param->cr_up); X param->cr_up = strdup(ans); X ret_code++; X } X break; X case 6: X if ((ans = menu_prompt(x_win, 10, 50, "LF translation (upload)", v_lf)) != NULL) { X free_ptr(param->lf_up); X param->lf_up = strdup(ans); X ret_code++; X } X break; X case 7: X if ((num = num_prompt(x_win, 14, 50, "Transfer timeout", "(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 free_ptr(param->cr_dn); X param->cr_dn = strdup(ans); X ret_code++; X } X break; X case 9: X if ((ans = menu_prompt(x_win, 16, 50, "LF translation (download)", v_lf)) != NULL) { X free_ptr(param->lf_dn); X param->lf_dn = strdup(ans); X ret_code++; X } X break; X default: X beep(); X } X mvwaddch(x_win, 20, 12, (chtype) ' '); X clear_line(x_win, 21, 0, 0); X clear_line(x_win, 22, 0, 0); X wmove(x_win, 20, 12); X wrefresh(x_win); X } X delwin(x_win); X return(ret_code); X} SHAR_EOF if test 3938 -ne "`wc -c < 's_axfer.c'`" then echo shar: "error transmitting 's_axfer.c'" '(should have been 3938 characters)' fi fi echo shar: "extracting 's_gen.c'" '(4457 characters)' if test -f 's_gen.c' then echo shar: "will not over-write existing file 's_gen.c'" else sed 's/^X//' << \SHAR_EOF > 's_gen.c' X/* X * Display the general setup, query for changes. A return code of 1 X * means something was changed. X */ X X#include <stdio.h> X#include <curses.h> X#include "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 *strdup(); X void free_ptr(), 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 free_ptr(param->logfile); X param->logfile = strdup(ans); X ret_code++; X } X break; X case 2: X if ((ans = str_prompt(g_win, 4, 50, "Default screen dump file", "")) != NULL) { X free_ptr(param->dumpfile); X param->dumpfile = strdup(ans); X ret_code++; X } X break; X case 3: X if ((ans = menu_prompt(g_win, 6, 50, "Strip high bit?", v_yes)) != NULL) { X free_ptr(param->strip); X param->strip = strdup(ans); X line_set(); X ret_code++; X } X break; X case 4: X if ((c = chr_prompt(g_win, 8, 50, "Pause character", "1 second")) != NULL) { X param->pause_char = c; X ret_code++; X } X break; X case 5: X if ((c = chr_prompt(g_win, 9, 50, "CR character", "(carriage return)")) != NULL) { X param->cr_char = c; X ret_code++; X } X break; X case 6: X if ((c = chr_prompt(g_win, 10, 50, "CTRL character", "(control)")) != NULL) { X param->ctrl_char = c; X ret_code++; X } X break; X case 7: X if ((c = chr_prompt(g_win, 11, 50, "ESC character", "(escape)")) != NULL) { X param->esc_char = c; X ret_code++; X } X break; X case 8: X if ((c = chr_prompt(g_win, 12, 50, "Break character", "")) != NULL) { 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 free_ptr(param->abort); X param->abort = strdup(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, 0); X clear_line(g_win, 22, 0, 0); X wmove(g_win, 20, 12); X wrefresh(g_win); X } X delwin(g_win); X return(ret_code); X} SHAR_EOF if test 4457 -ne "`wc -c < 's_gen.c'`" then echo shar: "error transmitting 's_gen.c'" '(should have been 4457 characters)' fi fi echo shar: "extracting 's_menu.c'" '(2732 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 return X * code of 1 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, 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, 4, 30, "1) TTY Setup"); X mvwaddstr(s_win, 6, 30, "2) Modem Setup"); X mvwaddstr(s_win, 8, 30, "3) Terminal Setup"); X mvwaddstr(s_win, 10, 30, "4) General Setup"); X mvwaddstr(s_win, 12, 30, "5) ASCII Transfer Setup"); X mvwaddstr(s_win, 14, 30, "S) Save setup to disk"); X 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 ret_code = 0; X /* get the options */ X while ((ans = get_str(s_win, 1, "12345Ss", "")) != NULL) { X if (xmc > 0) { X clear_line(s_win, 0, 0, 0); X wrefresh(s_win); X } X switch (*ans) { X case '1': X if (tty_setup()) X modem_flag++; X break; X case '2': X if (modem_setup()) X modem_flag++; X break; X case '3': 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 's': X case 'S': X if (xmc > 0) X top_line(s_win); X if (param_flag || modem_flag) { X wmove(s_win, 22, 27); X /* X * Writes to disk are not critical, X * the changes are made in memory. X */ X if (param_flag) { X wattrstr(s_win, A_BLINK, "Updating Parameter File"); X wrefresh(s_win); X wait_key(s_win, 3); X if (up_param()) { X touchwin(s_win); X wrefresh(s_win); X } X } X if (modem_flag) { X wattrstr(s_win, A_BLINK, "Updating Modem Database"); X wrefresh(s_win); X wait_key(s_win, 3); X if (up_modem()) { X touchwin(s_win); X wrefresh(s_win); X } X } X clear_line(s_win, 22, 27, 0); X wrefresh(s_win); X } X break; X default: X beep(); X } X touchwin(s_win); X if (xmc > 0) X top_line(s_win); X X mvwaddch(s_win, 20, 12, (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, 0); 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 2732 -ne "`wc -c < 's_menu.c'`" then echo shar: "error transmitting 's_menu.c'" '(should have been 2732 characters)' fi fi echo shar: "extracting 's_modem.c'" '(6867 characters)' if test -f 's_modem.c' then echo shar: "will not over-write existing file 's_modem.c'" else sed 's/^X//' << \SHAR_EOF > 's_modem.c' X/* X * Display the modem setup, query for changes. A return code of 1 means X * something was changed. X */ X X#include <stdio.h> X#include <curses.h> X#include "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, *strdup(), *str_prompt(), *menu_prompt(); X void disp_modem(), free_ptr(); X static char *v_yn[3] = {"Y", "N", NULL}; 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, 40, "Modem init string", "sent to the modem once")) != NULL) { X free_ptr(modem->init[j]); X modem->init[j] = strdup(ans); X ret_code++; X } X break; X case 3: X if ((ans = str_prompt(mo_win, 4, 40, "Dialing command", "")) != NULL) { X free_ptr(modem->dial[j]); X modem->dial[j] = strdup(ans); X ret_code++; X } X break; X case 4: X if ((ans = str_prompt(mo_win, 5, 40, "Dialing cmd suffix", "typically the <CR> character")) != NULL) { X free_ptr(modem->suffix[j]); X modem->suffix[j] = strdup(ans); X ret_code++; X } X break; X case 5: X if ((ans = str_prompt(mo_win, 6, 40, "Hang up string", "")) != NULL) { X free_ptr(modem->hang_up[j]); X modem->hang_up[j] = strdup(ans); X ret_code++; X } X break; X case 6: X if ((ans = menu_prompt(mo_win, 7, 40, "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, 40, "300 baud connect string", "")) != NULL) { X free_ptr(modem->con_3[j]); X modem->con_3[j] = strdup(ans); X ret_code++; X } X break; X case 8: X if ((ans = str_prompt(mo_win, 9, 40, "1200 baud connect string", "")) != NULL) { X free_ptr(modem->con_12[j]); X modem->con_12[j] = strdup(ans); X ret_code++; X } X break; X case 9: X if ((ans = str_prompt(mo_win, 10, 40, "2400 baud connect string", "")) != NULL) { X free_ptr(modem->con_24[j]); X modem->con_24[j] = strdup(ans); X ret_code++; X } X break; X case 10: X if ((ans = str_prompt(mo_win, 11, 40, "4800 baud connect string", "")) != NULL) { X free_ptr(modem->con_48[j]); X modem->con_48[j] = strdup(ans); X ret_code++; X } X break; X case 11: X if ((ans = str_prompt(mo_win, 12, 40, "9600 baud connect string", "")) != NULL) { X free_ptr(modem->con_96[j]); X modem->con_96[j] = strdup(ans); X ret_code++; X } X break; X case 12: X if ((ans = str_prompt(mo_win, 13, 40, "19200 baud connect string", "")) != NULL) { X free_ptr(modem->con_192[j]); X modem->con_192[j] = strdup(ans); X ret_code++; X } X break; X case 13: X if ((ans = str_prompt(mo_win, 14, 40, "No connect string 1", "")) != NULL) { X free_ptr(modem->no_con1[j]); X modem->no_con1[j] = strdup(ans); X ret_code++; X } X break; X case 14: X if ((ans = str_prompt(mo_win, 15, 40, "No connect string 2", "")) != NULL) { X free_ptr(modem->no_con2[j]); X modem->no_con2[j] = strdup(ans); X ret_code++; X } X break; X case 15: X if ((ans = str_prompt(mo_win, 16, 40, "No connect string 3", "")) != NULL) { X free_ptr(modem->no_con3[j]); X modem->no_con3[j] = strdup(ans); X ret_code++; X } X break; X case 16: X if ((ans = str_prompt(mo_win, 17, 40, "No connect string 4", "")) != NULL) { X free_ptr(modem->no_con4[j]); X modem->no_con4[j] = strdup(ans); X ret_code++; X } X break; X default: X beep(); X } X /* clear the previous prompts */ X mvwaddstr(mo_win, 20, 12, " "); X clear_line(mo_win, 21, 0, 0); X clear_line(mo_win, 22, 0, 0); X wmove(mo_win, 20, 12); X wrefresh(mo_win); X } X delwin(mo_win); X return(ret_code); X} X X/* X * Prompts for the modem name. The user selects the currently showing X * choice by hitting a carriage return. Returns the modem entry number. X * DOES NOT change the value of modem->m_cur. X */ X 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] == NULL) 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, 40, 0); X wrefresh(win); X mvwattrstr(win, 2, 40, A_BOLD, modem->mname[i]); X mvwprintw(win, 2, 26, "(%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, 12, "1) Modem name ............. %-39.39s", modem->mname[i]); X mvwprintw(w, 2, 26, "(%d of %d) ", i+1, modem->m_entries); X mvwprintw(w, 3, 12, "2) Modem init string ...... %-39.39s", modem->init[i]); X mvwprintw(w, 4, 12, "3) Dialing command ........ %-39.39s", modem->dial[i]); X mvwprintw(w, 5, 12, "4) Dialing cmd suffix ..... %-39.39s", modem->suffix[i]); X mvwprintw(w, 6, 12, "5) Hang up string ......... %-39.39s", modem->hang_up[i]); X mvwprintw(w, 7, 12, "6) Auto baud detect ....... %c", modem->auto_baud[i]); X mvwprintw(w, 8, 12, "7) 300 baud connect ....... %-39.39s", modem->con_3[i]); X mvwprintw(w, 9, 12, "8) 1200 baud connect ...... %-39.39s", modem->con_12[i]); X mvwprintw(w, 10, 12, "9) 2400 baud connect ...... %-39.39s", modem->con_24[i]); X mvwprintw(w, 11, 11, "10) 4800 baud connect ...... %-39.39s", modem->con_48[i]); X mvwprintw(w, 12, 11, "11) 9600 baud connect ...... %-39.39s", modem->con_96[i]); X mvwprintw(w, 13, 11, "12) 19200 baud connect ..... %-39.39s", modem->con_192[i]); X mvwprintw(w, 14, 11, "13) No connect string 1 .... %-39.39s", modem->no_con1[i]); X mvwprintw(w, 15, 11, "14) No connect string 2 .... %-39.39s", modem->no_con2[i]); X mvwprintw(w, 16, 11, "15) No connect string 3 .... %-39.39s", modem->no_con3[i]); X mvwprintw(w, 17, 11, "16) No connect string 4 .... %-39.39s", modem->no_con4[i]); X return; X} SHAR_EOF if test 6867 -ne "`wc -c < 's_modem.c'`" then echo shar: "error transmitting 's_modem.c'" '(should have been 6867 characters)' fi fi echo shar: "extracting 's_prompt.c'" '(2972 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. 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, 39, "", "")) == NULL) X return(NULL); X /* check the value */ X if (!strcmp(ans, " ")) X ans = null_ptr; X /* display the value in bold */ X clear_line(win, y, x, 0); X wattrstr(win, A_BOLD, ans); X X return(ans); X} X X/* X * Same as above, except we return a single character. X */ X Xchar Xchr_prompt(win, y, x, p1, p2) XWINDOW *win; Xint y, x; Xchar *p1, *p2; X{ X char *ans, *get_str(); X /* print first prompt last */ X mvwaddstr(win, 22, 0, p2); X mvwaddstr(win, 21, 0, p1); X waddstr(win, ": "); X wrefresh(win); X X if ((ans = get_str(win, 1, "", "")) == NULL) X return(NULL); X /* display the value in bold */ X mvwaddstr(win, y, x, " "); X wrefresh(win); X mvwattrstr(win, y, x, A_BOLD, ans); X X return(*ans); X} X X/* X * Same as above, except that it prompts for a three digit number. X */ X Xint Xnum_prompt(win, y, x, p1, p2) XWINDOW *win; Xint y, x; Xchar *p1, *p2; X{ X int i; 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}; 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, 0); X wattrstr(win, A_BOLD, menu[i]); X /* return the value */ X return(menu[i]); X} SHAR_EOF if test 2972 -ne "`wc -c < 's_prompt.c'`" then echo shar: "error transmitting 's_prompt.c'" '(should have been 2972 characters)' fi fi echo shar: "extracting 's_term.c'" '(3172 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, *strdup(), *str_prompt(), *menu_prompt(); X void free_ptr(), 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 free_ptr(param->ascii_hot); X param->ascii_hot = strdup(ans); X ret_code = 1; X } X break; X case 3: X if ((ans = menu_prompt(t_win, 9, 50, "Duplex", v_duplex)) != NULL ) { X free_ptr(param->d_duplex); X param->d_duplex = strdup(ans); X ret_code = 1; X } X break; X case 4: X if ((ans = menu_prompt(t_win, 11, 50, "Flow control", v_flow)) != NULL ) { X free_ptr(param->flow); X param->flow = strdup(ans); X 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 free_ptr(param->cr_in); X X /* X * the "add lf to cr" function is X * performed by the input routine X */ X param->cr_in = strdup(ans); X if (!strcmp(ans, "CR/LF")) X status->add_lf = 1; X else X status->add_lf = 0; 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 free_ptr(param->cr_out); X param->cr_out = strdup(ans); X ret_code = 1; X } X break; X default: X beep(); X } X mvwaddch(t_win, 20, 12, (chtype) ' '); X clear_line(t_win, 21, 0, 0); X clear_line(t_win, 22, 0, 0); X wmove(t_win, 20, 12); X wrefresh(t_win); X } X delwin(t_win); X return(ret_code); X} SHAR_EOF if test 3172 -ne "`wc -c < 's_term.c'`" then echo shar: "error transmitting 's_term.c'" '(should have been 3172 characters)' fi fi echo shar: "extracting 's_tty.c'" '(4800 characters)' if test -f 's_tty.c' then echo shar: "will not over-write existing file 's_tty.c'" else sed 's/^X//' << \SHAR_EOF > 's_tty.c' X/* X * Display the TTY setup, query for changes. A return code of 1 X * means something was changed. X */ X X#include <stdio.h> X#include <curses.h> X#include "config.h" X#include "misc.h" X#include "modem.h" X Xint Xtty_setup() X{ X extern char *null_ptr; X WINDOW *tt_win, *newwin(); X char *strdup(), message[80]; 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 mvwprintw(tt_win, 15, 20, "%d) Add a TTY entry", NUM_TTY+1); X mvwprintw(tt_win, 16, 20, "%d) Delete a TTY entry", NUM_TTY+2); X 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 number */ X ret_code = 0; X while ((i = get_num(tt_win, 2)) != -1) { X /* if beyond t_entries, fake it */ X if (i > modem->t_entries && i <= NUM_TTY) X i=999; X /* change an entry */ X if (i >= 1 && i <= NUM_TTY) { X if (tty_prompt(tt_win, i-1)) X break; X /* requires modem update? */ X create_modem(modem->tname[i-1]); X del_modem(); X X ret_code++; X } X /* add a entry */ X if (i == NUM_TTY+1) { X if (modem->t_entries == NUM_TTY) { X sprintf(message, "'%s'", modem->m_path); X error_win(0, "No empty TTY slots in modem/TTY database", message); X continue; X } X /* prompt for info */ X j = modem->t_entries; X if (tty_prompt(tt_win, j)) X break; X /* add modem entry? */ X modem->t_entries++; X create_modem(modem->tname[j]); X X ret_code++; X } X /* delete an entry */ X if (i == NUM_TTY+2) { X mvwaddstr(tt_win, 21, 0, "Entry number to delete: "); X wrefresh(tt_win); X while ((num = get_num(tt_win, 4)) != -1) { X /* valid range */ X if (!num || num>modem->t_entries) { X beep(); X mvwaddstr(tt_win, 21, 24, " "); X 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 } X if (i == 0 || i>NUM_TTY+2) X beep(); X mvwaddstr(tt_win, 20, 12, " "); X clear_line(tt_win, 21, 0, 0); X clear_line(tt_win, 22, 0, 0); X wmove(tt_win, 20, 12); X wrefresh(tt_win); X } X delwin(tt_win); X return(ret_code); X} X X/* X * Display the current TTY list. No scrolling yet, so if your NUM_TTY is X * greater than ten, this routine will need some work. X */ X 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 return code of 1 means a X * user abort. The second argument is the zero based index. X */ X Xstatic int Xtty_prompt(win, i) XWINDOW *win; Xint i; X{ X char *ans, *temp_tty, *temp_tname, *str_prompt(), *menu_prompt(); X void free_ptr(); 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(1); X X temp_tty = strdup(ans); X clear_line(win, 21, 0, 0); X X /* get temp tname */ X if ((ans = str_prompt(win, i+4, 39, "Modem name", "")) == NULL) X return(1); X X temp_tname = strdup(ans); X clear_line(win, 21, 0, 0); X X /* get maximum baud */ X if ((ans = menu_prompt(win, i+4, 55, "Init speed", v_baud)) == NULL) X return(1); X X wrefresh(win); X /* store 'em for real */ X free_ptr(modem->tty[i]); X free_ptr(modem->tname[i]); X X modem->tty[i] = strdup(temp_tty); X modem->tname[i] = strdup(temp_tname); X modem->init_sp[i] = atoi(ans); X X free_ptr(temp_tty); X free_ptr(temp_tname); X return(0); X} X X/* X * Delete a TTY entry. Since the list must be contiguous, we collapse the X * list to cover the hole we made. X */ X Xstatic void Xdel_tty(i) Xint i; X{ X extern char *null_ptr; X int j; X char *strdup(); X void free_ptr(); X /* collapse the list */ X for (j=i; j<modem->t_entries-1; j++) { X free_ptr(modem->tty[j]); X free_ptr(modem->tname[j]); X modem->tty[j] = strdup(modem->tty[j+1]); X modem->tname[j] = strdup(modem->tname[j+1]); X modem->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 4800 -ne "`wc -c < 's_tty.c'`" then echo shar: "error transmitting 's_tty.c'" '(should have been 4800 characters)' fi fi echo shar: "extracting 'screen.c'" '(2074 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_out, *my_fopen(); X char buf[MAX_COL+2]; X void error_win(); X#ifdef SHAREDMEM X int i; X#else /* SHAREDMEM */ X FILE *fp_in; X#endif /* SHAREDMEM */ 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+2, fp_in) != NULL) X fputs(buf, fp_out); X X fclose(fp_in); X#endif /* SHAREDMEM */ 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#ifndef SHAREDMEM X FILE *fp, *my_fopen(); X int row, col; X char buf[MAX_COL+2]; X#endif /* SHAREDMEM */ X X clearok(curscr, TRUE); X erase(); 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 while (fgets(buf, MAX_COL+2, fp) != NULL) { X /* zap the line feed */ X buf[COLS] = NULL; 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 2074 -ne "`wc -c < 'screen.c'`" then echo shar: "error transmitting 'screen.c'" '(should have been 2074 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 == NULL) 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 'strings.c'" '(1329 characters)' if test -f 'strings.c' then echo shar: "will not over-write existing file 'strings.c'" else sed 's/^X//' << \SHAR_EOF > 'strings.c' X/* X * Miscellaneous string routines. X */ X X#include <stdio.h> X X/* X * Do a fancy string copy. If NULL, return null. If pointer to NULL, then X * return the special "null_ptr" variable. If a normal copy, allocate X * memory first. X */ X Xchar * Xstrdup(str) Xchar *str; X{ X extern char *null_ptr; X char *ret, *malloc(), *strcpy(); X X if (str == NULL) X return(NULL); X /* if pointer to null */ X if (*str == NULL) X return(null_ptr); X X ret = malloc((unsigned int) strlen(str)+1); X strcpy(ret, str); X return(ret); X} X X/* X * Perform the free(2) function, but check for NULL and the special X * "null_ptr" variable first. X */ X Xvoid Xfree_ptr(str) Xchar *str; X{ X extern char *null_ptr; X void free(); X X if (str != NULL && str != null_ptr) X free(str); X return; X} X X/* X * This routine is similar to strtok(3). But our version handles null X * strings and takes a single separator character as an argument. X * Returns a NULL on end of string or error. X */ X Xchar * Xstr_tok(str, c) Xchar *str, c; X{ X extern char *null_ptr; 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 == NULL) X return(NULL); X /* no separator? */ X if (!(sep = strchr(ptr, c))) X return(NULL); X /* zap the sep, move past it */ X *sep = NULL; X sep++; X X return(ptr); X} SHAR_EOF if test 1329 -ne "`wc -c < 'strings.c'`" then echo shar: "error transmitting 'strings.c'" '(should have been 1329 characters)' fi fi echo shar: "extracting 'terminal.c'" '(9686 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#ifdef OLDCURSES X#include <termio.h> X#endif /* OLDCURSES */ X#ifdef UNIXPC X#include <sys/phone.h> X#include <fcntl.h> X#endif /* UNIXPC */ X#include "dial_dir.h" X#include "misc.h" X#include "modem.h" X#include "param.h" X#include "status.h" X Xstatic int pid = -1; X Xterminal(input_status) Xint input_status; X{ X extern int fd; X int i, k, cr_lf; X char c, lf=10, *strdup(); X void help_screen(), line_set(), n_shell(), load_vs(), send_str(); X void hang_up(), do_input(), list_dir(), pexit(), zap_vs(); X void st_line(), chg_dir(), screen_dump(), input_off(), suspend(); X void info(), term_mode(); X X /* if starting out in command mode */ X if (!input_status) X st_line(""); X /* put stdin/stdout in terminal mode */ X resetterm(); X term_mode(); X X if (input_status) X do_input(); X X while (1) { X read(0, &c, 1); X /* is it the hot key? */ X if (c == param->hot) { X /* suspend input */ X input_status = 0; X suspend(1); X X /* X * Put in 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 /* 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 break; X case 'r': X case 'R': /* redial */ X if (redial()) X input_status = dial_win(); 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(0); 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 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 hang_up(1); 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 = strdup("CR/LF"); X status->add_lf = 1; X } X else { X param->cr_in = strdup("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 ioctl(fd, TCSBRK, 0); 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(1); X break; X#ifndef OLDCURSES X case KEY_DOWN: X case '\n': X#endif /* OLDCURSES */ X case 'n': X case 'N': /* receive files */ X input_status = xfer_menu(0); X break; X case '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 send_str(param->mac_1); X break; X case '@': X send_str(param->mac_2); X break; X case '#': X send_str(param->mac_3); X break; X case '$': X send_str(param->mac_4); X break; X case '%': X send_str(param->mac_5); X break; X case '^': X send_str(param->mac_6); X break; X case '&': X send_str(param->mac_7); X break; X case '*': X send_str(param->mac_8); X break; X case '(': X send_str(param->mac_9); X break; X case ')': X send_str(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 /* re-start input routine */ X if (input_status) X do_input(); X else X suspend(0); X X /* X * If you pressed a key during one of the sleeping X * periods (typically the delay to see the status X * line change), let the keyboard value fall thru X * to the write() below. X */ X if (k == -1) X continue; X c = k; X } X /* 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 * 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, TCSETA, &tbuf); X ioctl(0, TCFLSH, 2); X return; X} X X/* X * Fire up the input routine... X */ X Xstatic void 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]; X#endif /* SHAREDMEM */ X /* if no TTY, or already on */ X if (pid != -1 || fd == -1) X return; X X status->fd = fd; X if (!strcmp(param->cr_in, "CR/LF")) X status->add_lf = 1; X else X status->add_lf = 0; X X#ifdef SHAREDMEM X sprintf(first, "%d", shm_id); X#else /* SHAREDMEM */ X sprintf(first, "%d", status->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 SETUGID X setuid(getuid()); X setgid(getgid()); X#endif /* SETUGID */ X#ifdef SHAREDMEM X execlp("pcomm_input", "pcomm_input", first, (char *) 0); X#else /* SHAREDMEM */ X execlp("pcomm_input", "pcomm_input", first, add_lf, log, X 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#ifdef UNIXPC X char buf[40], *strcpy(), *ttyname(); X#endif /* UNIXPC */ 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 fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NDELAY); X line_set(); X } X else X#endif /* UNIXPC */ X send_str(modem->hang_up[modem->m_cur]); 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#ifndef SHAREDMEM X if (on) X sleep(1); X#endif /* SHAREDMEM */ X return; X} SHAR_EOF if test 9686 -ne "`wc -c < 'terminal.c'`" then echo shar: "error transmitting 'terminal.c'" '(should have been 9686 characters)' fi fi exit 0 # End of shell archive
egray@killer.DALLAS.TX.US (Emmet Gray) (09/05/88)
This is part 7 (of 8) to the Pcomm v1.1 release package. Emmet P. Gray US Army, HQ III Corps & Fort Hood ..!uunet!uiucuxc!fthood!egray Attn: AFZF-DE-ENV DEH, Environmental Management Office Fort Hood, TX 76544-5057 ------------------------------------------------------------------------------ #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # vcs.c # x_ascii.c # x_batch.c # x_extrnl.c # x_menu.c # x_rcv.c # This archive created: Sat Sep 3 15:35:07 1988 export PATH; PATH=/bin:/usr/bin:$PATH echo shar: "extracting 'vcs.c'" '(10169 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 <curses.h> X#include "config.h" X#ifndef OLDCURSES X#include <term.h> X#endif /* OLDCURSES */ X#include "vcs.h" 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 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 /* lead-in less than a space */ 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 buf[ptr++] = c; X buf[ptr] = -1; X /* test for match */ X maybe = 0; X for (i=0; i<NUM_VCS; i++) { X switch (match_codes(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 * 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 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 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 sprintf(buf, "13"); X else X sprintf(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 sprintf(buf, "35"); X else X sprintf(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] != NULL) { X if (buf[i] != putc_buf[i]) X break; X i++; X } X /* sanity checking */ X if (buf[i] == NULL) 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] != NULL) { X if (buf[i] != putc_buf[i]) X break; X i++; X } X temp[i] = 1001; X if (buf[i] == NULL) 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 routines that fakes curses(3) into outputing 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] = NULL; X tputs(s, 1, fake_putc); X putc_buf[putc_cnt] = NULL; X return; X} Xstatic int Xfake_putc(c) Xchar c; X{ 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 10169 -ne "`wc -c < 'vcs.c'`" then echo shar: "error transmitting 'vcs.c'" '(should have been 10169 characters)' fi fi echo shar: "extracting 'x_ascii.c'" '(7019 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#define CLIST 64 X X#include <stdio.h> X#include <fcntl.h> X#include <curses.h> X#include <signal.h> X#include "config.h" X#include "misc.h" X#include "param.h" X Xvoid Xxfer_ascii(list, up) Xchar *list; Xint up; X{ X int cr_lf; X char *file, *strtok(); X void send_ascii(), rcv_ascii(), line_set(), st_line(), suspend(); X void load_vs(), ascii_mode(); X unsigned int sleep(); X X touchwin(stdscr); X refresh(); X /* only one file from list */ X file = strtok(list, " "); X X cr_lf = !strcmp(param->cr_out, "CR/LF"); X ascii_mode(up); X if (up) { X /* un-suspend the input routine */ X suspend(0); X X send_ascii(file, cr_lf); X /* re-suspend the input routine */ X suspend(1); X } X else X rcv_ascii(file, cr_lf); X X /* X * Restoring the TTY modes is easier than setting them... The X * fixterm() and line_set() routines fix most of the damage. X */ X fcntl(0, F_SETFL, fcntl(0, F_GETFL, 0) & ~O_NDELAY); X line_set(); X fixterm(); 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 * Put the TTY line in a mode suitable for the ASCII transfer. Puts the X * terminal in the raw, non-blocking mode. X */ X Xstatic void Xascii_mode(up) Xint up; X{ X extern int fd; X struct termio tbuf; X void input_off(), term_mode(); 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 /* use NL delays if no CR */ X if (!strcmp(param->cr_up, "STRIP")) X tbuf.c_oflag = (OPOST|ONLRET); X X /* CR delay times */ X switch (param->cr_delay) { X case 0: X tbuf.c_oflag = 0; X break; X case 100: X tbuf.c_oflag |= (OPOST|CR2); X break; X case 150: X tbuf.c_oflag |= (OPOST|CR3); X break; X } X } X /* if down loading */ X else { X tbuf.c_iflag = (ISTRIP|IXOFF); X /* kill the input routine */ X input_off(); X } X X ioctl(fd, TCSETA, &tbuf); X ioctl(fd, TCFLSH, 2); X /* out of curses mode */ X resetterm(); X term_mode(); X /* non-blocking mode */ X fcntl(0, F_SETFL, fcntl(0, F_GETFL, 0) | O_NDELAY); 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; X int i, j, strip_cr, strip_lf, add_cr, add_lf, expand, lecho, pace; X unsigned char c, last; X unsigned int sleep(); X /* permission already checked */ X if (!(fp = fopen(file, "r"))) X return; X /* ASCII transfer options */ X strip_cr = !strcmp(param->cr_up, "STRIP"); X add_lf = !strcmp(param->cr_up, "ADD LF"); X strip_lf = !strcmp(param->lf_up, "STRIP"); X add_cr = !strcmp(param->lf_up, "ADD CR"); X expand = !strcmp(param->expand, "YES"); X lecho = !strcmp(param->lecho, "YES"); X pace = !strcmp(param->pace, "YES"); X X last = 0; X while ((i = fgetc(fp)) != EOF) { X /* any keyboard activity? */ X switch (j = getchar()) { X case -1: /* no key was pressed */ X break; X case ESC: /* <ESC> key for abort */ X fclose(fp); X sleep(2); X ioctl(fd, TCSBRK, 1); X return; X default: /* send the char */ X c = j & 0xff; X putc_line(c); X if (c == '\r' && cr_lf) X putc_line('\n'); X break; X } X c = i & 0xff; 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 ioctl(fd, TCSBRK, 1); X if (lecho) { X putchar((char) c); X fflush(stdout); X } X } X fclose(fp); X sleep(2); X ioctl(fd, TCSBRK, 1); 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; X int i, strip_cr, strip_lf, add_cr, add_lf, got_first; X unsigned int delay; X char c; X /* permission already checked */ X if (!(fp = fopen(file, "w"))) X return; X /* ASCII transfer options */ X strip_cr = !strcmp(param->cr_dn, "STRIP"); X add_lf = !strcmp(param->cr_dn, "ADD LF"); X strip_lf = !strcmp(param->lf_dn, "STRIP"); X add_cr = !strcmp(param->lf_dn, "ADD CR"); X X got_first = 0; X delay = 1; X while (1) { X /* keyboard activity */ X switch (i = getchar()) { X case -1: /* no key was pressed */ X break; X case ESC: /* <ESC> key */ X fclose(fp); X return; X default: /* send it */ X c = i & 0xff; 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 & 0xff; 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 bl_force(); X char c; X unsigned int alarm(); X X signal(SIGALRM, bl_force); X bl_flag = 0; X X alarm(sec); X if ((int) (c = buf_read()) < 0) { X alarm(0); X return(-1); X } X if (bl_flag) X return(-1); X alarm(0); X return(c & 0xff); X} X/*ARGSUSED*/ Xstatic int Xbl_force(dummy) Xint dummy; X{ X bl_flag = 1; 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]; X static char *bufp = buf; X static int n = 0; X X if (n <= 0) { X if ((n = read(fd, buf, CLIST)) <= 0) X return(-1); X bufp = buf; X } X while (--n >= 0) X return(*bufp++ & 0xff); X return(-1); X} SHAR_EOF if test 7019 -ne "`wc -c < 'x_ascii.c'`" then echo shar: "error transmitting 'x_ascii.c'" '(should have been 7019 characters)' fi fi echo shar: "extracting 'x_batch.c'" '(8478 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. 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, 1); 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, 1); X wattrstr(win, A_BOLD, "REMOTE ABORTED"); X wrefresh(win); X return(CANCEL); X } X /* fall thru... */ X default: X clear_line(win, 12, 24, 1); X waddstr(win, "NAME FAILED"); X wrefresh(win); X return(ERROR); X } X new_name++; X } X putc_line(CTRLZ); X /* verify the checksum */ X if (getc_line(10) != sum) { X putc_line('u'); X clear_line(win, 12, 24, 1); X waddstr(win, "CHECKSUM FAILED"); X wrefresh(win); X return(ERROR); X } X putc_line(ACK); X return(0); X} X X/* X * Receive a modem7 file name. A return code of 1 means the end of the X * batch transfers. X */ X Xint Xrcv_modem7(win, default_err) XWINDOW *win; Xint default_err; X{ X 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, 1); 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, 1); 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, 1); 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, 1); X wattrstr(win, A_BOLD, "REMOTE ABORTED"); X wrefresh(win); X return(CANCEL); X } X /* fall thru... */ X case 'u': /* bad name character */ X beep(); X clear_line(win, 12, 24, 1); X wattrstr(win, A_BOLD, "BAD NAME"); X wrefresh(win); X return(ERROR); X default: /* the name... */ X temp_name[i] = j & 0xff; X if (j != CTRLZ) X putc_line(ACK); X break; X } X } X temp_name[12] = NULL; X /* send our checksum */ X sum = calc_sum((unsigned char *) temp_name, 12); X putc_line(sum); X /* do they agree? */ X if (getc_line(10) != ACK) { X beep(); X clear_line(win, 12, 24, 1); X wattrstr(win, A_BOLD, "BAD NAME"); X wrefresh(win); X return(ERROR); X } X /* load the file_name array */ X unfix_name(temp_name); X /* any name collisions? */ X change_name(win, file_name); X return(0); X} X X/* X * Send the block 0 information for a ymodem batch transfer. Uses only X * the name component of the path and the file size. X */ X Xint Xsend_ymodem(win, file, size) XWINDOW *win; Xchar *file; Xlong size; X{ X register int i; X unsigned short crc, calc_crc(); X char *strcpy(); X unsigned char buf[133]; X /* start with a clean block */ X for (i=0; i<132; i++) X buf[i] = NULL; X /* the header */ X buf[0] = SOH; X buf[1] = 0; X buf[2] = 255; X X /* X * The block zero consists of the file name (no path component), X * a NULL, and the file length (as a string). The end of batch X * marker is an empty block. X */ X if (*file != NULL) { X strcpy((char *) &buf[3], file); X sprintf((char *) &buf[strlen(file)+4], "%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] = NULL; X /* read the zero block */ X if (code = rcv_block(win, 1, 1024, 0)) X return(code); X /* at end of batch */ X if (buf[3] == NULL) X return(0); X /* get the file name */ X change_name(win, (char *) &buf[3]); X /* any trouble? */ X if (file_name[0] == NULL) { X putc_line(CAN); X return(0); X } X /* X * The file length is placed after the NULL of the file name X * and is terminated by another NULL. If the length is missing, X * 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] = NULL; X /* write permission on directory? */ X if (access(".", 2)) { X beep(); X clear_line(win, 12, 24, 1); X wattrstr(win, A_BOLD, "NO WRITE ON DIRECTORY"); X wrefresh(win); X return; X } X /* prepend up to 13 "X"s */ X modified = 0; X for (i=1; i<14; i++) { X if (access(ans, 0)) { X if (modified) { X beep(); X clear_line(win, 12, 24, 1); X waddstr(win, "NAME COLLISION"); X wrefresh(win); X sleep(1); X } X strcpy(file_name, ans); X return; X } X X modified++; X strcpy(temp, "X"); X strncat(temp, ans, 13); X temp[14] = NULL; X strcpy(ans, temp); X } X beep(); X clear_line(win, 12, 24, 1); X waddstr(win, "BAD NAME"); X wrefresh(win); X return; X} X X/* X * Convert a perfectly good Unix file name to fit the CP/M file name X * rules. Used for the modem7 batch file transfer. Returns a pointer X * to the new name. X */ X Xchar * Xfix_name(path) Xchar *path; X{ X int dot; X char *s, *name, temp[15], *ext, *strcpy(), *strrchr(); X static char ans[13]; X /* ignore the path component */ X if (s = strrchr(path, '/')) X strcpy(temp, s++); X else X strcpy(temp, path); X name = temp; X X ext = NULL; X dot = 0; X for (s=name; *s; ++s) { X if (*s == '.' && !dot) { X dot++; X *s = NULL; X ext = s + 1; X } X if (islower(*s)) X *s = toupper(*s); X } X /* if null name component */ X if (*name == NULL) X name = "X"; X /* if name too long */ X if (strlen(name) > 8) X *(name+8) = NULL; X /* if extension too long */ X if (strlen(ext) > 3) X *(ext+3) = NULL; X X sprintf(ans, "%-8.8s%-3.3s%c", temp, ext, CTRLZ); X return(ans); X} X X/* X * Convert a CP/M style filename into a legal Unix file name. Loads the X * global character array "file_name". X */ X Xvoid Xunfix_name(cpm_name) Xchar *cpm_name; X{ X extern char file_name[15]; X register int i, n; X int dot; X char temp[15]; X X file_name[0] = NULL; X if (!*cpm_name) X return; X X strcpy(temp, cpm_name); X /* 8 character of the name */ X n = 0; X for (i=0; i<8; i++) { X if (temp[i] != ' ') { X if (isupper(temp[i])) X file_name[n++] = tolower(temp[i]); X else X file_name[n++] = temp[i]; X } X } X /* 3 character extension */ X dot = 0; X for (i=8; i<11; i++) { X if (temp[i] != ' ') { X if (!dot) { X dot++; X file_name[n++] = '.'; X } X if (isupper(temp[i])) X file_name[n++] = tolower(temp[i]); X else X file_name[n++] = temp[i]; X } X } X file_name[n] = NULL; X return; X} SHAR_EOF if test 8478 -ne "`wc -c < 'x_batch.c'`" then echo shar: "error transmitting 'x_batch.c'" '(should have been 8478 characters)' fi fi echo shar: "extracting 'x_extrnl.c'" '(1569 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. 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 <fcntl.h> X#include "config.h" X Xvoid Xextrnl(cmd) Xchar *cmd; X{ X extern int fd; X WINDOW *xt_win, *newwin(); X int (*istat)(), (*qstat)(), status, epid, w; X char *shell, *shellpath, *getenv(), *strrchr(), buf[40], *ttyname(); X char *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 shellpath = getenv("SHELL"); X if (shellpath == NULL || *shellpath == NULL) X shellpath = "/bin/sh"; X X shell = strrchr(shellpath, '/') + 1; X X if (!(epid = fork())) { X /* recreate the device name */ X strcpy(buf, ttyname(fd)); X close(fd); X /* swap the stdin */ X close(0); X open(buf, O_RDONLY); X /* swap the stdout */ X close(1); X open(buf, O_WRONLY); X#ifdef SETUGID X setgid(getgid()); X setuid(getuid()); X#endif /* SETUGID */ X execl(shellpath, shell, "-c", cmd, (char *) 0); X _exit(1); X } X istat = signal(SIGINT, SIG_IGN); X qstat = signal(SIGQUIT, SIG_IGN); X X while ((w = wait(&status)) != epid && 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(xt_win); X wrefresh(xt_win); X delwin(xt_win); X return; X} SHAR_EOF if test 1569 -ne "`wc -c < 'x_extrnl.c'`" then echo shar: "error transmitting 'x_extrnl.c'" '(should have been 1569 characters)' fi fi echo shar: "extracting 'x_menu.c'" '(5812 characters)' if test -f 'x_menu.c' then echo shar: "will not over-write existing file 'x_menu.c'" else sed 's/^X//' << \SHAR_EOF > 'x_menu.c' X/* X * Open a window to display the choices of file transfer protocols and X * prompt for the file name(s). A return code of 1 means turn the X * input routine back on. X */ X X#include <stdio.h> X#include <sys/types.h> X#include <sys/stat.h> X#include <curses.h> X#include "config.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 *list, *get_names(), *get_extrnl(); X int type, is_batch; X void xfer_win(), xfer_ascii(), free_ptr(), extrnl(), error_win(); X X xm_win = newwin(15, 20, 2, 45); X X mvwaddstr(xm_win, 2, 3, "1) xmodem"); X mvwaddstr(xm_win, 3, 3, "2) xmodem-1k"); X mvwaddstr(xm_win, 4, 3, "3) modem7"); X mvwaddstr(xm_win, 5, 3, "4) ymodem"); X mvwaddstr(xm_win, 6, 3, "5) ymodem-g"); X mvwaddstr(xm_win, 7, 3, "6) ASCII"); X mvwaddstr(xm_win, 8, 3, "7) (external)"); X mvwaddstr(xm_win, 11, 3, "<ESC> to Abort"); X mvwaddstr(xm_win, 13, 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, 13, 13); X wrefresh(xm_win); X /* get the protocol */ X while ((type = get_num(xm_win, 1)) != -1) { X if (type >= 1 && type <= PROTOCOLS) X break; X beep(); X mvwaddch(xm_win, 13, 13, (chtype) ' '); X wmove(xm_win, 13, 13); X wrefresh(xm_win); X } X type--; X werase(xm_win); X wrefresh(xm_win); X delwin(xm_win); X /* chickened out */ X if (type < 0) X return(0); X X if (fd == -1) { X error_win(0, "Not currently connected to any host", ""); X return(0); X } X /* is the external protocol? */ X if (type == EXTRNL) { X /* get the command line */ X if (!(list = get_extrnl(up))) X return(0); X extrnl(list); X return(1); X } X /* is a batch protocol? */ X is_batch = 0; X switch (type) { X case MODEM7: X case YMODEM: X case YMODEM_G: X is_batch++; X break; X default: X break; X } X X /* X * When receiving files in one of the batch modes, there is no X * need to prompt for a list of file names. X */ X list = null_ptr; X if (up || !is_batch) { X if (!(list = get_names(up, type, is_batch))) X return(0); X } X /* if ascii transfer */ X if (type == XASCII) { X xfer_ascii(list, up); X free_ptr(list); X if (up) X return(0); X return(1); X } X xfer_win(list, up, type); X free_ptr(list); X return(1); X} X Xchar *protocol[PROTOCOLS] = {"xmodem", "xmodem-1k", "modem7", "ymodem", X "ymodem-g", "ASCII", "(external)"}; X X/* X * Prompt for a list of files for the transfer programs. A NULL return X * code means you chickened out. X */ X Xstatic char * Xget_names(up, type, is_batch) Xint up, type, is_batch; X{ X int can; X WINDOW *gn_win, *newwin(); X char *list, *ans, *file, 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 sprintf(buf, " Send %s ", protocol[type]); X else X sprintf(buf, " Receive %s ", protocol[type]); 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, "", ""); X else X ans = get_str(gn_win, 60, "", " "); X X if (ans == NULL || *ans == NULL) { X list = NULL; X break; X } X list = expand(ans); X 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 */ X file = strtok(list, " "); 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, 1); 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, 1); X clear_line(gn_win, 3, 20, 1); 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, 1); X clear_line(gn_win, 3, 20, 1); 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, 1); X clear_line(gn_win, 3, 20, 1); X continue; X } X break; X } X /* check write permission */ X if (!(can = can_write(file))) { X beep(); X clear_line(gn_win, 4, 15, 1); X mvwattrstr(gn_win, 4, 15, A_BOLD, "No write permission"); X wrefresh(gn_win); X wait_key(gn_win, 3); X clear_line(gn_win, 4, 15, 1); X clear_line(gn_win, 3, 20, 1); X continue; X } X if (can == 2) { X if (!yes_prompt(gn_win, 4, 15, A_BOLD, "File exists, overwrite")) { X clear_line(gn_win, 4, 15, 1); X clear_line(gn_win, 3, 20, 1); X continue; X } X break; X } 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. A return code of NULL means forget it. X */ X Xstatic char * Xget_extrnl(up) Xint up; X{ X WINDOW *ge_win, *newwin(); X char *cmd, *ans, *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 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 wmove(ge_win, 3, 24); X wrefresh(ge_win); X /* get the line */ X ans = get_str(ge_win, 60, "", ""); X cmd = expand(ans); X if (*cmd == NULL) X cmd = NULL; X X werase(ge_win); X wrefresh(ge_win); X delwin(ge_win); X return(cmd); X} SHAR_EOF if test 5812 -ne "`wc -c < 'x_menu.c'`" then echo shar: "error transmitting 'x_menu.c'" '(should have been 5812 characters)' fi fi echo shar: "extracting 'x_rcv.c'" '(11805 characters)' if test -f 'x_rcv.c' then echo shar: "will not over-write existing file 'x_rcv.c'" else sed 's/^X//' << \SHAR_EOF > 'x_rcv.c' X/* X * Receive a list of files using a version of Ward Christensen's file X * transfer protocol. A return code of 1 means the user must acknowledge X * an error condition (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, " "); X /* dissect the file name */ X if ((name = strrchr(file, '/'))) X strcpy(file_name, name++); X else X strcpy(file_name, file); X } X /* get the modem7 file name */ X if (type == MODEM7) { X if (code = rcv_modem7(win, default_err)) X return(code +1); X X file = file_name; X } X /* get the block 0 */ X if (type == YMODEM || type == YMODEM_G) { X if (code = send_first(win, max_block, default_err)) X return(code +1); X X if (code = rcv_ymodem(win)) X return(code +1); X X /* at the end? */ X if (buf[3] == NULL) { X beep(); X wrefresh(win); X putc_line(ACK); X sleep(1); X return(0); X } X file = file_name; X } X /* any trouble? */ X if (file_name[0] == NULL) X continue; X X clear_line(win, 3, 24, 1); X waddstr(win, file_name); X /* if file length is known */ X if (file_length != 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, 1); X waddstr(win, "NONE"); X wrefresh(win); X X /* X * If the user supplied the name, write permission is checked X * by the get_names() routine in xfer_menu(). If 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. So why is this here? X */ X /* open the file */ X if (!(fp = my_fopen(file, "w"))) { X beep(); X clear_line(win, 12, 24, 1); X wattrstr(win, A_BOLD, "CAN'T OPEN FILE"); X wrefresh(win); X cancel_xfer(1); 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, 1); 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, 1); X wattrstr(win, A_BOLD, "WRITE ERROR"); X wrefresh(win); X cancel_xfer(1); 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_name, file_length)) { X beep(); X clear_line(win, 12, 24, 1); 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, 1); X waddstr(win, "ABORTED"); X wrefresh(win); X cancel_xfer(1); 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, 1); 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, 1); 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, 1); X waddstr(win, "BAD HEADER"); X wrefresh(win); X /* read some garbage... */ X fread_line(buf, 1028, 3); X putc_line(NAK); X break; X } X } X beep(); X clear_line(win, 12, 24, 1); X wattrstr(win, A_BOLD, "TIMED OUT"); X wrefresh(win); X return(ERROR); X} X X/* X * Receive a block of info from the host. Returns a 0 on success, a 1 on X * a duplicate block or the standard error codes. The variables X * err_method and block_size are global. X */ X Xint Xrcv_block(win, got_hdr, max_block, blk) XWINDOW *win; Xint got_hdr, max_block; Xunsigned char blk; X{ X int i, err_count, bad_block, out_of_sync; X unsigned short crc, calc_crc(); X unsigned int packet, sleep(); X unsigned char 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, 1); X waddstr(win, "ABORTED"); X wrefresh(win); X cancel_xfer(1); X sleep(3); X return(ABORT); X } X /* have we already got a hdr? */ X if (!got_hdr) { X if ((i = getc_line(10)) == -1) { X err_count++; X tot_err++; X clear_line(win, 12, 24, 1); X waddstr(win, "NO RESPONSE"); X wrefresh(win); X continue; X } X buf[0] = i; X#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, 1); X waddstr(win, "TRANSFER COMPLETE"); X wrefresh(win); X sleep(1); X return(0); X case SOH: /* small block follows */ X block_size = 128; X break; X case STX: /* large block follows */ X if (max_block == 1024) { X block_size = 1024; X break; X } X /* fall thru... */ X default: X err_count++; X tot_err++; X clear_line(win, 12, 24, 1); X waddstr(win, "BAD HEADER"); X wrefresh(win); X X /* flush a bad packet */ X fread_line(buf, 1028, 5); X putc_line(NAK); X continue; X } X } X got_hdr = 0; X /* read the rest of the packet */ X packet = block_size + 2 + (err_method == CHECKSUM ? 1 : 2); X if (fread_line(&buf[1], packet, 10) == -1) { X clear_line(win, 12, 24, 1); X waddstr(win, "TIMED OUT"); X wrefresh(win); X putc_line(NAK); X err_count++; X tot_err++; X continue; X } X X /* X * Validation of the packet includes checking the X * block number, its complement, and the crc/checksum. X */ X out_of_sync = 0; X if (buf[1] != blk || buf[2] != (unsigned char) ~blk) X out_of_sync++; X X bad_block = 0; X switch (err_method) { X case 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, 1); 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, 1); X waddstr(win, "OUT OF SYNC"); X wrefresh(win); X putc_line(NAK); X err_count++; X tot_err++; X continue; X } X return(0); X } X beep(); X clear_line(win, 12, 24, 1); X waddstr(win, "TOO MANY ERRORS"); X wrefresh(win); X cancel_xfer(1); X return(ERROR); X} SHAR_EOF if test 11805 -ne "`wc -c < 'x_rcv.c'`" then echo shar: "error transmitting 'x_rcv.c'" '(should have been 11805 characters)' fi fi exit 0 # End of shell archive
egray@killer.DALLAS.TX.US (Emmet Gray) (09/05/88)
This is part 8 (of 8) to the Pcomm v1.1 release package. Emmet P. Gray US Army, HQ III Corps & Fort Hood ..!uunet!uiucuxc!fthood!egray Attn: AFZF-DE-ENV DEH, Environmental Management Office Fort Hood, TX 76544-5057 ------------------------------------------------------------------------------ #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # x_send.c # x_win.c # xmodem.c # This archive created: Sat Sep 3 15:35:13 1988 export PATH; PATH=/bin:/usr/bin:$PATH echo shar: "extracting 'x_send.c'" '(11511 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, " "); X do { X /* is it a batch type? */ X file_count++; X if (file_count > 1 && !is_batch) X break; X /* display the name */ X clear_line(win, 3, 24, 1); X if ((name = strrchr(file, '/'))) X name++; X else X name = file; X waddstr(win, name); X wrefresh(win); X /* get the file size */ X if (stat(file, &stbuf) < 0) { X beep(); X clear_line(win, 12, 24, 1); X wattrstr(win, A_BOLD, "CAN'T FIND FILE"); X wrefresh(win); X sleep(3); X continue; X } X /* sanity checking */ X if ((stbuf.st_mode & S_IFREG) != S_IFREG) { X beep(); X clear_line(win, 12, 24, 1); 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, 1); X X if (!(fp = my_fopen(file, "r"))) { X beep(); X clear_line(win, 12, 24, 1); X wattrstr(win, A_BOLD, "PERMISSION DENIED"); X wrefresh(win); X sleep(3); X continue; X } X /* 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, 1); X waddstr(win, "NONE"); X wrefresh(win); X /* send the batch stuff */ X switch (type) { X case MODEM7: X if (code = rcv_first(win, default_err)) { X fclose(fp); X return(code +1); X } X X if (send_modem7(win, name)) { X fclose(fp); X return(1); X } X break; X case YMODEM: X case YMODEM_G: X if (code = rcv_first(win, default_err)) { X fclose(fp); X return(code +1); X } X X if (code = send_ymodem(win, name, size)) { X fclose(fp); X /* X * CANCEL now means that the other X * end can't open that file. X */ X if (code == CANCEL) X break; X return(code +1); X } X xmit_size -= 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, 1); 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, 1); X if (!got_it) { X /* X * So what??? We don't do anything if there is X * no acknowledge from the host!! X */ X waddstr(win, "NO ACKNOWLEDGE"); X } X else X waddstr(win, "TRANSFER COMPLETE"); X if (!is_batch) X beep(); X wrefresh(win); X sleep(2); X /* prepare to start again */ X fclose(fp); X } while (file = strtok((char *) NULL, " ")); X X /* X * The end of batch markers... For modem7 it's an ACK and EOT, for X * ymodem, it's an empty block 0. X */ X switch (type) { X case MODEM7: X if (code = rcv_first(win, default_err)) X return(code +1); X putc_line(ACK); X putc_line(EOT); X beep(); X wrefresh(win); X break; X case YMODEM: X case YMODEM_G: X if (code = rcv_first(win, default_err)) X return(code +1); X X if (code = send_ymodem(win, "", 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, 1); X waddstr(win, "ABORTED"); X wrefresh(win); X cancel_xfer(0); 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, 1); 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, 1); 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, 1); 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, 1); X wattrstr(win, A_BOLD, "TIMED OUT"); X wrefresh(win); X return(ERROR); X} X X/* X * Send a block of data, scan the keyboard for a user abort, and check X * the return codes from the host. Returns standard error codes or 0 X * on success. X */ X Xint Xsend_block(win, blk, packet) XWINDOW *win; Xunsigned char *blk; Xunsigned int packet; X{ X 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, 1); X waddstr(win, "ABORTED"); X wrefresh(win); X cancel_xfer(0); 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, 1); 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, 1); 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, 1); X wattrstr(win, A_BOLD, "REMOTE ABORTED"); X wrefresh(win); X return(CANCEL); X } X /* fall thru... */ X default: X clear_line(win, 12, 24, 1); X waddstr(win, "RESENDING"); X err_count++; X tot_err++; X break; X } X mvwprintw(win, 10, 24, "%-2d", err_count); X mvwprintw(win, 11, 24, "%-3d", tot_err); X wrefresh(win); X } X /* failed to get it right */ X beep(); X clear_line(win, 12, 24, 1); X wattrstr(win, A_BOLD, "TOO MANY ERRORS"); X wrefresh(win); X cancel_xfer(0); X return(ERROR); X} SHAR_EOF if test 11511 -ne "`wc -c < 'x_send.c'`" then echo shar: "error transmitting 'x_send.c'" '(should have been 11511 characters)' fi fi echo shar: "extracting 'x_win.c'" '(2577 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#ifdef OLDCURSES X#include <termio.h> X#endif /* OLDCURSES */ 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 ret_code, fast, my_speed; X void xmodem_mode(), input_off(), line_set(), error_win(), st_line(); 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 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, 1); X /* basic window stuff */ X mvwaddstr(xf_win, 2, 14, "Protocol:"); X mvwaddstr(xf_win, 3, 13, "File name:"); X mvwaddstr(xf_win, 4, 13, "File size:"); X mvwaddstr(xf_win, 5, 4, "Error check method:"); X mvwaddstr(xf_win, 6, 5, "Est transfer time:"); X mvwaddstr(xf_win, 7, 11, "Block count:"); X mvwaddstr(xf_win, 8, 6, "Percent complete:"); X mvwaddstr(xf_win, 9, 5, "Bytes transferred:"); X mvwaddstr(xf_win, 10, 5, "Errors this block:"); X mvwaddstr(xf_win, 11, 5, "Total error count:"); X mvwaddstr(xf_win, 12, 10, "Last message: NONE"); X box(xf_win, 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 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 ioctl(0, TCGETA, &tbuf); X my_speed = speed[tbuf.c_cflag & CBAUD]; X X if (my_speed >= dir->baud[dir->d_cur]) X fast++; X X if (up) X ret_code = send_xmodem(xf_win, list, type, fast); X else X ret_code = rcv_xmodem(xf_win, list, type, fast); X X nodelay(xf_win, 0); X /* prompt for a key on errors */ X if (ret_code) { X beep(); X clear_line(xf_win, 13, 9, 1); X wattrstr(xf_win, A_BOLD, "Press any key to continue"); X wrefresh(xf_win); X wgetch(xf_win); X } X werase(xf_win); X wrefresh(xf_win); X delwin(xf_win); X /* undo what xmodem_mode() did */ X line_set(); X return; X} SHAR_EOF if test 2577 -ne "`wc -c < 'x_win.c'`" then echo shar: "error transmitting 'x_win.c'" '(should have been 2577 characters)' fi fi echo shar: "extracting 'xmodem.c'" '(6652 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 CLIST 64 X X#include <stdio.h> X#include <signal.h> X#include <termio.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/* 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 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/*ARGSUSED*/ Xstatic int Xgl_force(dummy) Xint dummy; X{ X gl_flag = 1; X} X X/* X * Same as above, but reads a bunch of characters. The return code is X * now just a success/fail indicator. X */ X 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 characters */ X try = (len > CLIST) ? CLIST : len; 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/*ARGSUSED*/ Xstatic int Xrl_force(dummy) Xint dummy; X{ X rl_flag = 1; X} X X/* X * Put a character on the TTY line. This serves no useful purpose other X * than making the code look pretty. X */ X Xint Xputc_line(c) Xunsigned char c; X{ X extern int fd; X X return(write(fd, (char *) &c, 1)); X} X X/* X * Put the TTY driver in the mode suitable for xmodem transfers. X */ X Xvoid Xxmodem_mode(filedes) Xint filedes; X{ X struct termio tbuf; X X ioctl(filedes, 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; /* no parity */ X tbuf.c_cflag &= ~CSIZE; X tbuf.c_cflag |= CS8; /* 8 bit */ X X ioctl(filedes, TCSETA, &tbuf); X ioctl(filedes, TCFLSH, 2); X return; X} X X/* X * Cancel the file transfer. Send several ^X's to the remote, followed X * by an equal number of backspaces (in case they have already aborted and X * we're really at the command line). X */ X Xvoid Xcancel_xfer(recv) Xint recv; X{ X extern char file_name[15]; X X if (recv && !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 *tempfile, *mktemp(), buf[BUFSIZ]; X struct stat stbuf; X X if (stat(file, &stbuf) < 0) X return(1); X /* see if we have any work to do */ X if (len >= stbuf.st_size) X return(0); X X if (!(fp = 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 tempfile = mktemp("trunXXXXXX"); 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 6652 -ne "`wc -c < 'xmodem.c'`" then echo shar: "error transmitting 'xmodem.c'" '(should have been 6652 characters)' fi fi exit 0 # End of shell archive