DarkNET-1.08/                                                                                          755   21270   21270            0  6053360571   5771                                                                                                                                                                                                                                                                                                                                                                      DarkNET-1.08/ChangeLog                                                                                 644   21270   21270        15166  5647532321   7663                                                                                                                                                                                                                                                                                                                                                                      ----------------------------------------------------------------------------

Version 3.BETA-1
22-MAY-1994

** Initial public release

-----------------------------------------------------------------------------

Version 3.BETA-2
5-JUN-1994

** NEW PORTS:
** SunOS 4.x (SUNOS) and SunOS 5.x (SOLARIS)

** NEW FEATURES:
** Added lastlogin and fromhost field to LOGININFO struct, fixed bbs_login
   to fill them in, client displays lastlogin at bottom of welcome.
** Fixed builtin pager (more) to handle tabs and to support backward
   scrolling with the 'b' key.
** Added file implementation of the user table.
** Added and fixed up the Configurable Menus. Left old code in for now 
   as a safety measure for now. Added menu description file, menu.desc,
   into the config file directory. Also, changed for format of the access
   file somewhat.
** Added CTRL-C as an exit key from Chat.
** Added key to symbols to Monitor display.
** Added CTRL-U hotkey to Talk to get online user list.
** Fixed main read menu so 'E' key works for Edit Post

** BUG FIXES:
** Some fixes to Makefile.
** Fixed bug to cure garbage in USEREC fromhost field.
** Fixed NULL-pointer bug in MailRead.
** Fixed typecast bug in DoTalk.
** Added missing lines to config/access.
** Fixed bug causing bbs_check_mail to return true after unread mail
   has been deleted.
** Fixed chatd to disallow the empty string as a room name.
** Minor fixes to /query in Chat.
** Now highlighting the pointer in chat.
** Fix so chat can be used after a system crash.
** Fixed log function to seek to EOF before writing.
** Fix to chat_process_incoming to end crashing with /w.

-----------------------------------------------------------------------------

Version 3.BETA-3
20-JUN-1994

** NEW PORTS:
** IBM AIX 3.2.x (AIX), DEC OSF/1 (OSF), NeXTStep 3.2 (NEXTSTEP)

** NEW FEATURES:
** Added fromhost to possible environment in add-on programs, denoted by %H.
** New bbslog utility for add-on scripts to use for writing to the bbs log.
** New mkftplist.pl script for auto-generation of etc/ftplist.
** Added mail/post signatures.
** Increased length of Chat input line quite a bit (experimental)
** Added escape keys (CTRL-C/CTRL-D) to getdata function to allow selected
   prompts to be cancelled (login, chat entry, change username, etc).
** Moved chat help text out of program into config files.
** Added a "follow thread" option to Sequential Read.
** Added M_PAGE mode to show users who are Paging
** Added chat daemon configuration file, etc/chatconfig. 
   Chat ops and restricted accounts may be listed here; they are granted
   denied certain privileges in chat.
   The name of the main chat room (default 'main') by also be set here.
** Changed /op command in chat to relinquish Op status of the sender.
** Added a welcome message to chat telling how many users/rooms are present.

** BUG FIXES:
** Fix to set mode to "Mail" when reading/sending mail.
** Fix for pager to not insert a blank line after 80-character lines.
** Fixed Talk/Chat to be aware of cloak and adjust it accordingly.
** Fixed setpgrp call in chatserv to take parameters if needed.
** Fixed bug in menu access determination.

---------------

Version 3.BETA-4
5-JUL-1994

** NEW PORTS:
** Apple A/UX (AUX)

** NEW FEATURES:
** Added ability to see real names in Query, limited by showreal entry 
   in bbconfig and C_SEEREALNAME in access.
** Added somewhat more configurable default menu actions.
** Moved some of the hardcoded privileged functions (see cloak, etc.)
   into the access file for flexibility.
** Added C_PUBLICACCT access code to identify public (shared) accounts.
   For public accounts, the read bits are never set, and the menus in the
   local client always default to Help.
** Added parameter to bbs_login to allow non-public accounts to kick 
   stranded logins if their logon limit is exceeded.
** Added a idle timeout to the local client. The length of idle time
   before disconnection is configurable in the bbconfig file.
** Added File Forward function so files may be forwarded from the 
   File Menu. Binary files are first uuencoded.

** BUG FIXES:
** Fixed bug making post #(BBS_MAX_FILES) inaccessible.
** Added a new field to the read menu items so those functions could be
   granted/denied en masse instead of just through Read/Post/Manage flags.
** Added missing newline in bbs log entry for Kick.
** Fixed bug in Monitor causing Cloak field (#) to not update.

----------------

Version 3.BETA-5
19-AUG-1994

** NEW FEATURES:
** "Post now?" prompt added to Read New at the end of each board.
** Status messages displayed during Read New to inform reader of progress
   through each nonzapped board.
** bbfinger utility added for remote user listing through an unused port.
** Ability to prevent boards from being zapped has been added.
** Install script and make install target added to distribution.

** BUG FIXES:
** Fixed some bugs with 80-character lines in chat.
** Fixed bug causing marks on posts to not show up.
** Upped idle timeout during login to 5 minutes if user is creating a 
   new account.
** Replaced calls to access(2) since they work on real uid and we are
   probably running setuid.
** Added display of current pager setting to the Set Pager function.
** Now passing fatal signals on to client-side child processes to
   clean them up.
** Now clearing out the global user list used by Monitor so the "holes"
   caused by users logging out are filled upon Monitor re-entry.

----------------

Version 3.0
20-SEP-1994

** NEW FEATURES:
** EBBS-3.0-Guide added to distribution.
** New chat commands: /whois, /whoin, /long.
** Chat command /u changed back to short format.
** Notification of new mail added to chat.
** New FLG_SHARED account flag replaces the C_SHAREDACCT access code.
** Environment field added to records in etc/editors.

** BUG FIXES:
** Fix to back off to file-based user table if shmat(2) fails.
** Fixes to prevent premature chatd death: ignore SIGPIPE and set sockets
** to nonblocking.
** New checks to ensure only one chat daemon runs at a time.
** Small fixes to /i, /m and /n chat commands.
** Rearrangement of available options after reading posts.
** Fixed delete range to reset the message pointers correctly.
** Changed -e tests in Install.sh to the more portable -f.
** Display of plan no longer interprets %-escapes a la printf.
** Temporary file now gets deleted when you abort a post.
** Fix to addacct utility to correctly add 12-letter userids.
** Fix to delacct utility to make -c (user clean) flag work.
** Now preventing mail from being delivered to accounts which cannot
   read mail and preventing paging users who can't answer.
** Fixed menu.l and gram.y to work with lex and yacc.
** Fixed formatting of "To:" header in group mail.                                                                                                                                                                                                                                                                                                                                                                                                          DarkNET-1.08/EBBS-Guide                                                                                644   21270   21270       160225  5647532322   7620                                                                                                                                                                                                                                                                                                                                                                      
Eagles BBS 3.0 Administrator's Guide
by Ray Rocker (rock@seabass.st.usm.edu)

This guide is designed to help the EBBS administrator install and 
configure the bbs system. Some basic system administration knowledge
is assumed. It is not intended as a general user's guide.

TABLE OF CONTENTS 
I.    Installation
   1.  Choosing a Home Directory
   2.  Setting the Owner and Group
   3.  Building the Source
   4.  Installing the Software
II.   General Configuration
III.  How Permissions Work
   1.  Account Permissions and the permstrs file
   2.  Operations and the access File
IV.   Configuring the Menus
   1.  Menus
   2.  Menu Commands
   3.  Examples
   4.  Security Considerations
V.    Account Management
   1.  Overview of the Account System
   2.  Adding Accounts
   3.  Deleting Accounts
   4.  Modifying Account Attributes
   5.  Limiting Logons
VI.   Board Management
   1.  Overview of the Board System
   2.  Adding Boards
   3.  Deleting Boards
   4.  Modifying Board Attributes
   5.  Implementation Details
VII.  BBS Mail
   1.  Local Mail Storage
   2.  Internet Mail Support
VIII. Setting up the File Area
   1.  Setting Up Download and Upload Directories
   2.  Setting Up Protocols
   3.  File Transfer via Internet
IX.   Chat System Configuration
   1.  Chat Overview
   2.  Technical Information
X.    Miscellaneous
   1.  Issue and Welcome Files
   2.  Copyright Notice and License
   3.  Configuring Alternate Editors
   4.  Logging
   5.  Mail, Post, and File Forwarding
XI.   External Utilities
   1.  addacct
   2.  delacct
   3.  bbslog
   4.  mkftplist.pl
   5.  bbfinger
Appendix A. How To Set Up a Guest Account


I. Installation

1. Choosing a Home Directory

The first thing you need is a home directory for your bbs. The bbs program
and utilities make no assumptions about where the bbs home directory is.
This allows you maximum flexibility in placing the bbs into a suitable
location in your file system. It also requires that the bbs program and
utilities be able to find the bbs home directory, which I will address later.

You should be sure to pick a place with plenty of room to grow. The bbs
executables and configuration files total about 500K initially. As you add
users and boards, the disk usage will naturally go up. Accounts and boards
per se take very little space; posts and mail will occupy the majority of
the space under the bbs home directory. You should also make sure you have
plenty of inodes available in your filesystem. Each account will consume
up to 8 inodes plus one for each mail message. Each board will consume up
to 2 inodes plus one for each post. The total inode usage can get large in
a hurry, so placing the bbs in a separate filesystem from other high inode
usage software (such as a Usenet news spool) would be a good idea.

The bbs home directory will be referred to as /home/bbs (where the full path
is called for) or ~bbs (where shorthand is ok) in the rest of this document. 
Remember to mentally substitute in your selected home directory!


2. Setting the Owner and Group

Next, you need to decide on an owner and group for the bbs. The bbs runs as 
a single user on your system -- individual accounts do not have their own 
uids in /etc/passwd. ~bbs and everything beneath it must be owned by the 
same uid and gid.

The simplest solution is to create a 'bbs' account in /etc/passwd. If you
will be allowing remote access to your bbs (via telnet or rlogin) you will
need this passwd entry anyway. It should look like this:

bbs::9999:99:Bulletin Board System:/home/bbs:/home/bbs/bin/lbbs

Remember to substitute your bbs home directory for "/home/bbs" in the above.

The uid (9999) can be any unused value. The gid (99) can be an existing
gid defined in /etc/group, or a good idea would be to create a bbs group:

bbs::99:bbs

While we're editing /etc/passwd, I've found that a bbsadm account, with
the same uid/gid as bbs but a real login shell, is very handy.

bbsadm::9999:99:BBS Administrator:/home/bbs:/bin/sh

Be sure to put a secure password on this account though! Now, if you do
the rest of the installation as bbsadm, you won't have to worry about
file ownerships being wrong.

Now you can create /home/bbs (or whatever), chown it to bbs (or whoever),
chgrp it to bbs (or whichever), and chmod it to 770. Directory permissions
of 770 will allow full access to the bbs owner and group and no access to
anyone else. You might use 700 if only bbs and bbsadm are to be allowed into
the bbs area.


3. Building the Source

If you are using the binary distribution of EBBS 3.0, this section does
not apply. Skip ahead to "Installing the Software".

Unpack the source distribution if you haven't already.

First, edit osdeps.h to set the ifdefs correctly for your operating system.
It is already set up for LINUX, SUNOS, SOLARIS, AIX, OSF/1, NEXTSTEP, and AUX.
Any other operating systems may require more files to be edited.

Second, edit the Makefile, filling in the top part as necessary. If you 
chose not to create a bbs account in /etc/passwd, you must set INSTALLDIR
to point to the bbs home directory. There are a couple of #defines not 
covered in osdeps.h you can put in the CCFLAGS line to enable/disable
unimportant things, but I'll not go over them here (grep for them if
you're really curious).

The y.tab.h, y.tab.c, and lex.yy.c files were generated by flex 2.4.6 and
GNU Bison 1.22 for Linux. They are included so that you don't need flex 
and bison to build EBBS, but may not work on all non-Linux systems. If you
have a scanner (flex, lex, etc.) and parser generator (bison, yacc, etc.)
installed on your system, you may delete y.tab.h, y.tab.c, and lex.yy.c
and use the Makefile to build them. Set YACC, LEX, and YFLAGS appropriately
in the Makefile.

"make" with the supplied Makefile just builds the lbbs and chatd programs.

"make install" will create all the directories you need and copy the
executable and configuration files under ~bbs. NOTE: You should do the
install from the bbsadm account to get all the ownerships and permissions
right! If not you should do a "chown -R bbs ~bbs" to set them straight.
"make install" may also be used to copy new executables to the bbs if
you do any source modifications. It will not overwrite existing config files.

Alternatively, you can do a "make bindist" and then follow the directions
for installing the binary distribution in the following section of this Guide.
If your /bin/sh doesn't like the install script, this may come in very handy.

Other useful Makefile targets:
"make clean" deletes all of the object files.
"make clear" deletes all of the executables.
"make clobber" does both a clean and clear.
"make srcdist" makes the source distribution just like this one.


4. Installing the Software

If you successfully did a "make install" with the source distribution,
you're done! Skip to Chapter II (General Configuration).

If you have a binary distribution (either to start with, or the result of 
"make bindist" in the above section) just copy the tar archive into ~bbs 
and unbundle it with "tar -xvf". If you do this as someone other than the 
bbs owner, you must set the owner and group of all extracted files to the 
bbs owner and group, and restore the setuid/setgid bits on ~bbs/bin/lbbs.

And that's that. You're ready to configure and run.


II. General Configuration

Every file used and created by the bbs will be under ~bbs. Initially,
you have a bin subdirectory containing the local bbs shell (lbbs), the
chat daemon (chatd), and some other utilities; an etc subdirectory 
containing all the bbs configuration files; a home subdirectory under
which information and mail for each bbs account will go (the SYSOP account
is already there); a boards subdirectory under which information and 
posts for each board will go; and a tmp directory where work files will
be temporarily placed.

The rest of this Guide is primarily concerned with the bbs configuration
files under ~bbs/etc. Most of these files are record-oriented, and in
these any line beginning with # is a comment. You must edit all of these
by hand EXCEPT ~bbs/etc/passwds and ~bbs/etc/boardlist, which lbbs 
manipulates via commands in the (A)dmin menu. You should use caution 
when editing these two files by hand, especially ~bbs/etc/passwds, because
the records in it must all be exactly the same length.

The first one we'll look at is ~bbs/etc/bbconfig. This is the startup
configuration and MUST be present for lbbs or any of the utilities to run.
Recall that I pointed out in Chapter I of this Guide that these programs
do not automatically know where the bbs home directory is (and thus where
bbconfig is). So, to run any of these from the command line you must either
be currently in ~bbs, OR have the environment variable BBSHOME pointing to
/home/bbs (or whatever). So, take this time to define BBSHOME in your
.profile or .login -- or better yet in /etc/profile or /etc/csh.login.

That out of the way, look at bbconfig. Read the comments carefully.
You set things like the name of your bbs, how many users may log in 
at one time, the location of the bbs log file and how much stuff gets
logged, and whether new users may create their own accounts.
Change the default values to your liking.

Now is probably a good time to log in and set the SYSOP password. 
Execute ~bbs/bin/lbbs (you did set BBSHOME, right?). Type SYSOP at the
"Enter userid" prompt, and 'password' (without the quotes) as the password.
If all is well, you're in and can start navigating the menus. You should
change that SYSOP password first thing -- enter X to go to the Xyz Menu
and then P to change the password.

If anything went wrong, you should reread Chapters I and II of this Guide 
to make sure you didn't miss anything. If something REALLY went wrong
(like a fatal signal telling you to Run! Flee!) you may need to fix the 
source and rebuild lbbs. The rest of this Guide is a reference for configuring
the menus and everything else. 


III. How Permissions Work

1. Account Permissions and the permstrs File

The bbs uses a very flexible scheme for allowing and disallowing access
to each menu function. With flexibility comes complexity, however, and 
that is compounded by the fact that (with luck) someday in the future 
this bbs will be distributed, with a client composed of the user interface
and menus on a remote host and a much smaller server portion to run on
the bbs host. 

Each bbs account has a 32-bit permission mask -- the third field in each
~bbs/etc/passwds record. It is stored as an 8-digit hexadecimal number.
Each bit in that field corresponds to a permission name in ~bbs/etc/permstrs.
Ten of the thirty-two permstrs are already defined. The first five of these,
Basic-1, Basic-2, Basic-3, Basic-4, and Sysop, corresponding to the 5 least 
significant bits in the 32-bit mask, are used by the system. You can change
the names on these but NOT the function. Five others are used not by the
system but only in the default access and menu.desc files.

Basic-1 through Basic-4 are automatically granted to every account upon
creation. So, when a new account is created, the third field in the passwds
file will be 0000000f. The ready-made SYSOP account has all 10 predefined
permissions, so its third field is 000003ff. 

The strings in the permstrs file are what you see when setting the permissions
on an account or board via the (P)ermissions, (N)ewBoard, or (C)hangeBoard
functions on the Admin Menu. Any strings you add to ~bbs/etc/permstrs will
replace the "(unused)" entries. 

The position of the bits in the 32-bit mask are what is important -- the
strings are just to make the Admin Menu functions friendlier. This is why
you must ONLY add or change lines in the permstrs file, never delete them.
For instance, if you delete the Basic-4 line, then the string "Sysop"
becomes associated with the 4th bit in the permission setting screen. 
But the 5th bit is the one that the system uses to determine if a user
has full sysop permission!


2. Operations and the access File

I hope you're not lost yet, because there's more. The ~bbs/etc/access file
lists 85 operations that the bbs can perform. Entries in this file are in
the following format:

<operation-name>={ALL | NONE | <permstr-name>[,<permstr-name>,...]}

For now, just remember this: do NOT edit the <operation-name> or reorder
the first 85 of these. In a nutshell, these serve to limit access to each
operation to those accounts with the bits corresponding to the permstr-names
turned on, or to nobody (NONE), or to everybody (ALL). For example:

Login=ALL
Everyone can do the login operation.

AddAccount=AccountMgr 
Only accounts with the AccountMgr bit (as shown in (A)dmin/(P)ermissions)
can do the AddAccount operation. 

GetPermStrings=AccountMgr,BoardMgr
Accounts with either the AccountMgr or BoardMgr bit can do the 
GetPermStrings operation.

Upload=NONE
No one can do the Upload operation (until you change the NONE).

Most of these really don't mean anything at present -- they are set up 
for the planned future client/server split -- EXCEPT to the menu system.
The operation-names are referenced in the ~bbs/etc/menu.desc file, and
in conjunction with that you probably want to modify some of the records
in ~bbs/etc/access. That is the subject of the next chapter.


IV. Configuring the Menus

1. Menus

The bbs menus are completely configurable via the ~bbs/etc/menu.desc file.
There are comments in that file explaining the syntax. Here, I will try to
explain briefly what it all means as well:

A menu is defined as follows:
menu <menu-name>, <menu-title>, <menu-prompt>, <default-action> {
<command-entry>,
...
}

The <menu-name> string is used in the command-entries for jumping between
menus (more on this below).

The <menu-title> is displayed in the upper left corner of the screen when
the menu is active. A "*" here means to display the name of the bbs, as
given in ~bbs/etc/bbconfig.

The <menu-prompt> string is the prompt displayed when asking the user
for a command.

The <default-action> string specifies the first letter of the default
command when the menu is first entered. If this string begins with $, 
then it should have two letters following: the first is the default 
command if no new mail is waiting, and the second is the default command
if new mail is waiting.


2. Menu Commands

Each menu is made of one of more command entries in the following form:

(<command-name>, <next-command>, <error-command>, <operation-name>,
 <action>, <help-string>)

The <command-name> string is the command to be typed by the user. Only
the first letter of a command name need be typed. For this reason each
<command-name> in a menu must begin with a unique letter.

The <next-command> string is the default next command after completion 
of this command. If an error occurs during the command, then the
<error-command> is the default next command.

The <operation-name> is where the ~bbs/etc/access file comes into play.
For this menu command to be available to the user, their account must 
have permission to perform the operation, as defined in ~bbs/etc/access.
Here is where all the business with 32-bit permission values, permstrs,
and operations comes together. Pay close attention to this example:

("Welcome", "Exit",     "Exit",    EditWelcome, $EditWelcome,
"(W)elcome       Edit the Welcome Screen")

This is the menu command on the Xyz Menu through which the Welcome screen
may be edited. The operation associated with this menu command is
EditWelcome. EditWelcome MUST be listed in ~bbs/etc/access, or you'll 
see a "does not grok" error when the bbs starts up. It's there though:

EditWelcome=WelcomeMgr

This means that a user must have the WelcomeMgr permission (bit 10 in
the mask since it's the 10th string in ~bbs/etc/permstrs) in order to
do the EditWelcome operation, and hence to access the (X)yz/(W)elcome
menu command. I'll give more examples of how to use this later.
^L

The <action> string is the action to be taken by the menu command.
These all begin with $ and refer to functions built into lbbs.
Two special cases take parameters:

$Menu takes the name of another menu defined in menu.desc and jumps to 
that menu. For example: $Menu "Xyz" means this command should jump to 
the Xyz menu.

$exec, $exec.pause, $exec.more are available for you to hook in any
external programs into the bbs menu system. $exec executes an arbitrary
program. $exec.pause does the same and prompts the user to press RETURN
before returning to the menu prompt. $exec.more pipes the program's 
output through the builtin 'more'-like pager.

The format for the $exec actions is $exec "program[:environment]"
For example:

$exec "/bin/sh"
Executes /bin/sh, then returns to the bbs menu prompt.

$exec "/bin/sh:TERM=ansi"
Same as above but adds TERM=ansi to the environment passed to /bin/sh.

The $exec actions provide a default environment, which is defined at the
top of the menu.desc file in the "Environment" entry. You may edit this 
line as you like. Any environment specified in the $exec action is added 
to, and possibly overrides, this default environment. 

Information associated with the bbs user may be passed in the environment.
%T, %I, %E, %U, and %H are escape sequences which are replaced by the
bbs user's termtype, userid, editor, username, and remote host, respectively,
in the constructed environment. Example:

$exec "/usr/local/bin/irc:IRCNICK=%U,USER=%I,TERM=%T"

Finally, the <help-string> in a menu command is the string displayed for
the command by the builtin $Help command.


3. Examples

Now for some practical examples of how all of this mumbo-jumbo works.

Example #1. How to restrict a guest account from posting.
You'll notice an entry in the Main menu to posting messages:

("Post",    "Read",    "Read",     Post,      $Post,
"(P)ost          Post a message on current board")

The operation associated with this menu command is, suprisingly enough, 
Post. Looking in ~bbs/etc/access you'll find the 47th operation:

Post=ALL

You want users to be able to post by default, just not the guest account.
So, you want to restrict the Post operation to one of the four Basic
permissions, which all accounts get by default. Let's change it to:

Post=Basic-1

There. Now all you have to do is go to (A)dmin/(P)ermissions, bring up
the screen for 'guest', and change Basic-1 from ON to OFF. Voila.
'guest' cannot use (P)ost on the main menu. In addition, since the builtin
reply functions also test the Post operation, guests won't get the option
to post followups when reading either.

Example #2. How to hook an IRC client into the Talk Menu.
In menu.desc you first must add a command into menu "Talk". Fortunately
there is no command in that menu beginning with I already, so this will
work:

("IRC",    "IRC",    "Exit",     EnterIRC,     
$exec "/usr/local/bin/irc:IRCNICK=%U,USER=%I,TERM=%T"
"(I)RC          Enter IRC Chat")

Now, where did I get the EnterIRC operation? It's not in the access file!
Well, you can add it. Just put it at the END of ~bbs/etc/access after the
85 predefined operations. You can have as many of your own operations as
you want there. What about the right-hand side? It can be ALL if you want
everyone to be able to use IRC. Or, use one of the predefined permissions
like Basic-1. Or, add a permission string to ~bbs/etc/permstrs and turn
on that bit for those users you want to be able to use IRC.

Hopefully the flexibility of this complex permission system is apparent
by now, and you'll forgive me for making it so hard to understand :-)


4. Security Considerations

An important note about security. Remember that all files under ~bbs are
owned by the bbs owner, and bbs users are running as the bbs owner. Hence
you should take EXTREME CARE that any external program you hook in via
$exec does not have the ability to read and write arbitrary files on your
system, or even worse spawn a shell! (PLEASE, do NOT make root the bbs
owner under any circumstances!)

In the IRC client example above, you should know that IRC clients have
CD and EXEC commands, which are probably not things you want users of 
your bbs to be able to do. You should compile them, and anything else 
that looks suspicious, out of the IRC client you make available. This
holds true not only for IRC but any external program you choose to make 
available, of course.


V. Account Management

1. Account System Overview

Basic information about each bbs account is recorded in the ~bbs/etc/passwds
file. This consists of the userid, encrypted password, permission mask,
account flags, and username.

SYSOP       :AA6tQYSfGxd/A :000003ff:0000:System Operator          :

IMPORTANT: Each record must be the same length, or this file may be 
corrupted when the bbs writes out a modified record (when any of the 
fields are changed through Xyz or Admin menu commands). Therefore manual 
editing must be done with great care, and you should make a backup
copy of this file before doing any manual editing. Keep this in mind
even as I tell you a few paragraphs from now that you *have* to edit 
it by hand to set certain account flags.

Also, each account has two directories associated with it: ~bbs/home/<userid> 
and ~bbs/home/<userid>/mail. Naturally, the user's mail is stored under 
the latter of these. Files stored in the former include:

lastlogin: The user's remote host name is written here at login time.
overrides: User-configured list used to control Talk requests.
plan: User-created plan file, shown by the $Query action.
profile: Extra configuration information not stored in the passwds file.
   Real name, address, Internet email path, editor, terminal type, and
   upload/download protocol may be here. Certain default values (such as 
   vt100 for the terminal type) are not stored.
readbits: Used for saving information about which posts and mail have 
   been read. It consists of one record for each board which has been
   accessed, and one for mail (" $MAIL "). This is also where the new 
   message scan configuration (currently just the $Zap action) is stored.
signature: User-created signature file for posts and mail.


2. Adding Accounts

Accounts may be added by the $AddAccount action (Admin Menu/Add User).
You will be prompted to enter all the pertinent information. This will
create a record in the passwds file and create the user's directories
and profile. You may also use the addacct utility program for adding
accounts from the shell (see Chapter XI of this guide for details).

NOTE: Just adding lines to the passwds file is NOT sufficient!
You must add the directories too. Adding accounts in this way is not
recommended.

You can allow users to create accounts on demand by setting "new=yes" in
~bbs/etc/bbconfig. The users can then enter "new" at the bbs login prompt
and enter their userid, password, username, termtype, and email path.
Real name and address are not prompted for here like they are in the
Admin Menu (verifying them would be quite difficult anyway).


3. Deleting Accounts

Accounts may be deleted with the $DeleteAccount action (Admin Menu/
Delete User). If you built lbbs with FULL_USER_DELETE, this can be very
slow because the bbs will delete ALL references to the account in every 
other user's override files and all the board manager files. You can also
use the delacct utility to delete accounts from the shell, perhaps as a 
background job. 

The delacct utility also has a useful "user clean" feature, which allows
accounts to be cleaned en masse based on the elapsed time since the last
login. The exempt flag (see next paragraph) is used to mark accounts for
exemption from user clean. See Chapter XI for instruction on use of the
delacct utility.


4. Modifiying Account Attributes

Account information may be modified with the $SetUserData, $SetUserPerms,
and $ToggleExempt actions (Info, Permissions, and Xempt on the Admin Menu).
The Info command lets you change a user's userid, password, username,
terminal type, real name, address, or email path. If the userid is changed
and you built lbbs with FULL_USER_DELETE defined, there will be a delay 
while the bbs goes through all override and board manager files to attempt 
to change the userid. Otherwise it's fast, but up to you to fix the board
manager files. The Permissions command allows the 32 permission bits to be 
set. The strings from the permstrs file are displayed here to make things 
clear. The Xempt command toggles a flag in the account's flags field. This 
flag is used by the delacct utility in its user clean mode -- any accounts 
with this flag set will be spared deletion even if they are otherwise aged 
beyond the cutoff point.

Account flags other than the exempt flag cannot be set except some by
the user themself. The cloak flag and two talk request control flags may
be set by the user -- or by the sysop by careful editing of the passwds
record. Two other flags can only be toggled by editing the passwds record.
Recall the above warning about careful editing of this file!

The flags are positioned as follows, in the 4th field of the passwds record.
This is a 16-bit hexadecimal number, and you'll have to do a little 
hex-to-binary conversion to set the individual flags:

0000 hex   --->   0000 0000 0000 0000 binary
                  UUUU UUUU UUOP SDXC are the flags

U denotes unused.
O is the override flag: if set, users on the override list cannot Page.
P is the pager flag: if set, users NOT on the override list cannot Page.
S is the shared flag: if set, the account is considered "shared" and 
  cannot receive mail, the readbits are not set, and the default menu
  action is always "H" regardless of the menu.desc settings. This is
  something you'll want to set for a guest-type account.
D is the disabled flag: if set, the user cannot log in.
X is the xempt flag described above.
C is the cloak flag: is set, the user's presence is hidden from all users
  except those with permission to SeeCloaked in ~bbs/etc/access.

So, for example, if the flags on an account are 0000 and you want to turn
on the shared (S) flag, you would change the flags field in their passwds
record to 0008, which is hex for 0000 0000 0000 1000 binary.


5. Limiting Logons

The number of simultaneous logins an account may have is governed by
the "logons" entry in the bbconfig file. By default this is set to 0,
which means no limit. Changing it to 1 limits each user to one login
at a time. This value can be greater than 1 as well. If a login attempt
is made to an account that has reached its limit and the account does not
have the shared flag, the user is given the option to kill a previous
login to make room for a new one. This is useful when connections get
broken abnormally and do not terminate properly. 

The ~bbs/etc/logons file may be used to let certain accounts override
the system logon limit. For example, "guest=5" in the logons file allows
for 5 simultaneous logons to the guest account regardless of the limit
imposed in bbconfig.


VI. Board Management

1. Overview of the Board System

Information about each board (public forum) is recorded in the 
~bbs/etc/boardlist file. This consists of the board name, 32-bit permission
mask for read access, 32-bit permission mask for post access, and board
description. Permission masks are in hex like account permissions.

General:00000000:00000000:general board:

Each board has one directory associated with it: ~bbs/boards/<boardname>.
The board's posts are stored in this directory along with a couple of 
optional configuration files, which are:

managers: A list of userids who have manager access on the board, one
   userid per line. This list may be edited by the $SetBoardMgrs action
   (Managers on the Admin Menu).
nozap: If this file exists in the board directory, then the board may not
   be zapped via the $Zap action. This is so boards with important system
   information will always be seen in a new message scan. The nozap file's
   contents are not important; it may be zero length.


2. Adding Boards

Boards may be added by the $AddBoard action (Admin Menu/New Board).
You will be prompted to enter the board name and description, and whether
you would like to restrict access to the board. Read access and post
access are separate: if an account lacks read access to a board, the user
will not even be able to see or select it (hence, post access is irrelevant).
If you choose to restrict either one, you get a screen exactly like the 
account permission editing function. By turning any permission bit ON, 
you require a user to have that bit in order to read or post on the board. 
If more than one bit is set to ON, the user must have at least one of those 
permission bits to access the board. If all of the permissions are turned
OFF, access is granted to all accounts.

NOTE: As with adding accounts, just adding lines to the boardlist file is 
NOT sufficient to create a board. The board's directory must be created.
Adding boards in this way is not recommended.


3. Deleting Boards

Boards may be deleted with the $DeleteBoard action (Admin Menu/Board Delete). 
This can be a very slow action because the bbs erases the readbits entry
for that board from each user's readbits file, as well as deleting all of
the posts. There is no external utility (a la delacct) to remove boards from
outside the bbs at this time. 


4. Modifying Board Attributes

Board information may be modified with the $ChangeBoard and $SetBoardMgrs
actions (Change Board and Managers on the Admin Menu). The Change Board
menu command lets you change a board's name, description, and both
permission masks. If the board's name is changed, this will be very slow 
because the bbs will have to change the board name reference in each user's
readbits file. As mentioned above, the Managers menu command provides a
way to edit the board managers list within the bbs.

A user who is on the managers list for a board, or who has global board
manager capability as defined by the ManageAllBoards entry in ~bbs/etc/access
(by default, accounts with the BoardMgr permission bit), has certain extra
privileges within the board. These extra privileges are reflected by extra
options being given when a post is read, and extra commands being available
in the $MainRead menu (Main Menu/Read). The extra privileges are:

-- Ability to delete any post regardless of ownership.
-- Ability to mark posts. A marked post is spared by the Delete Range 
   function on the read-menu. Marks are not visible to non-managers, and
   are permanent until unmarked.
-- Ability to clean ranges of posts from the read-menu. Marks may be used
   to spare individual posts inside the range.

In addition, ability to edit posts may be granted to board managers by
lowering the access for ReplaceMessage in ~bbs/etc/access. By default
the permission required for this operation is Sysop.


5. Implementation Details

In the $ReadNew (Main Menu/New) action, which is used to scan all 
unzapped boards, the boards are presented in the order in which they
are listed in the boardlist file. If you would like to re-order this 
file, it can be done with an editor.

The filenames used for posts are 4-digit hexadecimal numbers. The numbers
are not significant -- in particular, post 0001 need not be older than
post 0002. When a board is accessed, the posts are ordered by the last
modification time of the file, which is stored by the operating system.
One ramification of this is that if you edit a post outside of the bbs,
it will start appearing later in the list of posts for the board, and
will seem out of order because the Date header still reflects the old
date and time. The builtin post editing facility compensates for this 
by "touching" the file back to its prior time of modification. 

There is no builtin facility for moving posts between boards at present;
you can do this from the shell by simply moving the file from one board
directory to another. The Posted-By header will still reflect the original
board it was posted on, however, unless you edit it. Be sure that you move
the file to a new filename not already in use -- for example don't move
~bbs/boards/board1/0001 to ~bbs/boards/board2/0001 without ensuring that
~bbs/boards/board2/0001 does not already exist. Moving a file does not 
change the modification time in most filesystems.

There is a limit of 2048 posts per board. This limit is not configurable
at the present time. When 2048 posts accumulate on a board, any attempts
to post will result in an error. You will probably want to keep fewer
posts than that around due to space requirements anyway.

There is no utility at this time to delete old posts automatically, a la
the "expire" program used by Usenet servers. Watch the bulletin boards and
ftp sites for this, I'm sure it'll get done someday soon because such a 
utility would come in very handy.


VII. BBS Mail

1. Local Mail Storage

Mail for each account is stored in ~bbs/home/<userid>/mail. The file
naming scheme is exactly the same as for posts -- 4 digit hex numbers.
Record of which mail is read and unread is kept in the user's readbits
file (~bbs/home/readbits) in the " $MAIL " record.

Mail is subject to the same nonconfigurable limit of 2048 messages per
directory as are boards. There is no Mail Clean function like earlier
versions of EBBS had. Another script/program that I plan to write soon
is something to run through each user's mail directory and tally up
their messages, for purposes of sending out reminders that mailboxes 
need to be kept clean. A script/program to do cleaning for uncooperative
users would be nice too.

Mail may not be Marked for immunity to Delete Range, because of the way
Group Mail is implemented. A mail message sent to multiple users is only
stored once on disk, and the other "copies" are hard links. This makes it
impossible to use chmod to mark individual copies, as can be done on boards.


2. Internet Mail Support

EBBS allows mail (and posts and files) to be manually forwarded to the
user's Internet email address. See Chapter X (Mail, Post, and File
Forwarding) for more details.

Incoming Internet mail is not supported. This is mainly due to the 
single-ownership of all bbs files -- that each account does not have its
own uid makes things difficult. With sendmail, however, anything is 
possible, and it's on my TODO list to get 2-way Internet mail working
with this software. The logistical details are far from trivial though
and it may be a while, if ever.


VIII. Setting up the File Area

1. Setting Up Download and Upload Directories

You may allow access to selected directories anywhere on your system by
adding to the ~bbs/etc/ftplist file. For each directory containing files 
you wish bbs users to be able to view and download, place an entry in the 
ftplist file in the following format:

<file-board-name>:<directory-path>:<description>

The <file-board-name> is a 2-12 character board name consisting of letters,
digits, dashes, and underscores -- the same restrictions as on account and
board (forum) names. 

The <directory-name> is the full path to the directory.

The <description> is an optional string describing the contents of the
directory. It is displayed by the $FileBoards (File Menu/List) action.

At this time, file boards do not feature the access control available 
in the forums. All users with access to the $FileDownload action
(File Menu/Download) can view and download from the file boards.
See Chapter X for notes regarding file forwarding via e-mail.

The special file-board-name UPLOAD may be used to specify a directory
for uploading instead of downloading. The same directory may be given
another file-board-name if download access is desired as well. Any user
with permission to use the $Upload function -- by default the Upload 
access is set to NONE -- may upload files to the UPLOAD directory.
Files may not be uploaded to directories other than the UPLOAD directory.

If you have a large or frequently-changing file area on your system,
configuring ~bbs/etc/ftplist by hand may prove tedious. The mkftplist.pl
Perl script is provided in ~bbs/bin to aid in this task. It recurses
through a directory tree and inserts entries into the ftplist file for
each directory, using the first 12 characters of the directory's basename
as the file-board-name. mkftplist.pl will not disturb existing entries, 
and will resolve conflicts between identical basenames by adding characters
to the file-board-names. See Chapter XI of this Guide for more information
on the mkftplist.pl script.


2. Setting Up Protocols

Text files may be viewed in the same manner as posts and mail through the
$FileDownload action. For transferring files to and from the user's 
machine, serial-line protocols such as kermit and zmodem may be used.
To do this, the user must select a protocol from the list in ~bbs/etc/protos. 
This file is already configured for Kermit, Xmodem, Ymodem, Zmodem, and ASCII, 
but you should make sure the given paths are correct for your system.

Records in the protos file are formatted like this:
<proto-name>:<download-command>:<upload-command>

For example:
Zmodem:/usr/bin/sz -be:/usr/bin/rz -bpe:

Then, if a user selects the Zmodem protocol and downloads the file foo.tar,
the bbs would change directory to the current file board directory and invoke 
"/usr/bin/sz -be foo.tar". To upload the file bar.c, the bbs would change
directory to the UPLOAD directory and execute "/usr/bin/rz -bpe bar.c".

If the <upload-command> begins with "|", then the destination file is
opened as standard output of the transfer program instead of being 
specified on the command line. The ASCII proto entry takes advantage of
this feature to use the "cat" utility for uploading.


3. File Transfer via Internet

If users will be accessing your bbs through telnet, they should be aware
that uploading and downloading of binary files will usually not work
because the escape characters used by telnet may be present in a binary
file and hence trigger telnet escapes. In general, use of serial-line 
protocols such as Zmodem across the Internet is iffy at best. You probably 
will want to set up anonymous ftp access to your file area if you expect 
to serve files to Internet users.


IX. Chat System Configuration

1. Chat Overview

The bbs chat system is for interactive chat between users of the bbs.
At this time no facility for linking chat daemons between bbses is
available. Separate rooms may be created on demand within the chat system
a la Internet Relay Chat, as well as several other special commands
that integrate the chat system with the rest of the bbs, such as commands
for getting user lists and querying users.

The files ~bbs/etc/chathlp.txt and ~bbs/etc/chatxhlp.txt are displayed
by the /help and /xhelp commands, respectively. These may be edited to
alter the output of the /help and /xhelp commands if you wish.

A separate config file is used by the chat daemon: ~bbs/etc/chatconfig.
At this time, most aspects of the chat system, such as the special chat
commands, are only configurable by modifying the source. The configuration
available through chatconfig is as follows:

mainroom=<main-room-name>
The main chat room, where all users start out when entering Chat, is named
"main" by default. You can change the name of this room by specifying it
in the mainroom entry.

operators=<userid>[,<userid>,...]
Chat operator privileges are given by the chat daemon to any userids 
specified on this line. These users can see and enter Locked and Secret
rooms and use /kick in all rooms including the main room. This definition
of "operator" is different from the room operator privilege given to a
user who creates a new room with /join. Room operators can set the Locked
and Secret flags, use /kick, give keys (to open Locks), and transfer the
operator privilege to other users in their room ONLY.

restricted=<userid>[,<userid>,...]
A special "restricted" mode is available for use by guest-type accounts
if you see fit. Any accounts listed on this line cannot join other rooms
or obtain information about the other rooms or the users in them.

At this time it is not possible to restrict accounts to read-only in 
chat. The TalkInChat and ExitChat operations are usable by anyone who
can use the Chat operation, regardless of how they are restricted in the
~bbs/etc/access file.


2. Technical Information

The chat daemon process (~bbs/bin/chatd) starts up when the first user
enters Chat, and dies when the last user exits. Its function is to
relay lines input by one chat user to the appropriate other users.
It also handles some of the special chat commands. Upon startup, it writes
its process-id to the file ~bbs/etc/.chatpid and its TCP port number
to the file ~bbs/etc/.chatport. Both numbers are written as 4-digit hex
values. These serve to synchronize the multiple lbbs processes connecting
to the chat daemon. If problems arise for some reason, a good start at
correcting then would be to remove the .chatpid and .chatport files and
then kill any running bbs.chatd processes.

The chat daemon uses a special handshake with the bbs program, wherein
the daemon uses the user table (in shared memory or a temporary file)
to verify that the connecting process is in fact a user logged into the
bbs. For this reason, connections to the chat port by non-bbs processes 
will not see any output, and will be closed as soon as they try to send 
input to the daemon.


X. Miscellaneous 

1. Issue and Welcome Files

The ~bbs/etc/issue file is a plain text file which is displayed by the
lbbs program prior to the bbs login prompt. It can be used, for example,
to show first-time users how to log in.

The ~bbs/etc/welcome file is a plain text file which is shown immediately
after a successful login and before the main menu prompt. It will be paged
if it contains more than one screenful. Many sites like this to be exactly
one page long and put some sort of ASCII picture there which serves to
personify the bbs. This file may be edited from within the bbs via the
$EditWelcome action (Xyz Menu/Welcome). 


2. Copyright Notice and License

The ~bbs/etc/COPYING file is the Free Software Foundation's GNU General
Public License, Version 2. This is the license under which this software
is distributed. You should read this document to understand your rights
regarding use and distribution of this software. The $GnuInfo action
(Xyz Menu/Gnu) allows users to view this document.

The ~bbs/etc/info file is another plain text file that is used to inform
users about the copyright and warranty associated with the bbs software.
Per the GNU General Public License, you must make this information
available to your users. You may add information pertaining to your
bbs or its administration below the copyright information. The $BoardInfo 
(Main Menu/Info) action displays this file.


3. Configuring Alternate Editors

The ~bbs/etc/editors file allows you to configure editors besides the 
builtin editor for use by your bbs users. No such external editors are
supplied with this distribution, but can probably be found near this
package on your favorite ftp site. 

Before offering external editors for use in the bbs, be SURE to heed the
warnings outlined in the editors file. Most popular editors (vi and emacs
included) allow functions which would be detrimental to the security of
your bbs if bbs users were allowed to use them. These include shell 
escapes, and the ability to load/view/write arbitrary files. You must
be sure these features are disabled in any alternate editor you offer.

The format of records in the editors file is as follows:
<editor-name>:<full-path>:<environment>:<comment>

The editor name is one which users can choose with the $SelectEditor
action (Xyz Menu/FileEditor). It is saved permanently in the user's 
profile file. The <full-path> and optional <environment> field follow
the same format as in the $exec actions in ~bbs/etc/menu.desc (see 
Chapter IV of this Guide).

In addition to add entries to this file, you'll need to modify the
~bbs/etc/access to allow ALL (or restricted) access to the SetEditor,
GetEditor, and EnumEditors operations, as their access is NONE by default.

You should be sure to uncomment the entry for the builtin editor if
other editors are offered.


4. Logging

The lbbs program writes a record of certain events to a log file.
The log file may be anywhere on your system; just specify the full path
in the "logfile" entry in ~bbs/etc/bbconfig. The default log file is 
~bbs/log.

You may also control the volume of logging information with the "loglevel"
entry in ~bbs/etc/bbconfig. This value may be zero or any positive integer.
Higher values mean more events are recorded in the log -- for any given
log level, log events associated with a lower log level are also included.
The default log level is 1. Here is a brief summary of the events logged
at each level (and above):

Level 0: System errors are always logged.
Level 1: Logins, failed login attempts, logouts, and account creations.
Level 2: Administrative actions -- account deletions and modifications;
         board creations, deletions, and modifications; manager actions
         on boards; cloak; kick.
Level 3: Posts, uploads, downloads, forwards.
Level 4: Entries to Chat; Talk requests, accepts, and refusals.

The log entries are designed to be easily parsed by Perl or shell scripts,
so that statistics may be tallied and saved. Such scripts are currently
under development and may be made available in the future.

External scripts invoked from the bbs through the configurable menus may also
write to the log file by using the bbslog utility. See Chapter XI, section 3
for details.


5. Mail, Post and File Forwarding

Mail messages, posts, and files may be forwarded to the user's email address
(as stored in their profile file -- see Chapter V) from the Mail Read, Main
Read, and Download read-menus, respectively. Two operations in the access 
file govern permission to do this:

ForwardMessage, the 73rd operation, controls mail and post forwarding;
ForwardFile, the 74th operation, controls file forwarding.
Both are set to ALL by default.

For the forwarding to work, the "mailer" entry in the bbconfig file must
specify a suitable mailer on your system. "/usr/lib/sendmail" is the default.
The name of the file to be forwarded is given as the first and only 
parameter to the mailer program. You may include flags in the mailer line;
for instance "/usr/lib/sendmail -odq" is recommended if you have heavy
forwarding traffic, since this flag tells sendmail to just queue the mail
and run it in the background later.


XI. External Utilities

1. addacct

Syntax: addacct -i <userid> -p <password> [-u <username>] [-t <termtype>]
                [-e <email>] [-r <realname>] [-a <address>] [-d <bbs-dir>]

userid:   The logon name of the new account. Must be specified.
          This is an alphanumeric string between 2 and 12 characters.
          It must begin with a letter, end with a letter or number, 
	  and may have - or _ provided they are surrounded by alphanumerics.

password: The password of the new account. Must be specified. 
	  Must be at least 1 character, at most 8 are significant.

username: Up to 24 characters, free form. Defaults to userid if not specified.

termtype: The terminal type for this account. Defaults to vt100.

email:    Email address for this account. Optional.

realname: Real name of the account's owner. Optional. Not accessable
          through the bbs except to sysops and account managers unless
	  showreal=yes in bbconfig, and then can be controlled with 
	  ShowRealName in the access file.

address:  Address of the account's owner. Optional. Same access restrictions
	  as the realname field.

bbs-dir:  Specifies the bbs home directory. Only needed if BBSHOME is 
	  not set in the environment.

Addacct adds a new account to ~bbs/etc/passwds and creates a home directory
and mail directory for them. The profile information (termtype, email, 
realname, address) is placed in ~bbs/home/<userid>/profile if given.

Addacct writes an error message to stderr if it encounters an error.
No output is written to the terminal if successful. A line is written to 
the bbs log file if one is configured and the log level is 1 or greater.

Return values: 0 == success, 1 == error, 2 == usage error.


2. delacct

Syntax: delacct [-a age] [-c] [-d bbs-dir] [-n] [-t] userid ...

age:      Only meaningful with the -c flag. Specifies a time period in
	  days which, if an account has not been used in that many days,
          it is deleted. Default is 30 days. Any value below 7 days is
	  illegal to prevent accidental deletion of too many accounts.

-c:       Directs delacct to do a user clean. No userids may be given
	  if -c is specified. All accounts not used within the period
	  specified by the age parameter are deleted, except account
	  that have been Exempted by the bbs (A)dmin/(X)empt function.
          Sysop accounts are always spared by user clean.

bbs-dir:  Specifies the bbs home directory. Only needed if BBSHOME is 
	  not set in the environment.

-n:       Directs delacct to only delete accounts which have never been
          used. This is so you can apply a different grace period to
          never-used accounts. Not meaningful unless -c is given also.

-t:       Test mode: delacct tells which accounts would be deleted,
          but does not delete them. 

userid:   Specifies the userids to delete. These may only be given if the
          -c flag is not, and vice versa. By not specifying -c and giving
          userids instead, delacct will delete the specified accounts.
          Age checks and exemption flags do not apply.

Delacct deletes accounts from ~bbs/etc/passwds and removes their home and 
mail directories.

Delacct writes a line to stdout for each account it deletes, or would have
deleted if the -t flag was given. If an error occurs a message is written
to stdout. In addition, for every deleted account a line is written to
the bbs log file if it is configured and the log level is at least 1.

Return values: 0 == success, 1 == error, 2 == usage error.


3. bbslog

Syntax: bbslog [-d bbs-dir] [-h log-header] log-level message

bbs-dir:    Specifies the bbs home directory. Only needed if BBSHOME is 
	    not set in the environment and the current directory is not
            the bbs home directory.

log-header: An optional 1-16 character tag which is saved as the first 
            field of the log message. The default is BBSLOG.

log-level:  A numeric value specifying the importance of the message.
            Lower numbers indicate greater importance (0 is always logged).
            If the bbs logging level in bbconfig is less than the log-level, 
            the message is not logged.

message:    The freeform text log message.

bbslog provides a way for external scripts to write messages into the bbs
log file. The location of the file and log level are specified in the
~bbs/etc/bbconfig file; see that file for more information.

Return values: 0 == success, 1 == error, 2 == usage error.


4. mkftplist.pl

This is a perl script that may be used to quickly generate and update the
~bbs/etc/ftplist file. This file lists the directories that may be accessed
via the File System Menu. If you have a large or constantly changing
anonymous ftp archive that you want bbs users to have access to, you may
want to run this script from cron(8) to keep ~bbs/etc/ftplist up to date.

Syntax: mkftplist.pl root-directory

The mkftplist script recursively scans all directories under root-directory
and adds entries to ~bbs/etc/ftplist for each. The file board name defaults
to the first 12 characters of the basename of the directory. If identical
basenames are encountered, the file board names are made unique by appending
digits, if possible. For example, suppose /usr/ftp/pub had these directories
under it:
               |--foo-----src
/usr/ftp/pub --|       |--src
               |--bar--|
                       |--test

Then "mkftplist.pl /usr/ftp/pub" would generate something like:

src:/usr/ftp/pub/foo/src:
foo:/usr/ftp/pub/foo:
src1:/usr/ftp/pub/bar/src:
test:/usr/ftp/pub/bar/test:
bar:/usr/ftp/pub/bar:
pub:/usr/ftp/pub:

Subsequent runs of mkftplist.pl will NOT alter existing entries in the
ftplist, so if you add comments to the ftplist, change file board names 
to more descriptive ones, or add text in the description fields, they will
not be modified. mkftplist.pl WILL remove any entries from the ftplist that 
point to directories that no longer exist.

Exit values: 0 on successful completion, nonzero if a fatal error occurs.


5. bbfinger

Syntax: bbfinger [-d bbs-dir]

bbfinger is a utility for displaying the list of logged-in users from 
outside the bbs. The -d flag may be used to specify the bbs home directory.
If this flag is not given, bbfinger will try to use $BBSHOME, or finally
the current directory.

The most obvious use for this program is as an Internet server to allow
bbs users to get the user list remotely without logging in. Here's how to
set this up on most systems:

1. Pick an unused tcp port -- 1992, the year EBBS was born, is common --
   and assign the 'bfinger' service to it. In /etc/services put this line:

bfinger         1992/tcp                        # EBBS 3.0 finger

2. Tell your inetd daemon to run bbfinger for connections to the bfinger
   port. Add a line like so to your /etc/inetd.conf following the example of 
   the other servers like fingerd. This example is from Slackware Linux:

bfinger stream tcp nowait bbs /usr/sbin/tcpd /home/bbs/bin/bbfinger -d /home/bbs
                  
3. Tell inetd to reread inetd.conf by sending it SIGHUP, e.g. 

kill -HUP <pid of inetd process>

Now, anyone can "telnet <your host> <bfinger port>" and get the online
user list.

Notes: With a little work, this can be a full-fledged finger daemon for
a system where the bbs is the focus of attention.

Exit values: 0 on successful completion, nonzero on error.


Appendix A
How To Set Up a Guest Account

You should probably read the rest of this Guide before this example will
make much sense. References to more detailed discussions in the main body
will be used. This Appendix serves as a useful summary.

We shall start by assuming that you have a bbs up and running with regular
accounts, boards, and perhaps a file area.

Step 1. Create the guest account (Chapter V, section 2). Use the Add User
     command on the Admin Menu or use addacct from the command line.
     Pick a password that's easy to guess, like 'guest'. Note: it is not
     possible to create passwordless accounts at this time.

Step 2. Restrict permissions (Chapter V, section 4). Use the Permissions
     command on the Admin Menu. Since Basic-1 through Basic-4 are available
     to all other users, you want to turn one or more of these OFF for guest.
     Let's assume you turn off Basic-1 (or this one plus others).

Step 3. This is the fun part. Go through ~bbs/etc/menu.desc, and make a 
     list of the menu commands you want to make off limits to guests. 
     Don't edit menu.desc, just note the operation names, which are the
     4th fields in the menu commands (Chapter IV, section 2). Here are 
     some you might consider: Post, ZapBoard, VisitBoard, AdminMenu, 
     Cloak, SetAddress, SetUsername, SetPassword, EditWelcome, SetPlan,
     SetSignature, SetEditor, Page, SetPager, SetOverrides, Kick.

     Now go through the ~bbs/etc/access file (Chapter III, section 2)
     and change the access from ALL to Basic-1 for each of these. Some of
     them, like AdminMenu, Cloak, and Kick, are already restricted to
     higher permission bits -- you don't want to alter them. Keep an eye
     open for other things in the access file you want to restrict that
     aren't listed in menu.desc (the Read and Download menus are not yet
     configurable). ForwardMessage and ForwardFile are good examples.

     You can make your own access file entries and deny access to whole
     menus like the Mail and Files menus by using the same trick as for
     the Admin Menu.

Step 4. Make the account shared (Chapter V, section 4). This keeps the
     guest account from receiving mail, keeping records of read posts,
     and makes all menus default to (H)elp. You must edit the 'guest' 
     record at the bottom of ~bbs/etc/passwds to do this. While you're 
     here, you can turn off guest's pager so users cannot page them if 
     you wish. Change the "0000" in the 4th field of the passwds record 
     to "0008", or "0038" to restrict paging too.

Step 5. Set a logon limit for guests (Chapter V, section 5). It may be
     a good idea to limit the guest account's simultaneous logons if you
     expect high usage. Add a line like "guest:5" in ~bbs/etc/logons.

Step 6. Go through your list of boards and restrict Read access to any
     that you don't want guests seeing (Chapter VI, section 4). Use
     the Change Board command on the Admin Menu.

Step 7. If you are allowing guests to use Chat, you may want to use the
     "restricted chat" feature to only let them in the main room
     (Chapter IX, section 1). Edit ~bbs/etc/chatconfig.

And that should do it. Login as guest to make sure the menus look like 
you want them to for guests. Congratulations, you're on your way to 
becoming a Master of EBBS Configuration. :-)
you can apply a different grace period to
          never-used accounts. Not meaningful unless -c is given also.

-t:       Test mode: delacct tells which accounts would be deleted,
          but does not delete them. 

userid:   Specifies the userids to delete. These may only be given if the
          -c flag is not, and vice versa. By not specifying -c and giDarkNET-1.08/Install.sh                                                                                755   21270   21270         5066  5743642003  10030                                                                                                                                                                                                                                                                                                                                                                      #!/bin/sh
# 
# Eagles BBS 3.0 install script
#

homedir=$1
if [ "$homedir" = "" ]
then
    homedir=$BBSHOME;
    if [ "$homedir" = "" ]
    then
        homedir=`grep ^bbs: /etc/passwd | cut -d: -f6`
        if [ "$homedir" = "" ]
        then
    	    echo Cannot determine bbs home directory\!
	    echo You must do one of the following\:
	    echo \ \ \ \ \-\- define INSTALLDIR in the Makefile
	    echo \ \ \ \ \-\- define BBSHOME in the environment
	    echo \ \ \ \ \-\- add an entry for 'bbs' into /etc/passwd.
	    exit 1
	fi
    fi
fi

echo Checking directories
if [ ! -d "$homedir" ]
then
    echo Creating "$homedir"
    mkdir $homedir
    chmod 770 $homedir
fi

if [ ! -d "$homedir/bin" ]
then
    echo Creating $homedir/bin
    mkdir $homedir/bin
fi

if [ -f "$homedir/bin/lbbs" ]
then
    echo Moving existing lbbs to lbbs.old
    mv $homedir/bin/lbbs $homedir/bin/lbbs.old
fi

if [ -f "$homedir/bin/chatd" ]
then
    echo Moving existing chatd to chatd.old
    mv $homedir/bin/chatd $homedir/bin/chatd.old
fi

if [ -f "$homedir/bin/pico" ]
then
    echo Moving existing pico to pico.old
    mv $homedir/bin/pico $homedir/bin/pico.old
fi

if [ -f "$homedir/bin/helvis" ]
then
    echo Moving existing helvis to helvis.old
    mv $homedir/bin/helvis $homedir/bin/helvis.old
fi

if [ -f "$homedir/bin/hana" ]
then
    echo Moving existing hana to hana.old
    mv $homedir/bin/hana $homedir/bin/hana.old
fi

if [ -f "$homedir/bin/pseudo" ]
then
    echo Moving existing pseudo to pseudo.old
    mv $homedir/bin/pseudo $homedir/bin/pseudo.old
fi

echo Copying new executables
cp lbbs chatd addacct delacct bbslog bbfinger pico.BBS/pico \
	helvis-1.8h1+.BBS/helvis tools/hana tools/pseudo $homedir/bin
(cd $homedir/bin; strip lbbs chatd addacct delacct bbslog bbfinger)
cp mkftplist.pl $homedir/bin
chmod 6755 $homedir/bin/lbbs

if [ ! -d "$homedir/etc" ]
then
    echo Creating $homedir/etc
    mkdir $homedir/etc
    echo Copying configuration files
    cp config/* $homedir/etc    
fi

if [ ! -d "$homedir/tmp" ]
then 
    echo Creatimg $homedir/tmp
    mkdir $homedir/tmp
fi

if [ ! -d "$homedir/tmp" ]
then 
    echo Creatimg $homedir/tmp
    mkdir $homedir/tmp
fi

if [ ! -d "$homedir/home" ]
then 
    echo Creatimg $homedir/home
    mkdir $homedir/home
fi

if [ ! -d "$homedir/home/SYSOP" ]
then 
    echo Creatimg $homedir/home/SYSOP
    mkdir $homedir/home/SYSOP
fi

if [ ! -d "$homedir/home/SYSOP/mail" ]
then 
    echo Creatimg $homedir/home/SYSOP/mail
    mkdir $homedir/home/SYSOP/mail
fi

if [ ! -d "$homedir/boards" ]
then 
    echo Creatimg $homedir/boards
    mkdir $homedir/boards
fi

                                                                                                                                                                                                                                                                                                                                                                                                                                                                          DarkNET-1.08/Makefile                                                                                  644   21270   21270        27332  6053360613   7542                                                                                                                                                                                                                                                                                                                                                                      
#############################################################################
#
# Makefile for Eagles BBS version 3
# 
#############################################################################

# This is the configurable part. Put anything OS-dependent here.
# You do not need to worry with LEX, YACC, or YFLAGS unless you want to
# modify the menu parser.

LIBFTPDIR	=	libftp
PICODIR		=	pico.BBS
HELVISDIR	=	helvis-1.8H1
IRCDIR		=	ircii-2.8.H1
TOOLSDIR	=	tools

# your C compiler of choice
#CC= gcc
CC= cc

# your C linker of choice
LD=$(CC)

# archiver of choice
AR=ar

# ranlib, if applicable. SunOS, OSF/1, NeXT, A/UX use RANLIB=ranlib.
#RANLIB=echo Not using ranlib:
RANLIB=ranlib

# special include paths?
INCLUDES=

# special libs? Solaris needs -lsocket -lnsl -L/usr/ccs/lib here.
# Unixware needs -lsocket -lnsl (and maybe -L/usr/ucblib -lucb)
LIBS=

# flags for the compiler -- NeXT wants -pipe -s -O4 -arch m68040
#CCFLAGS=-g -O2 -DBIT8 -DNO_STRCASECMP=1
CCFLAGS=-g -DBIT8 -DNO_STRCASECMP=1

# flags for the linker -- NeXT wants -s -O4
#==================================
LDFLAGS=-g -L/usr1/FTP/DarkNET-1.08
#==================================

# flags for the archiver -- remove s if using ranlib, add c for NeXT
#ARFLAGS=rs
ARFLAGS=r

# zipper for srcdist and bindist targets, if desired
ZIP=gzip

# scanner generator: lex or flex
LEX=flex

# parser: yacc or bison
YACC=bison

# flags for parser
YFLAGS=-d -o y.tab.c

# default install directory for the install script
#====================
#INSTALLDIR=/home/bbs
INSTALLDIR=/usr1/bbs
#====================

# The rest shouldn't need messing with.

##############################################################################

CFLAGS=$(CCFLAGS) $(INCLUDES)

all: lbbs chatd $(PICODIR)/pico $(HELVISDIR)/helvis tools

$(PICODIR)/pico:
	cd $(PICODIR); make

$(HELVISDIR)/helvis:
	cd $(HELVISDIR); make

irc:
	cd $(IRCDIR); configure --prefix=$(INSTALLDIR); make

$(TOOLSDIR)/hana $(TOOLSDIR)/pseudo:
	cd $(TOOLSDIR); make

BINS	= lbbs chatd addacct delacct bbslog bbfinger $(PICODIR)/pico $(HELVISDIR)/helvis

SCRIPTS=mkftplist.pl

DOCS=README ChangeLog EBBS-Guide ReleaseNotes

##############################################################################
# BBS Library make
##############################################################################

LIBOBJS=record.o util.o name.o log.o utable.o login.o passwd.o home.o init.o \
acct.o misc.o headers.o readbits.o board.o files.o exec.o uldl.o chat.o \
talk.o netmail.o edit.o lang.o routing.o

libbbs.a: $(LIBOBJS)
	-rm -f libbbs.a
	$(AR) $(ARFLAGS) libbbs.a $(LIBOBJS)
	$(RANLIB) libbbs.a

# Here are the makes for the external utility programs.

addacct.o: addacct.c server.h common.h
	$(CC) -c $(CFLAGS) addacct.c

addacct: addacct.o libbbs.a
	$(CC) $(LDFLAGS) -o addacct addacct.o libbbs.a $(LIBS)

delacct.o: delacct.c server.h common.h
	$(CC) -c $(CFLAGS) delacct.c

delacct: delacct.o libbbs.a 
	$(CC) $(LDFLAGS) -o delacct delacct.o libbbs.a $(LIBS)

bbslog.o: bbslog.c server.h common.h
	$(CC) -c $(CFLAGS) bbslog.c

bbslog: bbslog.o libbbs.a 
	$(CC) $(LDFLAGS) -o bbslog bbslog.o libbbs.a $(LIBS)

bbfinger.o: bbfinger.c server.h common.h
	$(CC) -c $(CFLAGS) bbfinger.c

bbfinger: bbfinger.o modes.o libbbs.a 
	$(CC) $(LDFLAGS) -o bbfinger bbfinger.o modes.o libbbs.a $(LIBS)

############################################################################
# BBS daemon make
############################################################################

#bbsd: packet.o libbbs.a
#     cd server; make CC=$(CC) CFLAGS=$(CFLAGS) LD=$(LD) LDFLAGS=$(LDFLAGS) LI
#
#DLIBS=libbbs.a
#
#DOBJS=bbsd.o packet.o xfer.o
#
#bbsd: $(DOBJS) $(DLIBS)
#     $(LD) $(LDFLAGS) -o bbsd $(DOBJS) $(DLIBS) $(LIBS)

############################################################################
# Chat daemon make
############################################################################

chatserv.o: chatserv.c
	$(CC) -c $(CFLAGS) chatserv.c

chatconf.o: chatconf.c
	$(CC) -c $(CFLAGS) chatconf.c

chatd: chatserv.o chatconf.o libbbs.a
	$(LD) $(LDFLAGS) -o chatd chatserv.o chatconf.o libbbs.a $(LIBS)

############################################################################
# BBS client make
############################################################################

#bbs: packet.o pbbs/libpbbs.a y.tab.c lex.yy.c
#     cd client; make CC=$(CC) CFLAGS=$(CFLAGS) LD=$(LD) LDFLAGS=$(LDFLAGS) AR

############################################################################
# Local client make
############################################################################

LLIBS=libbbs.a pbbs/libpbbs.a $(LIBFTPDIR)/libftp.a

LOBJS=client.o menus.o complete.o system.o c_users.o readmenu.o c_mail.o \
modes.o c_boards.o c_post.o readnew.o c_files.o c_chat.o c_irc.o c_talk.o \
c_lists.o c_msg.o nmenus.o env.o y.tab.o lex.yy.o

PLIBOBJS=pbbs/term.o pbbs/screen.o pbbs/io.o pbbs/stuff.o \
pbbs/more.o pbbs/vedit.o pbbs/hangul.o

pbbs/term.o: pbbs/term.c
	cd pbbs; $(CC) -c -I.. $(CFLAGS) term.c

pbbs/screen.o: pbbs/screen.c
	cd pbbs; $(CC) -c -I.. $(CFLAGS) screen.c

pbbs/io.o: pbbs/io.c
	cd pbbs; $(CC) -c -I.. $(CFLAGS) io.c

pbbs/stuff.o: pbbs/stuff.c
	cd pbbs; $(CC) -c -I.. $(CFLAGS) stuff.c

pbbs/more.o: pbbs/more.c
	cd pbbs; $(CC) -c -I.. $(CFLAGS) more.c

pbbs/vedit.o: pbbs/vedit.c
	cd pbbs; $(CC) -c -I.. $(CFLAGS) vedit.c

pbbs/hangul.o: pbbs/hangul.c
	cd pbbs; $(CC) -c -I.. $(CFLAGS) hangul.c

pbbs/libpbbs.a: $(PLIBOBJS)
	-rm -f pbbs/libpbbs.a
	$(AR) $(ARFLAGS) pbbs/libpbbs.a $(PLIBOBJS)
	$(RANLIB) pbbs/libpbbs.a

$(LIBFTPDIR)/libftp.a:
	cd libftp; make

lex.yy.c:  menu.l
	$(LEX) menu.l

lex.yy.o: lex.yy.c y.tab.o

y.tab.c: gram.y
	$(YACC) $(YFLAGS) gram.y

lbbs: $(LOBJS) $(LLIBS)
	$(LD) $(LDFLAGS) -o lbbs $(LOBJS) $(LLIBS) $(LIBS) -ltermcap #-lresolv

srcdist:
	rm -f ebbssrc.tar ebbssrc.tar.gz 
	tar -cvf ebbssrc.tar [A-Z]* *.[chly] *.pl pbbs/*.c pbbs/*.h config/*
	$(ZIP) ebbssrc.tar

bindist: $(BINS) 
	rm -f ebbsbin.tar ebbsbin.tar.gz
	if [ ! -d deliv ]; then \
	  mkdir deliv deliv/bin deliv/boards deliv/etc deliv/tmp; \
	  mkdir deliv/home deliv/home/SYSOP deliv/home/SYSOP/mail; \
	fi
	cp $(DOCS) deliv
	cp $(BINS) deliv/bin
	cp $(SCRIPTS) deliv/bin
	chmod 6755 deliv/bin/lbbs
	cp config/* deliv/etc
	(cd deliv/bin; strip $(BINS))	
	(cd deliv; tar -cvf ../ebbsbin.tar .)
	$(ZIP) ebbsbin.tar        

install: $(BINS) $(TOOLSDIR)/hana $(TOOLSDIR)/pseudo
	./Install.sh $(INSTALLDIR)
#	cd $(IRCDIR); make install

clean:
	rm -f *.o pbbs/*.o *~ pbbs/*~ config/*~ *# y.output $(BINS)
#	rm -f lex.yy.c y.tab.c y.tab.h
	rm -f libbbs.a pbbs/libpbbs.a
	cd $(LIBFTPDIR); make clean
	cd $(PICODIR); make clean
	cd $(IRCDIR); make clean
	cd $(HELVISDIR); make clean
	cd $(TOOLSDIR); make clean

clobber: clean
	rm -f $(BINS) libbbs.a pbbs/libpbbs.a


acct.o : acct.c server.h common.h osdeps.h modes.h retval.h clntcmds.h myctype.h \
  perms.h 
addacct.o : addacct.c server.h common.h osdeps.h modes.h retval.h clntcmds.h \
  myctype.h perms.h 
bbfinger.o : bbfinger.c server.h common.h osdeps.h modes.h retval.h clntcmds.h \
  myctype.h perms.h 
bbslog.o : bbslog.c server.h common.h osdeps.h modes.h retval.h clntcmds.h myctype.h \
  perms.h 
board.o : board.c server.h common.h osdeps.h modes.h retval.h clntcmds.h myctype.h \
  perms.h 
c_boards.o : c_boards.c client.h common.h osdeps.h modes.h retval.h clntcmds.h \
  myctype.h perms.h clientui.h pbbs/io.h c_msg.h 
c_chat.o : c_chat.c client.h common.h osdeps.h modes.h retval.h clntcmds.h myctype.h \
  perms.h clientui.h pbbs/io.h c_msg.h 
c_files.o : c_files.c client.h common.h osdeps.h modes.h retval.h clntcmds.h \
  myctype.h perms.h clientui.h pbbs/io.h c_msg.h 
c_irc.o : c_irc.c client.h common.h osdeps.h modes.h retval.h clntcmds.h myctype.h \
  perms.h clientui.h pbbs/io.h c_msg.h 
c_lists.o : c_lists.c client.h common.h osdeps.h modes.h retval.h clntcmds.h \
  myctype.h perms.h clientui.h pbbs/io.h c_msg.h 
c_mail.o : c_mail.c client.h common.h osdeps.h modes.h retval.h clntcmds.h myctype.h \
  perms.h clientui.h pbbs/io.h c_msg.h 
c_msg.o : c_msg.c c_msg.h 
c_post.o : c_post.c client.h common.h osdeps.h modes.h retval.h clntcmds.h myctype.h \
  perms.h clientui.h pbbs/io.h c_msg.h 
c_talk.o : c_talk.c client.h common.h osdeps.h modes.h retval.h clntcmds.h myctype.h \
  perms.h clientui.h pbbs/io.h c_msg.h 
c_users.o : c_users.c client.h common.h osdeps.h modes.h retval.h clntcmds.h \
  myctype.h perms.h clientui.h pbbs/io.h c_msg.h 
chat.o : chat.c server.h common.h osdeps.h modes.h retval.h clntcmds.h myctype.h \
  perms.h 
chatconf.o : chatconf.c server.h common.h osdeps.h modes.h retval.h clntcmds.h \
  myctype.h perms.h 
chatserv.o : chatserv.c server.h common.h osdeps.h modes.h retval.h clntcmds.h \
  myctype.h perms.h 
client.o : client.c client.h common.h osdeps.h modes.h retval.h clntcmds.h myctype.h \
  perms.h clientui.h pbbs/io.h c_msg.h 
complete.o : complete.c client.h common.h osdeps.h modes.h retval.h clntcmds.h \
  myctype.h perms.h clientui.h pbbs/io.h c_msg.h 
delacct.o : delacct.c server.h common.h osdeps.h modes.h retval.h clntcmds.h \
  myctype.h perms.h 
edit.o : edit.c server.h common.h osdeps.h modes.h retval.h clntcmds.h myctype.h \
  perms.h 
env.o : env.c client.h common.h osdeps.h modes.h retval.h clntcmds.h myctype.h \
  perms.h clientui.h pbbs/io.h c_msg.h 
exec.o : exec.c server.h common.h osdeps.h modes.h retval.h clntcmds.h myctype.h \
  perms.h 
files.o : files.c server.h common.h osdeps.h modes.h retval.h clntcmds.h myctype.h \
  perms.h 
headers.o : headers.c server.h common.h osdeps.h modes.h retval.h clntcmds.h \
  myctype.h perms.h 
home.o : home.c osdeps.h 
init.o : init.c server.h common.h osdeps.h modes.h retval.h clntcmds.h myctype.h \
  perms.h 
lang.o : lang.c server.h common.h osdeps.h modes.h retval.h clntcmds.h myctype.h \
  perms.h 
log.o : log.c server.h common.h osdeps.h modes.h retval.h clntcmds.h myctype.h \
  perms.h 
login.o : login.c server.h common.h osdeps.h modes.h retval.h clntcmds.h myctype.h \
  perms.h 
menus.o : menus.c client.h common.h osdeps.h modes.h retval.h clntcmds.h myctype.h \
  perms.h clientui.h pbbs/io.h c_msg.h 
misc.o : misc.c server.h common.h osdeps.h modes.h retval.h clntcmds.h myctype.h \
  perms.h 
modes.o : modes.c client.h common.h osdeps.h modes.h retval.h clntcmds.h myctype.h \
  perms.h clientui.h pbbs/io.h c_msg.h 
name.o : name.c common.h osdeps.h modes.h retval.h clntcmds.h myctype.h 
netmail.o : netmail.c server.h common.h osdeps.h modes.h retval.h clntcmds.h \
  myctype.h perms.h 
nmenus.o : nmenus.c client.h common.h osdeps.h modes.h retval.h clntcmds.h myctype.h \
  perms.h clientui.h pbbs/io.h c_msg.h 
packet.o : packet.c common.h osdeps.h modes.h retval.h clntcmds.h myctype.h \
  packet.h 
packfmt.o : packfmt.c common.h osdeps.h modes.h retval.h clntcmds.h myctype.h \
  packet.h 
passwd.o : passwd.c common.h osdeps.h modes.h retval.h clntcmds.h myctype.h 
readbits.o : readbits.c server.h common.h osdeps.h modes.h retval.h clntcmds.h \
  myctype.h perms.h 
readmenu.o : readmenu.c client.h common.h osdeps.h modes.h retval.h clntcmds.h \
  myctype.h perms.h clientui.h pbbs/io.h c_msg.h 
readnew.o : readnew.c client.h common.h osdeps.h modes.h retval.h clntcmds.h \
  myctype.h perms.h clientui.h pbbs/io.h c_msg.h 
record.o : record.c server.h common.h osdeps.h modes.h retval.h clntcmds.h myctype.h \
  perms.h 
routing.o : routing.c client.h common.h osdeps.h modes.h retval.h clntcmds.h \
  myctype.h perms.h clientui.h pbbs/io.h c_msg.h 
system.o : system.c client.h common.h osdeps.h modes.h retval.h clntcmds.h myctype.h \
  perms.h clientui.h pbbs/io.h c_msg.h 
talk.o : talk.c server.h common.h osdeps.h modes.h retval.h clntcmds.h myctype.h \
  perms.h 
uldl.o : uldl.c server.h common.h osdeps.h modes.h retval.h clntcmds.h myctype.h \
  perms.h 
utable.o : utable.c server.h common.h osdeps.h modes.h retval.h clntcmds.h myctype.h \
  perms.h 
util.o : util.c common.h osdeps.h modes.h retval.h clntcmds.h myctype.h 
 Chat daemon make
############################################################################

chatserv.o: chatserv.c
	$(CC) -c $(CFLAGS) chatserv.c

chatconf.o: chatconf.c
	$(CC) -c $(CFLAGS) chatconf.c

chatd: chatserv.o chatconf.o libbbs.a
	$(LD) $(LDFLAGS) -o chatd chatserv.o chatconf.o lDarkNET-1.08/README                                                                                    644   21270   21270        10564  5647532322   6767                                                                                                                                                                                                                                                                                                                                                                      
Welcome to Eagles BBS 3.0

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version. See the COPYING file for further information.

Eagles BBS 3.0 is a standalone, screen-oriented bulletin board package. 
It is the successor to Eagles BBS version 2, which was built upon Ed Luke's
Pirates BBS package. The user interface from those programs has been kept
intact for the most part, and some code has been reused. For the most part
this is a complete rewrite though, to correct some basic limitations and
inefficiencies present in Pirates and Eagles 2.x. 

This software has a fairly full-featured message posting and private mail
system, its own IRC-like chat system, and private talk facility. It has
configurable menus allowing custom arrangement of the builtin functions 
and any external programs you care to hook in.

One thing Eagles BBS is not suited for is as a fancy shell. All BBS users
run as a single user, so things like shell access and external mail and
news do not integrate very well. You should probably look elsewhere if
BBS users are to be anything more than guests on your system.

One improvement over Pirates and old Eagles is much greater runtime
configuration. A lot of stuff you used to have to recompile to change is
now in config files read in at runtime. All of these files are ASCII so
they may be patched with an editor if needed. The stock config files are
in the config directory and reside in ~bbs/etc at runtime.

If you are already using a beta version of EBBS 3.0, be SURE to read the
ReleaseNotes and ChangeLog to see what has changed before continuing.

All documentation has been moved into the EBBS-Guide. Please consult it
for installation and configuration instructions, examples, and technical
information. 

The Linux binary distribution, ebbs-3.0-Linux.tar.gz, was built with gcc 2.5.8.
You should have Linux 1.0 or later, the GNU shared C library version 4.5.19 
or later, and the dynamic loader ld.so. Earlier versions of the kernel and
shared C library may or may not work.

The source distribution, ebbs-3.0.tar.gz, should build under recent versions
of Linux, SunOS, Solaris, AIX, OSF/1, NextStep, and A/UX. You should go
through the Makefile and osdeps.h to set up the conditional defines for
your operating system -- see EBBS-Guide under "Building the Source" for
details. 

If you have an operational EBBS 2.x that you want to convert to 3.0,
you'll need the source distribution and the conversion package, cvtpkg.tar.gz.
It should be available at //ftp:/seabass.st.usm.edu/pub/EaglesBBS or
other sites. Get it and see the enclosed README for the scoop on getting 
your existing BBS converted to version 3.0.
   
Add-on packages (useful scripts, safe editors, etc.) are under development.
Check the EaglesBBS directory on seabass mentioned above to see what's there.


The TODO list
-------------

These features aren't done yet, but might be one day:

-- Post expire program that can be run from cron.
-- Mail clean program.
-- Ability to receive/send Internet mail from the BBS Mail Menu.
-- Tagging of messages in mail, for deleting or forwarding.
-- Reading lists that allow each user to specify the order to scan the
   boards during a new message scan.
-- Configurable read-menus (read menu, mail read menu, download menu).
-- The big TODO: A split into client and server, with which the client 
   can run on a different machine and do things like editing, menu movements,
   shell escapes, job control, etc. locally.


Known Bugs
----------

-- On the File Menu, the "Current Board" is shown is not the currently
   selected File board. It is correct on the Download read-menu.

Credits
-------

Thanks to these people for helping code, test, debug, and port EBBS 3.0!
Ed Luke
Ray Seyfarth
Bill Schwartz
Xabier Vazquez Gallardo
John Salmi
Paul Snow
Mark Roe
Andre Schmidt
Jon Stevens
Everyone at the Eagle's Nest and Auggie BBS

Additional of the hat for assistance with the previous incarnation of EBBS:
Guy Vega, Dominic Tynes, Randy Austin, Alex Schubert, Jim Morton, Carey Chou

------------------------------------------------------------------------------

Good luck, and happy BBSing!

TheRock
In real life:  Ray Rocker
On the air:    WQ5L
Internet:      rock@seabass.st.usm.edu
	       rocker@iquest.com
CompuServe:    72673,2105 
                                                                                                                                            DarkNET-1.08/ReleaseNotes                                                                              644   21270   21270         2550  5647532322  10377                                                                                                                                                                                                                                                                                                                                                                      
This is the first post-Beta release of EBBS 3.0.
Directions for installation are now in the EBBS-Guide. 

See the ChangeLog for details on bug fixes and new features in each of
the Beta releases. You should replace all of the executables in ~bbs/bin
with the ones in this distribution. You may have to replace or update 
some of the configuration files depending on which Beta you have. The 
configuration files are in ~bbs/etc at runtime and in the binary 
distribution, and in the config subdirectory of the source distribution. 
Here's a rough road map:

access, menu.desc, bbconfig: These stabilized around BETA-4, so you don't
have to replace them if you have BETA-4 or BETA-5. The C_PUBLICACCT entry
in the access file was removed for the real 3.0. If you had a guest account
depending on it you must turn on the Shared bit for that account instead
(see EBBS-Guide for details).

editors: A fourth field for environment to be passed to editors was added
for the real 3.0. Replace your editors file with the one included here,
merging in any additions you've already made, of course.

chatconfig, chathlp.txt, chatxhlp.txt: These are new as of BETA-3. They're
unchanged since then except for chathlp.txt, which got some new entries in 
the real 3.0. Be sure to copy this one over.

The rest of the configuration files haven't changed except for some on the 
comments, perhaps.

                                                                                                                                                        DarkNET-1.08/acct.c                                                                                    644   21270   21270        40066  5751534444   7170                                                                                                                                                                                                                                                                                                                                                                      
/*
Eagles Bulletin Board System
Copyright (C) 1994, Ray Rocker, rrrocker@rock.b11.ingr.com
                                rock@seabass.st.usm.edu
                                72673.2105@compuserve.com

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "server.h"
#include <sys/stat.h>

extern SERVERDATA server;

/* lastlogin file stuff */

#define LASTLOGIN      "lastlogin"

get_lastlog_file(userid, buf)
char *userid;
char *buf;
{
  get_home_directory(userid, buf);
  strcat(buf, "/");
  strcat(buf, LASTLOGIN);
}

get_lastlog_time(userid, tbuf)
char *userid;
LONG *tbuf;
{
  PATH lastlog;
  struct stat stbuf;
  *tbuf = 0;
  get_lastlog_file(userid, lastlog);
  if (stat(lastlog, &stbuf) == 0) {
    *tbuf = (LONG)stbuf.st_mtime;
  }
}

get_lastlog_host(userid, host)
char *userid;
char *host;
{
  PATH lastlog;
  FILE *fp;
  host[0] = '\0';
  get_lastlog_file(userid, lastlog);
  if (fp = fopen(lastlog, "r")) {
    fgets(host, HOSTLEN, fp);
    fclose(fp);
  }
}    

set_lastlog(userid, host)
char *userid;
char *host;
{
  PATH lastlog;
  FILE *fp;
  get_lastlog_file(userid, lastlog);
  if (fp = fopen(lastlog, "w")) {
    fputs(host, fp);
    fclose(fp);
  }
}    

/* 
   Profile. Bunch of optional information stored one per line, 
   XXXX=data, where XXXX is TERM, ADDR, NAME, MAIL, PROT.
*/

#define PROFILE       "profile"
#define PROFILE_TERM  "TERM"
#define PROFILE_NAME  "NAME"
#define PROFILE_ADDR  "ADDR"
#define PROFILE_MAIL  "MAIL"
#define PROFILE_PROT  "PROT"
#define PROFILE_EDIT  "EDIT"
#define PROFILE_LANG  "LANG"

#define DEFAULT_TERMINAL "vt100"
#define DEFAULT_EDITOR   "builtin"

struct profile_data {
  char *key;
  char *data;
};

get_profile_file(userid, buf)
char *userid;
char *buf;
{
  get_home_directory(userid, buf);
  strcat(buf, "/");
  strcat(buf, PROFILE);
}

_match_profile_key(rec, key)
char *rec;
char *key;
{
  if (!strncmp(rec, key, 4) && rec[4] == '=') return S_EXISTS;
  return S_OK;
}

_profile_upd(newrec, oldrec, data)
char *newrec;
char *oldrec;
char *data;
{
  strncpy(newrec, oldrec, 5);
  strcpy(newrec+5, data);
  strcat(newrec, "\n");
  return S_OK;
}

_profile_format(rec, pd)
char *rec;
struct profile_data *pd;
{
  sprintf(rec, "%s=%s\n", pd->key, pd->data);
  return S_OK;
}

set_profile_data(userid, key, data)
char *userid;
char *key;
char *data;
{
  int rc;
  PATH profile;
  struct stat stbuf;
  get_profile_file(userid, profile);

  if (data[0] == '\0' || 
     (!strcmp(key, PROFILE_TERM) && !strcmp(data, DEFAULT_TERMINAL)) ||
     (!strcmp(key, PROFILE_EDIT) && !strcmp(data, DEFAULT_EDITOR))) {
    _record_delete(profile, _match_profile_key, key);
    return S_OK;
  }

  rc = _record_replace(profile, _match_profile_key, key, _profile_upd, data);
  if (rc != S_OK) {
    struct profile_data pd;
    pd.key = key;
    pd.data = data;
    rc = _record_add(profile, _match_profile_key, key, _profile_format, &pd);
  }
  return rc;
}

/*ARGSUSED*/
_profile_fill(indx, rec, acct)
int indx;
char *rec;
ACCOUNT *acct;
{
  strip_trailing_space(rec);
  if (rec[4] != '=') return S_OK;
  rec[4] = '\0';
  if (!strcmp(rec, PROFILE_TERM)) 
    strncpy(acct->terminal, rec+5, TERMLEN);
  else if (!strcmp(rec, PROFILE_NAME)) 
    strncpy(acct->realname, rec+5, RNAMELEN);
  else if (!strcmp(rec, PROFILE_ADDR)) 
    strncpy(acct->address, rec+5, ADDRLEN);
  else if (!strcmp(rec, PROFILE_MAIL)) 
    strncpy(acct->email, rec+5, MAILLEN);
  else if (!strcmp(rec, PROFILE_PROT)) 
    strncpy(acct->protocol, rec+5, NAMELEN);
  else if (!strcmp(rec, PROFILE_EDIT)) 
    strncpy(acct->editor, rec+5, NAMELEN);
  else if (!strcmp(rec, PROFILE_LANG)) {
    strncpy(acct->lang, rec+5, LANGLEN);
    if (strcmp(acct->lang, "Kr") == 0)
      acct->flags |= FLG_KOREAN;
    else
      acct->flags &= ~FLG_KOREAN;
  }
  return S_OK;
}

enum_profile_data(userid, acct)
char *userid;
ACCOUNT *acct;
{
  PATH profile;
  extern int lang;

  get_profile_file(userid, profile);
  _record_enumerate(profile, 0, _profile_fill, acct);
  if (acct->terminal[0] == '\0')
    strcpy(acct->terminal, DEFAULT_TERMINAL);
/*
  if (acct->lang[0] != '\0' && strcmp(acct->lang, "Kr") == 0)
    lang = 1;
  else
    lang = 0;
*/
  return S_OK;
}

_fill_profile_name(rec, buf)
char *rec;
char *buf;
{
  strip_trailing_space(rec);
  strncpy(buf, rec+5, RNAMELEN);
  return S_OK;
}

lookup_profile_name(userid, namebuf)
char *userid;
char *namebuf;
{
  PATH profile;
  int rc;
  get_profile_file(userid, profile);
  rc = _record_find(profile, _match_profile_key, PROFILE_NAME, 
                             _fill_profile_name, namebuf);
  return rc;
}  

/* Now for the passfile itself. */

#define PASSFILE       "etc/passwds"
#define PASSFLUSH      ".pflush"

#define PF_USERID_OFFSET      0
#define PF_PASSWD_OFFSET      (PF_USERID_OFFSET+NAMELEN+1)
#define PF_PERMS_OFFSET       (PF_PASSWD_OFFSET+PASSLEN+1)
#define PF_FLAGS_OFFSET       (PF_PERMS_OFFSET+9)
#define PF_USERNAME_OFFSET    (PF_FLAGS_OFFSET+5)
#define PF_END_OF_RECORD      (PF_USERNAME_OFFSET+UNAMELEN+1)

format_passent(rec, acct)
char *rec;
ACCOUNT *acct;
{
  memset(rec, ' ', PF_USERNAME_OFFSET+UNAMELEN);
  memcpy(rec+PF_USERID_OFFSET, acct->userid, strlen(acct->userid));
  *(rec+PF_PASSWD_OFFSET-1) = ':';
  memcpy(rec+PF_PASSWD_OFFSET, acct->passwd, strlen(acct->passwd));
  *(rec+PF_PERMS_OFFSET-1) = ':';
  LONGcpy(rec+PF_PERMS_OFFSET, acct->perms);
  *(rec+PF_FLAGS_OFFSET-1) = ':';
  SHORTcpy(rec+PF_FLAGS_OFFSET, acct->flags);
  *(rec+PF_USERNAME_OFFSET-1) = ':';
  memcpy(rec+PF_USERNAME_OFFSET, acct->username, strlen(acct->username));
  memcpy(rec+PF_END_OF_RECORD-1, ":\n", 3);
  return S_OK;
}

passent_to_account(rec, acct)
char *rec;
ACCOUNT *acct;
{
  acct->userid[NAMELEN] = '\0';
  acct->passwd[PASSLEN] = '\0';
  acct->username[UNAMELEN] = '\0';
  strncpy(acct->userid, rec+PF_USERID_OFFSET, NAMELEN);
  strip_trailing_space(acct->userid);
  strncpy(acct->passwd, rec+PF_PASSWD_OFFSET, PASSLEN);
  strip_trailing_space(acct->passwd);
  strncpy(acct->username, rec+PF_USERNAME_OFFSET, UNAMELEN);
  strip_trailing_space(acct->username);
  acct->perms = hex2LONG(rec+PF_PERMS_OFFSET);
  acct->flags = hex2SHORT(rec+PF_FLAGS_OFFSET);
  enum_profile_data (acct->userid, acct);
  return S_OK;
}

hide_priv_acct_fields(acct)
ACCOUNT *acct;
{
  int myself = is_me(acct->userid);
  if (!myself) memset(acct->passwd, '\0', PASSLEN);
  if (!_has_perms(PERM_SYSOP) && !_has_perms(PERM_ACCTMGR)
	&& !_has_perms(PERM_BRDMGR))
	acct->perms = 0;
  if (!_has_access(C_SEEALLAINFO)) {
    if (myself) acct->flags &= ~FLG_EXEMPT;   /* hide only this flag */    
    else acct->flags = 0;                     /* hide all from others */
  }
}  

_lookup_account(userid, acct)
char *userid;
ACCOUNT *acct;
{
  int rc;
  rc = _record_find(PASSFILE, _match_first, userid, passent_to_account, acct);
  return rc;
}

local_bbs_add_account(newacct, is_encrypted)
ACCOUNT *newacct;
SHORT is_encrypted;
{

  int rc;
  ACCOUNT acct;
  PATH homedir;
  PATH maildir;
  char *adder;

  memcpy(&acct, newacct, sizeof acct);
  if (!is_valid_userid(acct.userid)) return S_INVALID;
  if (!is_valid_password(acct.passwd)) return S_INVALID;

  if (!is_encrypted) {
    encrypt_passwd(acct.passwd, newacct->passwd);
  }

  acct.flags = newacct->flags;
  acct.perms = PERM_DEFAULT;

  rc = _record_add(PASSFILE, _match_first, acct.userid, format_passent, &acct);
  if (rc != S_OK) return S_EXISTS; 

  get_home_directory(acct.userid, homedir);
  get_mail_directory(acct.userid, maildir);
  recursive_rmdir (homedir);
  if (mkdir(homedir, 0700) || mkdir(maildir, 0700)) {
    _record_delete(PASSFILE, _match_first, acct.userid);
    bbslog(0, "ERROR local_bbs_add_account: mkdir failed: %s or %s\n",
           homedir, maildir);
    return S_SYSERR;
  }

  if (acct.terminal[0]) 
    set_profile_data(acct.userid, PROFILE_TERM, acct.terminal);
  if (acct.realname[0]) 
    set_profile_data(acct.userid, PROFILE_NAME, acct.realname);
  if (acct.address[0]) 
    set_profile_data(acct.userid, PROFILE_ADDR, acct.address);
  if (acct.email[0]) 
    set_profile_data(acct.userid, PROFILE_MAIL, acct.email);
  if (acct.protocol[0]) 
    set_profile_data(acct.userid, PROFILE_PROT, acct.protocol);
  if (acct.editor[0]) 
    set_profile_data(acct.userid, PROFILE_EDIT, acct.editor);
  if (acct.lang[0]) 
    set_profile_data(acct.userid, PROFILE_LANG, acct.lang);

  adder = my_userid();
  if (*adder == '\0')
    bbslog(1, "NEWACCT %s\n", acct.userid);
  else bbslog(1, "ADDACCT %s by %s\n", acct.userid, adder);

  touch_flush(PASSFLUSH);
  return S_OK;
}

local_bbs_delete_account(userid)
char *userid;
{
  int rc;
  ACCOUNT acct;
  PATH homedir;

  rc = _record_find(PASSFILE, _match_first, userid, passent_to_account, &acct);
  if (rc != S_OK) return S_NOTFOUND;

  if ((acct.perms & PERM_SYSOP) && !_has_perms(PERM_SYSOP) && !_has_perms(PERM_ACCTMGR)) {
    return S_DENIED;
  }

  rc = _record_delete(PASSFILE, _match_first, acct.userid);
  if (rc != S_OK) return S_SYSERR;

  get_home_directory(acct.userid, homedir);
  recursive_rmdir(homedir);
#if FULL_USER_DELETE
  _board_enum_fix_managers(acct.userid, NULL);
  _acct_enum_fix_overrides(acct.userid, NULL);
#endif
  touch_flush(PASSFLUSH);

  bbslog(2, "DELETEACCT %s by %s\n", acct.userid, my_userid());
  return S_OK;
}

/*ARGSUSED*/
update_passent(newrec, oldrec, acct)
char *newrec;
char *oldrec;
ACCOUNT *acct;
{
  format_passent(newrec, acct);    
  return S_OK;
}

_set_account(userid, newacct, flags)
char *userid;
ACCOUNT *newacct;
SHORT flags;
{
  int rc;
  ACCOUNT acct;
  NAME saveid;
    
  rc = _record_find(PASSFILE, _match_first, userid, passent_to_account, &acct);
  if (rc != S_OK) return S_NOTFOUND;

  if ((acct.perms & PERM_SYSOP) && !_has_perms(PERM_SYSOP) && !_has_perms(PERM_ACCTMGR)) {
    return S_DENIED;
  }

  if (flags & MOD_USERID) {
    if (!is_valid_userid(newacct->userid)) return S_INVALID;
    rc = _record_find(PASSFILE, _match_first, newacct->userid, NULL, NULL);
    if (rc != S_NOTFOUND) return S_EXISTS;
    strcpy(saveid, acct.userid);
    strncpy(acct.userid, newacct->userid, NAMELEN);
  }

  if (flags & MOD_PASSWD) {
    if (!is_valid_password(newacct->passwd)) return S_INVALID;
    encrypt_passwd(acct.passwd, newacct->passwd);
  }

  if (flags & MOD_USERNAME)
    strncpy(acct.username, newacct->username, UNAMELEN);
    
  if (flags & _MOD_PERMS)
    acct.perms = newacct->perms;

  if (flags & _TOGGLE_FLAGS)
    acct.flags ^= newacct->flags;
  if (flags & _TOGGLE_FLAG)
    acct.flags |= newacct->flags;
  if (flags & MOD_LANG)
    {
	if (newacct->flags & FLG_KOREAN)
	  acct.flags |= FLG_KOREAN;
	else
	  acct.flags &= ~FLG_KOREAN;
    }
    
  rc = _record_replace(PASSFILE, _match_first, userid, update_passent, &acct);

  if (rc != S_OK) return S_SYSERR;

  if (flags & MOD_USERID) {
    PATH oldhome, newhome;
    get_home_directory(saveid, oldhome);
    get_home_directory(acct.userid, newhome);
    recursive_rmdir(newhome);
    rename(oldhome, newhome);
#if FULL_USER_DELETE
    _board_enum_fix_managers(saveid, acct.userid);
    _acct_enum_fix_overrides(saveid, acct.userid);
#endif
    touch_flush(PASSFLUSH);
  }

  if (flags & MOD_TERMINAL)
    set_profile_data(acct.userid, PROFILE_TERM, newacct->terminal);
  if (flags & MOD_REALNAME) 
    set_profile_data(acct.userid, PROFILE_NAME, newacct->realname);
  if (flags & MOD_ADDRESS) 
    set_profile_data(acct.userid, PROFILE_ADDR, newacct->address);
  if (flags & MOD_EMAIL) 
    set_profile_data(acct.userid, PROFILE_MAIL, newacct->email);
  if (flags & MOD_PROTOCOL) 
    set_profile_data(acct.userid, PROFILE_PROT, newacct->protocol);
  if (flags & MOD_EDITOR) 
    set_profile_data(acct.userid, PROFILE_EDIT, newacct->editor);
  if (flags & MOD_LANG) 
    set_profile_data(acct.userid, PROFILE_LANG, newacct->lang);

  return S_OK;
}

local_bbs_modify_account(userid, acct, flags)
char *userid;
ACCOUNT *acct;
SHORT flags;
{
  /* Clear the internal-only flags */
  flags &= MOD_ACCOUNT_MASK;

  if (flags & MOD_USERID)
    bbslog(2, "MODIFYACCT %s to %s by %s\n", 
           userid, acct->userid, my_userid());
  else bbslog(2, "MODIFYACCT %s by %s\n", userid, my_userid());

  return(_set_account(userid, acct, flags));
}

local_bbs_modify_perms(userid, perms)
char *userid;
LONG perms;
{
  ACCOUNT acct;
  acct.perms = perms;
  bbslog(2, "SETPERMS %s to %08x by %s\n", userid, perms, my_userid());
  return (_set_account(userid, &acct, _MOD_PERMS));
}

local_bbs_toggle_exempt(userid)
char *userid;
{
  ACCOUNT acct;
  acct.flags = FLG_EXEMPT;
  bbslog(2, "EXEMPT %s by %s\n", userid, my_userid());
  return (_set_account(userid, &acct, _TOGGLE_FLAGS));
}

local_bbs_query(userid, acct)
char *userid;
ACCOUNT *acct;
{
  int rc;
  memset(acct, 0, sizeof(*acct));
  rc = _record_find(PASSFILE, _match_first, userid, passent_to_account, acct);
  if (rc != S_OK) return S_NOTFOUND;
  if (my_utable_slot() == -1)
    {
      /* Not logged in -- only allow test of userid's existence */
      memset(acct, 0, sizeof(*acct));
      return S_OK;
    }
  hide_priv_acct_fields(acct);
  get_lastlog_time(acct->userid, &acct->lastlogin);
  get_lastlog_host(acct->userid, acct->fromhost);
  if (server.queryreal && _has_access(C_SEEREALNAME)) {
    lookup_profile_name(acct->userid, acct->realname);    
  }
  return S_OK;
}

local_bbs_get_userinfo(userid, acct)
char *userid;
ACCOUNT *acct;
{
  int rc;
  memset(acct, 0, sizeof(*acct));
  rc = _record_find(PASSFILE, _match_first, userid, passent_to_account, acct);
  if (rc != S_OK) return S_NOTFOUND;
  hide_priv_acct_fields(acct);
  get_lastlog_time(acct->userid, &acct->lastlogin);
  get_lastlog_host(acct->userid, acct->fromhost);
  enum_profile_data(acct->userid, acct);
  return S_OK;
}  

_enum_accounts(indx, rec, en)
int indx;
char *rec;
struct enumstruct *en;
{
  ACCOUNT acct;
  memset(&acct, 0, sizeof acct);
  passent_to_account(rec, &acct);
  get_lastlog_time(acct.userid, &acct.lastlogin);
  hide_priv_acct_fields(&acct);
  if (en->fn(indx, &acct, en->arg) == ENUM_QUIT) return ENUM_QUIT;
  return S_OK;
}

/*ARGSUSED*/
local_bbs_enum_accounts(chunk, startrec, enumfn, arg)
SHORT chunk;
SHORT startrec;
int (*enumfn)();
void *arg;
{
  struct enumstruct en;
  en.fn = enumfn;
  en.arg = arg;
  _record_enumerate(PASSFILE, startrec, _enum_accounts, &en);
  return S_OK;
}

local_bbs_acctnames(list)
NAMELIST *list;
{
  FILE *fp;
  NAME userid;
  char rec[128];
  register int i;
  register char *p1, *p2;

  static time_t lastupdate = 0;

  if (!test_flush(PASSFLUSH, lastupdate)) {
    return S_NOUPDATE;
  }
  create_namelist(list, MAXUSER);
  if ((fp = fopen(PASSFILE, "r")) == NULL)
    return S_NOUPDATE;
  while (fgets(rec, 128, fp))
  {
     if (*rec == '#' || myisspace(*rec)) continue;
     for (i=0, p1=userid, p2=rec;
	  i<NAMELEN && *p2 && !myisspace(*p2);
	  i++, p1++, p2++)
	{
	  *p1 = *p2;
	}
     *p1 = '\0';
     add_namelist(list, userid, NULL);
  }
  fclose(fp);
  sort_list(list);
  return S_OK;
}

/* 
   Called from bbs_delete_board and bbs_modify_board:
   loop through each account and fix the readbits file.
   (jumping thru lots of hoops in the name of modularity!)
*/

extern int fix_readbit_entry();

_acct_enum_fix_readbits(oldbname, newbname)
char *oldbname;
char *newbname;
{
  struct namechange ncs;
  ncs.oldname = oldbname;
  ncs.newname = newbname;
  _record_enumerate(PASSFILE, 0, fix_readbit_entry, &ncs);
  return S_OK;
}

#if FULL_USER_DELETE
/* 
   Called from bbs_delete_account and bbs_modify_account;
   loop through all each user's override file and fix it for them.
   Aren't we nice?
*/

extern int fix_override_entry();

_acct_enum_fix_overrides(oldname, newname)
char *oldname;
char *newname;
{
  struct namechange ncs;
  ncs.oldname = oldname;
  ncs.newname = newname;
  _record_enumerate(PASSFILE, 0, fix_override_entry, &ncs);
  return S_OK;
}
#endif
"ERROR local_bbs_add_account: mkdir failed: %s or %s\n",
           homedir, maildir);
    return S_SYSERR;
  }

  if (acct.terminal[0]) 
    set_profile_data(acct.userid, PROFILE_TERM, acct.terminal);
  if (acct.realname[0]) 
    set_profile_data(acct.userid, PROFILE_NAME, acct.realname);
  if (acct.address[0]) 
    set_profile_data(acct.userid, PROFILE_ADDR, acct.address);
  if (acct.email[0]) 
    set_profile_data(acct.userid, PROFILE_MAIL, acct.emailDarkNET-1.08/addacct.c                                                                                 644   21270   21270         6374  5715306775   7631                                                                                                                                                                                                                                                                                                                                                                      
/*
Eagles Bulletin Board System
Copyright (C) 1994, Ray Rocker, rrrocker@rock.b11.ingr.com
                                rock@seabass.st.usm.edu
                                72673.2105@compuserve.com

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "server.h"

extern USERDATA user_params;

extern char *optarg;

usage(prog)
char *prog;
{
  fprintf(stderr, 
	  "Usage: %s -i userid -p passwd [-u username] [-t termtype]\n", prog);
  fprintf(stderr,
	  "       [-e email] [-r realname] [-a address] [-d bbs-dir]\n");
}

main(argc, argv)
int argc;
char *argv[];
{
    char *bbshome = NULL;
    int iflg, pflg, uflg;
    int c;
    ACCOUNT acct;
    int rc;

    memset(&acct, 0, sizeof(acct));
    iflg = pflg = uflg = 0;

    while ((c = getopt(argc, argv, "a:d:e:i:p:r:t:u:?")) != -1)
      {
	switch (c)
	  {
	  case 'a':
	    strncpy(acct.address, optarg, sizeof acct.address-1);
	    break;
	  case 'd':
	    bbshome = optarg;
	    break;
	  case 'e':
	    strncpy(acct.email, optarg, sizeof acct.email-1);
	    break;
	  case 'i':
	    iflg++;
	    strncpy(acct.userid, optarg, sizeof acct.userid-1);
	    break;
	  case 'p':
	    pflg++;
	    strncpy(acct.passwd, optarg, sizeof acct.passwd-1);
	    break;
	  case 'r':
	    strncpy(acct.realname, optarg, sizeof acct.realname-1);
	    break;
	  case 't':
	    strncpy(acct.terminal, optarg, sizeof acct.terminal-1);
	    break;
	  case 'u':
	    uflg++;
	    strncpy(acct.username, optarg, sizeof acct.username-1);
	    break;
	  case '?':
	    usage(argv[0]);
	    return 2;
	  }
      }

    if (!iflg || !pflg) {
        fprintf(stderr, "%s: userid and passwd args must be given\n", argv[0]);
	return 1;
    }

    if (home_bbs(bbshome) == -1) {
        fprintf(stderr, "%s: Cannot chdir to %s\n", argv[0], bbshome);
        return 1;
    }

    if (local_bbs_initialize() != S_OK) {
        fprintf(stderr, "%s: local_bbs_initialize failed\n", argv[0]);
	return 1;
    }

    /* Identify ourself for the log file */
    strcpy(user_params.u.userid, "[addacct]");
    user_params.perms = ~0;

    if (!uflg) strncpy(acct.username, acct.userid, sizeof acct.username-1);

    rc = local_bbs_add_account(&acct, 0);
    switch (rc) {
    case S_INVALID:
      fprintf(stderr, "%s: invalid userid or password\n", acct.userid);
      break;
    case S_EXISTS:
      fprintf(stderr, "%s: userid already exists\n", acct.userid);
      break;
    case S_SYSERR:
      fprintf(stderr, "%s: error creating account\n", acct.userid);
      fprintf(stderr, "Wrong -d argument or $BBSHOME?\n");
    }

    local_bbs_disconnect();

    return (rc == S_OK ? 0 : 1);
}    

/* dummy func. to satisfy the server lib. -- DKIM */
getdata()
{
	return 0;
}
                                                                                                                                                                                                                                                                    DarkNET-1.08/bbfinger.c                                                                                644   21270   21270         3457  6044631251  10005                                                                                                                                                                                                                                                                                                                                                                      #include "server.h"

#define MODEFILE	"etc/modes"
extern char *optarg;
extern int optind;

extern USERDATA user_params;
extern SERVERDATA server;

extern char *ModeToString __P((SHORT));
extern int _init_modes_func ();
extern int _record_enumerate();

usage(prog)
char *prog;
{
  fprintf(stderr, 
	  "Usage: %s [-d bbs-dir]\n", prog);
}

/*ARGSUSED*/
one_line_display(indx, urec, count)
int indx;
USEREC *urec;
int *count;
{
  printf("%-12s    %-25s %-20s %s %s\n", urec->userid, 
	 urec->username, urec->fromhost, 
	 (BITISSET(urec->flags, FLG_KOREAN) ? " Kr  " : " Eng "),
         ModeToString(urec->mode));

  (*count)++;
  return S_OK;
}

main(argc, argv)
int argc;
char *argv[];
{
    char *bbshome = NULL;
    int c, count = 0;

    while ((c = getopt(argc, argv, "d:?")) != -1)
      {
	switch (c)
	  {
	  case 'd':
	    bbshome = optarg;
	    break;
	  case '?':
	    usage(argv[0]);
	    return 2;
	  }
      }

    if (home_bbs(bbshome) == -1) {
        fprintf(stderr, "%s: Cannot chdir to %s\n", argv[0], bbshome);
        return 1;
    }

    if (local_bbs_initialize() != S_OK) {
        fprintf(stderr, "%s: local_bbs_initialize failed\n", argv[0]);
	return 1;
    }
    _record_enumerate(MODEFILE, 0, _init_modes_func, NULL);

    /* Identify ourself for the log file, just in case */
    strcpy(user_params.u.userid, "[bbfinger]");
    /* assume lowest possible priviliges */    
    user_params.perms = 0;

    /* Do it! */
    printf("[%s]\n\n", server.name);
    printf("%-12s    %-25s %-20s %s  %s\n", 
	   "User Id", "User Name", "From", "Lang", "Mode");
    local_bbs_enum_users(50, 0, NULL, one_line_display, &count);
    printf("\n%d %s displayed\n\n", count, count==1?"user":"users");

    local_bbs_disconnect();

    return 0;
}    

/* dummy func. to satisfy server lib. - dkim */
getdata()
{
    return 0;
}
                                                                                                                                                                                                                 DarkNET-1.08/bbslog.c                                                                                  644   21270   21270         2277  5715307052   7501                                                                                                                                                                                                                                                                                                                                                                      #include "server.h"

extern char *optarg;
extern int optind;

usage(prog)
char *prog;
{
  fprintf(stderr, 
	  "Usage: %s [-d bbs-dir] [-h log-header] log-level message\n", prog);
}

main(argc, argv)
int argc;
char *argv[];
{
    char *bbshome = NULL;
    char *logheader = NULL;
    char *msg;
    int c;
    int loglevel, rc;

    while ((c = getopt(argc, argv, "d:h:?")) != -1)
      {
	switch (c)
	  {
	  case 'd':
	    bbshome = optarg;
	    break;
	  case 'h':
	    logheader = optarg;
	    break;
	  case '?':
	    usage(argv[0]);
	    return 2;
	  }
      }

    if (optind+2 > argc) {
        usage(argv[0]);
        return 2;
    }

    if (logheader == NULL) logheader = "BBSLOG";
    loglevel = atoi(argv[optind++]);
    msg = argv[optind];
    
    if (home_bbs(bbshome) == -1) {
        fprintf(stderr, "%s: Cannot chdir to %s\n", argv[0], bbshome);
        return 1;
    }

    if (local_bbs_initialize() != S_OK) {
        fprintf(stderr, "%s: local_bbs_initialize failed\n", argv[0]);
	return 1;
    }

    set_log_header(logheader);
    bbslog(loglevel, "%s\n", msg);    

    local_bbs_disconnect();

    return 0;
}    

/* dummy func. to satisfy server lib - DKIM */
getdata()
{
    return 0;
}
                                                                                                                                                                                                                                                                                                                                 DarkNET-1.08/board.c                                                                                   644   21270   21270        22420  5751534470   7336                                                                                                                                                                                                                                                                                                                                                                      
/*
Eagles Bulletin Board System
Copyright (C) 1994, Ray Rocker, rrrocker@rock.b11.ingr.com
                                rock@seabass.st.usm.edu
                                72673.2105@compuserve.com

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "server.h"
#include <time.h>
#if NEXTSTEP == 1
# include <sys/stat.h>
#endif
 
#define BOARDFILE  "etc/boardlist"
#define BOARDFLUSH ".bflush"

#define MGR_FILE    "managers"

get_managers_file(bname, buf)
char *bname;
char *buf;
{
  get_board_directory(bname, buf);
  strcat(buf, "/");
  strcat(buf, MGR_FILE);
}

local_bbs_set_boardmgrs(bname, list)
char *bname;
NAMELIST list;
{
  BOARD board;
  PATH buf;
  if (_lookup_board(bname, &board) != S_OK) return S_NOTFOUND;
  get_managers_file(board.name, buf);
  return (write_namelist(buf, list));
}

local_bbs_get_boardmgrs(bname, list)
char *bname;
NAMELIST *list;
{
  BOARD board;
  PATH buf;
  if (_lookup_board(bname, &board) != S_OK) return S_NOTFOUND;
  get_managers_file(board.name, buf);
  return (read_namelist(buf, list));
}

_has_read_access(board)
BOARD *board;
{
  if (board->readmask == 0) return 1;
  return (_has_perms(board->readmask));
}

_has_post_access(board)
BOARD *board;
{
  if (!_has_access(C_POST)) return 0;
  if (board->postmask == 0) return 1;
  return (_has_perms(board->postmask));
}

_has_manager_access(board)
BOARD *board;
{
  PATH mgrfile;
  if (_has_access(C_ALLBOARDMGR)) return 1;
  get_managers_file(board->name, mgrfile);
  if (_record_find(mgrfile, _match_full, my_userid(), NULL, NULL) == S_OK) 
    return 1;
  else return 0;
}  

format_boardent(rec, board)
char *rec;
BOARD *board;
{
  rec[0] = '\0';
  rec = _append_quoted(rec, board->name);
  rec = LONGcpy(rec, board->readmask);
  *rec++ = ':';
  rec = LONGcpy(rec, board->postmask);
  *rec++ = ':';
  rec = _append_quoted(rec, board->description);
  rec = _append_quoted(rec, board->kdescription);
  strcat(rec, "\n");
  return S_OK;
}

boardent_to_board(rec, board)
char *rec;
BOARD *board;
{
  rec = _extract_quoted(rec, board->name, sizeof(board->name));
  board->readmask = hex2LONG(rec);
  rec+=9;
  board->postmask = hex2LONG(rec);
  rec+=9;
  rec = _extract_quoted(rec, board->description, sizeof(board->description));
  rec = _extract_quoted(rec, board->kdescription, sizeof(board->kdescription));
  return S_OK;
}

hide_priv_board_fields(board)
BOARD *board;
{
  if (!_has_access(C_SEEALLBINFO)) {
    board->readmask = 0;
    board->postmask = 0;
  }
}  

_lookup_board(bname, board)
char *bname;
BOARD *board;
{
  int rc;
  memset(board, 0, sizeof *board);
  rc = _record_find(BOARDFILE, _match_first, bname, boardent_to_board, board);
  return rc;
}

local_bbs_add_board(newboard)
BOARD *newboard;
{
  int rc;
  BOARD board;
  PATH homedir;
  extern void set_cmap();

  memcpy(&board, newboard, sizeof board);
  if (!is_valid_boardname(board.name)) return S_INVALID;

  rc = _record_add(BOARDFILE,_match_first,board.name,format_boardent,&board);
  if (rc != S_OK) return S_EXISTS; 

  get_board_directory(board.name, homedir);
  recursive_rmdir (homedir);
  if (mkdir(homedir, 0700)) {
    _record_delete(BOARDFILE, _match_first, board.name);
    bbslog(0, "ERROR local_bbs_add_board: mkdir failed: %s\n", homedir);
    return S_SYSERR;
  }
  set_cmap(homedir);
  bbslog(2, "ADDBOARD %s by %s\n", board.name, my_userid());
  touch_flush(BOARDFLUSH);
  return S_OK;
}

local_bbs_delete_board(bname)
char *bname;
{
  int rc;
  BOARD board;
  PATH homedir;

  rc = _lookup_board(bname, &board);
  if (rc != S_OK) return S_NOTFOUND;

  rc = _record_delete(BOARDFILE, _match_first, board.name);
  if (rc != S_OK) return S_SYSERR;

  get_home_directory(board.name, homedir);
  recursive_rmdir(homedir);
  _acct_enum_fix_readbits(board.name, NULL);
  touch_flush(BOARDFLUSH);

  bbslog(2, "DELETEBOARD %s by %s\n", board.name, my_userid());
  return S_OK;
}

local_bbs_get_board(bname, board)
char *bname;
BOARD *board;
{
  int rc;
  BOARD myboard;
  SHORT order;
  rc = _lookup_board(bname, &myboard);
  if (rc != S_OK) return S_NOTFOUND;
  if (!_has_read_access(&myboard)) return S_NOTFOUND;
  get_read_order(myboard.name, &order);
  if (order & READ_ORDER_ZAPPED) myboard.flags |= BOARD_ZAPPED;
  hide_priv_board_fields(&myboard);
  memcpy(board, &myboard, sizeof(*board));
  return S_OK;
}

/*ARGSUSED*/
update_boardent(newrec, oldrec, board)
char *newrec;
char *oldrec;
BOARD *board;
{
  format_boardent(newrec, board);    
  return S_OK;
}

_set_board(bname, newboard, flags)
char *bname;
BOARD *newboard;
SHORT flags;
{
  int rc;
  BOARD board;
  NAME saveid;
    
  rc = _lookup_board(bname, &board);
  if (rc != S_OK) return S_NOTFOUND;

  strcpy(saveid, board.name);

  if (flags & MOD_BNAME) {
    if (!is_valid_boardname(newboard->name)) return S_INVALID;
    rc = _record_find(BOARDFILE, _match_first, newboard->name, NULL, NULL);
    if (rc != S_NOTFOUND) return S_EXISTS;
    strncpy(board.name, newboard->name, NAMELEN);
  }

  if (flags & MOD_READMASK)
    board.readmask = newboard->readmask;

  if (flags & MOD_POSTMASK)
    board.postmask = newboard->postmask;

  if (flags & MOD_BOARDDESC)
      strncpy(board.description, newboard->description, TITLELEN);
  if (flags & MOD_BOARDKDESC)
      strncpy(board.kdescription, newboard->kdescription, TITLELEN);
    
  rc = _record_replace(BOARDFILE,_match_first,saveid,update_boardent,&board);

  if (rc != S_OK) return S_SYSERR;

  if (flags & MOD_BNAME) {
    PATH oldhome, newhome;
    get_board_directory(saveid, oldhome);
    get_board_directory(board.name, newhome);
    recursive_rmdir(newhome);
    rename(oldhome, newhome);
    _acct_enum_fix_readbits(saveid, board.name);
    touch_flush(BOARDFLUSH);
  }

  return S_OK;
}

local_bbs_modify_board(bname, board, flags)
char *bname;
BOARD *board;
SHORT flags;
{
  if (flags & MOD_BNAME)
    bbslog(2, "MODIFYBOARD %s to %s by %s\n", bname, board->name, my_userid());
  else bbslog(2, "MODIFYBOARD %s by %s\n", bname, my_userid());

  return(_set_board(bname, board, flags));
}

_enum_boards(indx, rec, en)
int indx;
char *rec;
struct enumstruct *en;
{
  BOARD board;
  SHORT order;
  int zapped;
  memset(&board, '\0', sizeof board);
  boardent_to_board(rec, &board);
  if (!_has_read_access(&board)) return S_OK;

  get_read_order(board.name, &order);

  if (order == READ_ORDER_ZAPPED) {
    if (!(en->flags & BE_ZAPPED)) return S_OK;
    board.flags |= BOARD_ZAPPED;
  }  
  else if (!(en->flags & BE_UNZAPPED)) return S_OK;

  if (en->flags & BE_DO_COUNTS) {
    READINFO rinfo;
    get_bitfile_ent(board.name, &rinfo);
    _board_count(&board, &rinfo);
  }      
  
  hide_priv_board_fields(&board);
  if (en->fn(indx, &board, en->arg) == ENUM_QUIT) return ENUM_QUIT;
  return S_OK;
}

/*ARGSUSED*/
local_bbs_enum_boards(chunk, startrec, flags, enumfn, arg)
SHORT chunk;
SHORT startrec;
SHORT flags;
int (*enumfn)();
void *arg;
{
  struct enumstruct en;
  en.fn = enumfn;
  en.arg = arg;
  en.flags = flags;
  _record_enumerate(BOARDFILE, startrec, _enum_boards, &en);
  return S_OK;
}

_fill_boardnames(indx, rec, list)
int indx;
char *rec;
NAMELIST *list;
{
  BOARD board;
  boardent_to_board(rec, &board);
  if (_has_read_access(&board)) {
    add_namelist(list, board.name, NULL);
  }
  return S_OK;
}

local_bbs_boardnames(list)
NAMELIST *list;
{
  static time_t lastupdate = 0;
  if (!test_flush(BOARDFLUSH, lastupdate)) {
    return S_NOUPDATE;
  }
  create_namelist(list, MAXBOARD);
  _record_enumerate(BOARDFILE, 0, _fill_boardnames, list);  
  sort_list(list);
  return S_OK;
}

/*ARGSUSED*/
_visit_all_boards(indx, rec, arg)
int indx;
char *rec;
void *arg;
{
  BOARD board;
  boardent_to_board(rec, &board);
  if (_has_read_access(&board))
    _mark_all_as_read(board.name);

  return S_OK;
}

local_bbs_visit_board(bname)
char *bname;
{
  int rc;
  BOARD board;
  if (!strcmp(bname, "*")) {
    _record_enumerate(BOARDFILE, 0, _visit_all_boards, NULL);
  }
  else {
    rc = _lookup_board(bname, &board);
    if (rc != S_OK) return S_NOTFOUND;
    if (!_has_read_access(&board)) return S_NOTFOUND;
    _mark_all_as_read(board.name);
  }
  return S_OK;
}

#if FULL_USER_DELETE
/* 
   For changing the board manager files when a user changes id
   or gets deleted.
*/

/*ARGSUSED*/
_do_fix_manager(indx, rec, ncs)
int indx;
char *rec;
struct namechange *ncs;
{
  BOARD board;
  PATH mgrfile;
  boardent_to_board(rec, &board);
  get_managers_file(board.name, mgrfile);

  if (ncs->newname == NULL)
    _record_delete(mgrfile, _match_full, ncs->oldname);
  else _record_replace(mgrfile, _match_full, ncs->oldname,
                       _change_name, ncs->newname);
  return S_OK;
}

_board_enum_fix_managers(oldname, newname)
char *oldname;
char *newname;
{
  struct namechange ncs;
  ncs.oldname = oldname;
  ncs.newname = newname;
  _record_enumerate(BOARDFILE, 0, _do_fix_manager, &ncs);
  return S_OK;
}
#endif
int rc;
  BOARD board;
  PATH homedir;
  extern void set_cmap();

  memcpy(&board, newboard, sizeof board);
  if (!is_valid_boardname(board.name)) return S_INVALID;

  rc = _record_add(BOARDFILE,_match_first,board.name,format_boardent,&boarDarkNET-1.08/c_boards.c                                                                                644   21270   21270        37267  5751526407  10043                                                                                                                                                                                                                                                                                                                                                                      
/*
Eagles Bulletin Board System
Copyright (C) 1994, Ray Rocker, rrrocker@rock.b11.ingr.com
                                rock@seabass.st.usm.edu
                                72673.2105@compuserve.com

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "client.h"
#include <time.h>
#include <ctype.h>

/* The currently selected board */
NAME currboard;

/* stuff in c_users.c for the permission mask setting */
extern LONG SetPermMenu __P((LONG));

CheckBoardName(bname)
char *bname;
{
  BOARD buf;
  if (bname[0] == '\0') return 1;
  if (!is_valid_boardname(bname)) return 3;
  if (bbs_get_board(bname, &buf) != S_NOTFOUND) return 2; 
  return 0;
}

/*ARGSUSED*/
AllBoardsFunc(indx, board, info)
int indx;
BOARD *board;
struct enum_info *info;
{
  extern int lang;

  if (info->topline == info->currline) {
    move(info->topline-1, 0);
    standout();
    if (lang)
      prints(" %-16s   %-58s\n", "º¸µåÀÌ¸§", "º¸µå¼³¸í");
    else
      prints(" %-16s   %-58s\n", "Name", "Description");
    standend();
  }

  if (lang && *board->kdescription)
    prints("%c%-15s %c%c %s\n", 
	 BITISSET(board->flags, BOARD_ZAPPED) ? '*' : ' ',
	 board->name, 
	 board->readmask ? 'R' : ' ',
	 board->postmask ? 'P' : ' ',
	 board->kdescription);
  else
    prints("%c%-15s %c%c %s\n", 
	 BITISSET(board->flags, BOARD_ZAPPED) ? '*' : ' ',
	 board->name, 
	 board->readmask ? 'R' : ' ',
	 board->postmask ? 'P' : ' ',
	 board->description);

  info->currline++;
  info->count++;

  if (info->currline > info->bottomline) {
    int ch;
    standout();
    c_msg(INFO_MORE, FALSE);
    standend();
    clrtoeol();
    while((ch = igetch()) != EOF) {
      if(ch == '\n' || ch == '\r' || ch == ' ')
	break;
      if(toupper(ch) == 'Q') {
	move(info->currline, 0);
	clrtoeol();
	return ENUM_QUIT;
      }
      else bell();
    }
    info->currline = info->topline;
  }
  return S_OK;
}

Boards()
{
  struct enum_info info;
  extern int lang;

  info.count = 0;
  info.topline = info.currline = 4;
  info.bottomline = t_lines-2;
  move(2,0);
  clrtobot();    
  bbs_enum_boards(t_lines-5, 0, BE_ALL, AllBoardsFunc, &info);
  clrtobot();
  move(t_lines-1, 0);
  if (lang)
    prints("%d %s ÀÖ½À´Ï´Ù\n", info.count, info.count==1?"º¸µå°¡":"º¸µåµé");
  else
    prints("%d %s displayed\n", info.count, info.count==1?"board":"boards");
  return PARTUPDATE;
}

/*ARGSUSED*/
BoardCountsFunc(indx, board, info)
int indx;
BOARD *board;
struct enum_info *info;
{
  extern int lang;
  extern char *Ctime __P((time_t *));

  if (info->topline == info->currline) {
    move(info->topline-1, 0);
    if (lang)
      prints(" %-16s   %6s %6s   %-30s\n",
	"º¸µå", "ÇÕ°è", "¾ÊÀÐÀº±Û", "¸¶Áö¸· Æ÷½ºÆÃ");
    else
      prints(" %-16s   %6s %6s   %-30s\n",
	"Board", "Total", "Unread", "Last Post");
  }

  prints("%c%-16s   %6d %6d   %s\n", 
	 BITISSET(board->flags, BOARD_ZAPPED) ? '*' : ' ',
	 board->name, 
	 board->totalposts,
       	 board->newposts,
	 (board->lastpost == 0 ? "" : Ctime((time_t *)&board->lastpost)));

  info->currline++;
  info->count++;
  info->totals[0] += board->totalposts;
  info->totals[1] += board->newposts;

  if (info->currline > info->bottomline) {
    int ch;
    standout();
    c_msg(INFO_MORE, FALSE);
    standend();
    clrtoeol();
    while((ch = igetch()) != EOF) {
      if(ch == '\n' || ch == '\r' || ch == ' ')
	break;
      if(toupper(ch) == 'Q') {
	move(info->currline, 0);
	clrtoeol();
	return ENUM_QUIT;
      }
      else bell();
    }
    info->currline = info->topline;
  }
  return S_OK;
}

BoardCounts()
{
  struct enum_info info;
  SHORT flags;
  char ans[9];
  extern int lang;

  info.count = 0;
  info.topline = info.currline = 4;
  info.bottomline = t_lines-2;
  info.totals[0] = info.totals[1] = 0;
    
  move(2,0);
  clrtobot();
  if (lang) {
    if (getdata(3, 0, "(U)-Á¦¿Ü½ÃÅ°Áö ¾ÊÀº °Í¸¸, (Z)-Á¦¿Ü½ÃÅ² °Í¸¸, or (A)-¸ðÁ¶¸®? [U]: ",
          ans, sizeof ans, DOECHO, 1) == -1) return FULLUPDATE;
  } else {
    if (getdata(3, 0, "(U)nzapped only, (Z)apped only, or (A)ll? [U]: ",
          ans, sizeof ans, DOECHO, 1) == -1) return FULLUPDATE;
  }

  if (*ans == 'Z' || *ans == 'z') flags = BE_ZAPPED;
  else if (*ans == 'A' || *ans == 'a') flags = BE_ALL;
  else flags = BE_UNZAPPED;

  flags |= BE_DO_COUNTS;
  bbs_enum_boards(t_lines-5, 0, flags, BoardCountsFunc, &info);
  
  clrtobot();
  move(info.currline, 0);

  if (lang)
    prints(" %-16s   %6d %6d\n", "*** ÇÕ°è ***", 
         info.totals[0], info.totals[1]);
  else
    prints(" %-16s   %6d %6d\n", "*** TOTALS ***", 
         info.totals[0], info.totals[1]);

  return PARTUPDATE;
}

SelectBoard()
{
  NAME newboard;
  NAMELIST boardlist = NULL;
  extern int lang;

  move(2,0);
  clrtobot();
  move(3,0);
  bbs_boardnames(&boardlist);
  if (boardlist->size == 0) {
    c_msg(ERR_NOTHING, TRUE);
    free_namelist(&boardlist);
    pressreturn();
    return FULLUPDATE;
  }
  if (lang)
    namecomplete(boardlist, "º¸µåÀÌ¸§?: ", newboard);
  else
    namecomplete(boardlist, "Enter a board name: ", newboard);
  if (newboard[0] == '\0') return FULLUPDATE;
  else if (!is_in_namelist(boardlist, newboard)) {
    move(4,0);
    c_msg(ERR_NOT_EXIST, TRUE);
    free_namelist(&boardlist);
    pressreturn();
    return FULLUPDATE;
  }
  strcpy(currboard, newboard);
  free_namelist(&boardlist);
  return (FULLUPDATE | NEWDIRECT);
}

Zap()
{
  NAME zapboard;
  BOARD brec;
  SHORT notzapped;
  NAMELIST boardlist = NULL;
  extern int lang;

  move(2,0);
  clrtobot();
  bbs_boardnames(&boardlist);
  if (boardlist->size == 0) {
    c_msg(ERR_NOTHING, TRUE);
    free_namelist(&boardlist);
    pressreturn();
    return FULLUPDATE;
  }
  if (lang)
    namecomplete(boardlist, "Á¦¿ÜÇÒ º¸µå: ", zapboard);
  else
    namecomplete(boardlist, "Board to zap/unzap: ", zapboard);
  if (zapboard[0] == '\0') return PARTUPDATE;
  if (!is_in_namelist(boardlist, zapboard) || 
      bbs_get_board(zapboard, &brec) != S_OK) {
    move(4,0);
    c_msg(ERR_NOT_EXIST, TRUE);
    free_namelist(&boardlist);
    pressreturn();
    return FULLUPDATE;
  }
  notzapped = !BITISSET(brec.flags, BOARD_ZAPPED);
  if (bbs_zap_board(brec.name, notzapped) == S_ILLEGAL) {
    move(3,0);
    c_msg(ERR_FAILURE, TRUE);
  }
  free_namelist(&boardlist);
  return PARTUPDATE;
}

Visit()
{
  NAME visitboard;
  char ans[4];
  NAMELIST boardlist = NULL;
  extern int lang;

  move(2,0);
  clrtobot();
  bbs_boardnames(&boardlist);
  if (boardlist->size == 0) {
    c_msg(ERR_NOTHING, TRUE);
    free_namelist(&boardlist);
    pressreturn();
    return FULLUPDATE;
  }
  add_namelist(&boardlist, "*", NULL);
  sort_list(&boardlist);

  if (lang)
    namecomplete(boardlist, "¾î´À º¸µå¸¦ (*=zap ¾ÈÇÑ º¸µå ¸ù¶¥): ", visitboard);
  else
    namecomplete(boardlist, "Visit board (* = all unzapped boards): ", visitboard);
  remove_namelist(&boardlist, "*");
  sort_list(&boardlist);
  if (visitboard[0] == '\0') return FULLUPDATE;
  else if (visitboard[0] != '*' && !is_in_namelist(boardlist, visitboard)) {
    move(4,0);
    c_msg(ERR_NOT_EXIST, TRUE);
    free_namelist(&boardlist);
    pressreturn();
    return FULLUPDATE;
  }
  if (lang)
    getdata(3,0,"Á¤¸» (Y/N)? [N]: ", ans, sizeof(ans), DOECHO, 0);
  else
    getdata(3,0,"Are you sure (Y/N)? [N]: ", ans, sizeof(ans), DOECHO, 0);
  move(4,0);
  if (*ans != 'Y' && *ans != 'y') {
    c_msg(INFO_CANCELLED, TRUE);
    free_namelist(&boardlist);
    pressreturn();
    return FULLUPDATE;
  }

  /* this can take a while, so...*/
  c_msg(INFO_IN_PROGRESS, TRUE);
  refresh();
  if (bbs_visit_board(visitboard) == S_OK) {
    c_msg(INFO_DONE, TRUE);
  } else {
    c_msg(ERR_FAILURE, TRUE);
  }
  free_namelist(&boardlist);
  pressreturn();
  return FULLUPDATE;
}

SetBoardPerms(brec, postp)
BOARD *brec;
int postp;
{
  LONG newperms;
  extern int lang;

  move(2,0);
  clrtobot();
  if (lang)
    prints("%s º¸µåÀÇ ±Û %s Æì¹Ì¼Ç Á¤ÇÏ±â\n",
	 brec->name, (postp ? "¾²±â":"ÀÐ±â"));
  else
    prints("Set the %s permissions for board '%s'\n", 
	 (postp ? "post" : "read"), brec->name);
  newperms = SetPermMenu(postp ? brec->postmask : brec->readmask);	
  clear();
  if (newperms != (postp ? brec->postmask : brec->readmask)) {
    if (postp) brec->postmask = newperms;
    else brec->readmask = newperms;
    return 0;
  }
  else return -1;
}

AddBoard()
{
  BOARD board;
  int y, grok;
  int rc;
  char ans[4];
  extern int lang;

  move(2,0);
  clrtobot();
  memset(&board, 0, sizeof(BOARD));
  do {
    if (lang)
      {
        if (getdata(3,0,"»õº¸µå ÀÌ¸§: ",board.name,NAMELEN+1,DOECHO,1)==-1)
          return FULLUPDATE;
      }
    else
      {
        if (getdata(3,0,"New board name: ",board.name,NAMELEN+1,DOECHO,1)==-1)
          return FULLUPDATE;
      }

    grok = CheckBoardName(board.name);
    switch (grok) {
    case 0:
	break;
    case 1:
	c_msg(ERR_NO_NAME, TRUE);
	break;
    case 2:
	c_msg(ERR_EXIST, TRUE);
	break;
    case 3:
	c_msg(ERR_INVALID_NAME, TRUE);
	break;
    default:
	c_msg(ERR_UNKNOWN, TRUE);
	break;
    }
  } while (grok);

  if (lang)
    {
      getdata(4,0,"º¸µå¼³¸í (¿µ¾î): ", board.description, TITLELEN+1, DOECHO, 0);
      getdata(5,0,"º¸µå¼³¸í (ÇÑ±Û): ", board.kdescription, TITLELEN+1, DOECHO, 0);
      getdata(6,0,"ÀÐ±â Á¦ÇÑ (Y/N)? [N]: ",ans,sizeof(ans),DOECHO,0);
    }
  else
    {
      getdata(4,0,"Board description (English): ", board.description, TITLELEN+1, DOECHO, 0);
      getdata(5,0,"Board description (Korean): ", board.kdescription, TITLELEN+1, DOECHO, 0);
      getdata(6,0,"Set read restrictions (Y/N)? [N]: ",ans,sizeof(ans),DOECHO,0);
    }
  if (*ans == 'Y' || *ans == 'y') {
    SetBoardPerms(&board, 0);
    y = 0;
  }
  else y = 7;
  if (lang)
    getdata(y,0,"±Û¾²±â Á¦ÇÑ (Y/N)? [N]: ",ans,sizeof(ans),DOECHO,0);
  else
    getdata(y,0,"Set post restrictions (Y/N)? [N]: ",ans,sizeof(ans),DOECHO,0);
  if (*ans == 'Y' || *ans == 'y') {
    SetBoardPerms(&board, 1);
    y = 0;
  }
  else y = 8;
  if (lang)
    getdata(y,0,"º¸µå Á¤¸»·Î ´õÇÒ±î¿ä (Y/N)? [N]: ",ans,sizeof(ans), DOECHO, 0);
  else
    getdata(y,0,"Add board: are you sure (Y/N)? [N]: ",ans,sizeof(ans), DOECHO, 0);
  if (*ans != 'Y' && *ans != 'y') {
    c_msg(INFO_CANCELLED, TRUE);
  } else {
    if ((rc = bbs_add_board(&board)) == S_OK)
	c_msg(INFO_ADDED, TRUE);
    else 
	c_msg(ERR_FAILURE, TRUE);
  }
  pressreturn();
  return FULLUPDATE;
}

DeleteBoard()
{
  NAME namebuf;
  char ans[4];
  NAMELIST boardlist = NULL;
  extern int lang;

  move(2,0);
  clrtobot();
  bbs_boardnames(&boardlist);
  if (boardlist->size  == 0) {
    c_msg(ERR_NOTHING, TRUE);
    free_namelist(&boardlist);
    pressreturn();
    return FULLUPDATE;
  }
  namecomplete(boardlist, "Delete which board: ", namebuf);        
  if (namebuf[0] == '\0') return FULLUPDATE;
  else if (!is_in_namelist(boardlist, namebuf)) {
    c_msg(ERR_NOT_EXIST, TRUE);
    free_namelist(&boardlist);
    pressreturn();
    return FULLUPDATE;
  }
  c_msg(INFO_DELETING, TRUE);
  if (lang) {
    getdata(5,0,"Áö¿ï±î¿ä (Y/N)? [N]: ",ans,sizeof(ans), DOECHO, 0);    
  } else {
    getdata(5,0,"Are you sure (Y/N)? [N]: ",ans,sizeof(ans), DOECHO, 0);    
  }
  if (ans[0] != 'Y' && ans[0] != 'y') {
    c_msg(INFO_CANCELLED, TRUE);
    free_namelist(&boardlist);
    pressreturn();
    return FULLUPDATE;
  }
  if (bbs_delete_board(namebuf) == S_OK) {
    c_msg(INFO_DELETED, TRUE);
  } else {
    c_msg(ERR_FAILURE, TRUE);
  }
  free_namelist(&boardlist);
  pressreturn();
  return FULLUPDATE;
}

ChangeBoard()
{
  NAME namebuf, oldname;
  BOARD brec;
  int y, grok;
  SHORT flags = 0;
  char ans[4];
  NAMELIST boardlist = NULL;
  extern int lang;

  move(2,0);
  clrtobot();
  bbs_boardnames(&boardlist);
  if (boardlist->size == 0) {
    c_msg(ERR_NOTHING, TRUE);
    free_namelist(&boardlist);
    pressreturn();
    return FULLUPDATE;
  }
  namecomplete(boardlist, "Change which board: ", namebuf);
  if (namebuf[0] == '\0') return FULLUPDATE;
  else if (!is_in_namelist(boardlist, namebuf)) {
    c_msg(ERR_NOT_EXIST, TRUE);
    free_namelist(&boardlist);
    pressreturn();
    return FULLUPDATE;
  }
  if (bbs_get_board(namebuf, &brec) != S_OK) {
    c_msg(ERR_FAILURE, TRUE);
    free_namelist(&boardlist);
    pressreturn();
    return FULLUPDATE;
  }
  strncpy(oldname, brec.name, NAMELEN);
  move(3,0);
  clrtobot();
  move(4,0);
  if (lang)
    {
      prints("º¸µå ÀÌ¸§: %s\n", brec.name);
      prints("º¸µå ¼³¸í (¿µ¾î): %s\n", brec.description);
      prints("º¸µå ¼³¸í (ÇÑ±Û): %s\n", brec.kdescription);
      prints("º¸µå °ü¸®ÀÚ¸¦ ¹Ù²ãÁÖ·Á¸é (M)-¸Å´ÏÁ® ¸¦ »ç¿ëÇÏ¼¼¿ä.\n");
      if (brec.readmask) prints("ÀÐ±â Á¦ÇÑÀÌ ÀÖ½À´Ï´Ù.\n");
      if (brec.postmask) prints("¾²±â Á¦ÇÑÀÌ ÀÖ½À´Ï´Ù.\n");
    }
  else
    {
      prints("Board name: %s\n", brec.name);
      prints("Board description (English): %s\n", brec.description);
      prints("Board description (Korean): %s\n", brec.kdescription);
      prints("Use (M)anagers to view and set board managers.\n");
      if (brec.readmask) prints("Read restrictions are in effect.\n");
      if (brec.postmask) prints("Post restrictions are in effect.\n");
    }
  do {
    if (lang)
      {
        getdata(10,0,"»õº¸µå ÀÌ¸§ (¸®ÅÏ Ä¡¸é º¯µ¿¾ø½À´Ï´Ù): ", 
	    namebuf, NAMELEN+1, DOECHO, 0);
      }
    else
      {
        getdata(10,0,"New board name (ENTER to leave unchanged): ", 
	    namebuf, NAMELEN+1, DOECHO, 0);
      }
    grok = CheckBoardName(namebuf);
    switch (grok) {
    case 0: BITSET(flags, MOD_BNAME);
      strncpy(brec.name, namebuf, sizeof(brec.name));
      break;
    case 1: grok = 0;
      break;
    case 2:
      c_msg(ERR_EXIST, TRUE);
      break;
    case 3:
      c_msg(ERR_INVALID_NAME, TRUE);
      break;
    default:
      c_msg(ERR_UNKNOWN, TRUE);
      break;
    }
  } while (grok);

  if (lang)
    getdata(11,0,"»õ º¸µå ¼³¸í (¿µ¾î): ", brec.description, TITLELEN, DOECHO, 0);
  else
    getdata(11,0,"New description (English) if any: ", brec.description, TITLELEN, DOECHO, 0);

  if (brec.description[0] != '\0') BITSET(flags, MOD_BOARDDESC);

  if (lang)
    getdata(12,0,"»õ º¸µå ¼³¸í (ÇÑ±Û): ", brec.kdescription, TITLELEN, DOECHO, 0);
  else
    getdata(12,0,"New description (Korean) if any: ", brec.kdescription, TITLELEN, DOECHO, 0);

  if (brec.kdescription[0] != '\0') BITSET(flags, MOD_BOARDKDESC);

  if (lang)
    getdata(13,0,"ÀÐ±â Á¦ÇÑÀ» ¹Ù²Ü±î¿ä (Y/N)? [N]: ", ans,sizeof(ans),DOECHO,0);
  else
    getdata(13,0,"Alter read restrictions (Y/N)? [N]: ", ans,sizeof(ans),DOECHO,0);
  if (*ans == 'Y' || *ans == 'y')
    {
      if (SetBoardPerms(&brec, 0) != -1)
        BITSET(flags, MOD_READMASK);
      y = 0;
    }
   else
    {
      y = 14;
    }

  if (lang)
    getdata(y,0,"¾²±â Á¦ÇÑÀ» ¹Ù²Ü±î¿ä (Y/N)? [N]: ", ans,sizeof(ans),DOECHO,0);
  else
    getdata(y,0,"Alter post restrictions (Y/N)? [N]: ", ans,sizeof(ans),DOECHO,0);
  if (*ans == 'Y' || *ans == 'y')
    {
      if (SetBoardPerms(&brec, 1) != -1)
        BITSET(flags, MOD_POSTMASK);
      y = 0;
    }
  else
    {
      y = 16;
    }

  if (lang)
    getdata(y,0,"Á¤¸» º¸µå¸¦ ¹Ù²Ü±î¿ä (Y/N)? [N]: ",ans,sizeof(ans), DOECHO,0);
  else
    getdata(y,0,"Change board: are you sure (Y/N)? [N]: ",ans,sizeof(ans), DOECHO,0);

  if (*ans != 'Y' && *ans != 'y')
    {
      c_msg(INFO_CANCELLED, TRUE);
    }
  else
    {
      if (bbs_modify_board(oldname, &brec, flags) == S_OK)
	c_msg(INFO_CHANGED, TRUE);
      else
	c_msg(ERR_FAILURE, TRUE);
    }
  free_namelist(&boardlist);
  pressreturn();
  return FULLUPDATE;
}
DOECHO, 0);
  move(4,0);
  if (*ans != 'Y' && *ans != 'y') {
    c_msg(INFO_CANCELLED, TRUE);
    free_namelist(&boardlist);
    pressreturn();
    return FULLUPDATE;
  }

  /* this can take a while, so...*/
  c_msg(INFO_IN_PROGRESS, TRUE);
  refresh();
  if (bbs_visit_board(visitboard) == S_OK) {
    c_msg(INFO_DONE, TRUE);
  DarkNET-1.08/c_chat.c                                                                                  644   21270   21270        42105  5743775131   7474                                                                                                                                                                                                                                                                                                                                                                      
/*
Eagles Bulletin Board System
Copyright (C) 1994, Ray Rocker, rrrocker@rock.b11.ingr.com
                                rock@seabass.st.usm.edu
                                72673.2105@compuserve.com

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "client.h"
#include <ctype.h>
#include <varargs.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>

#define CHAT_PROMPT  "-->"
#define CHAT_HELP_FILE "etc/chathlp.txt"
#define CHAT_KHELP_FILE "etc/kchathlp.txt"
#define CHAT_XTRA_HELP_FILE "etc/chatxhlp.txt"
#define CHAT_XTRA_KHELP_FILE "etc/kchatxhlp.txt"

extern BBSINFO serverinfo;
extern char *Ctime __P((time_t *));      /* for query */

int g_currline;
int g_echatwin;

print_chatid(chatid)
char *chatid;
{
  char buf[CHATID_MAX+2];
  int i;
  memset(buf, 0, sizeof buf);
  strncpy(buf, chatid, CHATID_MAX);
  i = strlen(buf);
  buf[i] = ':';
  for (i++; i<=CHATID_MAX; i++) buf[i] = ' ';
  buf[CHATID_MAX+1] = '\0';
  move(g_echatwin+1, 0);
  prints("%s", buf);
  return 0;
}

printchatline(str)
char *str;
{
  int linelen = t_columns-1, len = strlen(str);
  static int you_have_mail = 0;
  extern int lang;

  if (!you_have_mail && bbs_check_mail()) {
    int i, len;
    move(g_echatwin, 0);
    prints("---");
    move(g_echatwin, 3);
    len = c_msg(INFO_MAIL, FALSE);
    move(g_echatwin, len+3);
    for (i=len+4; i<linelen; i++) prints("-");
    you_have_mail++;
  }  
  while (len) {
    move(g_currline, 0);
    clrtoeol();
    if (linelen < t_columns-1) move(g_currline, CHATID_MAX+2);
    if (len >= linelen) {
      int eoln;
      char c;
      for (eoln = linelen-1; eoln >= t_columns/4; eoln--)
	if (myisspace(str[eoln])) break;
      if (!myisspace(str[eoln])) eoln = linelen-1;
      c = str[eoln];
      str[eoln] = '\0';
      prints("%s", str);
      str[eoln] = c;
      if (myisspace(c)) eoln++;
      len -= eoln;
      str += eoln;
      if (linelen == t_columns-1) linelen -= (CHATID_MAX+2);
    }
    else {
      prints("%s", str);
      len = 0;
    }
    if (++g_currline == g_echatwin) g_currline = 0;
    move(g_currline, 0);
    standout();
    prints(CHAT_PROMPT);
    standend();
    clrtoeol();
  }
}

chat_help(helpfile)
char *helpfile;
{
  FILE *fp;
  char buf[84];
  fp = fopen(helpfile, "r");
  if (fp == NULL) {
    printchatline("*** Cannot open help file\n");
  }
  else {
    strcpy(buf, "*** ");
    while (fgets(buf+4, sizeof(buf)-4, fp)) 
      if (buf[4] != '#') printchatline(buf);
    fclose(fp);
  }
  return 0;
}

chat_resetscreen(chatid)
char *chatid;
{
  int i;
  char buf[256];
  int lang;

  clear();
  g_currline = 0;
  g_echatwin = t_lines - 2;
  move(g_echatwin, 0);
  for (i=0; i<t_columns-1; i++) prints("-");
  if (lang)
    sprintf(buf, "%s ³îÀÚ¹æ -- µµ¿ò¸»À» º¸½Ã·Á¸é '/µµ'", serverinfo.boardname);
  else
    sprintf(buf, "%s Chat System -- type /h for Help", serverinfo.boardname);
  printchatline(buf);
  print_chatid(chatid);
  return 0;
}

struct _chatlist {
  int start;
  int stop;
  int col;
  int verbose;
  char buf[256];
};

chat_list_users_func(indx, urec, cl)
int indx;
USEREC *urec;
struct _chatlist *cl;
{
  indx++;    /* Start counting at one, not zero. */
  if (indx < cl->start) return S_OK;
  else if (cl->stop && (indx > cl->stop)) return ENUM_QUIT;
  if (cl->verbose) {
    sprintf(cl->buf, "*** %-14s %-25s %c%-8s %s", 
  	    urec->userid, urec->username,
	    BITISSET(urec->flags, FLG_CLOAK) ? '#' : ' ',
	    ModeToString(urec->mode), urec->fromhost);
    printchatline(cl->buf);
  }
  else {
    if (cl->col == 0) {
      strcpy(cl->buf, "*** ");
      cl->col = 4;
    }     
    sprintf(cl->buf+cl->col, "[%c]%s%-13s ", ModeToChar(urec->mode), 
            BITISSET(urec->flags, FLG_CLOAK) ? " #" : " ", urec->userid);
    if ((cl->col += 18) > 70) {
      printchatline(cl->buf);
      cl->col = 0;
    }          
  }
  return S_OK;
}

chat_list_users(cbuf, verbose)
char *cbuf;
int verbose;
{
  struct _chatlist cl;
  extern char global_modechar_key[];
  extern int lang;
  if (!HasPerm(C_USERS)) {
    if (lang)
      printchatline("*** ÀÓ¸¶ ³Í ÀÌ°Å Çã¶ôµµ ¾øÀÌ..´©°¡ ÇÏ¶ó ±×·¨¾î!");
    else
      printchatline("*** You do not have permission to list users");
    return 0;
  }
  while (*cbuf && !myisspace(*cbuf)) cbuf++;
  while (*cbuf && myisspace(*cbuf)) cbuf++;
  cl.start = atoi(cbuf);
  while (*cbuf && myisdigit(*cbuf)) cbuf++;
  while (*cbuf && !myisdigit(*cbuf)) cbuf++;
  cl.stop = atoi(cbuf);
  cl.col = 0;
  cl.verbose = verbose;
  printchatline("***");
  if (verbose) {
    sprintf(cl.buf, "*** %-14s %-25s  %-8s %s", "Userid", "Username", 
            "Mode", "From");
    printchatline(cl.buf);
    sprintf(cl.buf, "*** %-14s %-25s  %-8s %s", "------", "--------",
  	    "----", "----");
    printchatline(cl.buf);
  }
  else {
    if (global_modechar_key[0] == '\0') form_modechar_key();
    sprintf(cl.buf, "*** %s", global_modechar_key);
    printchatline(cl.buf);
    printchatline("*** ------------------------------------------------------------------------");
  }
  bbs_enum_users(t_lines-5, 0, NULL, chat_list_users_func, &cl);
  if (!verbose && cl.col > 0) printchatline(cl.buf);
  return 0;
}

extern int _query_if_logged_in __P((int, USEREC *, int *));

chat_query_user(cbuf)
char *cbuf;
{
  ACCOUNT acct;
  char buf[256];
  int in_now = 0;
  extern int lang;

  while (*cbuf && !myisspace(*cbuf)) cbuf++;
  while (*cbuf && myisspace(*cbuf)) cbuf++;
  strip_trailing_space(cbuf);
  if (!HasPerm(C_QUERY)) {
    if (lang)
      printchatline("*** ÀÓ¸¶ ³Í ÀÌ°Å Çã¶ôµµ ¾øÀÌ..´©°¡ ÇÏ¶ó ±×·¨¾î!");
    else
      printchatline("*** You do not have permission to query");
    return 0;
  }
  if (*cbuf == '\0') {
    if (lang)
      printchatline("*** ¶î¶îÇÏ±ä..´©±¸ µÞÁ¶»ç ÇÏ¶õ ¸»¾ß!");
    else
      printchatline("*** You must specify a userid to query");
    return 0;
  }
  if (bbs_query(cbuf, &acct) != S_OK) {
    if (lang)
      sprintf(buf, "*** ¸ÛÃ»ÇÏ°Ô .. '%s' - ÀÌ·±»ç¶÷ ¾ø´Ü´Ù!", cbuf);
    else
      sprintf(buf, "*** Userid '%s' not found", cbuf);
    printchatline(buf);
    return 0;
  }     
  bbs_enum_users(20, 0, acct.userid, _query_if_logged_in, &in_now);
  printchatline("***");
  sprintf(buf, "*** %s (%s):", acct.userid, acct.username);
  printchatline(buf);
  if (acct.lastlogin == 0)
    strcpy(buf, "*** Never logged in.");
  else sprintf(buf, "*** %s from %s %s %s", 
               in_now ? "Logged in" : "Last login", 
               acct.fromhost, in_now ? "since" : "at", 
               Ctime((time_t *)&acct.lastlogin));
  printchatline(buf);
  if (acct.realname[0] != '\0') {
    sprintf(buf, "*** Real name: %s", acct.realname);
    printchatline(buf);
  }
  return 0;
}

chat_show_page_request()
{
  USEREC urec;
  char buf[256];
  extern int lang;

  if (bbs_get_talk_request(&urec, NULL, NULL) != S_OK) {
    /* Whoever was paging stopped. */
    return 0;
  }
  if (lang)
    sprintf(buf, "*** %s (%s) ÀÌ ÅäÅ©ÇÏÁ¦¿ä!", urec.userid, urec.username);
  else
    sprintf(buf, "*** Being paged by %s (%s)", urec.userid, urec.username);
  printchatline(buf);
  return 0;
}

chat_process_incoming(fd, chatid)
int fd;
char *chatid;
{
  static char buf[CHATLINE_MAX*2+1];
  static int bufstart = 0;
  int c, len;
  char *bptr;

  len = sizeof(buf) - bufstart - 1;
  if ((c = recv(fd, buf+bufstart, len, 0)) <= 0) return -1;
  c += bufstart;

  bptr = buf;
  while (c > 0) {
    len = strlen(bptr)+1;
    if (len > c && len < (sizeof buf / 2)) break;
    if (!strncmp(bptr, CHAT_CTRL_CHATID, 3)) {
      memset(chatid, 0, CHATID_MAX+1);
      strncpy(chatid, bptr+4, CHATID_MAX);
      print_chatid(chatid);
    }
    else printchatline(bptr);
    c -= len;
    bptr += len;
  }        

  if (c > 0) {
    char temp[CHATLINE_MAX*2+1];
    strcpy(temp, bptr);
    strcpy(buf, temp);
    bufstart = len-1;
  }            
  else bufstart = 0;
  return 0;  
}

chat_exit(buf)
char *buf;
{
  /* Send the line, then return 1 so we exit. */
  bbs_chat_send(buf);
  return 1;
}

chat_cmd_match(buf, str)
char *buf;
char *str;
{
  int c;

  if (*buf != '/') return 0;
  for (buf++; *str && *buf && !myisspace(*buf); buf++, str++) {
	c = (*buf >= 'A' && *buf <= 'Z')? (tolower(*buf)):(*buf);
	if (c != *str) return 0;
  }      
  return 1;
}

chat_process_local(cbuf, chatid)
char *cbuf;
char *chatid;
{
  extern int lang;
  /* 
     See if the typed line should be handled locally. If not, return -1.
     If so, return 1 if we should exit, 0 if we keep going.
  */
  if (!strncmp(cbuf, "Goodbye!", 8)) {
    chat_exit("/e\n");
    return 1;
  }

  if (chat_cmd_match(cbuf, "clear") || chat_cmd_match(cbuf, "Áö¿ì±â")) 
    return (chat_resetscreen(chatid));
  else if (chat_cmd_match(cbuf, "exit") || chat_cmd_match(cbuf, "³¡"))
    return (chat_exit(cbuf));
  else if (chat_cmd_match(cbuf, "help") || chat_cmd_match(cbuf, "µµ¿ÍÁà") ||
	chat_cmd_match(cbuf, "µµ¿ò")) {
    if (lang)
      return (chat_help(CHAT_KHELP_FILE));
    else
      return (chat_help(CHAT_HELP_FILE));
  } else if (chat_cmd_match(cbuf, "long")||chat_cmd_match(cbuf, "±ä°Å"))
    return (chat_list_users(cbuf, 1));
  else if (chat_cmd_match(cbuf, "query")||chat_cmd_match(cbuf, "Á¶»ç"))
    return (chat_query_user(cbuf));
  else if (chat_cmd_match(cbuf, "users")||chat_cmd_match(cbuf, "°£´Ü"))
    return (chat_list_users(cbuf, 0));
  else if (chat_cmd_match(cbuf, "xhelp")||chat_cmd_match(cbuf, "´õµµ¿ÍÁà")||
	chat_cmd_match(cbuf, "´õÀÚ¼¼È÷")) {
    if (lang)
      return (chat_help(CHAT_XTRA_KHELP_FILE));
    else
      return (chat_help(CHAT_XTRA_HELP_FILE));
  }

  return -1;
}

Chat()
{
  CHATID chatid;
  char cbuf[CHATLINE_TEXT_MAX+1];
  int cfd;
  int rc;
  int done_chatting = 0;
  int margin, curspos, maxpos, endpos;
  int ch, i;
  int metakey = 0;
  int shift, shiftdelta;
  extern int lang;
  static int hbufout[2];

  move(2, 0);
  clrtobot();

  do {  
    if (lang) {
      if (getdata(2,0,"»ç¿ëÇÒ º°¸í: ",chatid,sizeof chatid,DOECHO,1)==-1)
        return FULLUPDATE;
    } else {
      if (getdata(2,0,"Enter chatid: ",chatid,sizeof chatid,DOECHO,1)==-1)
        return FULLUPDATE;
    }

    if (*chatid == '\0') {
      strncpy(chatid, myinfo.userid, CHATID_MAX);
      chatid[CHATID_MAX] = '\0';
    }
    rc = bbs_chat(chatid, (LONG *)&cfd);
    switch (rc) {
    case S_OK:
      break;
    case S_SYSERR:
      c_msg(ERR_CONNECT, TRUE);
      return PARTUPDATE;
    case S_INVALID:
      c_msg(ERR_INVALID_NAME, TRUE);
      break;
    case S_EXISTS:
      c_msg(ERR_EXIST, TRUE);
      break;
    default:
      c_msg(ERR_UNKNOWN, TRUE);
      break;
    }
  } while (rc != S_OK);

  add_io(cfd, 0);
  chat_resetscreen(chatid);

  memset(cbuf, '\0', sizeof cbuf);
  margin = CHATID_MAX+2;
  maxpos = sizeof(cbuf) - margin - 1;
  curspos = 0;
  endpos = 0;
  shift = 0;
  shiftdelta = (t_columns - margin) / 2;
    
  while (!done_chatting) {
    move(g_echatwin+1, margin+(curspos-shift));

    ch = igetch();
    if (NewPagePending()) {
      chat_show_page_request();
    }
    if (ch == -1) done_chatting = 1;
    else if (ch == I_OTHERDATA) {
      /* Incoming! */
      if (chat_process_incoming(cfd, chatid) == -1)
        done_chatting = 1;
    } else if (metakey) {
      switch (ch) {
      case 'b': case 'B':
	if (curspos == 0) bell();
	else {
	  while (curspos && myisspace(cbuf[curspos-1])) curspos--;
	  while (curspos && !myisspace(cbuf[curspos-1])) curspos--;
	}
	break;
      case 'f': case 'F':
	if (curspos == endpos) bell();
	else {
	  while (curspos < endpos && myisspace(cbuf[curspos])) curspos++;
	  while (curspos < endpos && !myisspace(cbuf[curspos])) curspos++;
	}
	break;
      default: 
	bell();
	break;
      }
      metakey = 0;
      hbufout[0] = '\0';
    }
    else switch (ch) {
    case '\r': 
    case '\n':
      if (endpos > 0) {
	if (endpos >= maxpos) {
	  endpos = maxpos;
	}
	if (isHan(cbuf, endpos-1) == 1) {
	  /* incomplete hangul cut it out before sending it to the server */
	  endpos--;
	}
        cbuf[endpos] = '\n';
	cbuf[endpos+1] = '\0';
        done_chatting = chat_process_local(cbuf, chatid);
        if (done_chatting == -1) {
          done_chatting = (bbs_chat_send(cbuf) != S_OK);
        }
      }
      memset(cbuf, '\0', sizeof cbuf);
      endpos = curspos = 0;
      move(g_echatwin+1, margin);
      clrtoeol();
      hbufout[0] = '\0';
      break;
    case CTRL('A'):
      if (curspos == 0) bell();
      else curspos = 0;
      hbufout[0] = '\0';
      break;
    case CTRL('B'):
      if (curspos == 0) {
	bell();
	hbufout[0] = '\0';
	break;
      }
      curspos--;
      if (isHan(cbuf, curspos) == 2)
        curspos --;
      hbufout[0] = '\0';
      break;
    case CTRL('C'):
      bbs_chat_send("/e\n");
      done_chatting = 1;
      hbufout[0] = '\0';
      break;
    case CTRL('D'):
      if (curspos == endpos || endpos < 1) {
	bell();
	hbufout[0] = '\0';
	break;
      }
      if (endpos > 1 && isHan(cbuf, curspos) == 1) {
        endpos -= 2;
        for (i=curspos; i<=endpos; i++) cbuf[i] = cbuf[i+2];        
      } else {
        endpos--;
        for (i=curspos; i<=endpos; i++) cbuf[i] = cbuf[i+1];        
      }
      cbuf[endpos+1] = '\0';
      move(g_echatwin+1, margin+(curspos-shift));
      prints("%s", cbuf+curspos);
      clrtoeol();
      hbufout[0] = '\0';
      break;
    case CTRL('E'):
      if (curspos == endpos) bell();
      else curspos = endpos;
      hbufout[0] = '\0';
      break;
    case CTRL('F'):
      if (curspos >= endpos) {
	bell();
	hbufout[0] = '\0';
	break;
      }
      curspos++;
      if (curspos < endpos && isHan(cbuf, curspos) == 2)
        curspos++;
      hbufout[0] = '\0';
      break;
    case CTRL('H'):
    case 127:
      if (curspos == 0) bell();
      else {
	if (curspos > 1  && endpos > 1 && isHan(cbuf, curspos-1) == 2) {
	  for (i=curspos; i<=endpos; i++) cbuf[i-2] = cbuf[i];
	  endpos -= 2;
	  curspos -= 2;
	} else {
	  for (i=curspos; i<=endpos; i++) cbuf[i-1] = cbuf[i];
	  endpos--;
	  curspos--;
	}
	cbuf[endpos+1] = '\0';
        move(g_echatwin+1, margin+(curspos-shift));
        prints("%s", cbuf+curspos);
	clrtoeol();
      }
      hbufout[0] = '\0';
      break;
    case CTRL('U'):
      if (endpos == 0) bell();
      else {
        memset(cbuf, '\0', sizeof cbuf);
        curspos = endpos = 0;
        move(g_echatwin+1, margin);
        clrtoeol();
      }
      hbufout[0] = '\0';
      break;
    case CTRL('W'):
      if (curspos == 0) bell();
      else {
        while (curspos && myisspace(cbuf[curspos-1])) {
          for (i=curspos; i<=endpos; i++) cbuf[i-1] = cbuf[i];
	  curspos--, endpos--;
	}
        while (curspos && !myisspace(cbuf[curspos-1])) {
          for (i=curspos; i<=endpos; i++) cbuf[i-1] = cbuf[i];
	  curspos--, endpos--;
	}
        move(g_echatwin+1, margin+(curspos-shift));
        prints("%s", cbuf+curspos);
        clrtoeol();
      }
      hbufout[0] = '\0';
      break;
    case 27:   /* ESC */
      metakey = 1;
      hbufout[0] = '\0';
      break;
    default:
      if (myisprint(ch) && endpos < maxpos) {
	switch (isHan(cbuf, curspos)) {
	case 1:
	  /* char at cur pos is 1st half of hangul... darn.. */
	  /* what should we do???*/
	  /* well.. let's delete it since it's gonna screw up the screen */
	  endpos--;
	  for (i=curspos; i<=endpos; i++) cbuf[i] = cbuf[i+1];        

	  /* then process the new ch. as if it is normal */
	case 0:
	case 2:
	default:
	  if (ishangul(ch)) {
	    if (hbufout[0]) {
	      hbufout[1] = ch;
	      hbufout[2] = '\0';
	    } else {
	      hbufout[0] = ch;
	      hbufout[1] = '\0';
	    }
	  } else {
	    hbufout[0] = '\0';
	  }
	  break;
	}
	if (hbufout[0] == '\0') {
	  /* plain english */
	  for (i=endpos; i>curspos; i--) cbuf[i] = cbuf[i-1];
	  cbuf[curspos] = ch;
	  move(g_echatwin+1, margin+(curspos-shift));
	  prints("%s", cbuf+curspos);
	  curspos++;
	  endpos++;
	} else {
	  if (hbufout[1]) {
	    /* 2 byte completed ! */
	    /* put it out! if we have room */
	    if (endpos < maxpos -1) {
	      for (i=endpos; i>curspos; i--) cbuf[i+1] = cbuf[i-1];
	      cbuf[curspos] = hbufout[0];
	      cbuf[curspos+1] = hbufout[1];
	      hbufout[0] = '\0';
	      move(g_echatwin+1, margin+(curspos-shift));
	      prints("%s", cbuf+curspos);
	      curspos += 2;
	      endpos +=2;
	    } else {
	      /* we don't have space discard */
	      hbufout[0] = '\0';
	    }
	  }
	}
      } else {
	bell();
	hbufout[0] = '\0';
      }
      break;
    }
    if (curspos-shift >= (t_columns-margin)) {
      while (curspos-shift >= (t_columns-margin)) shift += shiftdelta;
      move(g_echatwin+1, margin);
      prints("%s", cbuf+shift);
      clrtoeol();
    }
    else if (curspos < shift) {
      while (curspos < shift) shift -= shiftdelta;
      move(g_echatwin+1, margin);
      prints("%s", cbuf+shift);
      clrtoeol();
    }
  }

  bbs_exit_chat();
  add_io(0, 0);
  return FULLUPDATE;
}
f (chat_cmd_match(cbuf, "exit") || chat_cmd_match(cbuf, "³¡"))
    return (chat_exit(cbuf));
  else if (chat_cmd_match(cbuf, "help") || chat_cmd_match(cbuf, "µµ¿ÍÁà") ||
	chat_cmd_match(cbuf, "µµ¿ò")) {
    if (lang)
      return (chat_help(CHAT_KHELP_FILE));
    else
      return (chat_help(CHAT_HELP_FILE));
  } else if (chat_cmd_match(cbuf, "long")||chat_cmd_match(cbuf, "±ä°Å"))
    return (chat_list_users(cbuf, 1));
  else if (chat_cmd_DarkNET-1.08/c_files.c                                                                                 644   21270   21270        24450  5747645162   7666                                                                                                                                                                                                                                                                                                                                                                      
/*
Eagles Bulletin Board System
Copyright (C) 1994, Ray Rocker, rrrocker@rock.b11.ingr.com
                                rock@seabass.st.usm.edu
                                72673.2105@compuserve.com

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "client.h"
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>
#include <time.h>
#include <ctype.h>
#if NEXTSTEP == 1
# include <malloc.h>
#endif

/* The currently selected file board */
NAME currfileboard;

/* The currently selected protocol */
NAME currprotocol;

/*ARGSUSED*/
AllFileBoardsFunc(indx, board, info)
int indx;
BOARD *board;
struct enum_info *info;
{
  extern int lang;

  if (info->topline == info->currline) {
    move(info->topline-1, 0);
    if (lang)
      prints(" %-16s   %-58s\n", "ÀÌ¸§", "¼³¸í");
    else
      prints(" %-16s   %-58s\n", "Name", "Description");
  }

  if (lang && *board->kdescription)
    prints(" %-15s    %s\n", board->name, board->kdescription);
  else
    prints(" %-15s    %s\n", board->name, board->description);

  info->currline++;
  info->count++;

  if (info->currline > info->bottomline) {
    int ch;
    standout();
    c_msg(INFO_MORE, FALSE);
    standend();
    clrtoeol();
    while((ch = igetch()) != EOF) {
      if(ch == '\n' || ch == '\r' || ch == ' ')
	break;
      if(toupper(ch) == 'Q') {
	move(info->currline, 0);
	clrtoeol();
	return ENUM_QUIT;
      }
      else bell();
    }
    info->currline = info->topline;
  }
  return S_OK;
}

FileBoards()
{
  struct enum_info info;
  extern int lang;

  info.count = 0;
  info.topline = info.currline = 4;
  info.bottomline = t_lines-2;
  move(2,0);
  clrtobot();    
  move(3,0);
  bbs_enum_fileboards(t_lines-5, 0, AllFileBoardsFunc, &info);
  clrtobot();
  move(t_lines-1, 0);
  if (lang)
    prints("º¸µå %d °³°¡ º¸¿©Á³½À´Ï´Ù.\n", info.count);
  else
    prints("%d %s displayed\n", info.count, info.count==1?"board":"boards");
  return PARTUPDATE;
}

FileSelect()
{
  NAME newboard;
  NAMELIST fileboardlist;
  extern int lang;

  move(2,0);
  clrtobot();
  move(3,0);
  bbs_fileboardnames(&fileboardlist);
  if (fileboardlist->size == 0) {
    c_msg(ERR_NOTHING, TRUE);
    pressreturn();
    free_namelist(&fileboardlist);
    return FULLUPDATE;
  }
  if (lang)
    namecomplete(fileboardlist, "º¸µå ÀÌ¸§: ", newboard);
  else
    namecomplete(fileboardlist, "Enter a board name: ", newboard);
  if (newboard[0] == '\0') return FULLUPDATE;
  else if (!is_in_namelist(fileboardlist, newboard)) {
    move(4,0);
    c_msg(ERR_NOT_EXIST, TRUE);
    pressreturn();
    free_namelist(&fileboardlist);
    return FULLUPDATE;
  }
  strcpy(currfileboard, newboard);
  free_namelist(&fileboardlist);
  return (FULLUPDATE | NEWDIRECT);
}

OpenFileBoard(openflags, newonly, resp)
int *openflags;
int newonly;
int *resp;
{
  int code;
  OPENINFO openinfo;
  code = bbs_open_fileboard(currfileboard, &openinfo);    
  if (resp) *resp = code;
  if (code != S_OK) return -1;
  if (openflags) *openflags = openinfo.flags;
  return (newonly ? openinfo.newmsgs : openinfo.totalmsgs);
}

CloseFileBoard()
{
  int code;
  code = bbs_close_board();
  return (code == S_OK ? 0 : -1);
}

#if !REMOTE_CLIENT
SelectProtocol()
{
  NAME protoname;
  NAMELIST protolist;
  extern int lang;

  move(2,0);
  clrtobot();
  move(3,0);
  bbs_protonames(&protolist);
  if (protolist->size == 0) {
    c_msg(ERR_NOTHING, TRUE);
    pressreturn();
    free_namelist(&protolist);
    return FULLUPDATE;
  }
  if (lang)
    namecomplete(protolist, "ÇÁ·ÎÅäÄÝÀ» °ñ¸£¼¼¿ä: ", protoname);
  else
    namecomplete(protolist, "Select a protocol: ", protoname);
  if (protoname[0] == '\0') return FULLUPDATE;
  else if (!is_in_namelist(protolist, protoname)) {
    move(4,0);
    c_msg(ERR_NOT_EXIST, TRUE);
    pressreturn();
    free_namelist(&protolist);
    return FULLUPDATE;
  }
  strcpy(currprotocol, protoname);
  bbs_set_protocol(protoname);  
  free_namelist(&protolist);
  return FULLUPDATE;
}

FileView(hptr, currmsg, numrecs, openflags)
HEADER *hptr;
int currmsg, numrecs, openflags;
{
  int rc;
  PATH fname;
  extern int lang;

  clear();
  if (BITISSET(hptr->flags, FILE_BINARY)) {
    char ans[4];
    if (lang)
      {
	getdata(0, 0, "¹ÙÀÌ³Ê¸® È­ÀÏ °°Àº µ¥¿ä °è¼ÓÇÒ±î¿ä (Y/N)? [N]: ",
            ans, sizeof ans, DOECHO, 0);
      }
    else
      {
	getdata(0, 0, "This may be a binary file. Continue (Y/N)? [N]: ",
            ans, sizeof ans, DOECHO, 0);
      }
    if (*ans != 'Y' && *ans != 'y')
      return FULLUPDATE;
  }      

  if (bbs_download(hptr->title, NULL, fname) != S_OK) {
    c_msg(ERR_FAILURE, TRUE);
    pressreturn();
    return FULLUPDATE;
  }
  More(fname, 1);
  return FULLUPDATE;
}

GetSavedProtocol()
{
  ACCOUNT acct;
  if (bbs_owninfo(&acct) == S_OK) {
    strncpy(currprotocol, acct.protocol, sizeof currprotocol-1);
  }
}  
#endif

FileUpload()
{
  PATH fname;
  char *base, *slash;
  char ans[4];
  extern int lang;

#if REMOTE_CLIENT
  strcpy(currprotocol, "builtin");
#else
  if (currprotocol[0] == '\0') {
    GetSavedProtocol();
    if (currprotocol[0] == '\0') {
      clear();
      c_msg(ERR_NOT_SELECTED, TRUE);
      pressreturn();
      return FULLUPDATE;
    }
  }
#endif
  clear();
  if (lang)
    {
      if (getdata(0, 0, "È­ÀÏ ÀÌ¸§: ", fname, sizeof fname, DOECHO, 1) == -1)
	return FULLUPDATE;
    }
  else
    {
      if (getdata(0, 0, "Enter filename: ", fname, sizeof fname, DOECHO, 1) == -1)
	return FULLUPDATE;
    }

  if ((slash = strrchr(fname, '/')) != NULL) base = slash+1;
  else base = fname;

  if (lang)
    {
      prints("È­ÀÏ '%s' ¾÷·Îµå ÇÕ´Ï´Ù.\n", base);
      prints("Àü¼Û ÇÁ·ÎÅäÄÝÀº %s ÀÔ´Ï´Ù.\n", currprotocol);
    }
  else
    {
      prints("Uploading '%s'.\n", base);
      prints("Using %s protocol.\n", currprotocol);
    }
  if (lang)
    getdata(2, 0, "Á¤¸»·Î Àü¼ÛÇÒ±î¿ä (Y/N)? [Y]: ", ans, sizeof(ans), DOECHO, 0);
  else
    getdata(2, 0, "Are you sure (Y/N)? [Y]: ", ans, sizeof(ans), DOECHO, 0);

  if (*ans == 'N' || *ans == 'n') {
    c_msg(INFO_CANCELLED, TRUE);
  }
  else {
    int rc;

#if REMOTE_CLIENT
    c_msg(INFO_IN_PROGRESS, TRUE);
    rc = bbs_upload(fname, base, currprotocol);
#else
    c_msg(INFO_READY_START, TRUE);
    refresh();
    fgetc(stdin);
    reset_tty();
    rc = bbs_upload(NULL, base, currprotocol);
    c_msg(INFO_DONE_PRESS, TRUE);
    fgetc(stdin);
    restore_tty();
#endif
    clear();
    switch (rc) {
    case S_OK: 
      c_msg(INFO_UPLOADED, TRUE);
      break;
    case S_INVALID: 
      c_msg(ERR_PROTOCOL, TRUE);
      break;
#if REMOTE_CLIENT
    case S_BADPATH:
      c_msg(ERR_FILE, TRUE);
      break;
#endif
    default:
      c_msg(ERR_FAILURE, TRUE);
      break;
    }
  }
  pressreturn();
  return FULLUPDATE;
}

FileReceive(hptr, currmsg, numrecs, openflags)
HEADER *hptr;
LONG currmsg, numrecs, openflags;
{
  char ans[4];
  extern int lang;
#if REMOTE_CLIENT
  PATH fname;
  strcpy(currprotocol, "builtin");
#else
  if (currprotocol[0] == '\0') {
    GetSavedProtocol();
    if (currprotocol[0] == '\0') {
      clear();
      c_msg(ERR_NOT_SELECTED, TRUE);
      pressreturn();
      return FULLUPDATE;
    }
  }
#endif
  clear();
  if (lang) {
    prints("'%s' ´Ù¿î·Îµù ÇÕ´Ï´Ù.\n", hptr->title);
    prints("ÇÁ·ÎÅäÄÝÀº %s.\n", currprotocol);
    getdata(2, 0, "°è¼ÓÇÒ±î¿ä (Y/N)? [Y]: ", ans, sizeof(ans), DOECHO, 0);
  } else {
    prints("Downloading '%s'.\n", hptr->title);
    prints("Using %s protocol.\n", currprotocol);
    getdata(2, 0, "Are you sure (Y/N)? [Y]: ", ans, sizeof(ans), DOECHO, 0);
  }
  if (*ans == 'N' || *ans == 'n') {
    c_msg(INFO_CANCELLED, TRUE);
  }
  else {
    int rc;
#if REMOTE_CLIENT
    if (getdata(3, 0, "Download to (RETURN = current directory): ",
                fname, sizeof fname, DOECHO, 1) == -1) {
      return FULLUPDATE;
    }      
    if (fname[0] == '\0') strncpy(fname, hptr->title, sizeof fname);
    prints("Receiving %d bytes. Please stand by.\n", hptr->size);
    rc = bbs_download(hptr->title, currprotocol, fname);
#else
    c_msg(INFO_READY_START, TRUE);
    refresh();
    fgetc(stdin);
    reset_tty();
    rc = bbs_download(hptr->title, currprotocol, NULL);
    c_msg(INFO_DONE_PRESS, TRUE);
    fgetc(stdin);        
    restore_tty();
    clear();
#endif
    switch (rc) {
    case S_OK: 
      c_msg(INFO_DOWNLOADED, TRUE);
      break;
    case S_INVALID: 
      c_msg(ERR_PROTOCOL, TRUE);
      break;
#if REMOTE_CLIENT
    case S_BADPATH:
      c_msg(ERR_FILE, TRUE);
      break;
#endif
    default:
      c_msg(ERR_FAILURE, TRUE);
      break;
    }
  }
  pressreturn();
  return FULLUPDATE;
}

/*ARGSUSED*/
FileForward(hptr, currmsg, numrecs, openflags)
HEADER *hptr;
int currmsg, numrecs, openflags;
{
  int rc = FULLUPDATE;
  ACCOUNT acct;
  char ans[4];
  extern int lang;

  clear();
  if (bbs_owninfo(&acct) != S_OK) {
    c_msg(ERR_ACCT, TRUE);
    pressreturn();
    return rc;
  }
  if (lang)
    prints("(%s) ¸¦ (%s) ¿¡°Ô º¸³À´Ï´Ù\n", hptr->title, acct.email);
  else
    prints("Mailing '%s' to: %s\n", hptr->title, acct.email);
  if (lang)
    getdata(2,0,"Á¤¸» º¸³¾±î (Y/N)? [Y]: ",ans,sizeof(ans),DOECHO,0);
  else
    getdata(2,0,"Are you sure (Y/N)? [Y]: ",ans,sizeof(ans),DOECHO,0);
  move(4,0);
  if (*ans == 'N' || *ans == 'n') {
    c_msg(INFO_CANCELLED, TRUE);
  } else {
    switch (bbs_forward_file(hptr->title)) {
    case S_OK:
      c_msg(INFO_SENT, TRUE);
      break;
    case S_INVALID:
      c_msg(ERR_ADDR, TRUE);
      break;
    case S_NOTFOUND:
      c_msg(ERR_FILE, TRUE);
      break;
    default:
      c_msg(ERR_FAILURE, TRUE);
      break;
    }
  }
  pressreturn();
  return rc;
}

/*ARGSUSED*/
FileReadMenuSelect(hptr, currmsg, numrecs, openflags)
HEADER *hptr;
int currmsg, numrecs, openflags;
{
  return (FileSelect());
}

#if !REMOTE_CLIENT

/*ARGSUSED*/
FileReadMenuProto(hptr, currmsg, numrecs, openflags)
HEADER *hptr;
int currmsg, numrecs, openflags;
{
  return (SelectProtocol());
}
#endif
);
  clrtobot();
  move(t_lines-1, 0);
  if (lang)
    prints("º¸µå %d °³°¡ º¸¿©Á³½À´Ï´Ù.\n", info.count);
  else
    prints("%d %s displayed\n", info.count, info.count==1?"board":"boards");
  return PARTUPDATE;
}

FDarkNET-1.08/c_lists.c                                                                                 644   21270   21270        13235  5741125175   7710                                                                                                                                                                                                                                                                                                                                                                      
/*
Eagles Bulletin Board System
Copyright (C) 1994, Ray Rocker, rrrocker@rock.b11.ingr.com
                                rock@seabass.st.usm.edu
                                72673.2105@compuserve.com

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "client.h"

extern NAMELIST acctlist;

struct disp_list {
  int x;
  int y;
};

/*ARGSUSED*/
display_list_element(indx, name, arg)
int indx;
char *name;
void *arg;
{
  struct disp_list *info = arg;
  move(info->y, info->x);
  prints(name);
  (info->y)++;
  if (info->y == t_lines - 1) {
    info->y = 4;
    info->x+=(NAMELEN + 2);
  }
}
  
display_list(header, list)
char *header;
NAMELIST list;
{
  struct disp_list info;
  info.x = 0;
  info.y = 4;

  move(2,0);
  clrtobot();
  move(3,0);
  prints("%s\n", header);
  apply_namelist(list, display_list_element, &info);
}

SetOverrides()
{
  int done = 0, change = 0;
  char ans[7];
  NAME userid;
  NAMELIST overlist = NULL;
  extern int lang;

  clear();
  if (acctlist == NULL)
    bbs_acctnames(&acctlist);
  create_namelist(&overlist, MAXOVERRIDE);
  bbs_get_overrides(&overlist);
  c_msg(INFO_OVERLIST, TRUE);
  while (!done) {
    if (lang)
    {
      display_list("*** ¿À¹ö¶óÀÌµå ¸®½ºÆ®ÀÇ À¯Àúµé ***", overlist);
      getdata(1,0,"[A] ´õÇÏ±â, [D] »©±â, [Q] ³¡? [Q]: ",
	    ans, sizeof(ans), DOECHO, 0);
    }
    else
    {
      display_list("*** Users on Override List ***", overlist);
      getdata(1,0,"[A]-Add, [D]-Remove, or [Q]-Quit? [Q]: ",
	    ans, sizeof(ans), DOECHO, 0);
    }
    switch (ans[0]) {
    case 'A': case 'a':
      move(2,0);
      if (lang)
        namecomplete(acctlist, "´©±¼ ´õÇÒ±î¿ä: ", userid);
      else
        namecomplete(acctlist, "Add which user: ", userid);
      if (is_in_namelist(acctlist, userid) && 
          !is_in_namelist(overlist, userid)) {
        add_namelist(&overlist, userid, NULL);
	sort_list(&overlist);
        change++;
      }
      break;
    case 'D': case 'd':
      if (overlist->size == 0) {
	c_msg(ERR_NOTHING, TRUE);
        clrtobot();
	pressreturn();
      } else {
	if (lang)
	  namecomplete(overlist, "´©±¸¸¦ »¬±î¿ä: ", userid);
	else
	  namecomplete(overlist, "Remove which user: ", userid);
	if (remove_namelist(&overlist, userid) == S_OK)
	  {
	    change++;
	    sort_list(&overlist);
	  }
      }
      break;
    default:
      done = 1;
    }
    move(2,0);
    clrtoeol();    
  }
  if (change) {
    if (bbs_set_overrides(overlist) == S_OK)
      c_msg(INFO_CHANGED, TRUE);
    else
      c_msg(ERR_FAILURE, TRUE);
  } else {
    c_msg(INFO_CANCELLED, TRUE);
  }
  free_namelist(&overlist);
  pressreturn();
  return FULLUPDATE;
}

SetBoardMgrs()
{
  int done = 0, change = 0;
  char ans[7];
  NAME namebuf;
  BOARD board;
  NAMELIST mgrlist = NULL;
  NAMELIST boardlist = NULL;
  extern int lang;

  clear();
  bbs_boardnames(&boardlist);
  if (boardlist->size == 0) {
    c_msg(ERR_NOTHING, TRUE);
    free_namelist(&boardlist);
    pressreturn();
    return FULLUPDATE;
  }
  if (acctlist == NULL)
    bbs_acctnames(&acctlist);

  if (lang)
    namecomplete(boardlist, "¾î´À º¸µå ¸Å´ÏÁ®¸¦ Á¤ÇÒ±î¿ä: ", namebuf);
  else
    namecomplete(boardlist, "Set manager for which board: ", namebuf);

  if (namebuf[0] == '\0')
    return FULLUPDATE;

  if (!is_in_namelist(boardlist, namebuf)) {
    c_msg(ERR_NOT_EXIST, TRUE);
    free_namelist(&boardlist);
    pressreturn();
    return FULLUPDATE;
  }
  if (bbs_get_board(namebuf, &board) != S_OK) {
    c_msg(ERR_FAILURE, TRUE);
    free_namelist(&boardlist);
    pressreturn();
    return FULLUPDATE;
  }
  create_namelist(&mgrlist, MAXMANAGER);
  bbs_get_boardmgrs(board.name, &mgrlist);
  c_msg(INFO_BMGR, TRUE);
  while (!done) {
    if (lang) {
      display_list("*** º¸µå °ü¸®ÀÚ ***", mgrlist);
      getdata(1,0,"[A]-´õÇÏ±â, [D]-»èÁ¦, or [Q]-³¡? [Q]: ",
	    ans, sizeof(ans), DOECHO, 0);
    } else {
      display_list("*** Board Managers ***", mgrlist);
      getdata(1,0,"[A]-Add, [D]-Delete, or [Q]-Quit? [Q]: ",
	    ans, sizeof(ans), DOECHO, 0);
    }
    switch (ans[0]) {
    case 'A': case 'a':
      move(2,0);
      if (lang)
        namecomplete(acctlist, "´©±¼ ´õÇÒ±î: ", namebuf);
      else
        namecomplete(acctlist, "Add which user: ", namebuf);
      if (is_in_namelist(acctlist, namebuf) && 
          !is_in_namelist(mgrlist, namebuf)) {
        add_namelist(&mgrlist, namebuf, NULL);
	sort_list(&mgrlist);
        change++;
      }
      break;
    case 'D': case 'd':
      if (mgrlist->size == 0) {
	c_msg(ERR_NOTHING, TRUE);
        clrtobot();
	pressreturn();
      } else {
	if (lang)
	  namecomplete(mgrlist, "´©±¼ »¬±î: ", namebuf);
	else
	  namecomplete(mgrlist, "Remove which user: ", namebuf);
	if (remove_namelist(&mgrlist, namebuf) == S_OK)
	  {
	    change++;
	    sort_list(&mgrlist);
	  }
      }
      break;
    default:
      done = 1;
    }
    move(2,0);
    clrtoeol();    
  }
  if (change) {
    if (bbs_set_boardmgrs(board.name, mgrlist) == S_OK)
      c_msg(INFO_CHANGED, TRUE);
    else
      c_msg(ERR_FAILURE, TRUE);
  } else
    c_msg(INFO_CANCELLED, TRUE);
  free_namelist(&mgrlist);
  free_namelist(&boardlist);
  pressreturn();
  return FULLUPDATE;
}
                                                                                                                                                                                                                                                                                                                                                                   DarkNET-1.08/c_mail.c                                                                                  644   21270   21270        31645  5741130660   7474                                                                                                                                                                                                                                                                                                                                                                      
/*
Eagles Bulletin Board System
Copyright (C) 1994, Ray Rocker, rrrocker@rock.b11.ingr.com
                                rock@seabass.st.usm.edu
                                72673.2105@compuserve.com

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "client.h"
#include <stdlib.h>
#include <sys/stat.h>

extern NAMELIST acctlist;

OpenMailbox(openflags, newonly, resp)
int *openflags;
int newonly;
int *resp;
{
  int code;
  OPENINFO openinfo;
  code = bbs_open_mailbox(&openinfo);    
  if (resp) *resp = code;
  if (code != S_OK) return -1;
  if (openflags) *openflags = (int)openinfo.flags;
  return (newonly ? (int)openinfo.newmsgs : (int)openinfo.totalmsgs);
}

CloseMailbox()
{
  int code;
  code = bbs_close_board();
  return (code == S_OK ? 0 : -1);
}

/* 
  If mail to ANY recipients fails, return -1 with retcode holding the mask.
  Abort mail, return -2. 
  Zero length file, return -3.
  Otherwise return 0.
*/

DoMailSend(recips, subject, textfile, doedit, retcode)
NAMELIST recips;  /* list of intended recipients */
char *subject;    /* subject string */
char *textfile;   /* file to send: if NULL invoke editor */
int doedit;       /* edit even if textfile != NULL */
LONG *retcode;    /* bit mask of failed destinations */
{
  int rc = 0;
  struct stat stbuf;
  
  if (textfile == NULL || doedit) {
    if (textfile == NULL) textfile = c_tempfile;
    if (Edit(textfile)) { 
      rc = -2;
    }
  }
  if (rc == 0) {
    if (stat(textfile, &stbuf) != 0 || stbuf.st_size == 0) {
      rc = -3;
    }
    if (rc == 0 && bbs_mail(recips, subject, textfile, retcode) != S_OK) {
      rc = -1;
    }
  }
  if (textfile == c_tempfile) unlink(c_tempfile);
  return rc;
}            

show_names(indx, userid, mask)
int indx;
char *userid;
LONG *mask;
{
  int x, y;
  if ((*mask) & (LONG)(1<<indx)) {
    getyx(&y, &x);
    if (strlen(userid)+3 > (t_columns-x)) prints("\n");
    else if (x > 0) prints(", ");
    prints("%s", userid);
  }
  return S_OK;
}

GenericMailSend(group)
int group;
{
  int rc;
  NAME nbuf;
  NAMELIST recips = NULL;
  TITLE subject;
  int max, count = 0;
  char *prompt;
  LONG failmask = ~0;
  extern int lang;

  bbs_set_mode(M_MAIL);
  if (group) {
    max = BBS_MAX_MAILRECIPS;
    if (lang)
	{
	    prompt = "´©±¸¿¡°Ô (´Ù³ÖÀº´ã¿¡ RETURN): ";
	}
    else
	{
	    prompt = "Enter userid (RETURN when done): ";
	}
  } else {
    max = 1;
    if (lang)
    {
      prompt = "´©±¸¿¡°Ô: ";
    }
    else
    {
      prompt = "Enter userid: ";
    }
  }

  if (acctlist == NULL)
    bbs_acctnames(&acctlist);   /* should be maillist one day? */
  create_namelist (&recips, max);

  move(2,0);
  clrtobot();
  for (count = 0; count < max; count++) {
    move(2,0);
    namecomplete(acctlist, prompt, nbuf);    
    if (nbuf[0] == '\0') break;
    if (!is_in_namelist(acctlist, nbuf)) {
      move(3,0);
      c_msg(ERR_NOT_EXIST, TRUE);
      refresh();
      continue;
    }
    if (!is_in_namelist(recips, nbuf)) {
      add_namelist(&recips, nbuf, NULL);
      sort_list(&recips);
    }
    if (group) {
      move(4,0);
      c_msg(INFO_SENDING_TO, TRUE);
      apply_namelist(recips, show_names, &failmask);
    }
  }

  if (recips->last > 0) {
    if (lang)
      getdata(3,0,"Á¦¸ñ: ", subject, sizeof subject, DOECHO, 0);
    else
      getdata(3,0,"Subject: ", subject, sizeof subject, DOECHO, 0);
    rc = DoMailSend(recips, subject, (char *)NULL, 0, &failmask);
    clear();
    move(0,0);
    switch (rc) {
    case -3:
      c_msg(ERR_ZERO, TRUE);
      break;
    case -2:
      c_msg(ERR_FAILURE, TRUE);
      break;
    case -1:        
      c_msg(ERR_SEND_TO, TRUE);
      apply_namelist(recips, show_names, &failmask);
      break;
    case 0:
      c_msg(INFO_SENT, TRUE);
      break;
    default:
      c_msg(ERR_UNKNOWN, TRUE);
      break;
    }
  }
  free_namelist(&recips);
  pressreturn();
  bbs_set_mode(M_UNDEFINED);
  return FULLUPDATE;
}

GroupSend()
{
  return (GenericMailSend(1));
}

MailSend()
{
  return (GenericMailSend(0));
}

NetMailSend()
{
  char to[129];
  char subj[129];
  char cmd[129];
  char *textfile;
  int rc;
  HEADER hdr;
  char *tfile;
  struct stat stbuf;
  extern int lang;

  bbs_set_mode(M_MAIL);
  move (2,0);
  clrtobot();
  if (lang) {
    getdata(2,0, "´©±¸ÇÑÅ× (Internet Email): ",  to, 128, DOECHO, 0);
    getdata(3,0, "Á¦¸ñ: ", subj, 128, DOECHO, 0);
  } else {
    getdata(2,0, "To (Internet Email): ",  to, 128, DOECHO, 0);
    getdata(3,0, "Subject: ", subj, 128, DOECHO, 0);
  }
  textfile = c_tempfile;
  if (Edit(textfile)) {
     unlink(textfile);
     bbs_set_mode (M_UNDEFINED);
     return FULLUPDATE;
  }
  if (stat(textfile, &stbuf) != 0 || stbuf.st_size == 0) {
     unlink(textfile);
     c_msg(ERR_ZERO, TRUE);
     pressreturn();
     bbs_set_mode (M_UNDEFINED);
     return FULLUPDATE;
  }

  if ((tfile = tmpnam(NULL)) == NULL) {
    unlink (textfile);
    c_msg(ERR_FAILURE, TRUE);
    pressreturn();
    bbs_set_mode (M_UNDEFINED);
    return FULLUPDATE;
  }
  sprintf(cmd, "/usr/local/bin/hcode -ki < %s > %s", textfile, tfile);
  system(cmd);
  unlink (textfile);
  mail_to_outside(tfile, subj, to);
  unlink (tfile);
  c_msg(INFO_SENT, TRUE);
  pressreturn();
  bbs_set_mode (M_UNDEFINED);
  return FULLUPDATE;
}

/*ARGSUSED*/
MailDelete(hptr, currmsg, numrecs, openflags)
HEADER *hptr;
int currmsg, numrecs, openflags;
{
  int rc = FULLUPDATE;
  char ans[4];
  extern int lang;

  clear();
  if (lang) {
    prints("%s ¿¡°Ô¼­ ¿Â ÆíÁö »èÁ¦\n", hptr->owner);
    prints("Á¦¸ñÀº '%s'\n", hptr->title);
  } else {
    prints("Delete message from %s\n", hptr->owner);
    prints("entitled '%s'\n", hptr->title);
  }
  if (lang)
    getdata(2,0,"Á¤¸»·Î (Y/N)? [N]: ",ans,sizeof(ans),DOECHO, 0);
  else
    getdata(2,0,"Are you sure (Y/N)? [N]: ",ans,sizeof(ans),DOECHO, 0);
  move(4,0);
  if (*ans != 'Y' && *ans != 'y') {
    c_msg(INFO_CANCELLED, TRUE);
  } else {
    if (bbs_delete_message(hptr->fileid) == S_OK) {
      c_msg(INFO_DELETED, TRUE);
      rc |= FETCHNEW;
    } else {
      c_msg(ERR_FAILURE, TRUE);
    }
  }
  pressreturn();
  return rc;
}

/*ARGSUSED*/
MailDelRange(hptr, currmsg, numinbox, openflags)
HEADER *hptr;
int currmsg, numinbox, openflags;
{
  int rc = FULLUPDATE;
  char ans[5];
  SHORT n1 = 0, n2 = 0, deleted;
  extern int lang;

  clear();
  if (numinbox <= 0) {
    c_msg(ERR_NOTHING, TRUE);
    pressreturn();
    return rc;
  }
  c_msg(INFO_DELETE_RANGE, TRUE);
  do {
    if (lang) {
      if (getdata(2,0,"»èÁ¦ÇÒ Ã¹¹øÂ° ÆíÁö¹øÈ£: ",
	    ans,sizeof(ans), DOECHO, 1) == -1) return rc;
    } else {
      if (getdata(2,0,"Enter number of first message to delete: ",
	    ans,sizeof(ans), DOECHO, 1) == -1) return rc;
    }
    n1 = atoi(ans);
    if (n1 <= 0 || n1 > numinbox) {
      bell();
      move(3,0);
      c_msg(ERR_RANGE, TRUE);
    }        
  } while (n1 <= 0 || n1 > numinbox);
  do {
    if (lang) {
      if (getdata(3,0,"»èÁ¦ÇÒ ¸¶Áö¸· ÆíÁö¹øÈ£: ",
	    ans,sizeof(ans), DOECHO, 1) == -1) return rc;
    } else {
      if (getdata(3,0,"Enter number of last message to delete: ",
	    ans,sizeof(ans), DOECHO, 1) == -1) return rc;
    }
    n2 = atoi(ans);
    if (n2 < n1 || n2 > numinbox) {
      bell();
      move(4,0);
      c_msg(ERR_RANGE, TRUE);
    }        
  } while (n2 < n1 || n2 > numinbox);
  
  move(4,0);
  clrtobot();
  if (lang) {
    getdata(4,0,"Á¤¸» Áö¿ï±î¿ä (Y/N)? [N]: ",ans,sizeof(ans),DOECHO,0);
  } else {
    getdata(4,0,"Are you sure (Y/N)? [N]: ",ans,sizeof(ans),DOECHO,0);
  }
  move(6,0);
  if (*ans != 'Y' && *ans != 'y') {
    c_msg(INFO_CANCELLED, TRUE);
  } else {
    switch (bbs_delete_range(n1, n2, &deleted)) {
    case S_OK:
      c_msg(INFO_DELETED, TRUE);
      rc |= FETCHNEW;
      break;	    
    default:
      c_msg(ERR_FAILURE, TRUE);
      break;
    }
  }
  pressreturn();
  return rc;
}

/*ARGSUSED*/
Forward(hptr, currmsg, numrecs, openflags)
HEADER *hptr;
int currmsg, numrecs, openflags;
{
  int rc = FULLUPDATE;
  ACCOUNT acct;
  char ans[4];
  extern int lang;

  clear();
  if (bbs_owninfo(&acct) != S_OK) {
    c_msg(ERR_ACCT, TRUE);
    pressreturn();
    return rc;
  }

  if (lang) {
    prints("'%s' ¸¦ [%s] ·Î º¸³À´Ï´Ù\n", hptr->title, acct.email);
    getdata(2,0,"Á¤¸»·Î (Y/N)? [Y]: ",ans,sizeof(ans),DOECHO,0);
  } else {
    prints("Mailing '%s' to:\n", hptr->title);
    prints("%s\n", acct.email);
    getdata(2,0,"Are you sure (Y/N)? [Y]: ",ans,sizeof(ans),DOECHO,0);
  }
  move(4,0);
  if (*ans == 'N' || *ans == 'n') {
    c_msg(INFO_CANCELLED, TRUE);
  } else {
    switch (bbs_forward_message(hptr->fileid)) {
    case S_OK:
      c_msg(INFO_SENT, TRUE);
      break;
    case S_INVALID:
      c_msg(ERR_ADDR, TRUE);
      break;
    case S_NOTFOUND:
      c_msg(ERR_FILE, TRUE);
      break;
    default:
      c_msg(ERR_FAILURE, TRUE);
      break;
    }
  }
  pressreturn();
  return rc;
}

GenericMailReply(hptr, group, msgsrc)
HEADER *hptr;
int group;
char *msgsrc;
{
  NAMELIST recips = NULL;
  TITLE subject;
  char ans[4];
  int rc, retcode = FULLUPDATE;
  LONG failmask;
  PATH msgfile;  
  extern int lang;

  clear();

  if (msgsrc == NULL) {
    if (bbs_read_message(hptr->fileid, msgfile) != S_OK) {
      c_msg(ERR_FILE, TRUE);
      pressreturn ();
      return retcode;
    }
  } else
    strcpy(msgfile, msgsrc);

  create_namelist(&recips, BBS_MAX_MAILRECIPS);
  add_namelist(&recips, hptr->owner, NULL);
  sort_list(&recips);

  if (group)
    parse_to_list(&recips, msgfile, myinfo.userid);

  if (strncasecmp(hptr->title, "Re:", 3)) {
    strcpy(subject, "Re: ");
    strncat(subject, hptr->title, TITLELEN-5);
  } else
    strncpy(subject, hptr->title, TITLELEN-1);
  
  if (lang)
    getdata(0,0,"º»¹®À» ´äÀå¿¡ Æ÷ÇÔÇÒ±î¿ä (Y/N)? [N]: ",
	  ans, sizeof(ans), DOECHO, 0);
  else
    getdata(0,0,"Include message text in reply (Y/N)? [N]: ",
	  ans, sizeof(ans), DOECHO, 0);

  if (*ans == 'Y' || *ans == 'y') {
    AnnotateMessageBody(c_tempfile, msgfile);
  }
  
  rc = DoMailSend(recips, subject, c_tempfile, 1, &failmask);

  clear();
  move(0,0);
  switch (rc) {
  case -3:
    c_msg(ERR_ZERO, TRUE);
    break;
  case -2:        
    c_msg(ERR_FAILURE, TRUE);
    break;
  case -1:
     c_msg(ERR_SEND_TO, TRUE);
    if (group) {
      apply_namelist(recips, show_names, &failmask);
    }
    break;
  case 0:
    c_msg(INFO_SENT, TRUE);
    if (is_in_namelist(recips, myinfo.userid))
      BITSET(retcode, FETCHNEW);
  }
  unlink(c_tempfile);
  free_namelist(&recips);
  pressreturn();
  return retcode;
}

/*ARGSUSED*/
MailReply(hptr, currmsg, numrecs, openflags)
HEADER *hptr;
int currmsg, numrecs, openflags;
{
  return (GenericMailReply(hptr, 0, NULL));
}    

/*ARGSUSED*/
GroupReply(hptr, currmsg, numrecs, openflags)
HEADER *hptr;
int currmsg, numrecs, openflags;
{
  return (GenericMailReply(hptr, 1, NULL));
}    

/*ARGSUSED*/
MailDisplay(hptr, currmsg, numrecs, openflags)
HEADER *hptr;
int currmsg, numrecs, openflags;
{
  char ans[9], promptstr[80];
  PATH msgfile;
  int rc = FULLUPDATE;
  int done = 0, replied = 0;
  extern int lang;
#if REMOTE_CLIENT
  int saved = 0;
#else
  int forwarded = 0;
#endif
  if (bbs_read_message(hptr->fileid, msgfile) != S_OK) {
    c_msg(ERR_FILE, TRUE);
    pressreturn();
    return rc;
  }
  BITCLR(hptr->flags, FILE_UNREAD);
  clear();
  More(msgfile, 0);
  while (!done) {
    promptstr[0] = '\0';
    if (!replied)
    {
	if (lang)
	  strcat(promptstr, "[R]-´ä, [G]-¸ðÁ¶¸® ´ä, ");
	else
	  strcat(promptstr, "[R]eply, [G]roup reply, ");
    }
#if REMOTE_CLIENT
    if (!saved) strcat(promptstr, "[S]ave, ");
#else
    if (!forwarded)
    {
      if (lang)
	 strcat(promptstr, "[F]-Æ÷¿öµù, ");
      else
	 strcat(promptstr, "[F]orward, ");
    }
#endif
    if (lang)
      strcat(promptstr, "[D]-»èÁ¦, [C]-°è¼Ó? [C]: ");
    else
      strcat(promptstr, "[D]elete, or [C]ontinue? [C]: ");
    getdata(t_lines-1, 0, promptstr, ans, sizeof ans, DOECHO, 0);
    switch (*ans) {
    case 'r': case 'R': 
    case 'g': case 'G':
      if (replied) done = 1;
      else {
	rc |= GenericMailReply(hptr, toupper(*ans)=='G'?1:0, msgfile);
	replied = 1;
      }
      break;
#if REMOTE_CLIENT
    case 's': case 'S':
      if (saved) done = 1;
      else {
	rc |= SaveFile(msgfile);
	saved = 1;
      }
      break;
#else
    case 'f': case 'F':
      if (forwarded) done = 1;
      else {
        rc |= Forward(hptr, currmsg, numrecs, openflags);
        forwarded = 1;
      }
      break;
#endif
    case 'd': case 'D': 
      rc |= MailDelete(hptr, currmsg, numrecs, openflags);
      /* fall through */
    default:
      done = 1;
      break;
    }
  }
  return rc;
}
",  to, 128, DOECHO, 0);
    getdata(3,0, "Subject: ", subj, 128, DOECHO, 0);
  }
  textfilDarkNET-1.08/c_post.c                                                                                  644   21270   21270        35527  5751544136   7552                                                                                                                                                                                                                                                                                                                                                                      
/*
Eagles Bulletin Board System
Copyright (C) 1994, Ray Rocker, rrrocker@rock.b11.ingr.com
                                rock@seabass.st.usm.edu
                                72673.2105@compuserve.com

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "client.h"
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>


int
OpenBoard(openflags, newonly, resp)
int *openflags;
int newonly;
int *resp;
{
  int code;
  OPENINFO openinfo;
  code = bbs_open_board(currboard, &openinfo);    
  if (resp) *resp = code;
  if (code != S_OK) return -1;
  if (openflags) *openflags = openinfo.flags;
  return (newonly ? openinfo.newmsgs : openinfo.totalmsgs);
}

CloseBoard()
{
  int code;
  code = bbs_close_board();
  return (code == S_OK ? 0 : -1);
}

/* 
   Return codes for DoPostSend:
   0 == success
   -1 == posting failed
   -2 == post was manually aborted
   -3 == post is zero length -- aborted
*/

DoPostSend(subject, textfile, doedit)
char *subject;    /* subject string */
char *textfile;   /* file to send: if NULL invoke editor */
int doedit;       /* edit even if textfile != NULL */
{
  int rc = 0;
  struct stat stbuf;
  
  if (textfile == NULL || doedit) {
    if (textfile == NULL) textfile = c_tempfile;
    if (Edit(textfile)) { 
      if (textfile == c_tempfile) unlink(c_tempfile);
      return -2;
    }
  }
  if (stat(textfile, &stbuf) != 0 || stbuf.st_size == 0) {
    rc = -3;
  } else {
    OPENINFO openinfo;
    if (bbs_open_board(currboard, &openinfo) != S_OK) {
      rc = -1;
    }
    if (rc == 0 && bbs_post(currboard, subject, textfile) != S_OK) {
      rc = -1;
    }
    bbs_close_board();
  }
  if (textfile == c_tempfile) unlink(c_tempfile);
  return rc;
}

FtpPost ()
{
  int rc;
  LONG retcode = FULLUPDATE;
  TITLE subject;
  SHORT flags;
  char ftphost[64];
  char uname[12];
  char passwd[32];
  char fname[128];
  char arg[256];
  FILE *in, *out;
  int c;
  extern int lang;
  extern FILE *FtpFullOpen();

  clear();
  if (currboard[0] == '\0') {
    c_msg(ERR_NOT_SELECTED, TRUE);
    pressreturn();
    return FULLUPDATE;
  }
  if (bbs_test_board(currboard, &flags) != S_OK) {
    c_msg(ERR_NOT_EXIST, TRUE);
    pressreturn();
    return FULLUPDATE;
  }
  if (!BITISSET(flags, OPEN_POST)) {
    c_msg(ERR_PERM, TRUE);
    pressreturn();
    return FULLUPDATE;
  }
  bbs_set_mode(M_FTP);
  c_msg(INFO_POSTING, TRUE);
  if (lang) {
    getdata(1, 0, "Á¦¸ñ: ", subject, sizeof(subject), DOECHO, 0);
  } else {
    getdata(1, 0, "Subject: ", subject, sizeof(subject), DOECHO, 0);
  }

  clear();

  memset(ftphost, '\0', 64);
  memset(uname, '\0', 12);
  memset(passwd, '\0', 32);
  memset(fname, '\0', 128);
  memset(arg, '\0', 256);

 move(1,0);
 c_msg(INFO_FTP_POSTING, TRUE);
 if (lang) {
  if (getdata(2, 0, "¾îµð¼­ FTP?  : ", ftphost, sizeof(ftphost), DOECHO, 1) == -1 ||
      getdata(3, 0, "´©±¸·Î?      : ", uname, sizeof(uname), DOECHO, 1) == -1 ||
      getdata_echo(4, 0, "¾ÏÈ£´Â?      : ", passwd, sizeof(passwd), NOECHO, '*', 1) == -1 ||
      getdata(5, 0, "¾î¶² È­ÀÏÀ»? : ", fname, sizeof(fname), DOECHO, 1) == -1)
    {
      c_msg(INFO_CANCELLED, TRUE);
      pressreturn();
      bbs_set_mode(M_UNDEFINED);
      return FULLUPDATE;
    }
 } else {
  if (getdata(2, 0, "FTP from?  : ", ftphost, sizeof(ftphost), DOECHO, 1) == -1 ||
      getdata(3, 0, "FTP user?  : ", uname, sizeof(uname), DOECHO, 1) == -1 ||
      getdata_echo(4, 0, "FTP passwd?: ", passwd, sizeof(passwd), NOECHO, '*', 1) == -1 ||
      getdata(5, 0, "File Name? : ", fname, sizeof(fname), DOECHO, 1) == -1)
    {
      c_msg(INFO_CANCELLED, TRUE);
      pressreturn();
      bbs_set_mode(M_UNDEFINED);
      return FULLUPDATE;
    }
 }

  sprintf(arg, "%s/%s@%s:%s", uname, passwd, ftphost, fname);

  if ((in = (FILE*)Ftpfopen(arg, "rb")) == NULL) {
    c_msg(ERR_FAILURE, TRUE);
    pressreturn();
    bbs_set_mode(M_UNDEFINED);
    return FULLUPDATE;
  }

  if ((out = fopen(c_tempfile, "w")) == NULL) {
    c_msg(ERR_FAILURE, TRUE);
    pressreturn();
    bbs_set_mode(M_UNDEFINED);
    return FULLUPDATE;
  }
  while ((c=getc(in)) != EOF)
    putc(c, out);
  Ftpfclose(in);
  fclose(out);

  clear();

  rc = DoPostSend(subject, c_tempfile, 0);

  clear();
  move(0,0);
  switch (rc) {
  case -3:
    c_msg(ERR_ZERO, TRUE);
    break;
  case -2:
    c_msg(ERR_FAILURE, TRUE);
    break;
  case -1:
    c_msg(ERR_FILE, TRUE);
    break;
  case 0:
    c_msg(INFO_POSTED, TRUE);
    retcode |= FETCHNEW;
    break;
  }
  pressreturn();

  /* If docheck is true,  we came in from the main menu -- else, read menu */
  bbs_set_mode(M_UNDEFINED);
  return retcode;
}

GenericPost(docheck)
int docheck;
{
  int rc;
  LONG retcode = FULLUPDATE;
  TITLE subject;
  extern int lang;
  
  clear();
  if (docheck) {
    SHORT flags;
    if (currboard[0] == '\0') {
      c_msg(ERR_NOT_SELECTED, TRUE);
      pressreturn();
      return FULLUPDATE;
    }
    if (bbs_test_board(currboard, &flags) != S_OK) {
      c_msg(ERR_NOT_EXIST, TRUE);
      pressreturn();
      return FULLUPDATE;
    }
    if (!BITISSET(flags, OPEN_POST)) {
      c_msg(ERR_PERM, TRUE);
      pressreturn();
      return FULLUPDATE;
    }
  }
  bbs_set_mode(M_POSTING);
  c_msg(INFO_POSTING, TRUE);
  if (lang) {
    getdata(1, 0, "Á¦¸ñ: ", subject, sizeof(subject), DOECHO, 0);
  } else {
    getdata(1, 0, "Subject: ", subject, sizeof(subject), DOECHO, 0);
  }
  rc = DoPostSend(subject, (char *)NULL, 0);
  clear();
  move(0,0);
  switch (rc) {
  case -3:
    c_msg(ERR_ZERO, TRUE);
    break;
  case -2:
    c_msg(ERR_FAILURE, TRUE);
    break;
  case -1:
    c_msg(ERR_FILE, TRUE);
    break;
  case 0:
    c_msg(INFO_POSTED, TRUE);
    retcode |= FETCHNEW;
    break;
  }
  pressreturn();
  /* If docheck is true,  we came in from the main menu -- else, read menu */
  bbs_set_mode(docheck ? M_UNDEFINED : M_READING);
  return retcode;
}

Post()
{
  int rc;
  rc = GenericPost(1);
  return (rc);
}

/*ARGSUSED*/
PostMessage(hptr, currmsg, numrecs, openflags)
HEADER *hptr;
int currmsg, numrecs, openflags;
{
  int rc;
  if (!BITISSET(openflags, OPEN_POST)) {
    bell();
    return DONOTHING;
  }
  rc = GenericPost(0);   /* no need to check post privilege -- we do */
  return (rc);
}

/*ARGSUSED*/
ReadMenuSelect(hptr, currmsg, numrecs, openflags)
HEADER *hptr;
int currmsg, numrecs, openflags;
{
  return (SelectBoard());
}

GenericPostReply(hptr, msgsrc)
HEADER *hptr;
char *msgsrc;
{
  TITLE subject;
  char ans[4];
  int rc, retcode = FULLUPDATE;
  PATH msgfile;
  extern int lang;

  clear();

  if (msgsrc == NULL) {
    if (bbs_read_message(hptr->fileid, msgfile) != S_OK) {
      c_msg(ERR_FILE, TRUE);
      pressreturn();
      return retcode;
    }
  }
  else strcpy(msgfile, msgsrc);

  move(1,0);
  bbs_set_mode(M_POSTING);
  c_msg(INFO_REPLY, TRUE);
  if (lang)
    getdata(0, 0, "Á¦¸ñ: ", subject, sizeof(subject), DOECHO, 0);
  else
    getdata(0, 0, "Title: ", subject, sizeof(subject), DOECHO, 0);

  if (*subject == '\0') {
    if (strncasecmp(hptr->title, "Re:", 3)) {
      strcpy(subject, "Re: ");
      strncat(subject, hptr->title, TITLELEN-5);
    }
    else strncpy(subject, hptr->title, TITLELEN-1);
    move(0,0);
    if (lang)
      prints("Á¦¸ñ: %s\n", subject);
    else
      prints("Title: %s\n", subject);
  }    

  if (lang)
    getdata(1, 0, "º»¹®À» Æ÷½ºÆÃ¿¡ Æ÷ÇÔ½ÃÅ³±î¿ä (Y/N)? [N]: ",
	  ans, sizeof(ans), DOECHO, 0);
  else
    getdata(1, 0, "Include message text in followup (Y/N)? [N]: ",
	  ans, sizeof(ans), DOECHO, 0);
  if (*ans == 'Y' || *ans == 'y') {
    AnnotateMessageBody(c_tempfile, msgfile);
  }

  rc = DoPostSend(subject, c_tempfile, 1);
  clear();
  move(0,0);
  switch (rc) {
  case -3:
    c_msg(ERR_ZERO, TRUE);
    break;
  case -2:        
    c_msg(ERR_FAILURE, TRUE);
    break;
  case -1:
    c_msg(ERR_FILE, TRUE);
    break;
  case 0:
    c_msg(INFO_POSTED, TRUE);
    retcode |= FETCHNEW;
    break;
  }
  pressreturn();
  bbs_set_mode(M_READING);
  return retcode;
}    

/*ARGSUSED*/
PostReply(hptr, currmsg, numrecs, openflags)
HEADER *hptr;
LONG currmsg, numrecs, openflags;
{
  return (GenericPostReply(hptr, NULL));
}

/*ARGSUSED*/
PostDelete(hptr, currmsg, numrecs, openflags)
HEADER *hptr;
int currmsg, numrecs, openflags;
{
  int rc = FULLUPDATE;
  char ans[4];
  extern int lang;

  if (strcmp(myinfo.userid,hptr->owner) && !BITISSET(openflags,OPEN_MANAGE)) {
    bell();
    return DONOTHING;
  }
  clear();
  c_msg(INFO_DELETING, TRUE);
  if (lang)
  {
    getdata(2,0,"Á¤¸» Áö¿ï±î¿ä (Y/N)? [N]: ",ans,sizeof(ans),DOECHO, 0);
  }
  else
  {
    getdata(2,0,"Are you sure (Y/N)? [N]: ",ans,sizeof(ans),DOECHO, 0);
  }
  move(4,0);
  if (*ans != 'Y' && *ans != 'y') {
    c_msg(INFO_CANCELLED, TRUE);
  } else {
    if (bbs_delete_message(hptr->fileid) == S_OK) {
      c_msg(INFO_DELETED, TRUE);
      rc |= FETCHNEW;
    } else {
      c_msg(ERR_FAILURE, TRUE);
    }
  }
  bbslog(2, "DELETEPOST %d by %s\n", hptr->fileid, myinfo.userid);
  pressreturn();
  return rc;
}

/*ARGSUSED*/
PostDelRange(hptr, currmsg, numinbox, openflags)
HEADER *hptr;
int currmsg, numinbox, openflags;
{
  int rc = FULLUPDATE;
  char ans[5];
  SHORT n1 = 0, n2 = 0, deleted;
  if (!BITISSET(openflags, OPEN_MANAGE)) {
    bell();
    return DONOTHING;
  }
  clear();
  if (numinbox <= 0) {
    c_msg(ERR_NOTHING, TRUE);
    pressreturn();
    return rc;
  }
  c_msg(INFO_DELETE_RANGE, TRUE);
  do {
    if (getdata(2,0,"Enter number of first message to delete: ",
	    ans,sizeof(ans),DOECHO,1) == -1) return rc;
    n1 = atoi(ans);
    if (n1 <= 0 || n1 > numinbox) {
      bell();
      move(3,0);
      c_msg(ERR_RANGE, TRUE);
    }        
  } while (n1 <= 0 || n1 > numinbox);
  do {
    if (getdata(3,0,"Enter number of last message to delete: ",
	    ans,sizeof(ans),DOECHO,1) == -1) return rc;
    n2 = atoi(ans);
    if (n2 < n1 || n2 > numinbox) {
      bell();
      move(4,0);
      c_msg(ERR_RANGE, TRUE);
    }        
  } while (n2 < n1 || n2 > numinbox);
  
  move(4,0);
  clrtobot();
  getdata(4,0,"Are you sure (Y/N)? [N]: ",ans,sizeof(ans),DOECHO,0);
  move(6,0);
  if (*ans != 'Y' && *ans != 'y') {
    c_msg(INFO_CANCELLED, TRUE);
  } else {
    if (bbs_delete_range(n1, n2, &deleted) == S_OK) {
      c_msg(INFO_DELETED, TRUE);
      rc |= FETCHNEW;
    } else {
      c_msg(ERR_FAILURE, TRUE);
    }
  }
  pressreturn();
  return rc;
}

/*ARGSUSED*/
PostMark(hptr, currmsg, numrecs, openflags)
HEADER *hptr;
int currmsg, numrecs, openflags;
{
  SHORT ismarked = BITISSET(hptr->flags, FILE_MARKED);
  if (bbs_mark_message(hptr->fileid, !ismarked) != S_OK) return DONOTHING;
  if (ismarked) BITCLR(hptr->flags, FILE_MARKED);
  else BITSET(hptr->flags, FILE_MARKED);
  return PARTUPDATE;
}            

#define	UNMARKED_FILE_MODE	0660

/*ARGSUSED*/
PostEdit(hptr, currmsg, numrecs, openflags)
HEADER *hptr;
int currmsg, numrecs, openflags;
{
  struct stat stbuf;
  PATH msgfile;
  int fd;

  if (strcmp(myinfo.userid,hptr->owner) && !BITISSET(openflags,OPEN_MANAGE)) {
    bell();
    return DONOTHING;
  }
  if (bbs_read_message(hptr->fileid, msgfile) != S_OK) {
    c_msg(ERR_FILE, TRUE);
    pressreturn();
    return FULLUPDATE;
  }
  CopyMessageBody(c_tempfile, msgfile);
  if (Edit(c_tempfile)) { 
    c_msg(ERR_EDIT, TRUE);
    pressreturn();
    return FULLUPDATE;
  }
  if (stat(c_tempfile, &stbuf) != 0 || stbuf.st_size == 0) {
    unlink(c_tempfile);
    c_msg(ERR_ZERO, TRUE);
    pressreturn();
    return FULLUPDATE;
  }
  unlink (msgfile);
  fd = open(msgfile,  O_WRONLY|O_CREAT|O_EXCL, UNMARKED_FILE_MODE);
  if (fd == -1) {
    unlink(c_tempfile);
    c_msg(ERR_FILE, TRUE);
    pressreturn();
    return FULLUPDATE;
  }
  (void) write_post_headers(fd, hptr, myinfo.username, currboard);
  if (append_file (fd,  c_tempfile) == -1) {
    close(fd);
    unlink(c_tempfile);
    c_msg(ERR_FILE, TRUE);
    pressreturn();
    return FULLUPDATE;
  }
  close(fd);

  if (bbs_update_message(hptr->fileid, msgfile) == S_OK) {
    c_msg(INFO_EDITTED, TRUE);
  } else {
    c_msg(ERR_EDIT, TRUE);
  }
  return FULLUPDATE;
}            

/*ARGSUSED*/
PostDisplay(hptr, currmsg, numrecs, openflags)
HEADER *hptr;
int currmsg, numrecs, openflags;
{
  extern int lang;
  char ans[2], promptstr[80];
  PATH msgfile;
  int rc = FULLUPDATE;
  int done = 0, replied = 0, marked = 0;
#if !NO_POST_FOLLOWUP
  int posted = 0;
#endif
#if REMOTE_CLIENT
  int saved = 0;
#endif
  if (bbs_read_message(hptr->fileid, msgfile) != S_OK) {
    c_msg(ERR_FILE, TRUE);
    pressreturn();
    return rc;
  }
  BITCLR(hptr->flags, FILE_UNREAD);
  clear();
  More(msgfile, 0);
  while (!done) {
    promptstr[0] = '\0';
    if (!replied && HasPerm(C_MAIL)) 
    {
      if (lang)
        strcat(promptstr, "[M]-ÆíÁö·Î ´ä, ");
      else
        strcat(promptstr, "Mail reply, ");
    }
#if !NO_POST_FOLLOWUP
    if (!posted && BITISSET(openflags, OPEN_POST))
    {
      if (lang)
        strcat(promptstr, "[P]-´ä¿Ã¸®±â, ");
      else
        strcat(promptstr, "Post followup, ");
    }
#endif
#if REMOTE_CLIENT
    if (!saved) strcat(promptstr, "Save, ");
#endif

    if (!marked && BITISSET(openflags, OPEN_MANAGE))
      strcat(promptstr, 
	     BITISSET(hptr->flags, FILE_MARKED) ? "unmarK, " : "marK, ");

    if (BITISSET(openflags, OPEN_MANAGE) || 
             !strcmp(hptr->owner, myinfo.userid))
    {
      if (lang)
        strcat(promptstr, "[D]-»èÁ¦, ");
      else
        strcat(promptstr, "Delete, ");
    }

    if (promptstr[0] == '\0') {
      pressreturn();
      break;
    }
    else
    {
      if (lang)
        strcat(promptstr, "[C]-°è¼Ó? [C]: ");
      else
        strcat(promptstr, "or Continue? [C]: ");
    }
    getdata(t_lines-1, 0, promptstr, ans, sizeof(ans), DOECHO, 0);
    switch (*ans) {
    case 'm': case 'M': 
      if (replied) done = 1;
      else {
	rc |= MailReply(hptr, currmsg, numrecs, openflags);
	replied = 1;
      }
      break;
#if !NO_POST_FOLLOWUP
    case 'p': case 'P':
      if (posted) done = 1;
      else {
	rc |= GenericPostReply(hptr, msgfile);
	posted = 1;
      }
      break;
#endif
#if REMOTE_CLIENT
    case 's': case 'S':
      if (saved) done = 1;
      else {
	SaveFile(msgfile);
	saved = 1;
      }
      break;
#endif
    case 'k': case 'K': 
      if (marked) done = 1;
      else {
	PostMark(hptr, currmsg, numrecs, openflags);
	marked = 1;
      }
      break;
    case 'd': case 'D': 
      if (marked) done = 1;
      else rc |= PostDelete(hptr, currmsg, numrecs, openflags);
      /* fall through */
    default:
      done = 1;
      break;
    }
  }
  return rc;
}
;
}

GenericPostReply(hptr, msgsrc)
HEADER *hptr;
char *msgsrc;
{
  TITLE subject;
  char ans[4];
  int rc, retcode = FULLUPDATE;
  PATH msgfile;
  extern int lang;

  cDarkNET-1.08/c_talk.c                                                                                  644   21270   21270        31532  5751536154   7511                                                                                                                                                                                                                                                                                                                                                                      
/*
Eagles Bulletin Board System
Copyright (C) 1994, Ray Rocker, rrrocker@rock.b11.ingr.com
                                rock@seabass.st.usm.edu
                                72673.2105@compuserve.com

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "client.h"
#include <signal.h>

#define TALK_MAX_COLS 128

int g_page_pending;
int g_page_need_notify;

struct talkwin {
  int firstln;
  int lastln;
  int currln;
  int firstcol;
  int lastcol;
  int currcol;
  char line[TALK_MAX_COLS];
  char buf[2];
};

#define MAX_HANDLED_LOGINS 20

struct usertopid {
  USEREC saved_urec;
  LONG pids[MAX_HANDLED_LOGINS];
  int count;
};

void
page_handler()
{
  signal(SIGUSR2, SIG_IGN);
  bell();
  bell();
  g_page_pending = 1;
  g_page_need_notify = 1;
  signal(SIGUSR2, page_handler);
}

PagePending()
{
  return g_page_pending;
}

/* We need this function to handle page requests in talk and chat mode.
   We only want to notify once, but need to keep the page request 
   around in case we want to go off and answer it. */

NewPagePending()
{
  if (g_page_need_notify) {
    g_page_need_notify = 0;
    return 1;
  }
  return 0;
}

PrintLoginEntry(num, urec)
int num;
USEREC *urec;
{
  prints("%2d %-12s  %-24s %-30s %s\n", num, urec->userid, 
	 urec->username, urec->fromhost, ModeToString(urec->mode));
}

/*ARGSUSED*/
PickLogin(indx, urec, info)
int indx;
USEREC *urec;
struct usertopid *info;
{
  if (info->count >= MAX_HANDLED_LOGINS) return ENUM_QUIT;
  info->pids[info->count++] = urec->pid;
  if (info->count == 1) {
    memcpy(&info->saved_urec, urec, sizeof(info->saved_urec));
    return S_OK;
  }        
  if (info->count == 2) {
    clear();
    PrintLoginEntry(1, &info->saved_urec);
  }
  PrintLoginEntry(info->count, urec);
  return S_OK;
}  

LONG
UseridToPid(userid)
char *userid;
{
  struct usertopid u2p;
  int x, y, indx;
  char ans[3];
  extern int lang;

  memset(&u2p, 0, sizeof u2p);
  bbs_enum_users(MAX_HANDLED_LOGINS, 0, userid, PickLogin, &u2p);
  if (u2p.count == 0) return (LONG)-1;
  else if (u2p.count == 1) return u2p.pids[0];
  /* Else, more than one. We must decide. */
  getyx(&y, &x);
  if (lang)
    getdata(y, x, "¾îµð¶û [1]?: ", ans, sizeof ans, DOECHO, 0);
  else
    getdata(y, x, "Which login [1]: ", ans, sizeof ans, DOECHO, 0);
  indx = atoi(ans);    
  if (indx < 1 || indx > u2p.count) indx = 1;
  return (u2p.pids[indx-1]);
}

Kick()
{
  NAME namebuf;
  LONG pid;
  char ans[4];
  NAMELIST userlist;
  extern int lang;

  move(2, 0);
  clrtobot();
  userlist = NULL;
  bbs_usernames(&userlist);
  if (lang)
    namecomplete(userlist, "´©±¼ Âû±î: ", namebuf);
  else
    namecomplete(userlist, "Kick whom: ", namebuf);
  if (namebuf[0] == '\0') {
    free_namelist(&userlist);
    return FULLUPDATE;
  }
  else if (!is_in_namelist(userlist, namebuf)) {
    c_msg(ERR_NOT_EXIST, TRUE);
    free_namelist(&userlist);
    pressreturn();
    return FULLUPDATE;
  }
  pid = UseridToPid(namebuf);
  if (pid == (LONG)-1) {
    c_msg(ERR_NO_LONGER_LOGGED, TRUE);
    free_namelist(&userlist);
    pressreturn();
    return FULLUPDATE;
  }
  if (lang)
    getdata(3, 0, "Á¤¸» (Y/N)? [N]: ", ans, sizeof ans, DOECHO, 0);
  else
    getdata(3, 0, "Are you sure (Y/N)? [N]: ", ans, sizeof ans, DOECHO, 0);
  if (*ans != 'Y' && *ans != 'y') {
    c_msg(ERR_FAILURE, TRUE);
    free_namelist(&userlist);
    pressreturn();
    return FULLUPDATE;
  }
  switch (bbs_kick_user(pid)) {
  case S_DENIED:
    c_msg(ERR_PERM, TRUE);
    break;
  case S_ILLEGAL:
    c_msg(ERR_FAILURE, TRUE);
    break;
  case S_NOTFOUND:
  case S_SYSERR:
    c_msg(ERR_NO_LONGER_LOGGED, TRUE);
    break;
  case S_OK:
    c_msg(INFO_KICKED, TRUE);
    break;
  }
  free_namelist(&userlist);
  pressreturn();
  return FULLUPDATE;
}

void
TalkAdvanceLine(ts)
struct talkwin *ts;
{
  if (++ts->currln > ts->lastln) ts->currln = ts->firstln;
  move((ts->currln == ts->lastln ? ts->firstln : ts->currln+1), 0);
  clrtoeol();
  move(ts->currln, 0);
  clrtoeol();
}

DoTalkChar(c, ts)
char c;
struct talkwin *ts;
{
  unsigned char ch;
  static unsigned char buf[2];

  ch = (unsigned char)c;

  /* This function handles backspaces, newlines, and printables. */
  move(ts->currln, ts->currcol);
  switch (ch) {
  case CTRL('H'):
  case 127:
    ts->buf[0] = '\0';
    if (ts->currcol == 0) return -1;
    move(ts->currln, --ts->currcol);
    addch(' ');
    ts->line[ts->currcol] = '\0';
    if (ts->currcol > 0 && isHan(ts->line, ts->currcol-1) == 1) {
      move(ts->currln, --ts->currcol);
      addch(' ');
      ts->line[ts->currcol] = '\0';
    }
    move(ts->currln, ts->currcol);
    break;

  case '\n':
  case '\r':
    if (ts->buf[0] && ts->buf[1]) {
	move(ts->currln, ts->currcol++);
	addch(ts->buf[0]);
	move(ts->currln, ts->currcol);
	addch(ts->buf[1]);
	refresh();
    }
    ts->buf[0] = '\0';
    ts->currcol = 0;
    TalkAdvanceLine(ts);
    memset(ts->line, 0, sizeof ts->line);
    break;

  default:
    if (myisprint(ch)) {
      if (ts->currcol < ts->lastcol) {
        ts->line[ts->currcol] = ch;
	if (isHan(ts->line, ts->currcol) == 0) {
	  ts->buf[0] = '\0';
	  ts->currcol++;
	  addch(ch);
	} else {
	  if (ts->buf[0]) {
	    ts->buf[1] = ch;
	    ts->buf[2] = '\0';
	    ts->line[ts->currcol++] = ts->buf[0];
	    ts->line[ts->currcol++] = ts->buf[1];
	    prints(ts->buf);
	    ts->buf[0] = '\0';
	  } else {
	    ts->line[ts->currcol] = '\0';
	    ts->buf[0] = ch;
	    ts->buf[1] = '\0';
	    return 0;
	  }
	}
      } else {
        char save[TALK_MAX_COLS];
        int i = ts->currcol;

        ts->line[i] = ch;
	memset(save, '\0', sizeof save);
        memcpy(save, ts->line, sizeof save);
        while (i && save[i] != ' ') i--;
        if (i == 0) {
  	  memset(ts->line, 0, sizeof(ts->line));
	  ts->currcol = 1;
	  TalkAdvanceLine(ts);
	  addch(ch);
	  ts->buf[0] = '\0';
        } else {
	  move(ts->currln, i);
	  clrtoeol();
	  ts->currcol -= i;
	  memset(ts->line, 0, sizeof(ts->line));
	  memcpy(ts->line, &save[i+1], ts->currcol);
	  if (isHan(ts->line, ts->currcol) == 0) {
	    ts->buf[0] = '\0';
	  } else {
	    if (ts->buf[0]) {
	      ts->buf[1] = ch;
	      ts->buf[2] = '\0';
	      ts->line[ts->currcol++] = ts->buf[0];
	      ts->line[ts->currcol++] = ts->buf[1];
	    } else {
	      ts->buf[0] = ch;
	      ts->buf[1] = '\0';
	    }
	    ts->line[ts->currcol] = '\0';
	  }
	  TalkAdvanceLine(ts);
	  prints(ts->line);
        }
      }
    } else {
      ts->buf[0] = '\0';
      return -1;
    }
    break;
  }
  refresh();
  return 0;
}

DoTalkString(s, tw)
char *s;
struct talkwin *tw;
{
  for (; s && *s; s++)
   DoTalkChar(*s, tw);
  return 0;
}

talk_show_page_request(ln)
int ln;
{
  USEREC urec;
  char buf[80];
  extern int lang;

  if (bbs_get_talk_request(&urec, NULL, NULL) != S_OK) {
    /* Whoever was paging stopped. */
    return 0;
  }
  if (lang)
    sprintf(buf, " %s (%s) °¡ ºÒ·¯¿ä!", urec.userid, urec.username);
  else
    sprintf(buf, " Being paged by %s (%s)", urec.userid, urec.username);
  move(ln, 3);
  prints(buf);
  move(ln, t_columns-20);  
  if (lang)
    prints("[Áö¿ì·Á¸é CTRL-R]");
  else
    prints("[CTRL-R to erase]");
  return 0;
}

_talk_enum_users(count, urec, tw)
int count;
USEREC *urec;
struct talkwin *tw;
{
  char buf[NAMELEN+10];
  sprintf(buf, ",%s%s [%c]", BITISSET(urec->flags, FLG_CLOAK) ? " #" : " ",
          urec->userid, ModeToChar(urec->mode));
  DoTalkString((tw->currcol == 0 ? buf+2 : buf), tw);
  memset(tw->buf, '\0', sizeof tw->buf);
  return S_OK;
}
    
talk_user_list(tw)
struct talkwin *tw;
{
  extern int lang;

  if (lang)
    DoTalkString("\n*** ÇöÀç »ç¿ëÀÚ ***\n", tw);
  else
    DoTalkString("\n*** Users currently online ***\n", tw);
  memset(tw->buf, '\0', sizeof tw->buf);

  bbs_enum_users(10, 0, NULL, _talk_enum_users, tw);

  DoTalkChar('\n', tw);
  memset(tw->buf, '\0', sizeof tw->buf);
  return 0;
}    

DrawDivider(ln)
int ln;
{
  register int i, j;
  move(ln, 0);
  for (i=0, j=t_columns-1; i<j; i++) {
    addch('-');
  }
  refresh();
}

DoTalk(sock)
int sock;
{
  int i, ch, cc;
  int divider;
  char c;  
  char incoming[256];
  struct talkwin me, them;

  divider = (t_lines-1) / 2;
  me.currln = me.firstln = 0;
  me.lastln = divider - 1;
  them.currln = them.firstln = divider + 1;
  them.lastln = t_lines - 1;
  me.currcol = me.firstcol = them.currcol = them.firstcol = 0;
  me.lastcol = them.lastcol = 
    (t_columns > TALK_MAX_COLS ? TALK_MAX_COLS : t_columns - 2);
  memset(me.line, 0, sizeof me.line);
  memset(me.buf, 0, sizeof me.buf);
  memset(them.line, 0, sizeof them.line);
  memset(them.buf, 0, sizeof them.buf);

  clear();
  DrawDivider(divider);
  move(0, 0);
  add_io(sock, 0);
  while (1) {
    ch = igetch();
    if (NewPagePending()) {
      talk_show_page_request(divider);
      move(me.currln, me.currcol);
    }
    if (ch == -1) {
      /* error in igetch! */
      break;
    }
    if (ch == I_OTHERDATA) {
      /* pending input on sock */
      cc = recv(sock, incoming, sizeof incoming, 0);
      if (cc <= 0) {
	/* other side closed connection */
	break;
      }
      for (i=0; i<cc; i++) {
	DoTalkChar(incoming[i], &them);
      }
    }
    else {
      /* something we typed */
      c = (char)ch;
      if (DoTalkChar(c, &me) == 0) {
	if (send(sock, &c, 1, 0) != 1) {
	  /* connection broken */
	  break;
	}
      }
      else if (c == CTRL('C') || c == CTRL('D')) {
	/* we're ending the talk */
	break;
      }
      else if (c == CTRL('R')) {
	/* clear message on divider line */
	DrawDivider(divider);
	move(me.currln, me.currcol);
      }
      else if (c == CTRL('U')) {
	/* show a brief user list */
	talk_user_list(&me);
      }
      else {
	/* a character we don't like, at this time */
	bell();
      }
    }
  }
  add_io(0,0);

  bbs_exit_talk();
  close(sock);
  return 0;
}

Talk()
{
  NAME namebuf;
  LONG pid;
  LONG sock;
  int rc;
  NAMELIST userlist;
  extern int lang;

  move(2, 0);
  clrtobot();

  userlist = NULL;
  bbs_usernames(&userlist);
  if (lang)
    namecomplete(userlist, "´©±¸¶û ÇÒ±î¿ä: ", namebuf);
  else
    namecomplete(userlist, "Page whom: ", namebuf);
  if (namebuf[0] == '\0') {
    free_namelist(&userlist);
    return FULLUPDATE;
  }
  else if (!is_in_namelist(userlist, namebuf)) {
    c_msg(ERR_NOT_EXIST, TRUE);
    free_namelist(&userlist);
    pressreturn();
    return FULLUPDATE;
  }
  pid = UseridToPid(namebuf);
  if (pid == (LONG)-1) {
    c_msg(ERR_NO_LONGER_LOGGED, TRUE);
    free_namelist(&userlist);
    pressreturn();
    return FULLUPDATE;
  }
  clear();
  if (lang)
    prints("%s ¸¦ ºÎ¸£´Â ÁßÀÔ´Ï´Ù.. Áß´ÜÇÏ·Á¸é CTRL-D ¸¦ Ä¡¼¼¿ä.\n", namebuf);
  else
    prints("Paging %s. Press CTRL-D to abort.\n", namebuf);
  refresh();
  do {
    bell();
    switch (rc = bbs_talk(pid, 0, &sock)) {
    case S_DISABLED:
      free_namelist(&userlist);
      return FULLUPDATE;
    case S_INVALID:
      c_msg(ERR_PAGER_OFF, TRUE);
      break;    
    case S_DENIED:
      c_msg(ERR_REFUSED, TRUE);
      break;
    case S_NOTFOUND:
      c_msg(ERR_NO_LONGER_LOGGED, TRUE);
      break;
    case S_SYSERR:
      c_msg(ERR_FAILURE, TRUE);
      break;
    case S_EXISTS:
      if (lang)
        prints("¶î¶îÇÏ±ä ÀÓ¸¶ ³Ê¶û ³Ê°¡ ÅäÅ©ÇÏ³Ä?\n");
      else
        prints("Huh? You want to talk to yourself?\n");
      break;
    case S_ILLEGAL:
      c_msg(ERR_PERM, TRUE);
      break;
    case S_TEMPFAIL:
      c_msg(ERR_TMP_PAGER_OFF, TRUE);
      break;
    case S_CMDTIMEOUT:
      c_msg(ERR_RING_AGAIN, TRUE);
      refresh();
      break;
    case S_OK:
      DoTalk((int)sock);
      break;
    }
  } while (rc == S_CMDTIMEOUT);
  if (rc != S_OK && rc != S_CMDTIMEOUT)
    pressreturn();
  free_namelist(&userlist);
  return FULLUPDATE;
}

Answer()
{
  USEREC urec;
  LONG addr, sock;
  SHORT port;
  char ans[4];
  extern int lang;
  
  g_page_pending = g_page_need_notify = 0;

  if (bbs_get_talk_request(&urec, &addr, &port) != S_OK) {
    /* Whoever was paging stopped. */
    return 0;
  }

  clear();
  if (lang) {
    prints("%s (%s) ÇÏ°í ÀÌ¾ß±â ÇÒ±î¿ä?", urec.userid, urec.username);
    getdata(1, 0, "(Y)-ÇØ, (N)-¸»¾î [Y]?: ", ans, sizeof ans, DOECHO, 0);
  } else {
    prints("Would you like to talk to %s (%s)?", urec.userid, urec.username);
    getdata(1, 0, "(Y)es/(N)o [Y]: ", ans, sizeof ans, DOECHO, 0);
  }
  if (*ans == 'n' || *ans == 'N') {
    bbs_refuse_page(addr, port);
    return 1;
  }

  if (bbs_accept_page(addr, port, &sock) != S_OK) {
    c_msg(ERR_NO_LONGER_PAGED, TRUE);
    pressreturn();
    return 1;
  }

  DoTalk((int)sock);
  return 1;
}
ts->currcol);
    addch(' ');
    ts->line[ts->currcol] = '\0';
    if (ts->currcol > 0 && isHan(ts->line, ts->currcol-1) == 1) {
      move(ts->currln, --ts->currcolDarkNET-1.08/c_users.c                                                                                 644   21270   21270       104226  6044622160   7725                                                                                                                                                                                                                                                                                                                                                                      /*
Eagles Bulletin Board System
Copyright (C) 1994, Ray Rocker, rrrocker@rock.b11.ingr.com
                                rock@seabass.st.usm.edu
                                72673.2105@compuserve.com

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "client.h"
#include <malloc.h>
#include <signal.h>
#include <time.h>

NAMELIST acctlist = NULL;
extern LOGININFO myinfo;     /* for idle timeout in Monitor */

static char *day_of_week[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
static char *mon_of_year[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};

CheckUserid(userid)
char *userid;
{
  ACCOUNT acct;
  if (userid[0] == '\0') return 1;
  if (!is_valid_userid(userid)) return 3;
  if (bbs_query(userid, &acct) != S_NOTFOUND) return 2; 
  return 0;
}

PromptForAccountInfo(acct, for_self)
ACCOUNT *acct;
int for_self;
{
  PASSWD passcfm;
  char ans[4];
  int lineno, userok = 0, passok, cfm = 1;
  extern int lang;

  memset(acct, 0, sizeof(*acct));
  if (for_self) {
    prints("Welcome, new user! Enter a userid, 1-%d characters, no spaces.\n",
	   NAMELEN);
    lineno = 0;
  }
  else lineno = 3;
  while (!userok) {
    if (getdata(lineno,0,"Userid: ",acct->userid,NAMELEN+1,DOECHO,1) == -1)
      return -1;

    switch (CheckUserid(acct->userid)) {
    case 0: userok = 1;
      break;
    case 1: if (!for_self) return -1;   /* bail out */
      break;
    case 2: prints("Userid is already in use. Try another.\n");
      break;
    case 3: prints("Invalid character in userid. Try another.\n");
      break;
    }
  }
  if (lineno) lineno++;
  while (cfm) {
    do {
      getdata(lineno,0,"Enter Passwd: ", acct->passwd, PASSLEN+1, NOECHO, 0);
      passok = is_valid_password(acct->passwd);
      if (!passok) prints("That's not an acceptable password.\n");
    } while (!passok);
    getdata(lineno+1,0,"Confirm Passwd: ", passcfm, PASSLEN+1, NOECHO, 0);
    if (cfm = strcmp(acct->passwd, passcfm))
      prints("\nPasswords did not match! Try again.\n");
  }
  if (lineno) lineno++;
  getdata(lineno,0,"User Name: ", acct->username, UNAMELEN+1, DOECHO, 0);
  if (lineno) lineno++;
  getdata(lineno,0,"Term type, IYAGI uses 'iyagi' (default=vt100): ",
	  acct->terminal, TERMLEN+1, DOECHO, 0);
  if (!for_self) {
    if (lineno) lineno++;
    getdata(lineno,0,"Real Name: ", acct->realname, RNAMELEN+1,DOECHO,0);
    if (lineno) lineno++;
    getdata(lineno,0,"Postal Address: ", acct->address, ADDRLEN+1,DOECHO,0);
  }
  if (lineno) lineno++;
  getdata(lineno,0,"E-mail address, if any: ",acct->email,MAILLEN+1,DOECHO,0);
  if (lineno) lineno++;
  cfm = 1;
  while (cfm) {
    char buf[2];
    getdata(lineno+1,0,"Language(Hangul=0/English=1): ", buf, 2, DOECHO, 0);
    if (cfm = (*buf != '0' && *buf != '1'))
      prints("\nChoice is '0' for Hangul or '1' for English! Try again.\n");
    else {
      if (*buf == '0') {
	strcpy(acct->lang, "Kr");
	acct->flags |= FLG_KOREAN;
	lang = 1;
      } else {
	strcpy(acct->lang, "Eng");
	acct->flags &= ~FLG_KOREAN;
	lang = 0;
      }
    }
  }
  return 0;
}

/*ARGSUSED*/
AllUsersFunc(acct, info)
ACCOUNT *acct;
struct enum_info *info;
{
  extern char *Ctime __P((time_t *));

  prints("%-14s %-30s %c %s\n", acct->userid, acct->username,
   BITISSET(acct->flags, FLG_EXEMPT) ? 'X': ' ',
   (acct->lastlogin == 0) ? "":(char*)Ctime((time_t *)&acct->lastlogin));

  info->currline++;
  info->count++;

  if (info->currline > info->bottomline) {
    int ch;
    standout();
    c_msg(INFO_MORE, FALSE);
    standend();
    clrtoeol();
    while((ch = igetch()) != EOF) {
      if(ch == '\n' || ch == '\r' || ch == ' ')
	break;
      if(toupper(ch) == 'Q') {
	move(info->currline, 0);
	clrtoeol();
	return ENUM_QUIT;
      } else bell();
    }
    info->currline = info->topline;
    move (info->currline, 0);
  }
  return S_OK;
}

#define	PASSFILE_LINELEN	80
#define	PASSFILE		"etc/passwds"

AllUsers()
{
  struct enum_info info;
  char rec[PASSFILE_LINELEN+1];
  FILE *fp;
  ACCOUNT acct;
  extern int lang;

  info.count = 0;
  info.topline = info.currline = 4;
  info.bottomline = t_lines-2;
  move(2,0);
  clrtobot();
  move(3,0);
  standout();
  if (lang)
    prints("%-14s %-30s   %s\n","»ç¿ëÀÚ", "»ç¿ëÀÚ ÀÌ¸§", "¸¶Áö¸· ·Î±ä");
  else
    prints("%-14s %-30s   %s\n","User Id", "User Name", "Last Login");
  standend();

  if ((fp = fopen (PASSFILE, "r")) == NULL)
  {
    c_msg(ERR_FILE, TRUE);
    return PARTUPDATE;
  }
  while (fgets(rec, PASSFILE_LINELEN, fp))
  {
    if (*rec == '#' || myisspace(*rec)) continue;
    passent_to_account(rec, &acct);
    get_lastlog_time (acct.userid, &acct.lastlogin);
    hide_priv_acct_fields (&acct);
    if (AllUsersFunc (&acct, &info) == ENUM_QUIT)
	break;
  }
  fclose(fp);
  clrtobot();
  move(t_lines-1, 0);
  if (lang)
    prints("%d %s ³ª¿­µÇ¾ú½À´Ï´Ù\n", info.count, info.count==1?"»ç¿ëÀÚ°¡":"»ç¿ëÀÚµéÀÌ");
  else
    prints("%d %s displayed\n", info.count, info.count==1?"user":"users");
  return PARTUPDATE;
}

/*ARGSUSED*/
OnlineUsersFunc(indx, urec, info)
int indx;
USEREC *urec;
struct enum_info *info;
{
  char buf[16];
  extern int lang;

  if (info->topline == info->currline) {
    char head[256];
    register int i,j;

    j = t_columns - 1;
    move(info->topline-1, 0);
    if (lang)
      sprintf(head, "%-12s   %-25s %-20s %s %s %s", 
	   "»ç¿ëÀÚ", "      ÀÌ¸§", "¾îµð¼­", "P", " ¾ð¾î","¹¹ÇÏ³ª");
    else
      sprintf(head, "%-12s   %-25s %-20s %s %s %s", 
	   "User Id", "      User Name", "From", "P", " Lang", "Mode");
    for (i=strlen(head), j=t_columns-1; i<j; i++)
	head[i] = ' ';
    head[i] = '\0';
    standout();
    prints("%s\n", head);
    standend();
  }

  if (lang)
  {
    if (BITISSET(urec->flags, FLG_KOREAN))
      strcpy(buf, " ÇÑ±Û  ");
    else
      strcpy(buf, " ¿µ¾î  ");
  }
  else
  {
    if (BITISSET(urec->flags, FLG_KOREAN))
      strcpy(buf, " Kr  ");
    else
      strcpy(buf, " Eng ");
  }
  prints("%-12s %c %-25s %-20s %s %s %s\n",
	urec->userid, 
	(BITISSET(urec->flags, FLG_CLOAK) ? '#': ' '), 
	urec->username, urec->fromhost, 
	(BITISSET(urec->flags, FLG_NOPAGE)? "N": " "),
        buf,
        ModeToString((urec->mode & 0xff)));

  info->currline++;
  info->count++;

  if (info->currline > info->bottomline) {
    int ch;
    standout();
    c_msg(INFO_MORE, FALSE);
    standend();
    clrtoeol();
    while((ch = igetch()) != EOF) {
      if(ch == '\n' || ch == '\r' || ch == ' ')
	break;
      if(toupper(ch) == 'Q') {
	move(info->currline, 0);
	clrtoeol();
	return ENUM_QUIT;
      }
      else bell();
    }
    info->currline = info->topline;
  }
  return S_OK;
}

OnlineUsers()
{
  struct enum_info info;
  extern int lang;

  info.count = 0;
  info.topline = info.currline = 4;
  info.bottomline = t_lines-2;
  move(2,0);
  clrtobot();
  move(3,0);
  bbs_enum_users(t_lines-5, 0, NULL, OnlineUsersFunc, &info);
  clrtobot();
  move(t_lines-1, 0);
  if (lang)
    prints("%d ¸íÀÌ »ç¿ëÁßÀÔ´Ï´Ù\n", info.count);
  else
    prints("%d %s displayed\n", info.count, info.count==1?"user":"users");
  return PARTUPDATE;
}

struct shorturec {
  NAME userid;
  LONG pid;
  SHORT flags;
  SHORT mode;
  short wasfound;
  short found;
  short active;
} *global_ulist;

static int global_ulist_sz;

SetupGlobalList()
{
  global_ulist_sz = (t_lines - 4) * 4;
  global_ulist = 
    (struct shorturec *)calloc(global_ulist_sz, sizeof(struct shorturec));
  if (global_ulist == NULL)
    {
      move(2,0);
      c_msg(ERR_MEM, TRUE);
      return -1;
    }
  return 0;
}

/*ARGSUSED*/
FillShortUserList(indx, urec, arg)
int indx;
USEREC *urec;
void *arg;
{
  int i;
  for (i=0; i<global_ulist_sz; i++)
    if (global_ulist[i].pid == urec->pid) {
      global_ulist[i].flags = urec->flags;
      global_ulist[i].mode = urec->mode;
      global_ulist[i].found = 1;
      break;
    }
  if (i >= global_ulist_sz)
    for (i=0; i<global_ulist_sz; i++)
      if (!global_ulist[i].active)
	{
	  strcpy(global_ulist[i].userid, urec->userid);
	  global_ulist[i].pid = urec->pid;
	  global_ulist[i].flags = urec->flags;
	  global_ulist[i].mode = urec->mode;
	  global_ulist[i].active = global_ulist[i].found = 1;
	  break;
	}

  return S_OK;
}

DoShortUserList()
{
  int i, y = 6, x = 0, ucount = 0;
  time_t now;
  extern int lang;
  extern char *Ctime __P((time_t *));

  for (i=0; i<global_ulist_sz; i++) {
    global_ulist[i].wasfound = global_ulist[i].found;
    global_ulist[i].found = 0;
  }
  move(y, x);
  clrtobot();
  time(&now);

  bbs_enum_users(global_ulist_sz, 0, NULL, FillShortUserList, NULL);
  for (i=0; i<global_ulist_sz; i++)
    {
      if (global_ulist[i].found)
	{
	  prints("[%c]%s%-14s", ModeToChar(global_ulist[i].mode), 
                 BITISSET(global_ulist[i].flags, FLG_CLOAK) ? " #" : " ",
		 global_ulist[i].userid);
	  ucount++;
	}
      else if (global_ulist[i].wasfound) prints("%18s", " ");

      x+=18;
      if ((x+18) > t_columns)
	{
	  x=0; y++;
	}
      move(y, x);
    }
  move(t_lines-1, 0);
  if (lang)
    prints("%d ¸íÀÌ »ç¿ëÁß[%s]\n", ucount, (char*)Ctime(&now));
  else
    prints("%d user%s online at %s\n", ucount, (ucount==1?"":"s"), (char*)Ctime(&now));
  refresh();
  return ucount;
}

ShortList()
{
  int i;
  if (global_ulist)
  {
    free(global_ulist);
    global_ulist = NULL;
  }

  if (SetupGlobalList() == -1) return PARTUPDATE;
  DoShortUserList();
  memset(global_ulist, 0, global_ulist_sz * sizeof(*global_ulist));
  return PARTUPDATE;
}

struct shorturec *monitor_data;
int monitor_max;
int monitor_idle;
char global_modechar_key[256];

form_modechar_key()
{
  SHORT i, j;
  int left;
  char c, *s, buf[20];
  char c1,c2;
  strcpy(global_modechar_key, "Key:");
  left = sizeof(global_modechar_key) - 5;
  for (i=0, j=0; i<=BBS_MAX_MODE; i++) {
    c = ModeToChar(i);
    if (c == ' ') continue;
    s = ModeToString(i);
    sprintf(buf, " [%c]", c);
    if (myislower(c)) c1=toupper(c);
    if (myislower(*s)) c2=toupper(*s);
    if (c1 == c2) strncat(buf+4, s+1, 10);
    else strncat(buf+4, s, 10);
    if (left > strlen(buf)) {
      strcat(global_modechar_key, buf);
      left -= strlen(buf);
    j++;
    if ((j != 0) && ((j % 7) == 0))
      strcat(global_modechar_key, "\n");
    }
  }
  return 0;
}

static void monitor_refresh(sig)
int sig;
{
  int i, boottime;

  if (sig) signal(sig, SIG_IGN);
  boottime = myinfo.idletimeout*120;
  if (boottime && ((monitor_idle += MONITOR_REFRESH) > boottime)) {
    disconnect(EXIT_TIMEDOUT);
  }
  if (bbs_check_mail()) {
    move(0, t_columns - 17);
    standout();
    c_msg(INFO_MAIL, FALSE);
    standend();
    refresh();
  }
  DoShortUserList();
  for (i=0; i<global_ulist_sz; i++)
    if (!global_ulist[i].found) global_ulist[i].active = 0;

  signal(SIGALRM, monitor_refresh);
  alarm(MONITOR_REFRESH);
}

Monitor()
{
  void (*asig)();
  char ch;
  int saved_alarm;
  int i;

  if (global_modechar_key[0] == '\0') form_modechar_key();
  clear();
  refresh();
  move(0,0);
  c_msg(INFO_MONITOR, TRUE);
  standout();
  for (i=0; i<t_columns-1; i++) prints("-");
  standend();
  refresh();
  prints("\n");

  prints("%s", global_modechar_key);

  standout();
  for (i=0; i<t_columns-1; i++) prints("-");
  standend();
  prints("\n");

  if (global_ulist)
  {
    free(global_ulist);
    global_ulist = NULL;
  }
  if (SetupGlobalList() == -1) return PARTUPDATE;
  monitor_idle = 0;
  bbs_set_mode(M_MONITOR);
  saved_alarm = alarm(0);
  asig = signal(SIGALRM, SIG_IGN);
  monitor_refresh(0);
  while (1)
    {
      ch = igetch();
      monitor_idle = 0;
      if (ch == CTRL('C') || ch == CTRL('D')) break;
    }
  alarm(0);
  signal(SIGALRM, asig);
  if (saved_alarm) alarm(saved_alarm);
/*
  signal(SIGALRM, SIG_IGN);
*/
  bbs_set_mode(M_UNDEFINED);
  memset(global_ulist, 0, global_ulist_sz * sizeof(*global_ulist));
  return FULLUPDATE;
}

SetPasswd()
{
  ACCOUNT acct;
  PASSWD passbuf, passcfm;
  char prompt[32];
  extern int lang;

  move(2,0);
  clrtobot();
  move(3,0);
  if (bbs_owninfo(&acct) != S_OK) {
    move(4,0);
    c_msg(ERR_FILE, TRUE);
    pressreturn();
    return PARTUPDATE;
  }
  if (lang)
    strcpy(prompt, "¿¾³¯ ¾ÏÈ£: ");
  else
    strcpy(prompt, "Old password: ");

  if (getdata(3,0,prompt,passbuf,sizeof passbuf,NOECHO,1) == -1)
  {
    move(4,0);
    c_msg(ERR_FAILURE, TRUE);
    pressreturn();
    return FULLUPDATE;
  }

  if (passbuf[0] == '\0' || !is_passwd_good(acct.passwd, passbuf)) {
    move(4,0);
    c_msg(ERR_FAILURE, TRUE);
    pressreturn();
    return PARTUPDATE;
  } 

  if (lang)
    strcpy(prompt, "»õ ¾ÏÈ£: ");
  else
    strcpy(prompt, "New password: ");

  getdata(4,0,prompt,passbuf,sizeof passbuf,NOECHO,0);
  if(!is_valid_password(passbuf)) {
    move(5,0);
    c_msg(ERR_INVALID_NAME, TRUE);
    pressreturn();
    return PARTUPDATE;
  }
  if (lang)
    strcpy(prompt, "»õ¾ÏÈ£ È®ÀÎ: ");
  else
    strcpy(prompt, "Confirm password: ");
  getdata(5,0,prompt,passcfm,sizeof passbuf,NOECHO,0);
  move(6,0);
  if(strcmp(passbuf,passcfm)) {
    c_msg(ERR_FAILURE, TRUE);
    pressreturn();
    return PARTUPDATE;		
  }
  if (bbs_set_passwd(passbuf) == S_OK)
    c_msg(INFO_CHANGED, TRUE);
  else 
    c_msg(ERR_FAILURE, TRUE);
  return PARTUPDATE;
}

SetUsername()
{
  ACCOUNT acct;
  UNAME username;
  extern int lang;

  move(2,0);
  clrtobot();

  move(3,0);
  if (lang)
    {
      prints("ÇöÀç ÀÌ¸§Àº [%s] ÀÔ´Ï´Ù\n", myinfo.username);
      if (getdata(4,0,"ÀÌ¸§ (CTRL-C to cancel):",username,sizeof username,DOECHO,1)==-1)
	return FULLUPDATE;
    }
  else
    {
      prints("Current name is [%s]\n", myinfo.username);
      if (getdata(4,0,"Enter your name (Ctrl-C to cancel): ",username,sizeof username,DOECHO,1)==-1)
	return FULLUPDATE;
    }
  if (bbs_set_username(username) == S_OK)
  {
    strcpy(myinfo.username, username);
    c_msg(INFO_CHANGED, TRUE);
  }
  else 
  {
    c_msg(ERR_FAILURE, TRUE);
  }
  return PARTUPDATE;
}

SetAddress()
{
  ACCOUNT acct;
  MAIL email;
  extern int lang;

  move(2,0);
  clrtobot();
  move(3,0);
  if (bbs_owninfo(&acct) != S_OK) {
    c_msg(ERR_FILE, TRUE);
    pressreturn();
    return FULLUPDATE;
  }
  if (lang)
  {
    prints("ÇöÀç ÀÎÅÍ³Ý email ÁÖ¼Ò´Â [%s] ÀÔ´Ï´Ù.\n", acct.email);
    if (getdata(4, 0, "ÀÎÅÍ³Ý email ÁÖ¼Ò (Ctrl-C to cancel): ", email, sizeof email,DOECHO,1) == -1)
	 return FULLUPDATE;
  }
  else
  {
    prints("Current e-mail address is [%s].\n", acct.email);
    if (getdata(4, 0, "Enter your e-mail address (Ctrl-C to cancel): ", email, sizeof email,DOECHO,1) == -1)
	 return FULLUPDATE;
  }
  if (bbs_set_email(email) == S_OK)
    c_msg(INFO_CHANGED, TRUE);
  else 
    c_msg(ERR_FAILURE, TRUE);
  return PARTUPDATE;
}

SetLang()
{
  char buf[64];
  ACCOUNT acct;
  extern int lang;

  if (bbs_owninfo(&acct) != S_OK) {
    move(2,0);
    clrtobot();
    move(3,0);
    c_msg(ERR_FILE, TRUE);
    if (bbs_set_lang (1) != S_OK)
    {
       move(4,0);
       clrtobot();
       c_msg(ERR_FAILURE, TRUE);
    }
    pressreturn();
    return FULLUPDATE;
  }

  move(2,0);
  clrtobot();
  move(3,0);
  if (lang)
    sprintf(buf, "ÇöÀç ¾ð¾î´Â %s ÀÔ´Ï´Ù\n", acct.lang);
  else
    sprintf(buf, "Your CURRENT LANG is %s\n", acct.lang);
  prints(buf);
  move(4,0);
  memset(buf, '\0', 64);
  if (lang)
    {
      if (getdata(4,0,"»õ ¾ð¾î ¸ðµå (0 - ÇÑ±Û / 1 - ¿µ¾î): ",
		buf, 2, DOECHO, 1) == -1)
        return FULLUPDATE;
    }
  else
    {
      if (getdata(4,0,"Enter NEW LANG (0 for Hangul / 1 for English): ",
		buf, 2, DOECHO, 1) == -1)
        return FULLUPDATE;
    }

  if (*buf != '0' && *buf != '1') {
    move(5,0);
    c_msg(ERR_INVALID_NAME, TRUE);
    if (bbs_set_lang (1) != S_OK) {
      move(6,0);
      c_msg(ERR_FAILURE, TRUE);
    }
    pressreturn();
    return FULLUPDATE;
  }

  if (bbs_set_lang (((*buf == '0')?(0):(1))) != S_OK) {
    move(5,0);
    c_msg(ERR_FAILURE, TRUE);
    pressreturn();
  }

  /* we have to re-init. mode string due to hangul support */
  init_mode_strs_chars();
  return FULLUPDATE;
}

SetTermtype()
{
  ACCOUNT acct;
  TERM terminal;
  int rc;
  extern  int lang;

  move(2,0);
  clrtobot();
  move(3,0);
  if (lang) {
    prints("ÇöÀç ÅÍ¹Ì³¯ Å¸ÀÙÀº [%s] ÀÔ´Ï´Ù.\n", myinfo.terminal);
    if (getdata(4,0, "»õÅÍ¹Ì³¯ Å¸ÀÙ (Cntl-C to cancel): ", terminal, 
      sizeof terminal, DOECHO, 1) == -1) return FULLUPDATE;
  } else {
    prints("Current term type is [%s].\n", myinfo.terminal);
    if (getdata(4,0, "New term type (Cntl-C to cancel): ", terminal, 
      sizeof terminal, DOECHO, 1) == -1) return FULLUPDATE;
  }
  if(terminal[0] == '\0')
    return PARTUPDATE;
  if(term_init(terminal) == -1) {
    c_msg(ERR_INVALID_NAME, TRUE);
#if !REMOTE_CLIENT
    return PARTUPDATE;
#endif
  } else {
    initscr();
    clear();
  }
  _sync_currbrd();
  rc = bbs_set_terminal(terminal);
  if (rc == S_OK)
  {
    strcpy(myinfo.terminal, terminal);
    c_msg(INFO_CHANGED, TRUE);
  }
  else 
  {
    c_msg(ERR_FAILURE, TRUE);
  }
  pressreturn();
  return FULLUPDATE;
}

UserDisplay(acct)
ACCOUNT *acct;
{
  extern int lang;
  extern char *Ctime __P((time_t *));

  prints("[%s]\n", acct->userid);
  if (lang) {
    prints("ÀÌ¸§:            %s\n", acct->username);
    if (acct->lastlogin) {
      prints("¸¶Áö¸· ·Î±ä½Ã°£: %s\n", Ctime((time_t *)&acct->lastlogin));
      prints("¾îµð¼­:          %s\n", acct->fromhost);
    } else
      prints("ÇÑ¹øµµ µé¾î ¿ÂÀû ¾ø³×.\n");
    if (*acct->terminal) prints("ÅÍ¹Ì³¯ Å¸ÀÙ:     %s\n", acct->terminal);
    if (*acct->realname) prints("½Ç¸í:            %s\n", acct->realname);
    if (*acct->address)  prints("ÁÖ¼Ò:            %s\n", acct->address);
    if (*acct->email)    prints("ÀüÀÚ¿ìÆíÁÖ¼Ò:    %s\n", acct->email);
    prints("¾ð¾î:            ÇÑ±Û\n");
  } else {
    prints("User name:       %s\n", acct->username);
    if (acct->lastlogin) {
      prints("Last login time: %s\n", Ctime((time_t *)&acct->lastlogin));
      prints("Last login from: %s\n", acct->fromhost);
    } else
      prints("Never logged in.\n");
    if (*acct->terminal) prints("Terminal type:   %s\n", acct->terminal);
    if (*acct->realname) prints("Real name:       %s\n", acct->realname);
    if (*acct->address)  prints("Address:         %s\n", acct->address);
    if (*acct->email)    prints("E-mail address:  %s\n", acct->email);
    prints("Language:        English\n");
  }
  clrtobot();
}

ShowOwnInfo()
{
  ACCOUNT acct;

  move(2,0);
  clrtobot();
  move(3,0);
  if (bbs_owninfo(&acct) != S_OK)
    c_msg(ERR_FILE, TRUE);
  else
    UserDisplay(&acct);
  return PARTUPDATE;
}

AddAccount()
{
  int rc;
  ACCOUNT acct;
  char ans[4];
  extern int lang;

  move(2,0);
  clrtobot();
  move(3,0);
  if (PromptForAccountInfo(&acct, 0) == -1) {
    return PARTUPDATE;
  }
  if (lang)
    getdata(12, 0, "Á¤¸» (Y/N)? [N]: ", ans, sizeof ans, DOECHO, 0);
  else
    getdata(12, 0, "Are you sure (Y/N)? [N]: ", ans, sizeof ans, DOECHO, 0);
  move(13,0);
  if (ans[0] != 'Y' && ans[0] != 'y') {
    c_msg(INFO_CANCELLED, TRUE);
    return PARTUPDATE;
  }
  rc = bbs_add_account(&acct, 0);  
  switch (rc) {
  case S_OK:
    c_msg(INFO_ADDED, TRUE);
    break;
  case S_DENIED:
    c_msg(ERR_PERM, TRUE);
    break;
  case S_FULL:
    c_msg(ERR_FILE, TRUE);
    break;
  default:
    c_msg(ERR_UNKNOWN, TRUE);
    break;
  }
  return PARTUPDATE;
}

DeleteAccount()
{
  NAME namebuf;
  char ans[4];
  extern int lang;

  move(2,0);
  clrtobot();
  if (acctlist == NULL)
    bbs_acctnames(&acctlist);

  if (lang)
    namecomplete(acctlist, "Â¥¸¦ À¯Àú: ", namebuf);        
  else
    namecomplete(acctlist, "Enter userid to delete: ", namebuf);        
  if (namebuf[0] == '\0' || !is_in_namelist(acctlist, namebuf)) {
    c_msg(ERR_NOT_EXIST, TRUE);
    pressreturn();
    return FULLUPDATE;
  }
  c_msg(INFO_DELETING, TRUE);
  if (lang)
    getdata(5,0,"Á¤¸» (Y/N)? [N]: ",ans,sizeof(ans),DOECHO,0);    
  else
    getdata(5,0,"Are you sure (Y/N)? [N]: ",ans,sizeof(ans),DOECHO,0);    

  if (ans[0] != 'Y' && ans[0] != 'y') {
    c_msg(INFO_CANCELLED, TRUE);
    pressreturn();
    return FULLUPDATE;
  }
  if (bbs_delete_account(namebuf) == S_OK)
    c_msg(INFO_DELETED, TRUE);
  else
    c_msg(ERR_FAILURE, TRUE);
  bbs_acctnames(&acctlist);
  pressreturn();
  return FULLUPDATE;
}

DeleteMe()
{
  char ans[4];
  extern int lang;
  extern char *my_userid();

  move(2,0);
  clrtobot();
  if (lang)
  {
    prints("¾ÆÀÌµð (%s) Áö¿ó´Ï´Ù.\n", my_userid());
    getdata(5,0, "ÁøÂ¥ (Y/N)?[N]: ", ans, 4, DOECHO, 0);
  }
  else
  {
    prints("Deleting YOURSELF (%s).\n", my_userid());
    getdata(5,0, "Are you sure (Y/N)?[N]: ", ans, 4, DOECHO, 0);
  }

  if (*ans != 'Y' && *ans != 'y') {
    c_msg(INFO_CANCELLED, TRUE);
    pressreturn();
    return FULLUPDATE;
  }
  if (bbs_delete_account(my_userid()) == S_OK)
    c_msg(INFO_DELETED, TRUE);
  else
    c_msg(ERR_FAILURE, TRUE);
  pressreturn();
  return FULLUPDATE;
}

SetUserData()
{
  NAME userid;
  ACCOUNT acct, nr;
  SHORT flags = 0;
  PASSWD passcfm;
  int x, y, grok;
  char genbuf[256], ans[4];
  extern int lang;

  move(2,0);
  clrtobot();
  memset(&nr, 0, sizeof nr);
  if (acctlist == NULL)
    bbs_acctnames(&acctlist);

  if (lang)
    namecomplete(acctlist, "´©±¸ÀÇ À¯ÀúÁ¤º¸¸¦ ¹Ù²Ü±î¿ä: ", userid); 
  else
    namecomplete(acctlist, "Enter userid to set: ", userid); 
  if (userid[0] == '\0' || !is_in_namelist(acctlist, userid)) {
    c_msg(ERR_NOT_EXIST, TRUE);
    pressreturn();
    return FULLUPDATE;
  }
  if (bbs_get_userinfo(userid, &acct) != S_OK) {
    c_msg(ERR_NOT_EXIST, TRUE);
    bbs_acctnames(&acctlist);
    pressreturn();
    return FULLUPDATE;
  }
  move(3,0);
  UserDisplay(&acct);
  getyx(&y, &x);
  if (lang)
    getdata(++y,0,"»ç¿ëÀÚ Á¤º¸ ¹Ù²Ü±î¿ä (Y/N)? [N]: ",ans,sizeof(ans),
	  DOECHO, 0);
  else
    getdata(++y,0,"Change any user information (Y/N)? [N]: ",ans,sizeof(ans),
	  DOECHO, 0);
  if (ans[0] != 'Y' && ans[0] != 'y') {
    move(y,0);
    clrtobot();
    c_msg(INFO_CANCELLED, TRUE);
    pressreturn();
    return FULLUPDATE;
  }
  
  if (lang)
    sprintf(genbuf, "»õÀ¯Àú¾ÆÀÌµð [%s]: ", acct.userid);
  else
    sprintf(genbuf, "New userid [%s]: ", acct.userid);
  do {
    getdata(y+1, 0, genbuf, nr.userid, sizeof(nr.userid), DOECHO, 0);
    if (!nr.userid[0])
      break;
    if (grok = CheckUserid(nr.userid)) {
      move(y+2, 0);
      c_msg(ERR_INVALID_NAME, TRUE);
    } else
      BITSET(flags, MOD_USERID);
  } while (grok);
  y++;
  
  do {
    if (lang)
      getdata(y+1,0,"»õ¾ÏÈ£: ",nr.passwd,sizeof(nr.passwd),NOECHO, 0);
    else
      getdata(y+1,0,"New Password: ",nr.passwd,sizeof(nr.passwd),NOECHO, 0);
    if (!nr.passwd[0]) break;
    if (lang)
      getdata(y+2,0,"»õ¾ÏÈ£ È®ÀÎ: ", passcfm,sizeof(passcfm),NOECHO, 0);
    else
      getdata(y+2,0,"Confirm Pass: ", passcfm,sizeof(passcfm),NOECHO, 0);
    if (grok = strcmp(nr.passwd, passcfm)) {
      move(y+3, 0);
      c_msg(ERR_FAILURE, TRUE);
    }
    else BITSET(flags, MOD_PASSWD);
  } while (grok);
  move(y+2, 0);    
  clrtobot();
  y+=2;
  
  if (lang)
    sprintf(genbuf, "»õÀÌ¸§ [%s]: ", acct.username);
  else
    sprintf(genbuf, "New username [%s]: ", acct.username);
  getdata(y++, 0, genbuf, nr.username, sizeof(nr.username), DOECHO, 0);
  if (nr.username[0]) BITSET(flags, MOD_USERNAME);
  
  if (lang)
    sprintf(genbuf, "»õÅÍ¹Ì³¯ Å¸ÀÙ [%s]: ", acct.terminal);
  else
    sprintf(genbuf, "New terminal type [%s]: ", acct.terminal);
  getdata(y++, 0, genbuf, nr.terminal, sizeof(nr.terminal), DOECHO, 0);
  if (nr.terminal[0]) BITSET(flags, MOD_TERMINAL);
  
  if (lang)
    sprintf(genbuf, "»õ ½Ç¸í [%s]: ", acct.realname);
  else
    sprintf(genbuf, "New real name [%s]: ", acct.realname);
  getdata(y++, 0, genbuf, nr.realname, sizeof(nr.realname), DOECHO, 0);
  if (nr.realname[0]) BITSET(flags, MOD_REALNAME);
  
  if (lang)
    strcpy(genbuf, "»õÁÖ¼Ò: ");
  else
    strcpy(genbuf, "New address: ");
  getdata(y++, 0, genbuf, nr.address, sizeof(nr.address), DOECHO, 0);
  if (nr.address[0]) BITSET(flags, MOD_ADDRESS);
  
  if (lang)
    sprintf(genbuf, "»õ ÀüÀÚÆíÁö ÁÖ¼Ò [%s]: ", acct.email);
  else
    sprintf(genbuf, "New mail address [%s]: ", acct.email);
  getdata(y++, 0, genbuf, nr.email, sizeof(nr.email), DOECHO, 0);
  if (nr.email[0]) BITSET(flags, MOD_EMAIL);
  
  if (lang)
    sprintf(genbuf, "»õ »ç¿ë¾ð¾î (ÇÑ±Û=0/¿µ¾î=1): ");
  else
    sprintf(genbuf, "New language (Hangul=0/English=1): ");
  getdata(y++, 0, genbuf, ans, sizeof(ans), DOECHO, 0);
  if (*ans == '0')
  {
    strcpy(nr.lang, "Kr");
    nr.flags |= FLG_KOREAN;
  }
  else
  {
    strcpy(nr.lang, "Eng");
    nr.flags &= ~FLG_KOREAN;
  }
  BITSET(flags, MOD_LANG);

  if (lang)
    getdata(y, 0, "Á¤¸» (Y/N)? [N]: ", ans, sizeof(ans), DOECHO, 0);
  else
    getdata(y, 0, "Are you sure (Y/N)? [N]: ", ans, sizeof(ans), DOECHO, 0);
  if (ans[0] == 'Y' || ans[0] == 'y') {    
    if (bbs_modify_account(acct.userid, &nr, flags) == S_OK)
      c_msg(INFO_CHANGED, TRUE);
    else
      c_msg(ERR_FAILURE, TRUE);
  } else
    c_msg(INFO_CANCELLED, TRUE);
  pressreturn();
  return FULLUPDATE;
}

char *global_permstrs[32];

#define PERMMENULETTER(i) ((i)<26?('A'+(i)):('1'+(i)-26))
#define PERMMENUNUMBER(c) ((c)>='A'?((c)-'A'):((c)-'1'+26))
#define PBITSET(m,i)       (((m)>>(i))&1)

LONG
SetPermMenu(pbits)
LONG pbits;
{
  int i, done = 0;
  char buf[80], choice[2];
  extern int lang;

  if (global_permstrs[0] == NULL)
    if (bbs_get_permstrings(global_permstrs) != S_OK) {
      move(3,0);
      c_msg(ERR_FILE, TRUE);
      pressreturn();
      return pbits;
    }

  move(4,0);
  c_msg(INFO_TOGGLE, TRUE);
  move(6,0);
  for (i=0; i<16; i++) {
    sprintf(buf, "%c. %-20s %3s      %c. %-20s %3s\n", 
	    PERMMENULETTER(i), global_permstrs[i], 
            PBITSET(pbits,i) ? "YES" : "NO",
	    PERMMENULETTER(i+16), global_permstrs[i+16], 
            PBITSET(pbits,i+16) ? "YES" : "NO");
    prints(buf);
  }
  clrtobot(); 
  while (!done) {
    if (lang)
      getdata(t_lines-1, 0, "¼±ÅÃ (ENTER Ä¡¸é ³¡): ",choice,2,DOECHO,0);
    else
      getdata(t_lines-1, 0, "Choice (ENTER to quit): ",choice,2,DOECHO,0);
    *choice = toupper(*choice);
    if (*choice == '\n' || *choice == '\0') done = 1;
    else if (!isalnum(*choice) || (*choice>='7' && *choice<='9') ||
	     *choice == '0') bell();
    else {
      i = PERMMENUNUMBER(*choice);
      if (PBITSET(pbits,i))
	BITCLR(pbits,1<<i);
      else BITSET(pbits,1<<i);
      i%=16;
      sprintf(buf, "%c. %-20s %3s      %c. %-20s %3s\n", 
   	      PERMMENULETTER(i), global_permstrs[i], 
              PBITSET(pbits,i) ? "YES" : "NO",
	      PERMMENULETTER(i+16), global_permstrs[i+16], 
              PBITSET(pbits,i+16) ? "YES" : "NO");
      move(i+6,0);
      prints(buf);
    }
  }				
  return (pbits);
}

SetUserPerms()
{
  NAME namebuf;
  LONG newperms;
  ACCOUNT acct;
  extern int lang;

  move(2,0);
  clrtobot();
  if (acctlist == NULL)
    bbs_acctnames(&acctlist);

  if (lang)
    namecomplete(acctlist, "ÆÛ¹Ì¼Ç ¹Ù²Ü À¯Àú: ", namebuf);
  else
    namecomplete(acctlist, "Enter userid to set permissions: ", namebuf);
  if (namebuf[0] == '\0' || !is_in_namelist(acctlist, namebuf)) {
    move(3, 0);
    c_msg(ERR_NOT_EXIST, TRUE);
    pressreturn();
    return FULLUPDATE;
  }
  if (bbs_get_userinfo(namebuf, &acct) != S_OK) {
    move(3, 0);
    c_msg(ERR_NOT_EXIST, TRUE);
    bbs_acctnames(&acctlist);
    pressreturn();
    return FULLUPDATE;
  }
  move(2,0);
  clrtobot();
  if (lang)
    prints("ÆÛ¹Ì¼Ç ¹Ù²Ü »ç¿ëÀÚ : '%s'\n", acct.userid);
  else
    prints("Set the permissions for user '%s'\n", acct.userid);
  newperms = SetPermMenu(acct.perms);	
  move(2,0);
  if (newperms == acct.perms)
    c_msg(INFO_CANCELLED, TRUE);
  else {
    if (bbs_modify_perms(acct.userid, newperms) == S_OK)
      c_msg(INFO_CHANGED, TRUE);
    else
      c_msg(ERR_FAILURE, TRUE);
  }
  pressreturn();
  return FULLUPDATE;
}

QueryEdit()
{
  PATH planfile;
  char ans[7];
  extern int lang;

  move(3,0);
  clrtobot();
  if (lang) {
    if (getdata(4,0,"Plan (E)-ÆíÁý ¶Ç´Â (D)-»èÁ¦? [E]: ",ans,sizeof(ans),DOECHO,1)==-1)
      return FULLUPDATE;
  } else {
    if (getdata(4,0,"[E]-Edit or [D]-Delete plan? [E]: ",ans,sizeof(ans),DOECHO,1)==-1)
      return FULLUPDATE;
  }

  if (*ans == 'D' || *ans == 'd') {
    bbs_set_plan(NULL);
    move(6,0);
    c_msg(INFO_DELETED, TRUE);
    return PARTUPDATE;
  }
  bbs_get_plan(myinfo.userid, planfile);    
  if (Edit(planfile)) {
    clear();
    c_msg(ERR_FAILURE, TRUE);
  } else {
    clear();
    if (bbs_set_plan(planfile) == S_OK)
      c_msg(INFO_CHANGED, TRUE);
    else
      c_msg(ERR_FAILURE, TRUE);
  }
  pressreturn();
  return FULLUPDATE;
}

/*ARGSUSED*/
_query_if_logged_in(indx, urec, loggedin)
int indx;
USEREC *urec;
int *loggedin;
{
  (*loggedin)++;
  return ENUM_QUIT;
}

Query()
{
  NAME namebuf;
  ACCOUNT acct;
  PATH planfile;
  char buf[80];
  FILE *fp;
  int i, in_now = 0, firstsig = 6;
  extern int lang;
  extern char *Ctime __P((time_t *));

  if (acctlist == NULL)
    bbs_acctnames(&acctlist);

  move(3,0);
  clrtobot();
  if (lang)
    prints("<À¯Àú¾ÆÀÌµð¸¦ ³ÖÀ¸¼¼¿ä>\n");    
  else
    prints("<Enter Userid>\n");    
  move(2,0);
  if (lang)
    namecomplete(acctlist, "´©±¸¸¦: ", namebuf);
  else
    namecomplete(acctlist, "Query who: ", namebuf);
  move(2,0);
  clrtoeol();
  move(3,0);
  if (namebuf[0] == '\0' || !is_in_namelist(acctlist, namebuf)) {
    if (namebuf[0])
      c_msg(ERR_NOT_EXIST, TRUE);
    return PARTUPDATE;
  }

  if (bbs_query(namebuf, &acct) != S_OK) {
    c_msg(ERR_NOT_EXIST, TRUE);
    bbs_acctnames(&acctlist);
    return PARTUPDATE;
  }

  bbs_enum_users(20, 0, acct.userid, _query_if_logged_in, &in_now);

  prints("%s (%s):\n", acct.userid, acct.username);
  if (acct.lastlogin == 0) {
    c_msg(INFO_NEVER_LOGGED_IN, TRUE);
  } else {
    if (lang)
      prints("%s %s ¿¡¼­ %s %s\n",
		in_now ? "ÇöÀç" : "¸¶Áö¸··Î±äÀº",
		acct.fromhost,
		Ctime((time_t *)&acct.lastlogin),
		in_now ? "ÀÌÈÄºÎÅÍ µé¾î¿Í ÀÖ½À´Ï´Ù" : "¿¡ µé¾î¿Ô¾ú¾î¿ä");
    else
      prints("%s from %s %s %s\n", in_now ? "On" : "Last login", acct.fromhost,
	      in_now ? "since" : "at", Ctime((time_t *)&acct.lastlogin));
  }

  if (acct.realname[0] != '\0') {
    if (lang)
      prints("½Ç¸í: %s\n", acct.realname);
    else
      prints("Real name: %s\n", acct.realname);
    firstsig++;
  }

  if (bbs_get_plan(acct.userid, planfile) != S_OK) {
    c_msg(INFO_NO_PLAN, TRUE);
  } else {
    /* For now, just print one screen of the plan. In the future maybe
       prompt to ask if they want to page thru the whole plan, since
       we have it. */
    if (fp = fopen(planfile, "r")) {
      prints("Plan:\n");
      for (i=firstsig; i<t_lines; i++) {
	if (!fgets(buf, sizeof buf, fp)) break;
	prints("%s", buf);
      }
      fclose(fp);
    } else {
      c_msg(INFO_NO_PLAN, TRUE);
    }
  }
  return PARTUPDATE;
}

ToggleCloak()
{
  int rc;
  extern int lang;

  move(3,0);
  clrtobot();
  if (bbs_toggle_cloak() != S_OK)
    c_msg(ERR_FAILURE, TRUE);
  else
    c_msg(INFO_CHANGED, TRUE);
  return PARTUPDATE;
}

ToggleExempt()
{
  NAME namebuf;
  ACCOUNT acct;
  extern int lang;

  move(2,0);
  clrtobot();
  if (acctlist == NULL)
    bbs_acctnames(&acctlist);
  if (lang)
    namecomplete(acctlist, "À¯ÀúÅ¬¸°¼­ Á¦¿Ü/Æ÷ÇÔÇÒ À¯Àú: ", namebuf);
  else
    namecomplete(acctlist, "Enter userid to exempt/unexempt: ", namebuf);
  if (namebuf[0] == '\0' || !is_in_namelist(acctlist, namebuf)) {
    c_msg(ERR_NOT_EXIST, TRUE);
    pressreturn();
    return FULLUPDATE;
  }
  if (bbs_get_userinfo(namebuf, &acct) != S_OK) {
    c_msg(ERR_NOT_EXIST, TRUE);
    bbs_acctnames(&acctlist);
    pressreturn();
    return FULLUPDATE;
  }
  if (bbs_toggle_exempt(acct.userid) == S_OK) {
    if (BITISSET(acct.flags, FLG_EXEMPT)) {
      if (lang)
        prints("'%s' - ÀÌÁ¨ »ç¿ëÀÚ Á¤¸® ´ë»óÀÔ´Ï´Ù\n", acct.userid);
      else
        prints("User '%s' is now subject to user clean\n", acct.userid);
    } else {
      if (lang)
        prints("'%s' - »ç¿ëÀÚ Á¤¸®´ë»ó¿¡¼­ Á¦¿ÜÇß½À´Ï´Ù\n", acct.userid);
      else
        prints("User '%s' is now exempt from user clean\n", acct.userid);
    }
  } else {
    c_msg(ERR_FAILURE, TRUE);
  }
  pressreturn() ;
  return FULLUPDATE;
}

SetPager()
{
  char ans[3], buf[40];
  ACCOUNT acct;
  SHORT setting = 1, pageroff = 0, overrideoff = 0;
  extern int lang;

  move(2,0);
  clrtobot();
  if (bbs_owninfo(&acct) != S_OK) {
    c_msg(ERR_ACCT, TRUE);
    return PARTUPDATE;
  }    
  if (acct.flags & FLG_NOPAGE) setting += 1;
  if (acct.flags & FLG_NOOVERRIDE) setting += 2;  
  if (lang) {
    prints("ÇöÀç ÆäÀÌÁ®¼¼ÆÃ: %d. »õÆäÀÌÁ® ¼¼ÆÃÀº? :\n", setting);
    prints("1) ¾Æ¹«³ª ´Ù ºÎ¸¦¼ö ÀÖ´Ù\n");
    prints("2) ¿À¹ö¶óÀÌµå ¸®½ºÆ®¿¡ ÀÖ´Â »ç¶÷¸¸ ºÎ¸¦¼ö ÀÖ´Ù\n");
    prints("3) ¿À¹ö¶óÀÌµå ¸®½ºÆ®¿¡ ÀÖ´Â »ç¶÷ »©°ï ´Ù ºÎ¸¦¼ö ÀÖ´Ù\n");
    prints("4) ¾Æ¹«µµ ºÎ¸¦¼ö ¾ø´Ù\n");
    sprintf(buf, "¾î¶²°É °í¸¦±î¿ä? (1-4)? [%d]: ", setting);
  } else {
    prints("Current pager setting is %d. Select new setting:\n", setting);
    prints("1) Anyone can page\n");
    prints("2) Only users on override list can page\n");
    prints("3) Only users NOT on override list can page\n");
    prints("4) Nobody can page\n");
    sprintf(buf, "Your choice (1-4)? [%d]: ", setting);
  }

  if (getdata(8, 0, buf, ans, sizeof ans, DOECHO, 1)==-1)
    return FULLUPDATE;
  
  if (*ans != '1' && *ans != '2' && *ans != '3' && *ans != '4') {
    c_msg(ERR_FAILURE, TRUE);
    return PARTUPDATE;
  }
  if (*ans == '2' || *ans == '4') pageroff = 1;
  if (*ans == '3' || *ans == '4') overrideoff = 1;  
  if (bbs_set_pager(pageroff, overrideoff) != S_OK)
    c_msg(ERR_FAILURE, TRUE);
  else 
    c_msg(INFO_CHANGED, TRUE);
  return PARTUPDATE;
}

SignatureEdit()
{
  PATH sigfile;
  char ans[7];
  extern int lang;

  move(3,0);
  clrtobot();
  if (lang) {
    if (getdata(4,0,"¼­¸íÀ» (E)-ÆíÁý / (D)-»èÁ¦? [E]: ", 
      ans, sizeof(ans), DOECHO, 1) == -1) return FULLUPDATE;
  } else {
    if (getdata(4,0,"(E)-Edit / (D)-Delete signature? [E]: ", 
      ans, sizeof(ans), DOECHO, 1) == -1) return FULLUPDATE;
  }

  if (*ans == 'D' || *ans == 'd') {
    bbs_set_signature(NULL);
    move(5,0);
    c_msg(INFO_DELETED, TRUE);
    return PARTUPDATE;
  }
  bbs_get_signature(sigfile);    
  clear();
  if (Edit(sigfile)) {
    c_msg(ERR_FAILURE, TRUE);
  } else {
    if (bbs_set_signature(sigfile) == S_OK)
      c_msg(INFO_CHANGED, TRUE);
    else
      c_msg(ERR_FAILURE, TRUE);
  }
  pressreturn();
  return FULLUPDATE;
}
lse {
      i = PERMMENUNUMBER(*choice);
      if (PBITSET(pbits,i))
	BITCLR(pbits,1<<i);
      else BITSET(pbits,1<<i);
      i%=16;
      sprintf(buf, "%c. %-20s %3s      %c. %-20s %3s\n", 
   	      PERMMENULETTER(i), global_permstrs[i], 
              PBITSET(pbits,i) ? "YES" : "NO",
	      PERMMENULETTER(i+16), global_permstrs[i+16], 
              PBITSEDarkNET-1.08/chat.c                                                                                    644   21270   21270        13704  5747645175   7205                                                                                                                                                                                                                                                                                                                                                                      
/*
Eagles Bulletin Board System
Copyright (C) 1994, Ray Rocker, rrrocker@rock.b11.ingr.com
                                rock@seabass.st.usm.edu
                                72673.2105@compuserve.com

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "server.h"
#include <signal.h>
#include <errno.h>          /* this may be just temporary */
#include <sys/socket.h>
#include <netinet/in.h>
#if NEXTSTEP == 1
# include <sys/wait.h>
# include <sys/time.h>
# include <sys/resource.h>
# define waitpid wait3
#endif

#ifndef INADDR_LOOPBACK
# define INADDR_LOOPBACK 0x7f000001
#endif

extern SERVERDATA server;

int chatfd = -1;
int inchat = 0;

unsigned short
_read_daemoninfo(fname)
char *fname;
{
  FILE *fp;
  char buf[5];
  unsigned short number;
  if ((fp = fopen(fname, "r")) == NULL) {
    return 0;
  }
  fgets(buf, sizeof buf, fp);
  buf[4] = '\0';
  number = (unsigned short)hex2SHORT(buf);
  fclose(fp);
  return number;
}

_start_chat_daemon()
{
  int pid;
  char *argv0 = "bbs.chatd";
  char argv1[8];
  sprintf(argv1, "%d", server.maxutable);

  switch (pid = fork()) {
  case -1: 
    return -1;
  case 0: 
    execl(PATH_CHATD, argv0, argv1, NULL);
    bbslog(0, "ERROR _start_chat_daemon: execl failed: %s\n", PATH_CHATD);
    exit(1);
  default:
    /* The chat daemon forks so we can wait on it here. */
    waitpid(pid, NULL, 0);
  }
  return 0;
}

local_bbs_chat(chatid, pfd)
char *chatid;
LONG *pfd;
{
  CHATLINE sendbuf;
  int rc, daemon_started = 0;
  unsigned short port;
  if (inchat) return S_OK;

  if (my_real_mode() == M_TALK) return S_ILLEGAL;

  if (chatfd == -1) {
    int s;
    struct sockaddr_in sin;
setupchat:
    memset(&sin, 0, sizeof sin);
    sin.sin_family = PF_INET;
    sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
    sin.sin_port = port = ntohs(_read_daemoninfo(PATH_CHATPORT));
    if (sin.sin_port == 0) {
      _start_chat_daemon();
      daemon_started++;
      sin.sin_port = port = ntohs(_read_daemoninfo(PATH_CHATPORT));
      if (sin.sin_port == 0) {
        return S_SYSERR;
      }
    }
    if ((s = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
      bbslog(0, "ERROR local_bbs_chat: socket failed\n");
      return S_SYSERR;
    }
    rc = connect(s, (struct sockaddr *)&sin, sizeof sin);
    if (rc == -1) {
      if (errno == SIGINT) goto setupchat;
      bbslog(0, "ERROR local_bbs_chat: connect failed: errno %d\n", errno);
      if (!daemon_started) {
        unsigned long currport;
        close(s);
        currport = ntohs(_read_daemoninfo(PATH_CHATPORT));
        if (currport == port) {
          /* We may have crashed and left the chatport file there.
             Try to kill the running daemon if it's hung. */
          pid_t pid = (pid_t)_read_daemoninfo(PATH_CHATPID);
          if (pid > 0) kill(pid, SIGQUIT);
	  _start_chat_daemon();
          daemon_started++;
        }
        goto setupchat;
      }	
      close(s);
      return S_SYSERR;
    }            
    chatfd = s;
  }
  
  set_real_mode(M_CHAT);
  sprintf(sendbuf, "/! %d %s\n", my_utable_slot(), chatid);  
  if (send(chatfd, sendbuf, strlen(sendbuf), 0) != strlen(sendbuf)) {
    local_bbs_exit_chat();
    bbslog(0, "ERROR local_bbs_chat: send failed\n");
    return S_SYSERR;
  }
  if (recv(chatfd, sendbuf, 3, 0) != 3) {
    local_bbs_exit_chat();
    bbslog(0, "ERROR local_bbs_chat: recv failed\n");
    return S_SYSERR;
  }
  if (!strcmp(sendbuf, CHAT_LOGIN_OK)) {
    inchat = 1;
    *pfd = (LONG)chatfd;
    bbslog(4, "CHAT ENTER %s as %s\n", my_userid(), chatid);
    return S_OK;
  }
  else if (!strcmp(sendbuf, CHAT_LOGIN_EXISTS)) {
    set_real_mode(M_UNDEFINED);
    return S_EXISTS;
  }
  else if (!strcmp(sendbuf, CHAT_LOGIN_INVALID)) {
    set_real_mode(M_UNDEFINED);
    return S_INVALID;
  }

  /* else, server really didn't like us */
  local_bbs_exit_chat();
  bbslog(0, "ERROR local_bbs_chat: daemon sent back '%s'\n", sendbuf);
  return S_SYSERR;
}

local_bbs_exit_chat()
{
  if (chatfd != -1) {
    close(chatfd);
    chatfd = -1;
    inchat = 0;
    set_real_mode(M_UNDEFINED);
    bbslog(4, "CHAT EXIT %s\n", my_userid());
  }
  return S_OK;
}

local_bbs_chat_send(buf)
char *buf;
{
  int len = strlen(buf);
  if (chatfd == -1 || inchat == 0) return S_DENIED;
  if (send(chatfd, buf, len, 0) != len) {
    local_bbs_exit_chat();
    bbslog(0, "ERROR local_bbs_chat_send: send failed\n");
    return S_SYSERR;
  }
  return S_OK;
}  

remote_bbs_chat(chatid, pport, magicstr)
char *chatid;
unsigned short *pport;
char *magicstr;
{
  /* Assumes magicstr is big enough (should be 256 chars) */
  int daemon_started = 0;
  unsigned short port;
  pid_t pid;

  if (inchat) return S_OK;

  if (my_real_mode() == M_TALK) return S_ILLEGAL;

  pid = (pid_t)_read_daemoninfo(PATH_CHATPID);
  if (pid == 0 || kill(pid, 0) == -1) {
    _start_chat_daemon();
    daemon_started++;
  }

  port = ntohs(_read_daemoninfo(PATH_CHATPORT));
  if (port == 0) {
    if (daemon_started == 0) {
      _start_chat_daemon();
      daemon_started++;
      port = ntohs(_read_daemoninfo(PATH_CHATPORT));
    }
    if (port == 0) {
      return S_SYSERR;
    }
  }

  sprintf(magicstr, "/! %d %s\n", my_utable_slot(), chatid);  
  bbslog(4, "CHAT ENTER %s as %s\n", my_userid(), chatid);
  *pport = port;
  inchat = 1;
  set_real_mode(M_CHAT);
  return S_OK;
}

remote_bbs_exit_chat()
{
  if (inchat) {
    inchat = 0;
    set_real_mode(M_UNDEFINED);
    bbslog(4, "CHAT EXIT %s\n", my_userid());
  }
  return S_OK;
}
                                                            DarkNET-1.08/chatconf.c                                                                                644   21270   21270         4302  5735703425  10013                                                                                                                                                                                                                                                                                                                                                                       
/*
Eagles Bulletin Board System
Copyright (C) 1994, Ray Rocker, rrrocker@rock.b11.ingr.com
                                rock@seabass.st.usm.edu
                                72673.2105@compuserve.com

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "server.h"

#define CHATCONFIGFILE "etc/chatconfig"

/*
   This is a piece of the chat server; separated because chatserv.c
   is too damn big already.
*/

extern NAMELIST manager_list;
extern NAMELIST restricted_list;
extern NAME mainroom;

_chat_config_form_list(list, str)
NAMELIST *list;
char *str;
{
  char *userid;  
  while ((userid = strtok(str, ", \t")) != NULL) {
    str = NULL;
    add_namelist(list, userid, NULL);
  }
  sort_list(list);
  return 0;
}

/*ARGSUSED*/
_chat_init_config_func(indx, rec, arg)
int indx;
char *rec;
void *arg;
{
  char *equals;
  int i;
  strip_trailing_space(rec);

  if ((equals = strchr(rec, '=')) == NULL) return S_OK;
  *equals++ = '\0';
  strip_trailing_space(rec);
  strip_trailing_space(equals);
/*
  while (*rec && isspace(*rec)) rec++;
  while (*equals && isspace(*equals)) equals++;
*/
  while (*rec && myisspace(*rec)) rec++;
  while (*equals && myisspace(*equals)) equals++;

  if (!strcasecmp(rec, "mainroom")) {
    if (*equals != '\0') strncpy(mainroom, equals, NAMELEN);
  }
  else if (!strcasecmp(rec, "operators")) {
    _chat_config_form_list(&manager_list, equals);
  }
  else if (!strcasecmp(rec, "restricted")) {
    _chat_config_form_list(&restricted_list, equals); 
  }
  return S_OK;
}

chat_init_config()
{
  _record_enumerate(CHATCONFIGFILE, 0, _chat_init_config_func, NULL);
  return S_OK;
}
                                                                                                                                                                                                                                                                                                                              DarkNET-1.08/client.c                                                                                  644   21270   21270        24650  5747644744   7547                                                                                                                                                                                                                                                                                                                                                                      
/*
Eagles Bulletin Board System
Copyright (C) 1994, Ray Rocker, rrrocker@rock.b11.ingr.com
                                rock@seabass.st.usm.edu
                                72673.2105@compuserve.com

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "client.h"
#include <signal.h>
#include <time.h>
#if REMOTE_CLIENT
# include <pwd.h>
# include <stdlib.h>
#endif

BBSINFO serverinfo;		/* server's info structure */
LOGININFO myinfo;               /* user's info structure */

PATH c_tempfile;                /* work file for the client side */
int input_active;               /* for the idle timer */

#if REMOTE_CLIENT
char *tmpdir;
char *shell;
char *pager;
char *editor;
char *termtype;

extern char *optarg;
extern int optind;
#endif

extern PromptForAccountInfo();
extern SetPermTable();
extern char *_menudesc_file;
extern DoMenu();
extern MENUITEM cmdlist[];
extern void page_handler __P((int));
extern char *Ctime __P((time_t *));

void term_change()
{
  ACCOUNT acct;

  signal (SIGWINCH, SIG_IGN);
  if (bbs_owninfo(&acct) != S_OK) {
    c_msg(ERR_ACCT, TRUE);
    term_init("dumb");
    signal (SIGWINCH, term_change);
    return;
  }
  if (term_init(acct.terminal) == -1) {
    c_msg(ERR_TERM, TRUE);
    term_init("dumb");
  }
  signal (SIGWINCH, term_change);
  return;
}

disconnect(status)
int status;
{
  extern int ircpid;

  unlink(c_tempfile);
  bbs_disconnect();
  if (fullscreen()) {
    clear();
    refresh();
  }
  else oflush();
  reset_tty();
  printf("\n");
  switch (status) {
  case EXIT_LOGOUT:
    printf("Goodbye!\n");
#if AUX == 1
    clear();
#endif
    break;
  case EXIT_CLIERROR:
    printf("Something's wrong. Exiting.\n");
    break;
  case EXIT_LOSTCONN:
    printf("Server closed connection. Exiting.\n");
    break;
  case EXIT_TIMEDOUT:
    printf("Idle timeout exceeded. Exiting.\n");
    break;
  default:     /* assumed to be a signal */
    if (g_child_pid != -1) {
      kill(g_child_pid, status);
    }
    switch (status) {
    case SIGHUP: break;
    case SIGINT: 
      printf("Interrupt signal received. Goodbye!\n");
      break;
    case SIGQUIT: 
      printf("Quit signal received. Goodbye!\n");
      break;
    case SIGTERM: 
      printf("Terminate signal received. Goodbye!\n");
      break;
    default: 
      printf("Bad news: signal %d received. Run! Flee!\n", status);
      break;
    }
    break;
  } 
  /* should kill any child process */
  if (ircpid > 0)
  {
	kill (ircpid, SIGTERM);
  }
  exit(status);
}

generic_abort()		/* general "bail and exit" */
{
  disconnect(EXIT_CLIERROR);
}

#if REMOTE_CLIENT
bbslib_abort()
{
  disconnect(EXIT_LOSTCONN);
}
#endif

void
sig_handler(sig)
int sig;
{
  disconnect(sig == SIGALRM ? EXIT_TIMEDOUT : sig);
}

void
hit_alarm_clock()
{
  signal(SIGALRM, SIG_IGN);
  if (!input_active) {
    disconnect(EXIT_TIMEDOUT);
  }
  input_active = 0;
  signal(SIGALRM, hit_alarm_clock);
  if (myinfo.idletimeout) alarm((int)myinfo.idletimeout*60);
}

set_idle_alarm()
{
  if (myinfo.idletimeout != 0) {
    signal(SIGALRM, hit_alarm_clock);
    alarm((int)myinfo.idletimeout*60);
  }
}

cancel_idle_alarm()
{
  alarm(0);
}

void
InitializeTerminal()
{
  TERM t;
#if REMOTE_CLIENT
  if (termtype == NULL) {
#else /* !REMOTE_CLIENT */
  ACCOUNT acct;
  if (bbs_owninfo(&acct) != S_OK) {
#endif
    c_msg(ERR_ACCT, TRUE);
    term_init("dumb");
    return;
  }
  memset(t, '\0', sizeof(TERM));
#if REMOTE_CLIENT
  strncpy(t, termtype, TERMLEN);
#else
  strncpy(t, acct.terminal, TERMLEN);
#endif
  if (term_init(t) == -1) {
    c_msg(ERR_TERM, TRUE);
    term_init("dumb");
  }
  signal (SIGWINCH, term_change);
}
      
Login(newok)
SHORT newok;
{
  ACCOUNT acct;
  int rc;

  char *ustr = (newok ? "userid ('new' for new user): " : "userid: ");
  alarm(60);   /* You get one minute to log in succesfully */
  do {
    if (getdata(0, 0, ustr, acct.userid, sizeof(acct.userid), DOECHO, 1) == -1)
      disconnect(EXIT_LOGOUT);

    if (newok && !strcmp(acct.userid, "new")) {
      /* Give them five minutes to enter new user data */
      alarm(300);
      PromptForAccountInfo(&acct, 1);
      rc = bbs_newlogin(&acct, &myinfo);
    }
    else {
      getdata(0, 0, "Password: ", acct.passwd, sizeof(acct.passwd), NOECHO, 0);
      rc = bbs_login(acct.userid, acct.passwd, 0, &myinfo);
    }
login_switch:
    switch (rc) {
    case S_OK:
      break;
    case S_INVALID:
      prints("\nIncorrect userid or password.\n\n");
      break;
    case S_FULL:
      prints("\nBBS system is full. Try again later.\n\n");
      disconnect(EXIT_LOGOUT);
      break;
    case S_DISABLED:
      prints("\nThat login cannot be used at this time.\n\n");
      disconnect(EXIT_LOGOUT);
      break;
    case S_DENIED:
    case S_TEMPFAIL:
      prints("\nSorry, this account has reached its logon limit.\n\n");
      if (rc == S_TEMPFAIL) {
        char ans[4];
        getdata(0,0,"Kill other login (Y/N)? [Y]: ",ans,sizeof ans,DOECHO,0);
        if (*ans == 'N' || *ans == 'n') disconnect(EXIT_LOGOUT);
        rc = bbs_login(acct.userid, acct.passwd, 1, &myinfo);
	goto login_switch;
      }
      else disconnect(EXIT_LOGOUT);
      break;
    default: prints("\nLogin denied.\n\n");
    }          
  } while (rc != S_OK);
  alarm(0);
  set_idle_alarm();
  return 0;
}

#if REMOTE_CLIENT
usage(prog)
char *prog;
{
  fprintf(stderr, 
  "Usage: %s [-d tmpdir] [-e editor] [-m menu-file] [-p pager]\n", prog);
  fprintf(stderr,
  "       [-s shell] [-t terminal-type] [bbs-server] [port]\n");
}
#endif

main(argc, argv)
int argc;
char *argv[];
{
  extern NAMELIST acctlist;
  int rc;
  PATH fname;
  char *bbshomedir = NULL;
  char *servername = "localhost";
  SHORT port = EBBS_PORT;
  extern int lang;
#if REMOTE_CLIENT
  int c;
  struct passwd *pw;

  while ((c = getopt(argc, argv, "d:e:m:p:s:t:?")) != -1) {
    switch (c) {
    case 'd':
      tmpdir = optarg;
      break;
    case 'e':
      editor = optarg;
      break;
    case 'm':
      _menudesc_file = optarg;
      break;
    case 'p':
      pager = optarg;
      break;
    case 's':
      shell = optarg;
      break;
    case 't':
      termtype = optarg;
      break;
    case '?':
      usage(argv[0]);
      return 2;
    }
  }

  if (optind < argc) servername = argv[optind];
  if (optind+1 < argc) port = (SHORT)atoi(argv[optind+1]);

  if (shell == NULL) shell = getenv("SHELL");
  if (shell == NULL) shell = "/bin/sh";

  if (tmpdir == NULL) tmpdir = getenv("TMPDIR");
  if (tmpdir == NULL) tmpdir = "/tmp";

  if (pager == NULL) pager = getenv("BBS_PAGER");
  if (editor == NULL) editor = getenv("BBS_EDITOR");
  if (termtype == NULL) termtype = getenv("TERM");
  if (_menudesc_file == NULL) _menudesc_file = ".ebbsmenu";

  if ((pw = getpwuid(getuid())) != NULL)
    bbshomedir = pw->pw_dir;
#else
  _menudesc_file = "etc/menu.desc";
#endif

  if (get_tty() == -1) {
    perror("tty");
    fprintf(stderr, "Can't get terminal settings!\n");
    return 1;
  }
  
  home_bbs(bbshomedir);
  if ((rc = bbs_initialize()) != S_OK) {
    switch (rc) {
    case S_NOTFOUND:
      printf("Cannot open bbs config file!\n");
      printf("Make sure BBSHOME points to the bbs home directory.\n");
      break;
    default:
      printf("bbs initialize failed!\n");
    }
    return 1;
  }

  sprintf(c_tempfile, "tmp/bbl%05d", getpid());

  if ((rc = bbs_connect(servername, port, &serverinfo)) != S_OK) {
    printf("bbs_connect failed!\n");    
    return 1;
  }


#if REMOTE_CLIENT
  sprintf(c_tempfile, "%s/bbs%05d", tmpdir, getpid());
#else
  sprintf(c_tempfile, "tmp/bbl%05d", getpid());
#endif

  signal(SIGSTOP, sig_handler);
  signal(SIGCONT, sig_handler);
  signal(SIGTSTP, sig_handler);

  signal(SIGHUP, sig_handler);
  signal(SIGINT, sig_handler);
  signal(SIGQUIT, sig_handler);
  signal(SIGILL, sig_handler);
  signal(SIGIOT, sig_handler);
#ifdef SIGEMT
  signal(SIGEMT, sig_handler);
#endif
  signal(SIGFPE, sig_handler);
#ifdef SIGBUS
  signal(SIGBUS, sig_handler);
#endif
  signal(SIGSEGV, sig_handler);
#ifdef SIGSYS
  signal(SIGSYS, sig_handler);
#endif
  signal(SIGPIPE, sig_handler);
  signal(SIGTERM, sig_handler);
  signal(SIGALRM, sig_handler);
  signal(SIGCHLD, SIG_DFL);
#ifdef SIGIO
  signal(SIGIO, SIG_IGN);
#endif
#ifdef SIGURG
  signal(SIGURG, SIG_IGN);
#endif
#ifdef SIGPWR
  signal(SIGPWR, sig_handler);
#endif

#if !REMOTE_CLIENT
  /* This is how the local client gets paged -- via SIGUSR1. */
/*
  signal(SIGUSR1, page_handler);
*/
  /* I'll use SIGUSR2 - DKIM */
  signal(SIGUSR2, page_handler);
#endif

  init_tty();
  
  prints("\nWelcome to %s\n", serverinfo.boardname);
  if (bbs_get_issue(fname) == S_OK) {
    FILE *fp = fopen(fname, "r");
    char buf[256];
    if (fp) {
      while (fgets(buf, sizeof(buf), fp)) 
	prints(buf);
      fclose(fp);
    }
    prints("\n");
  }
  
  Login(serverinfo.newok);
  lang = myinfo.lang;
  SetPermTable();

  if (ParseMenu() == -1) {
    disconnect(EXIT_LOGOUT);
  }

  InitializeTerminal();
  initscr();
  clear();
  if (bbs_get_welcome(fname) == S_OK) {
    if (myinfo.lastlogin == 0) More(fname, 1);
    else {
      char buf[256], host[21], ans[3];

      memset(host, '\0', sizeof host);
      strncpy(host, myinfo.fromhost, sizeof(host)-1);
      More(fname, 0);
      if (lang)
        sprintf(buf, "¸¶Áö¸· ·Î±äÀº [%s] ¿¡ %s ¿¡¼­ [RETURN]:",
              Ctime((time_t *)&myinfo.lastlogin), host);
      else
        sprintf(buf, "Last login %s from %s [RETURN]: ",
              Ctime((time_t *)&myinfo.lastlogin), host);
      getdata(t_lines-1, 0, buf, ans, 2, NOECHO, 0);
    }
  }
  if (acctlist == NULL)
    {
      extern int lang;
      extern int t_lines;

      clear();
      move(t_lines/2, 20);
      if (lang)
        prints("ÀüÃ¼ À¯Àú ¸®½ºÆ® Ä³½¬ÇÕ´Ï´Ù....\n");
      else
	prints("Getting BBS User List for speedup.....\n");
      refresh();
      bbs_acctnames(&acctlist);
    }
  clear();
  
  init_mode_strs_chars();
  NDoMenu("Main") ; /* Start at the Main Menu */

  disconnect(EXIT_LOGOUT);
}  

Xit()
{
  clear();
  disconnect(EXIT_LOGOUT);
  return FULLUPDATE;
}
 default:     /* assumed to be a signal */
    if (g_child_pid != -1) {
      kill(g_chiDarkNET-1.08/client.h                                                                                  644   21270   21270        21113  5737375474   7543                                                                                                                                                                                                                                                                                                                                                                      
/*
Eagles Bulletin Board System
Copyright (C) 1994, Ray Rocker, rrrocker@rock.b11.ingr.com
                                rock@seabass.st.usm.edu
                                72673.2105@compuserve.com

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "common.h"
#include "perms.h"
#include <stdio.h>

#define CLIENT_VERSION_MAJ	0
#define CLIENT_VERSION_MIN	1

/* 
   One day there will be a different libbbs.a that will be the client side
   of a remote bbs service. The entry points will just pack the parameters
   into network form and ship them across to the server, who will unpack
   them and call the local_bbs_* functions to do the work.

   For the local libbbs.a, we can just #define all the entry points to the
   library to be the local_bbs_* functions.
*/

#if !REMOTE_CLIENT

#define bbs_initialize local_bbs_initialize
#define bbs_connect local_bbs_connect 
#define bbs_disconnect local_bbs_disconnect 
#define bbs_get_issue local_bbs_get_issue 
#define bbs_get_welcome local_bbs_get_welcome 
#define bbs_newlogin local_bbs_newlogin 
#define bbs_login local_bbs_login 
#define bbs_add_account local_bbs_add_account 
#define bbs_delete_account local_bbs_delete_account 
#define bbs_query local_bbs_query 
#define bbs_owninfo local_bbs_owninfo 
#define bbs_get_userinfo local_bbs_get_userinfo 
#define bbs_set_mode local_bbs_set_mode 
#define bbs_set_passwd local_bbs_set_passwd 
#define bbs_set_username local_bbs_set_username 
#define bbs_set_terminal local_bbs_set_terminal 
#define bbs_set_email local_bbs_set_email 
#define bbs_modify_perms local_bbs_modify_perms 
#define bbs_modify_account local_bbs_modify_account 
#define bbs_enum_accounts local_bbs_enum_accounts 
#define bbs_enum_users local_bbs_enum_users 
#define bbs_acctnames local_bbs_acctnames 
#define bbs_usernames local_bbs_usernames 
#define bbs_get_info local_bbs_get_info 
#define bbs_get_license local_bbs_get_license 
#define bbs_get_plan local_bbs_get_plan 
#define bbs_set_plan local_bbs_set_plan 
#define bbs_toggle_cloak local_bbs_toggle_cloak 
#define bbs_toggle_exempt local_bbs_toggle_exempt 
#define bbs_get_permstrings local_bbs_get_permstrings 
#define bbs_check_mail local_bbs_check_mail 
#define bbs_mail local_bbs_mail
#define bbs_open_mailbox local_bbs_open_mailbox 
#define bbs_close_board local_bbs_close_board 
#define bbs_enum_headers local_bbs_enum_headers 
#define bbs_read_message local_bbs_read_message 
#define bbs_delete_message local_bbs_delete_message 
#define bbs_delete_range local_bbs_delete_range 
#define bbs_mark_message local_bbs_mark_message 
#define bbs_set_welcome local_bbs_set_welcome
#define bbs_add_board local_bbs_add_board
#define bbs_delete_board local_bbs_delete_board
#define bbs_get_board local_bbs_get_board
#define bbs_modify_board local_bbs_modify_board
#define bbs_enum_boards local_bbs_enum_boards
#define bbs_boardnames local_bbs_boardnames
#define bbs_visit_board local_bbs_visit_board
#define bbs_post local_bbs_post
#define bbs_open_board local_bbs_open_board
#define bbs_test_board local_bbs_test_board
#define bbs_update_message local_bbs_update_message
#define bbs_zap_board local_bbs_zap_board
#define bbs_get_boardmgrs local_bbs_get_boardmgrs
#define bbs_set_boardmgrs local_bbs_set_boardmgrs
#define bbs_enum_fileboards local_bbs_enum_fileboards
#define bbs_fileboardnames local_bbs_fileboardnames
#define bbs_open_fileboard local_bbs_open_fileboard
#define bbs_protonames local_bbs_protonames
#define bbs_set_protocol local_bbs_set_protocol
#define bbs_upload local_bbs_upload
#define bbs_download local_bbs_download
#define bbs_chat local_bbs_chat
#define bbs_exit_chat local_bbs_exit_chat
#define bbs_chat_send local_bbs_chat_send
#define bbs_kick_user local_bbs_kick_user
#define bbs_talk local_bbs_talk
#define bbs_exit_talk local_bbs_exit_talk
#define bbs_get_talk_request local_bbs_get_talk_request
#define bbs_accept_page local_bbs_accept_page
#define bbs_refuse_page local_bbs_refuse_page
#define bbs_set_pager local_bbs_set_pager
#define bbs_get_overrides local_bbs_get_overrides
#define bbs_set_overrides local_bbs_set_overrides
#define bbs_forward_message local_bbs_forward_message
#define bbs_forward_file local_bbs_forward_file
#define bbs_set_editor local_bbs_set_editor
#define bbs_get_editor local_bbs_get_editor
#define bbs_enum_editors local_bbs_enum_editors
#define bbs_get_signature local_bbs_get_signature
#define bbs_set_signature local_bbs_set_signature
#define bbs_set_lang local_bbs_set_lang
#define bbs_get_modestrings local_bbs_get_modestrings
#define bbs_get_modechars local_bbs_get_modechars

#endif /* !REMOTE_CLIENT */

/* Function prototypes for libbbs entry points. */

int bbs_initialize __P((void));
int bbs_connect __P((char *, SHORT, BBSINFO *));
int bbs_disconnect __P((void));
int bbs_get_issue __P((char *));
int bbs_get_welcome __P((char *));
int bbs_newlogin __P((ACCOUNT *, LOGININFO *));
int bbs_login __P((char *, char *, SHORT, LOGININFO *));
int bbs_add_account __P((ACCOUNT *, SHORT));
int bbs_delete_account __P((char *));
int bbs_query __P((char *, ACCOUNT *));
int bbs_owninfo __P((ACCOUNT *));
int bbs_get_userinfo __P((char *, ACCOUNT *));
int bbs_set_mode __P((SHORT));
int bbs_set_passwd __P((char *));
int bbs_set_username __P((char *));
int bbs_set_terminal __P((char *));
int bbs_set_email __P((char *));
int bbs_modify_perms __P((char *, LONG));
int bbs_modify_account __P((char *, ACCOUNT *, SHORT));
int bbs_enum_accounts __P((SHORT, SHORT, int(), void *));
int bbs_enum_users __P((SHORT, SHORT, char *, int(), void *));
int bbs_acctnames __P((NAMELIST *));
int bbs_usernames __P((NAMELIST *));
int bbs_get_info __P((char *));
int bbs_get_license __P((char *));
int bbs_get_plan __P((char *, char *));
int bbs_set_plan __P((char *));
int bbs_toggle_cloak __P((void));
int bbs_toggle_exempt __P((char *));
int bbs_get_permstrings __P((char **));
int bbs_check_mail __P((void));
int bbs_mail __P((NAMELIST, char *, char *, LONG *));
int bbs_open_mailbox __P((OPENINFO *));
int bbs_close_board __P((void));
int bbs_enum_headers __P((SHORT, SHORT, SHORT, int(), void *));
int bbs_read_message __P((SHORT, char *));
int bbs_delete_message __P((SHORT));
int bbs_delete_range __P((SHORT, SHORT, SHORT *));
int bbs_mark_message __P((SHORT, SHORT));
int bbs_set_welcome __P((char *));
int bbs_add_board __P((BOARD *));
int bbs_delete_board __P((char *));
int bbs_get_board __P((char *, BOARD *));
int bbs_modify_board __P((char *, BOARD *, SHORT));
int bbs_enum_boards __P((SHORT, SHORT, SHORT, int(), void *));
int bbs_boardnames __P((NAMELIST *));
int bbs_visit_board __P((char *));
int bbs_post __P((char *, char *, char *));
int bbs_open_board __P((char *, OPENINFO *));
int bbs_test_board __P((char *, SHORT *));
int bbs_update_message __P((SHORT, char *));
int bbs_zap_board __P((char *, SHORT));
int bbs_get_boardmgrs __P((char *, NAMELIST *));
int bbs_set_boardmgrs __P((char *, NAMELIST));
int bbs_enum_file_boards __P((SHORT, SHORT, int(), void *));
int bbs_fileboardnames __P((NAMELIST *));
int bbs_open_fileboard __P((char *, OPENINFO *));
int bbs_protonames __P((NAMELIST *));
int bbs_set_protocol __P((char *));
int bbs_upload __P((char *, char *, char *));
int bbs_download __P((char *, char *, char *));
int bbs_chat __P((char *, LONG *));
int bbs_exit_chat __P((void));
int bbs_chat_send __P((char *));
int bbs_kick_user __P((LONG));
int bbs_talk __P((LONG, LONG, LONG *));
int bbs_exit_talk __P((void));
int bbs_get_talk_request __P((USEREC *, LONG *, SHORT *));
int bbs_accept_page __P((LONG, SHORT, LONG *));
int bbs_refuse_page __P((LONG, SHORT));
int bbs_set_pager __P((SHORT, SHORT));
int bbs_get_overrides __P((NAMELIST *));
int bbs_set_overrides __P((NAMELIST));
int bbs_forward_message __P((SHORT));
int bbs_forward_file __P((char *));
int bbs_set_editor __P((char *));
int bbs_get_editor __P((char *, char *, char *));
int bbs_enum_editors __P((NAMELIST *));
int bbs_get_signature __P((char *));
int bbs_set_signature __P((char *));
int bbs_set_lang __P((int));
int bbs_get_modestrings __P((char **));
int bbs_get_modechars __P((char *));

/* Now for the UI-dependent stuff. */

#include "clientui.h"

#include "c_msg.h"
_cloak local_bbs_toggle_cloak 
#define bbs_toggle_exempt local_bbs_toggle_exempt 
#define bbs_get_permstrings local_bbs_get_permstrings 
#define bbs_check_mail local_bbs_check_mail 
#define bbs_mail local_bbs_mail
#define bbs_open_mailbox local_bbs_open_mailbox 
#define bbs_close_board local_bbs_close_board 
#define bbs_enum_headers local_bbs_enum_headers 
#define bbs_read_message local_bbs_read_message 
#define bbs_delete_message loDarkNET-1.08/clientui.h                                                                                644   21270   21270         5315  5724022405  10042                                                                                                                                                                                                                                                                                                                                                                      
/*
Eagles Bulletin Board System
Copyright (C) 1994, Ray Rocker, rrrocker@rock.b11.ingr.com
                                rock@seabass.st.usm.edu
                                72673.2105@compuserve.com

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "pbbs/io.h"

/*
   Header file for the user interface. This plus the remote libbbs will 
   make up the client in a future version.
*/

typedef struct _MENUITEM {
  char *cmdname;
  int (*cmdfunc)();
  char *nextcmd;
  char *errorcmd;
  int enabled;
  char *helpstr;
  char *khelpstr;
} MENUITEM;

typedef struct _READMENUITEM {
  char cmdkey;
  int (*cmdfunc)();
  int openaccess;
  int permaccess;
  char *helpstr;
  char *khelpstr;
} READMENUITEM;

/* Flags for the menu commands */

#define DONOTHING	0
#define FULLUPDATE      0001
#define PARTUPDATE      0002
#define FETCHNEW	0004
#define NEWDIRECT	0010
#define EXITMENU        0020
#define MENUERROR	0040

struct enum_info {
  int count;
  int topline;
  int bottomline;
  int currline;
  int totals[2];   /* general purpose counters */
};

/* sleep time between Monitor refreshes */
#define MONITOR_REFRESH 10         

/* Additions for new_menu items */

#define MAXMENUSZ     (26)
#define MAXMENUDEPTH  (5)

typedef struct _NMENUITEM {
    char *name ;
    char *kname;
    int   enabled ;
    
    char *default_action ;
    char *error_action ;

    int (*action_func)() ;
    char *action_arg ;

    char *help ;
    char *khelp ;

    struct _NMENUITEM *next ;
} NMENUITEM ;

typedef struct _NMENU {
    char *menu_id ;
    char *kmenu_id;
    char *menu_title ;
    char *kmenu_title ;
    char *menu_default ;
    char *menu_prompt ;
    char *kmenu_prompt ;
    NMENUITEM *menucommands[MAXMENUSZ] ;
    NMENUITEM *commlist ;
    struct _NMENU *next ;
} NMENU ;

/* A few global variables */
extern LOGININFO myinfo;
extern char c_tempfile[];
extern NAME currboard;
extern NAME currfileboard;

/* Functions to check for page requests */
extern int PagePending __P((void));
extern int NewPagePending __P((void));

/* Other common functions */
extern char ModeToChar __P((SHORT));
extern char *ModeToString __P((SHORT));
                                                                                                                                                                                                                                                                                                                   DarkNET-1.08/clntcmds.h                                                                                644   21270   21270         6766  5731470537  10063                                                                                                                                                                                                                                                                                                                                                                      
/*
Eagles Bulletin Board System
Copyright (C) 1994, Ray Rocker, rrrocker@rock.b11.ingr.com
                                rock@seabass.st.usm.edu
                                72673.2105@compuserve.com

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/


/* 
   All of the interface points between the bbs client and server parts
   are listed here. These must not be changed, but new ones can be added
   up to MAX_CLNTCMDS.
*/

#define C_INIT         0
#define C_CONNECT      1
#define C_DISCONNECT   2
#define C_ISSUE        3
#define C_WELCOME      4
#define C_NEWLOGIN     5
#define C_LOGIN        6
#define C_ADDACCT      7
#define C_DELACCT      8
#define C_QUERY        9
#define C_OWNACCT     10
#define C_GETACCT     11
#define C_SETMODE     12
#define C_SETPASSWD   13
#define C_SETUSERNAME 14
#define C_SETTERMINAL 15
#define C_SETEMAIL    16
#define C_SETPERMS    17
#define C_SETACCT     18
#define C_ALLUSERS    19
#define C_USERS       20
#define C_ALLNAMES    21
#define C_NAMES       22
#define C_INFOFILE    23
#define C_LICENSE     24
#define C_GETPLAN     25
#define C_SETPLAN     26
#define C_CLOAK       27
#define C_EXEMPT      28
#define C_GETPERMSTRS 29
#define C_CHKMAIL     30
#define C_MAIL        31
#define C_OPENMAIL    32
#define C_CLOSEBRD    33
#define C_ENUMHDRS    34
#define C_READMSG     35
#define C_DELMSG      36
#define C_DELRANGE    37
#define C_MARKMSG     38
#define C_SETWELCOME  39
#define C_ADDBOARD    40
#define C_DELBOARD    41
#define C_GETBOARD    42
#define C_SETBOARD    43
#define C_ENUMBRDS    44
#define C_BNAMES      45
#define C_VISITBRD    46
#define C_POST        47
#define C_OPENBRD     48
#define C_TESTBRD     49
#define C_REPLACEMSG  50
#define C_ZAPBOARD    51
#define C_GETBMGRLIST 52
#define C_SETBMGRLIST 53
#define C_ENUMFBRDS   54
#define C_FBNAMES     55
#define C_OPENFBRD    56
#define C_PROTONAMES  57
#define C_SETPROTO    58
#define C_UPLOAD      59
#define C_DOWNLOAD    60
#define C_CHAT        61
#define C_EXITCHAT    62
#define C_CHATLINE    63
#define C_KICK        64
#define C_TALK        65
#define C_EXITTALK    66
#define C_GETTALKREQ  67
#define C_TALKACCEPT  68
#define C_TALKREFUSE  69
#define C_SETPAGER    70
#define C_GETOVERLIST 71
#define C_SETOVERLIST 72
#define C_FORWARDMSG  73
#define C_FORWARDFILE 74
#define C_SETEDITOR   75
#define C_GETEDITOR   76
#define C_ENUMEDITORS 77
#define C_GETSIGFILE  78
#define C_SETSIGFILE  79
#define C_SEEALLAINFO 80
#define C_SEEALLBINFO 81
#define C_ALLBOARDMGR 82
#define C_SEECLOAK    83
#define C_SEEREALNAME 84
#define C_NOTIMEOUT   85
#define C_IRC         86
#define C_SETLANG     87
#define C_DELME       88
#define C_XIT         89
#define	C_SENDEMAIL   90
#define	C_FTPPOST     91
#define	C_ROUTING     92
#define C_ADMINMENU   93
#define C_FILEMENU    94
#define C_MAILMENU    95
#define C_TALKMENU    96
#define C_XYZMENU     97
#define C_GETMODESTRS 98
#define C_GETMODECHRS 99

#define MAX_CLNTCMDS  256
          DarkNET-1.08/common.h                                                                                  644   21270   21270        17122  6044662642   7546                                                                                                                                                                                                                                                                                                                                                                      
/*
Eagles Bulletin Board System
Copyright (C) 1994, Ray Rocker, rrrocker@rock.b11.ingr.com
                                rock@seabass.st.usm.edu
                                72673.2105@compuserve.com

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include "osdeps.h"
#include "modes.h"
#include "retval.h"
#include "clntcmds.h"
#include "myctype.h"

#define	MAXUSER		6000
#define	MAXBOARD	100
#define	MAXEDITOR	10
#define	MAXUTABLE	80
#define	MAX_TMP		100
#define	MAXPROTO	10
#define	MAXFILEBOARD	50
#define	MAXOVERRIDE	100
#define	MAXMANAGER	32

/* 
   Common header file for all pieces of the bbs, client and server.
*/

/* The port bbsd listens on. */
#define EBBS_PORT       5150

/* Exit values for lbbs. */

#define EXIT_LOGOUT	0
#define EXIT_LOSTCONN	-1
#define EXIT_CLIERROR   -2
#define EXIT_TIMEDOUT   -3
#define EXIT_KICK	-4

/* Lengths for string data items. */

#define BBSNAMELEN      39
#define NAMELEN		12
#define PASSLEN		14
#define UNAMELEN	25
#define HOSTLEN		39
#define TERMLEN		11
#define RNAMELEN	29
#define ADDRLEN		99
#define MAILLEN		79
#define PATHLEN		255
#define TITLELEN	63
#define	LANGLEN		8

/* I like typedefs. */

typedef char BBSNAME[BBSNAMELEN+1];
typedef char NAME[NAMELEN+1];
typedef char PASSWD[PASSLEN+1];
typedef char UNAME[UNAMELEN+1];
typedef char HOST[HOSTLEN+1];
typedef char TERM[TERMLEN+1];
typedef char RNAME[RNAMELEN+1];
typedef char ADDR[ADDRLEN+1];
typedef char MAIL[MAILLEN+1];
typedef char PATH[PATHLEN+1];
typedef char TITLE[TITLELEN+1];
typedef char ACCESSCODES[MAX_CLNTCMDS];
typedef char LANG[LANGLEN+1];

/* Structures used in the bbs library functions. */

typedef struct _BBSINFO {
  BBSNAME boardname;
  SHORT majver;
  SHORT minver;
  SHORT newok;
} BBSINFO;

typedef struct _LOGININFO {
  NAME userid;
  SHORT flags;
  LONG idletimeout;
  LONG lastlogin;
  HOST fromhost;
  ACCESSCODES access;
  UNAME username;
  NAME editor;
  TERM terminal;
  SHORT lang;
} LOGININFO;

typedef struct _ACCOUNT {
  /* in the passwds file */ 
  NAME userid;
  PASSWD passwd;
  UNAME username;
  LONG perms;
  SHORT flags;
  /* in home/<userid>/lastlogin */
  LONG lastlogin;
  HOST fromhost;
  /* in home/<userid>/profile */
  TERM terminal;
  RNAME realname;
  ADDR address;
  MAIL email;
  NAME protocol;
  NAME editor;
  LANG lang;
} ACCOUNT;

typedef struct _USEREC {
  NAME userid;
  UNAME username;
  HOST fromhost;
  LONG pid;
  SHORT flags;
  SHORT mode;
} USEREC;

/* Account and userec flags. */
#define FLG_CLOAK	0x001     /* Invisibility */
#define FLG_EXEMPT	0x002     /* For use by user clean utilities */
#define FLG_DISABLED    0x004     /* Account is temporarily disabled */
#define FLG_SHARED      0x008     /* Account does not belong to one user */
#define FLG_NOPAGE      0x010     /* User not accepting page requests... */
#define FLG_NOOVERRIDE  0x020     /* ...not even friends! */
#define	FLG_KOREAN	0x080
#define	FLG_VOTE	0x100

#ifdef FOR_FUTURE_USE
/* More userec flags */
#define FLG_IN_BBS      0x100     /* User is connected to bbs */
#define FLG_IN_CHAT     0x200     /* User is connected to chat daemon */
#endif

/* Flags for bbs_modify_account */
#define MOD_USERID      0x001
#define MOD_PASSWD      0x002
#define MOD_USERNAME    0x004
#define MOD_TERMINAL    0x008
#define MOD_REALNAME    0x010
#define MOD_ADDRESS     0x020
#define MOD_EMAIL       0x040
#define MOD_PROTOCOL    0x080
#define MOD_EDITOR      0x100
#define MOD_LANG        0x200

/* Mode constants */
#define BBS_MAX_MODE       31       /* not including flags */
#define MODE_FLG_NOPAGE    0x0100   /* must be greater than BBS_MAX_MODE */

/* Max number of recipients for a mail message */
#define BBS_MAX_MAILRECIPS 32

typedef struct _OPENINFO {
  NAME name;
  SHORT flags;
  LONG totalmsgs;
  LONG newmsgs;
} OPENINFO;

/* Flags for OPENINFO */
#define OPEN_POST       0x001
#define OPEN_MANAGE     0x002
#define OPEN_REOPEN     0x004

typedef struct _HEADER {
  SHORT fileid;
  NAME owner;
  TITLE title;
  SHORT flags;
  LONG size;
  LONG mtime;
} HEADER;

/* flags for HEADER structures */
#define FILE_UNREAD	0x1
#define FILE_MARKED	0x2
#define FILE_BINARY     0x4
 
/* General-purpose board type constants */
#define BOARD_NONE      0
#define BOARD_MAIL      1
#define BOARD_POST      2
#define BOARD_FILE      3

typedef struct _BOARD {
    NAME name;
    TITLE description;
    TITLE kdescription;
    LONG readmask;
    LONG postmask;
    SHORT flags;
    LONG totalposts;
    LONG newposts;
    LONG ownedposts;     /* not supported at the moment! */
    LONG lastpost;
} BOARD;

/* Flags for BOARD structs */
#define BOARD_ZAPPED    0x001
#define BOARD_NOZAP     0x002

/* Flags for bbs_modify_board. */
#define MOD_BNAME       0x001
#define MOD_BOARDDESC   0x002
#define MOD_READMASK    0x004
#define MOD_POSTMASK    0x008
#define MOD_BOARDKDESC  0x010

/* Flags for bbs_enum_boards. */
#define BE_UNZAPPED     0x001
#define BE_ZAPPED       0x002
#define BE_ALL          (BE_ZAPPED | BE_UNZAPPED)
#define BE_UNDEFINED    0x004
#define BE_DO_COUNTS    0x008

/* Common stuff for chat. */
#define CHATID_MAX         8
typedef char CHATID[CHATID_MAX+1];

#define CHATLINE_MAX       255  /* Text plus /cmd at beginning */
#define CHATLINE_TEXT_MAX  200  /* Max size of test only */
typedef char CHATLINE[CHATLINE_MAX+1];

#define CHAT_CTRL_CHATID "**C"  /* Chatd-->client control message */

/* Initial responses sent by the chat daemon */
#define CHAT_LOGIN_OK       "OK"
#define CHAT_LOGIN_EXISTS   "EX"
#define CHAT_LOGIN_INVALID  "IN"
#define CHAT_LOGIN_BOGUS    "BG"

/* Namelists are very useful. */

typedef struct _NAMENODE {
  char word[NAMELEN+1];
} NAMENODE;

typedef struct {
  NAMENODE *data;
  int size;
  int last;
} *NAMELIST;

/* Useful bit-manipulation macros. */

#define BITISSET(mask,bit)     ((mask)&(bit))
#define BITSET(mask,bit)       ((mask)|=(bit))
#define BITCLR(mask,bit)       ((mask)&=~(bit))
#define BITTOGGLE(mask,bit)    ((mask)^=(bit))

/* Prototypes. */

void strip_trailing_space __P((char *));
int recursive_rmdir __P((char *));
int is_valid_userid __P((char *));
int is_valid_password __P((char *));
int is_valid_boardname __P((char *));
LONG hex2LONG __P((char *));
SHORT hex2SHORT __P((char *));
char *LONGcpy __P((char *, LONG));
char *SHORTcpy __P((char *, SHORT));
int is_text_file __P((char *));
int is_directory __P((char *));

int is_passwd_good __P((char *, char *));
void encrypt_passwd __P((char *, char *));

void free_namelist __P((NAMELIST *));
void create_namelist __P((NAMELIST *, int));
int add_namelist __P((NAMELIST *, char *, char *));
int remove_namelist __P((NAMELIST *, char *));
int is_in_namelist __P((NAMELIST, char *));
int apply_namelist __P((NAMELIST, int(), void *));
int read_namelist __P((char *, NAMELIST *));
int write_namelist __P((char *, NAMELIST));

int read_headers __P((char *, HEADER *));
int write_mail_headers __P((int, HEADER *, char *, NAMELIST));
int write_post_headers __P((int, HEADER *, char *, char *));
int parse_to_list __P((NAMELIST *, char *, char *));

static char *version[] = {"DarkNET Version 1.07", "´ÙÅ©ºñ ¹öÁ¯ 1.08"};
T {
  /* in the passwds file */ 
  NAME userid;
  PASSWD passwd;
  UNAME username;
  LONG perms;
  SHORT flags;
  /* in home/<userid>/lastlogin */
  LONG lastlogin;
  HOST fromhost;
  /* in home/<userid>/profile */
  TERM terminal;
  RNAME realname;
  ADDR address;
  MAIL email;
  NAME protocol;
  NAME editor;
  LANG lang;
} ACCOUNT;

typedef struct _USEREC {
  NAME userid;
  UNAME username;
  HOST fromhost;
  LONG pid;
  SHORDarkNET-1.08/complete.c                                                                                644   21270   21270        13043  5741710357  10057                                                                                                                                                                                                                                                                                                                                                                      
/*
	Too slow.

	Rewrote using new name.c

	Daeshik Kim

	dkim@hq.si.net
	hellcat@korea.slip.umd.edu
*/


/*
Eagles Bulletin Board System
Copyright (C) 1994, Ray Rocker, rrrocker@rock.b11.ingr.com
                                rock@seabass.st.usm.edu
                                72673.2105@compuserve.com

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

/*
   Adapted from Pirates BBS 1.8, namecomplete.c
   Copyright (C) 1990, Edward Luke, lush@Athena.EE.MsState.EDU
*/

#include "client.h"
#include <ctype.h>
#include <malloc.h>

#define WORDSIZE NAMELEN+1

static int NumInList(list)
NAMELIST list;
{
  return  (list->last);
}

ListMaxLen(list, lines)
NAMELIST list;
int lines;
{
/*
  register NAMENODE *ptr;
  register int i, size, len, max = 0;

  for (i=0, size=list->last, ptr=list->data; i<size; i++) {
    len = strlen (ptr[i].word);
    if (len > max) max = len;
  }
  return max;
*/
  return NAMELEN;
}

chkstr(tag,name)
char *tag, *name;
{
  register char c1, c2;
  while(*tag != '\0') {
    c1 = *tag++;
    c2 = *name++;
    if (c1 == c2) continue;
    if (myislower(c1)) c1 = toupper(c1);
    if (myislower(c2)) c2 = toupper(c2);
    if(c1 != c2)
      return 0;
  }
  return 1;
}

NAMELIST
GetSubList(tag, list)
register char *tag ;
register NAMELIST list;
{
  NAMELIST wlist;
  register NAMENODE *ptr;
  register int i, size;

  wlist = NULL;
  create_namelist (&wlist, MAXUSER);
  for (i=0, size=list->last, ptr=list->data; i<size; i++)
    {
      if (tag == NULL)
	add_namelist(&wlist, ptr[i].word, NULL);
      else
	{
	  if (chkstr(tag, ptr[i].word))
	    add_namelist(&wlist, ptr[i].word, NULL);
	}
    }
  sort_list(&wlist);
  return (wlist);
}

static void ClearSubList(list)
NAMELIST list;
{
  free_namelist(&list);
}

#define NUMLINES (t_lines-6)

namecomplete(list, prompt, data)
NAMELIST list;
char *prompt, *data ;
{
  NAMENODE dummynode;
  char *temp;
  int ch ;
  int count = 0 ;
  int clearbot = 0;
  int i;
  
  if(scrint) {
    NAMELIST cwlist, morelist ;
    NAMENODE *ptr;
    int x,y ;
    int origx, origy;
    int total = 0, size = 0;
    int more = 0;
    int j;
    
    if(prompt != NULL) {
      prints("%s",prompt) ;
      clrtoeol() ;
    }
    temp = data ;
    
    if (list == NULL) {
      create_namelist (&list, 1);
      add_namelist(&list, "", NULL);
    }    
    cwlist = GetSubList(NULL, list) ;
    morelist = NULL ;
    getyx(&y,&x) ;
    getyx(&origy, &origx);
    
    while((ch = igetch()) != EOF)
      {
	if(ch == '\n' || ch == '\r') {
	  *temp = '\0' ;
	  prints("\n") ;
	  if(NumInList(cwlist) == 1 && temp != data)
	    strncpy(data,cwlist->data[0].word,WORDSIZE) ;
	  ClearSubList(cwlist) ;
	  break ;
	}
	if(ch == ' ') {
	  int col,len;

	  if(NumInList(cwlist) == 1) {
	    strncpy(data,cwlist->data[0].word,WORDSIZE) ;
	    move(origy,origx) ;
	    prints("%s",data) ;
	    count = strlen(data) ;
	    temp = data + count ;
	    getyx(&y,&x) ;
	    continue ;
	  }

	  clearbot = 1 ;
	  col = 0 ;

	  /* new! or everything is displayed the, we have to recycle this */
	  if((!morelist) || (total && size && total == size)) {
	    morelist = cwlist ;
	    ptr = morelist->data;
	    size = morelist->last;
	    total = 0;
	    len = ListMaxLen(morelist,NUMLINES) ;
	  }
	  move(4,0) ;
	  clrtobot();
	  standout() ;
	  for (i=0, j=(t_columns-18)/2; i<j; i++)
	    prints("-");
	  prints(" Completion List ");
	  for (i+=18, j=t_columns-1; i<j; i++)
	    prints("-");
	  standend() ;

	  while(len+col < t_columns-1) {
	    register int j;

	    for (j=0; total < size && j < NUMLINES; j++, total++) {
		move (5+j, col);
		prints("%s", ptr[total].word);
	    }
	    col += len+2 ;
	    if(total == size)
	      break;
	    len = ListMaxLen(morelist,NUMLINES) ;
	  }
	  if(total < size) {
	    extern int lang;

	    move(t_lines - 1, 0) ;
	    standout() ;
	    c_msg(INFO_MORE, FALSE);
	    standend() ;
	  }
	  refresh();
	  move(y,x) ;
	  continue ;
	}
	if(ch == '\177' || ch == '\010') {
	  if(temp == data)
	    continue ;
	  temp-- ;
	  count-- ;
	  *temp = '\0' ;
	  ClearSubList(cwlist) ;
	  cwlist = GetSubList(data,list) ;
	  morelist = NULL ;
	  ptr = NULL;
	  x-- ;
	  move(y,x) ;
	  addch(' ') ;
	  move(y,x) ;
	  continue ;
	}
	if(count < WORDSIZE) {
	  NAMELIST node ;
	  *temp++ = ch ;
	  count++ ;
	  *temp = '\0' ;
	  node = GetSubList(data,cwlist) ;
	  if(node == NULL) {
	    bell() ;
	    temp-- ;
	    *temp = '\0' ;
	    count-- ;
	    continue ;
	  }
	  ClearSubList(cwlist) ;
	  cwlist = node ;
	  morelist = NULL ;
	  ptr = NULL;
	  move(y,x) ;
	  addch(ch) ;
	  x++ ;
	}
      }
    if(ch == EOF)
      generic_abort() ;
    if (*data) {
      move(origy,origx);
      prints("%s", data);
    }
    prints("\n") ;
    refresh() ;
    if(clearbot) {
      move(2,0) ;
      clrtobot() ;
      move(3,0) ;
    }
    return 0 ;
  }
  if(prompt != NULL) {
    printf("%s",prompt) ;
    fflush(stdout) ;
  }
  if(!fgets(data,WORDSIZE,stdin))
    generic_abort() ;
  data[WORDSIZE] = '\0';
  if(temp = strchr(data,'\n'))
    *temp = '\0' ;
  return 0 ;
}
ke, lush@Athena.EE.MsState.EDU
*/

#include "client.h"
#include <ctype.h>
#include <malloc.h>

#define WORDSIZE NAMELEN+1

static int NumInList(list)
NAMELIST list;
{
  return  (list->last);
}

ListMaxLen(list, lines)
NAMELIST list;
int lines;
{
/*
  register NAMENODE *ptr;
  register int i, size, len, max = 0;

  for (i=0, size=list->last, ptr=list->data; i<size; i++) {
    len = strlen (ptr[i].word);
    if (len > max) max = len;
  }
  return max;
*/
  return NAMELEN;
}
DarkNET-1.08/cvtacct.c                                                                                 644   21270   21270         5276  5647532323   7667                                                                                                                                                                                                                                                                                                                                                                      
/*
Eagles Bulletin Board System
Copyright (C) 1994, Ray Rocker, rrrocker@rock.b11.ingr.com
                                rock@seabass.st.usm.edu
                                72673.2105@compuserve.com

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "oldbbs.h"
#include "server.h"
#include <fcntl.h>

extern char *optarg;
extern int optind;

usage(prog)
char *prog;
{
  fprintf(stderr, "Usage: %s [-d bbs-dir] old-PASSWDS-file\n", prog);
}

main(argc, argv)
int argc;
char *argv[];
{
  char *bbshome = NULL;
  int c, fd, rc;
  struct ouserec oldacct;
  ACCOUNT acct;

  while ((c = getopt(argc, argv, "d:?")) != -1)
    {
      switch (c)
	{
	case 'd':
	  bbshome = optarg;
	  break;
	case '?':
	  usage(argv[0]);
	  return 2;
	}
    }

  if (optind > argc-1) {
    usage(argv[0]);
    return 2;
  }

  if (home_bbs(bbshome) == -1) {
    fprintf(stderr, "%s: Cannot chdir to %s\n", argv[0], bbshome);
    return 1;
  }

  if ((fd = open(argv[optind], O_RDONLY)) == -1) {
    fprintf(stderr, "%s: Cannot open %s\n", argv[0], argv[optind]);
    return 1;
  }

  while (read(fd, &oldacct, sizeof oldacct) == sizeof oldacct) {
    memset(&acct, 0, sizeof acct);
    strncpy(acct.userid, oldacct.userid, NAMELEN);
    strncpy(acct.passwd, oldacct.passwd, PASSLEN);
    strncpy(acct.username, oldacct.username, UNAMELEN);
    strncpy(acct.terminal, oldacct.termtype, TERMLEN);
    strncpy(acct.email, oldacct.email, MAILLEN);
#if REALINFO
    strncpy(acct.realname, oldacct.realname, RNAMELEN);
    strncpy(acct.address, oldacct.address, ADDRLEN);
#endif
    rc = local_bbs_add_account(&acct, 1);
    switch (rc) {
    case S_OK:
      fprintf(stderr, "%s: added\n", acct.userid);
      break;
    case S_INVALID:
      fprintf(stderr, "%s: invalid userid or password\n", acct.userid);
      break;
    case S_EXISTS:
      fprintf(stderr, "%s: userid already exists\n", acct.userid);
      break;
    case S_SYSERR:
      fprintf(stderr, "%s: error creating account\n", acct.userid);
      fprintf(stderr, "Wrong -d argument or $BBSHOME?\n");
      close(fd);
      return 1;
    }
  }
  close(fd);
  return 0;
}    








                                                                                                                                                                                                                                                                                                                                  DarkNET-1.08/delacct.c                                                                                 644   21270   21270        11304  5740447074   7646                                                                                                                                                                                                                                                                                                                                                                      
/*
Eagles Bulletin Board System
Copyright (C) 1994, Ray Rocker, rrrocker@rock.b11.ingr.com
                                rock@seabass.st.usm.edu
                                72673.2105@compuserve.com

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "server.h"
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <sys/stat.h>

extern char *optarg;
extern int optind;

extern USERDATA user_params;

struct userclean {
  time_t cutoff;
  time_t age;
  int inactives;
  int nologins;
  int for_grins;
};

do_delete(userid, really)
char *userid;
int really;
{
  int rc;
  if (really) {
    rc = local_bbs_delete_account(userid);
    if (rc == S_OK) printf("DELETED  %s\n", userid);
    else printf("ERROR %d deleting %s\n", rc, userid);
  }
  else printf("would have DELETED  %s\n", userid);
}

user_clean_func(indx, userid, info)
int indx;
char *userid;
struct userclean *info;
{
  ACCOUNT acct;
  time_t lastlog;
  
  if (local_bbs_get_userinfo(userid, &acct) != S_OK) return 0;

  if (info->inactives) {
    if (acct.flags & FLG_EXEMPT) {
      return 0;
    }
    if (acct.perms & PERM_SYSOP) {
      return 0;
    }
    if (acct.perms & PERM_ACCTMGR) {
      return 0;
    }
    if (acct.perms & PERM_BRDMGR) {
      return 0;
    }
  }

  if (acct.lastlogin == 0) {
    /* Never logged in, so go by creation time of home directory */
    /* I wish I was saving creation time somewhere besides the log */
    PATH buf;
    struct stat stbuf;
    get_home_directory(acct.userid, buf);
    if (stat(buf, &stbuf) == 0) acct.lastlogin = (LONG)stbuf.st_mtime;
  }
  else {
    if (info->nologins) return 0;
  }

  if (acct.lastlogin + info->age < info->cutoff) {
    do_delete(acct.userid, !info->for_grins);
  }

  return 0;
}

usage(prog)
char *prog;
{
  fprintf(stderr,
    "Usage: %s [-a age] [-c] [-d bbsdir] [-n] [-t] userid ...\n", prog);
  fprintf(stderr,
    "       -c means clean all inactive accounts (subject to age)\n");
  fprintf(stderr,
    "       -n means only clean accounts that have never been used\n");
  fprintf(stderr,
    "       -t is test mode: only show what would happen\n");
}

main(argc, argv)
int argc;
char *argv[];
{
    struct userclean info;
    char *homedir = NULL;
    NAMELIST names;
    int c, cflg = 0;

    info.age = 30;          /* 30 days default */
    info.for_grins = 0;
    info.nologins = 0;
    info.inactives = 0;

    /* I should copy the passfile somewhere for safety */

    while ((c = getopt(argc, argv, "a:cd:nt?")) != -1)
      {
	switch (c)
	  {
	  case 'a':
	    info.age = atoi(optarg);
	    break;
	  case 'c':
            cflg++;
            break;
	  case 'd':
            homedir = optarg;
	  case 'n':
	    info.nologins++;
	    break;
	  case 't':
	    info.for_grins++;
	    break;
      	  case '?':
	    usage(argv[0]);
	    return 2;
	  }
      }
    
    /* Just a safety feature, delete it if you wish */
    if (info.age < 7) {
      fprintf(stderr, "%s: age parameter must be at least 7\n", argv[0]);
      return 1;
    }

    if (home_bbs(homedir) == -1) {
      fprintf(stderr, "%s: Cannot chdir to %s\n", argv[0], homedir);
      return -1;
    }

    if (local_bbs_initialize() != S_OK) {
        fprintf(stderr, "%s: local_bbs_initialize failed\n", argv[0]);
	return 1;
    }

    /* Identify ourself for the log file */
    strcpy(user_params.u.userid, "[delacct]");
    user_params.perms = ~0;
    user_params.access[C_SEEALLAINFO] = '1';

    names = NULL;
    create_namelist(&names, MAXUSER);
    while (optind < argc) {
      add_namelist(&names, argv[optind], NULL);
      optind++;
    }
  
    if (names->last == 0) {
      if (!cflg) {
        fprintf(stderr, "%s: -c not specified and no names given\n", argv[0]);
	local_bbs_disconnect();
        return 2;
      }
      /* Delete all inactive accounts */
      info.inactives++;
      local_bbs_acctnames(&names);
    }
    sort_list(&names);

    time(&info.cutoff);
    info.age *= 86400;   /* convert to seconds */

    apply_namelist(names, user_clean_func, &info);

    free_namelist(&names);
    local_bbs_disconnect();
    return 0;
}

/* dummy func. to satisfy server lib. - dkim */
getdata()
{
    return 0;
}
0;
  }

  if (acct.lastlogin + info->age < info->cutoff) {
    do_delete(acct.userid, !info->for_grins);
  }

  return 0;
}

usage(prog)
char *prog;
{
  fprintf(stderr,
    "Usage: %s [-a age] [-c] [-d bbsdir] [-n] [-t] userid ...\n", prog);
  fprintf(stderr,
    "       -c means clean all inactive accounts (subjecDarkNET-1.08/edit.c                                                                                    644   21270   21270         4233  5735704527   7162                                                                                                                                                                                                                                                                                                                                                                      
/*
Eagles Bulletin Board System
Copyright (C) 1994, Ray Rocker, rrrocker@rock.b11.ingr.com
                                rock@seabass.st.usm.edu
                                72673.2105@compuserve.com

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "server.h"

extern char *ExpandString __P((char *));

/* 
   List of available editors for the local client. 
   This stuff is completely moot for the remote client.
   bbs_set_editor is in login.c.
*/

#define EDITORFILE "etc/editors"

/* Struct for getting entries from the etc/editors file. */

typedef struct _EDITSTRUCT {
  NAME name;
  PATH bin;
  PATH envp;
} EDITSTRUCT;

editent_to_es(rec, es)
char *rec;
EDITSTRUCT *es;
{
  rec = _extract_quoted(rec, es->name, sizeof(es->name));
  rec = _extract_quoted(rec, es->bin, sizeof(es->bin));
  rec = _extract_quoted(rec, es->envp, sizeof(es->envp));
  return S_OK;
}

local_bbs_get_editor(name, path, envp)
char *name;
char *path;
char *envp;
{
  int rc;
  EDITSTRUCT es;
  memset(&es, 0, sizeof es);
  rc = _record_find(EDITORFILE, _match_first, name, editent_to_es, &es);
  if (rc == S_OK) {
    strncpy(path, es.bin, PATHLEN);
    strncpy(envp, ExpandString(es.envp), PATHLEN);
  }
  return rc;
}

/*ARGSUSED*/
_fill_editornames(indx, rec, list)
int indx;
char *rec;
NAMELIST *list;
{
  EDITSTRUCT es;
  editent_to_es(rec, &es);
  add_namelist(list, es.name, NULL);
  return S_OK;
}

local_bbs_enum_editors(list)
NAMELIST *list;
{
  create_namelist(list, MAXEDITOR);
  _record_enumerate(EDITORFILE, 0, _fill_editornames, list);  
  sort_list(list);
  return S_OK;
}
                                                                                                                                                                                                                                                                                                                                                                     DarkNET-1.08/env.c                                                                                     644   21270   21270         5614  5741412546   7023                                                                                                                                                                                                                                                                                                                                                                      
#include "client.h"

char *default_env = "TERM=dumb,SHELL=/bin/false,LANG=HANGUL" ;


char *ExpandString(s)
char *s ;
{
    static char buf[1024] ;
    char *sr = buf ;
    int cnt = 0 ;
    static ACCOUNT acct ;
    static int acct_filled = 0 ;
    
    for(cnt=0;cnt<sizeof(buf);cnt++,sr++) {
        *sr = *s ;
        if(*s == '\0') break ;
        if(*s == '%') {
            if(!acct_filled) {
                bbs_owninfo(&acct) ;
                acct_filled = 1 ;
            }
            switch(*(s+1)) {
                int len ;
              case 'T':
              case 't':
                len =strlen(acct.terminal) ;
                if(len+cnt<sizeof(buf)) {
                    strcpy(sr,acct.terminal) ;
                    sr += len-1 ;
                    cnt += len-1 ;
                }
                s++ ;
                break ;
              case 'I':
              case 'i':
                len = strlen(acct.userid) ;
                if(len+cnt<sizeof(buf)) {
                    strcpy(sr,acct.userid) ;
                    sr += len-1 ;
                    cnt += len-1 ;
                }
                s++ ;
                break ;
              case 'U':
              case 'u':
                len = strlen(acct.username) ;
                if(len+cnt<sizeof(buf)) {
                    strcpy(sr,acct.username) ;
                    sr += len-1 ;
                    cnt += len-1 ;
                }
                s++ ;
                break ;
              case 'E':
              case 'e':
                len = strlen(acct.editor) ;
                if(len+cnt<sizeof(buf)) {
                    strcpy(sr,acct.editor) ;
                    sr += len-1 ;
                    cnt += len-1 ;
                }
                s++ ;
                break ;
              case 'H':
              case 'h':
                len = strlen(acct.fromhost) ;
                if(len+cnt<sizeof(buf)) {
                    strcpy(sr,acct.fromhost) ;
                    sr += len-1 ;
                    cnt += len-1 ;
                }
                s++ ;
                break ;
	      case 'L':
	      case 'l':
		len = strlen(acct.lang);
		if (len + cnt < sizeof(buf)) {
		    strcpy(sr, acct.lang);
		    sr += len - 1;
		    cnt += len - 1;
		}
		s++;
		break;
              default:
                sr-- ;
                break ;
            }
        }
        s++ ;
    }
        
    return buf ;
}


parse_environment(s)
char *s ;
{
    char buf[4096] ;
    char *p1, *p2, *p3 ;
    strncpy(buf,s,sizeof(buf)) ;
    buf[sizeof(buf)-1] = '\0' ;
    p1 = buf ;
    while(p1!=NULL) {
        p2 = strchr(p1,'=') ;
        p3 = strchr(p1,',') ;
        if(p2 == NULL)
          break ;
        *p2 = '\0' ;
        if(p3!=NULL)
          *p3 = '\0' ;
        bbssetenv(p1,p2+1) ;
        if(p3== NULL)
          break ;
        p1 = p3 + 1 ;
        
    }
}


parse_default()
{
    parse_environment(default_env) ;
}
            len = strlen(acct.userid) ;
                if(len+cnt<sizeof(buf)) {
                    strcpy(sr,acctDarkNET-1.08/exec.c                                                                                    644   21270   21270         7211  5647532323   7153                                                                                                                                                                                                                                                                                                                                                                      
/*
Eagles Bulletin Board System
Copyright (C) 1994, Ray Rocker, rrrocker@rock.b11.ingr.com
                                rock@seabass.st.usm.edu
                                72673.2105@compuserve.com

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "server.h"
#include <fcntl.h>
#include <signal.h>

#define MAXCOMSZ   (1024) /* Maximum length of do_exec command */
#define MAXFILELEN (80)   /* Maximum length of the executable file name */
#define MAXARGS    (40)   /* Maximum number of args to a do_exec command */

#define LOOKFIRST  (0)
#define LOOKLAST   (1)
#define QUOTEMODE  (2)

_set_io(fname, fd, append)
char *fname;
int fd;
int append;
{
  int newfd;
  int mode;
  if (fd == 0) mode = O_RDONLY;
  else {
    mode = O_WRONLY | O_CREAT;
    if (append) mode |= O_APPEND;
  }
  close(fd);
  newfd = open(fname, mode, 0600);
  if (newfd == -1) {
    bbslog(0, "ERROR _set_io: open failed: %s mode %d\n", fname, mode);
    return -1;
  }
  if (newfd != fd && dup2(newfd, fd) == -1) {
    bbslog(0, "ERROR _set_io: dup2 failed\n");
    return -1;
  }
  return 0;
}

/*
   Adapted from Pirates BBS 1.6, do_exec in stuff.c
   Copyright (C) 1990, Edward Luke, lush@Athena.EE.MsState.EDU
   This one is suitable for the server, doesn't try to set the screen
*/

execute(com, wd, infile, outfile, errfile, envp, append)
char *com, *wd, *infile, *outfile, *errfile;
char **envp;
int append;
{
  char path[MAXFILELEN] ;
  char pcom[MAXCOMSZ] ;
  char *arglist[MAXARGS] ;
  register int i,len ;
  register int argptr ;
  int status, pid, w ;
  int pmode ;
  int saved_alarm ;
  void (*isig)(), (*qsig)();
  
  strncpy(pcom,com,MAXCOMSZ) ;
  len = strlen(com)+1;
  if (len > MAXCOMSZ) len = MAXCOMSZ;
  pmode = LOOKFIRST ;
  for(i=0,argptr=0;i<len;i++) {
    if(pcom[i] == '\0')
      break ;
    if(pmode == QUOTEMODE) {
      if(pcom[i] == '\"') {
	pmode = LOOKFIRST ;
	pcom[i] = '\0' ;
	continue ;
      }
      continue ;
    }
    if(pcom[i] == '\"') {
      pmode = QUOTEMODE ;
      arglist[argptr++] = &pcom[i+1] ;
      if(argptr+1 == MAXARGS)
	break ;
      continue ;
    }
    if(pmode == LOOKFIRST)
      if(pcom[i] != ' ') {
	arglist[argptr++] = &pcom[i] ;
	if(argptr+1 == MAXARGS)
	  break ;
	pmode = LOOKLAST ;
      } else continue ;
    if(pcom[i] == ' ') {
      pmode = LOOKFIRST ;
      pcom[i] = '\0' ;
    }
  }
  arglist[argptr] = NULL ;
  if(argptr == 0)
    return -1 ;
  strncpy(path,arglist[0],MAXFILELEN) ;
  saved_alarm = alarm(0);
  if((pid = fork()) == 0) {
    if(wd)
      if(chdir(wd)) {
        bbslog(0, "ERROR execute: chdir failed: %s\n", wd);
	exit(-1) ;
      }
    if (infile) _set_io(infile, 0, append);
    if (outfile) _set_io(outfile, 1, append);
    if (errfile) _set_io(errfile, 2, append);
    execve(path, arglist, envp);
    bbslog(0, "ERROR execute: execve failed: %s\n", path);
    exit(-1) ;
  }
  isig = signal(SIGINT, SIG_IGN);
  qsig = signal(SIGQUIT, SIG_IGN);
  while ((w = wait(&status)) != pid && w != -1);
  if (saved_alarm) alarm(saved_alarm);
  signal(SIGINT, isig) ;
  signal(SIGQUIT, qsig) ;
  return((w == -1)? w: status) ;
}
                                                                                                                                                                                                                                                                                                                                                                                       DarkNET-1.08/files.c                                                                                   644   21270   21270        62313  5751527470   7360                                                                                                                                                                                                                                                                                                                                                                      
/*
Eagles Bulletin Board System
Copyright (C) 1994, Ray Rocker, rrrocker@rock.b11.ingr.com
                                rock@seabass.st.usm.edu
                                72673.2105@compuserve.com

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "server.h"
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>

#include <sys/stat.h>
#include <fcntl.h>
#include <malloc.h>
#include <time.h>
#include <utime.h>
#if NEXTSTEP == 1
#include <sys/dir.h>
#include <sys/dirent.h>
#include <sys/stat.h>
#else
#include <dirent.h>
#endif
#include <ctype.h>

#if NEXTSTEP == 1
typedef unsigned short mode_t;
struct utimbuf {
  time_t  actime;
  time_t  modtime;
};
#endif

extern LONG mail_file_to_outside __P((char *, char *, int));

extern SERVERDATA server;    /* for append_sig */

#define MAIL_READBITS_NAME "$MAIL$"

typedef struct _FILENODE {
  SHORT fileid;
  SHORT flags;
  LONG size;
  time_t mtime;
  struct _FILENODE *next;
} FILENODE;

typedef struct _FILENODE *FILELIST;

typedef LONG COUNTMAP[BBS_MAX_FILES+1];

struct _openboard {
  int btype;
  OPENINFO oi;
  READINFO ri;
  PATH bdir;
  FILELIST bcache;
  time_t bsync;
} _currbrd;


#define UNMARKED_FILE_MODE  0660
#define MARKED_FILE_MODE    0640
#define	COUNTMAP_FILE		"cmap"

LONG get_count();
void set_cmap();

static void set_count();
static void inc_count();

free_filelist(list)
FILELIST *list;
{
  FILENODE *curr = *list, *next;
  while (curr != NULL) {
    next = curr->next;
    free(curr);
    curr = next;
  }
  *list = NULL;
}    

insert_filelist(list, node)
FILELIST *list;
FILENODE *node;
{
  FILENODE *curr = *list, *prev = NULL;
  
  if (*list == NULL || (*list)->mtime > node->mtime ||
     ((*list)->mtime == node->mtime && (*list)->fileid > node->fileid)) {
    node->next = *list;
    *list = node;
    return S_OK;
  }
  
  do {
    prev = curr;
    curr = curr->next;
  } while (curr && (curr->mtime < node->mtime ||
                (curr->mtime == node->mtime && curr->fileid < node->fileid)));

  node->next = curr;
  prev->next = node;
  return S_OK;
}

build_filelist(dir, list, fn, arg)
char *dir;
FILELIST *list;
int (*fn)();
void *arg;
{
  DIR *dp;
  struct dirent *dent;
  PATH fname;
  char *fnamebase;
  struct stat stbuf;
  FILENODE *node;
  SHORT fileid;
  FILE *fp;

  free_filelist(list);

  strcpy(fname, dir);
  strcat(fname, "/");
  fnamebase = fname+strlen(fname);

  if ((dp = opendir(dir)) == NULL) {
    return S_SYSERR;
  }

  while ((dent = readdir(dp)) != NULL) {
    strcpy(fnamebase, dent->d_name);
    fileid = hex2SHORT(dent->d_name);
    if (fileid > 0 && fileid <= BBS_MAX_FILES && stat(fname, &stbuf) == 0) {
      if (stbuf.st_size == 0) continue;
      else if ((node = (FILENODE *)malloc(sizeof(*node))) != NULL) {
        node->fileid = fileid;
        node->flags = FILE_UNREAD;
        if ((stbuf.st_mode & 0777) == MARKED_FILE_MODE)
	  node->flags |= FILE_MARKED;
        node->size = stbuf.st_size;
        node->mtime = stbuf.st_mtime;        
        insert_filelist(list, node);
        if (fn) fn(node, arg);
      }
    }
  }

  closedir(dp);
  return S_OK;
}

_enum_files(dir, fn, arg)
char *dir;
int (*fn)();
void *arg;
{
  PATH fname;
  DIR *dp;
  struct dirent *dent;
  int indx = 0;

  if ((dp = opendir(dir)) == NULL) {
    return S_SYSERR;
  }
              
  while ((dent = readdir(dp)) != NULL) {
    if (dent->d_name[0] == '.') continue;
    strcpy(fname, dir);
    strcat(fname, "/");
    strcat(fname, dent->d_name);
    if (is_directory(fname)) continue;
    if (fn(indx++, dir, dent->d_name, arg) == ENUM_QUIT) break;
  }

  closedir(dp);
  return S_OK;
}

FILENODE *
_bcache_find(fileid)
SHORT fileid;
{
  FILENODE *trav = _currbrd.bcache;
  while (trav) {
    if (trav->fileid == fileid) break;
    trav = trav->next;
  }
  return trav;
}    

_msg_tally(node, newinfo)
FILENODE *node;
READINFO *newinfo;
{
  _currbrd.oi.totalmsgs++;
  if ((node->mtime < (time_t)_currbrd.ri.stamp) &&
      test_readbit(&_currbrd.ri, node->fileid)) {
    set_readbit(newinfo, node->fileid);
    node->flags &= ~FILE_UNREAD;
  }
  else _currbrd.oi.newmsgs++;
  return S_OK;
}      

/*ARGSUSED*/
_file_tally(indx, dir, fname, arg)
int indx;
char *dir;
char *fname;
void *arg;
{
  _currbrd.oi.totalmsgs++;
  return S_OK;
}      

_sync_currbrd()
{
  struct stat stbuf;
  READINFO newinfo;
  if (stat(_currbrd.bdir, &stbuf)) {
    _currbrd.oi.totalmsgs = _currbrd.oi.newmsgs = 0;
    return S_SYSERR;
  }
  if (stbuf.st_mtime < _currbrd.bsync) {
    /* No files created or deleted, so we don't re-read */
    return S_OK;
  }
  _currbrd.oi.totalmsgs = _currbrd.oi.newmsgs = 0;
  switch (_currbrd.btype) {
  case BOARD_MAIL:
  case BOARD_POST:
    clear_all_readbits(&newinfo);
    build_filelist(_currbrd.bdir, &_currbrd.bcache, _msg_tally, &newinfo);
    time((time_t *)&newinfo.stamp);
    memcpy(&_currbrd.ri, &newinfo, sizeof(_currbrd.ri));
    break;
  case BOARD_FILE:
    _enum_files(_currbrd.bdir, _file_tally, NULL);
    break;
  default:
    return S_INVALID;
  }
  time(&_currbrd.bsync);
  return S_OK;
}
  
get_filelist_ids(dir, rinfo)
char *dir;
READINFO *rinfo;
{
  DIR *dp;
  struct dirent *dent;
  SHORT fileid;

  clear_all_readbits(rinfo);

  if ((dp = opendir(dir)) == NULL) {
    return S_SYSERR;
  }
              
  while ((dent = readdir(dp)) != NULL) {
    fileid = hex2SHORT(dent->d_name);
    if (fileid > 0 && fileid <= BBS_MAX_FILES)
      set_readbit(rinfo, fileid);
  }

  closedir(dp);
  return S_OK;
}

fileid_to_fname(dir, fileid, fname)
char *dir;
SHORT fileid;
char *fname;
{
  char *eodir;
  strcpy(fname, dir);
  strcat(fname, "/");
  eodir = fname+strlen(fname);
  SHORTcpy(eodir, fileid);
  eodir[4] = '\0';
}

struct _sendmsgstruct {
  int btype;
  HEADER hdr;
  UNAME username;
  NAMELIST to_list;
  PATH destfile;
  char *srcfile;
};

append_sig(fd)
int fd;
{
  FILE *fp;
  PATH sigfile;
  char buf[81];
  int i;

  /* 
     Append current user's sig to open file fd.
     Honor maxsiglines defined in the global SERVERDATA struct.
  */

  if (server.maxsiglines == 0) {
    return S_OK;
  }

  local_bbs_get_signature(sigfile);
  if ((fp = fopen(sigfile, "r")) != NULL) {
    for (i=0; i<server.maxsiglines; i++) {
      if (fgets(buf, sizeof(buf), fp)) {
        write(fd, buf, strlen(buf));
      }
    }      
    fclose(fp);
  }

  return S_OK;
}  

_do_message(indx, bname, sm)
int indx;
char *bname;
struct _sendmsgstruct *sm;
{
  PATH msgdir;
  PATH msgfile;
  READINFO readinfo;
  SHORT fileid;
  NAME goodbname;
  struct stat stbuf;
  int fd, ok = 0;
    
  if (indx >= BBS_MAX_MAILRECIPS) return S_OK;

  if (sm->btype == BOARD_MAIL) {
    ACCOUNT acct;

    if (strcmp(acct.userid, "Anonymous") == 0) {
      sm->hdr.size |= (1 << indx);
      return S_OK;
    }
    if (_lookup_account(bname, &acct) != S_OK) {
      sm->hdr.size |= (1 << indx);
      return S_OK;
    }
    if (acct.flags & FLG_SHARED || !_they_have_access(C_OPENMAIL,acct.perms)) {
      sm->hdr.size |= (1 << indx);
      return S_OK;
    }
    strncpy(goodbname, acct.userid, sizeof(goodbname));    
    get_mail_directory(goodbname, msgdir);
  }
  else {
    BOARD board;
    if (_lookup_board(bname, &board) != S_OK) {
      sm->hdr.size |= (1 << indx);
      return S_OK;
    }
    strncpy(goodbname, board.name, sizeof(goodbname));
    get_board_directory(goodbname, msgdir);
  }

  if (stat(msgdir, &stbuf) == -1 || !S_ISDIR(stbuf.st_mode)) {
    /* A directory is missing! */
    bbslog(0, "ERROR _do_message: cannot access %s\n", msgdir);
    sm->hdr.size |= (1 << indx);
    return S_OK;
  }
  get_filelist_ids(msgdir, &readinfo);

  for (fileid = 1; fileid <= BBS_MAX_FILES; fileid++) {
    if (test_readbit(&readinfo, fileid)) continue;
    fileid_to_fname(msgdir, fileid, msgfile);
    if (sm->destfile[0]) {
      /* Carbon copy! Hopefully we can just link. */
      if (link(sm->destfile, msgfile) == 0) {
        ok++;
        break;
      }
      /* Damn! Copy the stupid thing. */
      fd = open(msgfile, O_WRONLY|O_CREAT|O_EXCL, UNMARKED_FILE_MODE);
      if (fd != -1) {
        append_file(fd, sm->destfile);
	if (strcmp(sm->hdr.owner, "Anonymous"))
	{
	  char ans[4];
	  extern int lang;

	  if (lang)
	    getdata(2, 0, "¼­¸íÀ» ÇÒ±î¿ä? (Y/N) [Y]: ", ans, 2, 1, 0);
	  else
	    getdata(2, 0, "Append Sig? (Y/N) [Y]: ", ans, 2, 1, 0);
	  if (*ans != 'N' && *ans != 'n')
	    append_sig(fd);
	}
	fsync(fd);
        close(fd);
        ok++;
        break;
      }
    }
    else {
      /* First copy. We have to write the file with headers. */
      fd = open(msgfile, O_WRONLY|O_CREAT|O_EXCL, UNMARKED_FILE_MODE);
      if (fd != -1) {
        if (sm->btype == BOARD_MAIL)
          write_mail_headers(fd, &sm->hdr, sm->username, sm->to_list);
        else
          write_post_headers(fd, &sm->hdr, sm->username, goodbname);
        append_file(fd, sm->srcfile);
	if (strcmp(sm->hdr.owner, "Anonymous"))
	{
	  char ans[4];
	  extern int lang;

	  if (lang)
	    getdata(2, 0, "¼­¸íÀ» ÇÒ±î¿ä? (Y/N) [Y]: ", ans, 2, 1, 0);
	  else
	    getdata(2, 0, "Append Sig? (Y/N) [Y]: ", ans, 2, 1, 0);
	  if (*ans != 'N' && *ans != 'n')
	    append_sig(fd);
	}
	fsync(fd);
        close(fd);
        strncpy(sm->destfile, msgfile, PATHLEN);
        ok++;
        break;
      }
    }
  }
  
  if (ok) {
    if (sm->btype == BOARD_MAIL) notify_new_mail(bname, 1);
    else {
      /* mark as read by the poster */
      READINFO newinfo;
      FILENODE *node;

/*
      sync();
*/
      sleep(1);
      clear_all_readbits(&newinfo);
      build_filelist(_currbrd.bdir, &_currbrd.bcache, _msg_tally, &newinfo);
      time((time_t *)&newinfo.stamp);
      set_readbit(&newinfo, fileid);
      memcpy(&_currbrd.ri, &newinfo, sizeof(_currbrd.ri));

      for (node = _currbrd.bcache; node != NULL; node = node->next) {
	if (node->fileid == fileid)
	  break;
      }
      if (node)
	node->flags &= ~FILE_UNREAD;
      set_bitfile_ent (bname, &_currbrd.ri);
/*
      sync();
*/
    }
  }
  else {
    /* Too many files, I guess! */
    bbslog(0, "ERROR _do_message: cannot create message in %s\n", msgdir);
    sm->hdr.size |= (1 << indx);
  }
  return S_OK;
}    
    
local_bbs_mail(to_list, subject, fname, success)
NAMELIST to_list;
char *subject;
char *fname;
LONG *success;
{
  struct _sendmsgstruct sm;
  
  sm.btype = BOARD_MAIL;
  memset(&sm.hdr, 0, sizeof sm.hdr);
  strncpy(sm.hdr.owner, my_userid(), sizeof sm.hdr.owner);
  strncpy(sm.username, my_username(), sizeof sm.username);
  strncpy(sm.hdr.title, subject, TITLELEN);
  sm.to_list = to_list;
  sm.srcfile = fname;
  sm.destfile[0] = '\0';

  apply_namelist(to_list, _do_message, &sm);
  
  /* how's this for a kludge? */
  *success = sm.hdr.size;
  return (*success == 0 ? S_OK : S_SYSERR);
}

local_bbs_post(bname, subject, fname)
char *bname;
char *subject;
char *fname;
{
  struct _sendmsgstruct sm;
  char ans[4];
  extern int lang;
  
  sm.btype = BOARD_POST;
  memset(&sm.hdr, 0, sizeof sm.hdr);


  if (strncmp(bname, "Free", 4) == 0 || strncmp(bname, "Sex", 3) == 0) {
    if (lang)
       getdata(1, 0, "¹«¸í¾¾·Î? (Y/N) [Y]: ", ans, 2, 1, 0);
    else
       getdata(1, 0, "Anonymous? (Y/N) [Y]: ", ans, 2, 1, 0);
    if (*ans == 'N' || *ans == 'n') {
      strncpy(sm.hdr.owner, my_userid(), sizeof sm.hdr.owner);
      strncpy(sm.username, my_username(), sizeof sm.username);
    } else {
      strcpy(sm.hdr.owner, "Anonymous");
      strcpy(sm.username, "Anonymous");
    }
  } else {
    if (lang)
       getdata(1, 0, "¹«¸í¾¾·Î? (Y/N) [N]: ", ans, 2, 1, 0);
    else
       getdata(1, 0, "Anonymous? (Y/N) [N]: ", ans, 2, 1, 0);
    if (*ans == 'Y' || *ans == 'Y') {
      strcpy(sm.hdr.owner, "Anonymous");
      strcpy(sm.username, "Anonymous");
    } else {
      strncpy(sm.hdr.owner, my_userid(), sizeof sm.hdr.owner);
      strncpy(sm.username, my_username(), sizeof sm.username);
    }
  }
  strncpy(sm.hdr.title, subject, TITLELEN);
  sm.to_list = NULL;
  sm.srcfile = fname;
  sm.destfile[0] = '\0';
  _do_message(0, bname, &sm);
  bbslog(3, "POST '%s' in %s by %s\n", subject, bname, my_userid());
  return (sm.hdr.size == 0 ? S_OK : S_SYSERR);
}

local_bbs_open_mailbox(oinfo)
OPENINFO *oinfo;
{
  if (_currbrd.btype != BOARD_NONE && _currbrd.btype != BOARD_MAIL) {
    return S_EXISTS;
  }
  if (_currbrd.btype == BOARD_MAIL) {
    _currbrd.oi.flags |= OPEN_REOPEN;
  }
  else {
    _currbrd.btype = BOARD_MAIL;
    strncpy(_currbrd.oi.name, my_userid(), sizeof _currbrd.oi.name);
    get_mail_directory(_currbrd.oi.name, _currbrd.bdir);
    _currbrd.oi.flags = OPEN_POST | OPEN_MANAGE;
    get_bitfile_ent(MAIL_READBITS_NAME, &_currbrd.ri);
    _currbrd.bsync = 0;
  }
  _sync_currbrd();
  memcpy(oinfo, &_currbrd.oi, sizeof(*oinfo));
  return S_OK;
}  

local_bbs_open_board(bname, oinfo)
char *bname;
OPENINFO *oinfo;
{
  BOARD board;
  if (_currbrd.btype != BOARD_NONE && _currbrd.btype != BOARD_POST) {
    return S_EXISTS;
  }
  if (_currbrd.btype == BOARD_POST) {
    _currbrd.oi.flags |= OPEN_REOPEN;
  }
  else {
    if (_lookup_board(bname, &board) != S_OK) return S_NOTFOUND;
    if (!_has_read_access(&board)) return S_NOTFOUND;
    _currbrd.btype = BOARD_POST;
    strcpy(_currbrd.oi.name, board.name);
    get_board_directory(_currbrd.oi.name, _currbrd.bdir);
    _currbrd.oi.flags = 0;
    if (_has_post_access(&board)) _currbrd.oi.flags |= OPEN_POST;
    if (_has_manager_access(&board)) _currbrd.oi.flags |= OPEN_MANAGE;
    get_bitfile_ent(board.name, &_currbrd.ri);
    _currbrd.bsync = 0;
  }
  _sync_currbrd();
  memcpy(oinfo, &_currbrd.oi, sizeof(*oinfo));
  return S_OK;
}  

local_bbs_open_fileboard(bname, oinfo)
char *bname;
OPENINFO *oinfo;
{
  BOARD board;
  if (_currbrd.btype != BOARD_NONE && _currbrd.btype != BOARD_FILE) {
    return S_EXISTS;
  }
  if (_currbrd.btype == BOARD_FILE) {
    _currbrd.oi.flags |= OPEN_REOPEN;
  }
  else {
    if (_lookup_ftpent(bname, &board) != S_OK) return S_NOTFOUND;
    _currbrd.btype = BOARD_FILE;
    strcpy(_currbrd.oi.name, board.name);
    get_fileboard_directory(_currbrd.oi.name, _currbrd.bdir);
    _currbrd.oi.flags = 0;
    _currbrd.bsync = 0;
  }
  _sync_currbrd();
  memcpy(oinfo, &_currbrd.oi, sizeof(*oinfo));
  return S_OK;
}  

local_bbs_test_board(bname, pflags)
char *bname;
SHORT *pflags;
{
  BOARD board;
  if (_lookup_board(bname, &board) != S_OK) return S_NOTFOUND;
  if (!_has_read_access(&board)) return S_NOTFOUND;
  *pflags = 0;
  if (_has_post_access(&board)) (*pflags) |= OPEN_POST;
  if (_has_manager_access(&board)) (*pflags) |= OPEN_MANAGE;
  return S_OK;
}  

local_bbs_close_board()
{
  free_filelist(&_currbrd.bcache);

  if (_currbrd.btype == BOARD_POST)
    set_bitfile_ent(_currbrd.oi.name, &_currbrd.ri);
  else if (_currbrd.btype == BOARD_MAIL)
    set_bitfile_ent(MAIL_READBITS_NAME, &_currbrd.ri);

  _currbrd.btype = BOARD_NONE;
  return S_OK;
}

struct fileenum {
  SHORT chunk;
  SHORT start;
  int (*fn)();
  void *arg;
};

_get_file_headers(indx, dir, fname, info)
int indx;
char *dir;
char *fname;
struct fileenum *info;
{
  struct stat stbuf;
  HEADER hdr;
  PATH path;
  strcpy(path, dir);
  strcat(path, "/");
  strcat(path, fname);
  if (indx < info->start) return S_OK;
  if (stat(path, &stbuf) || stbuf.st_size == 0) return S_OK;
  memset(&hdr, 0, sizeof hdr);
  strncpy(hdr.title, fname, sizeof(hdr.title));
  hdr.size = stbuf.st_size;
  hdr.flags = is_text_file(path) ? 0 : FILE_BINARY;
  return (info->fn(indx, &hdr, info->arg));
}

/*ARGSUSED*/
local_bbs_enum_headers(chunk, start, newonly, enumfn, arg)
SHORT chunk;
SHORT start;
SHORT newonly;
int (*enumfn)();
void *arg;
{
  FILENODE *node;
  PATH fname;
  HEADER hdr;
  SHORT indx;
  
  if (_currbrd.btype == BOARD_NONE) 
    return S_INVALID;

  if (_currbrd.btype == BOARD_FILE) {
    /* this case is completely different -- blech */
    struct fileenum fe;
    fe.chunk = chunk;
    fe.start = start;
    fe.fn = enumfn;
    fe.arg = arg;
    return (_enum_files(_currbrd.bdir, _get_file_headers, &fe));
  }

  _sync_currbrd();  

  for (node=_currbrd.bcache, indx=0; node; node=node->next, indx++) {
    if (indx < start) continue;
    if (newonly && !(node->flags & FILE_UNREAD)) continue;
    fileid_to_fname(_currbrd.bdir, node->fileid, fname);
    hdr.fileid = node->fileid;
    hdr.flags = node->flags;
    if (!(_currbrd.oi.flags & OPEN_MANAGE)) hdr.flags &= ~FILE_MARKED;
    hdr.size = node->size;
    hdr.mtime = (LONG)node->mtime;
    read_headers(fname, &hdr);
    if (hdr.owner[0] == '\0') strcpy(hdr.owner, SYSOP_ACCOUNT);
    if (enumfn(indx, &hdr, arg) == ENUM_QUIT)
      break;
  }

  return S_OK;
}

local_bbs_read_message(fileid, fname)
SHORT fileid;
char *fname;
{
  FILENODE *node;
  PATH myfname;
  struct stat stbuf;
  mode_t mode;

  if (_currbrd.btype != BOARD_MAIL &&_currbrd.btype != BOARD_POST) 
    return S_INVALID;

  node = _bcache_find(fileid);
  fileid_to_fname(_currbrd.bdir, fileid, myfname);
  if (_currbrd.btype == BOARD_POST)
    inc_count(_currbrd.bdir, fileid);
  if (node == NULL || stat(myfname, &stbuf))
    return S_NOTFOUND;
  else node->flags &= ~FILE_UNREAD;

  if (!test_readbit(&_currbrd.ri, fileid)) {
    set_readbit(&_currbrd.ri, fileid);
    if (_currbrd.btype == BOARD_MAIL)
      notify_new_mail(_currbrd.oi.name, -1);
  }

  strcpy(fname, myfname);
  return S_OK;  
}

local_bbs_mark_message(fileid, mflag)
SHORT fileid;
SHORT mflag;
{
  FILENODE *node;
  PATH fname;
  struct stat stbuf;
  mode_t mode;

  if (_currbrd.btype != BOARD_POST)
    return S_INVALID;

  if (!(_currbrd.oi.flags & OPEN_MANAGE))
    return S_DENIED;

  node = _bcache_find(fileid);
  fileid_to_fname(_currbrd.bdir, fileid, fname);
  if (node == NULL || stat(fname, &stbuf))
    return S_NOTFOUND;

  if (mflag) {
    mode = MARKED_FILE_MODE;
    node->flags |= FILE_MARKED;
  }
  else {
    mode = UNMARKED_FILE_MODE;
    node->flags &= ~FILE_MARKED;
  }

  bbslog(2, "MARKMSG %s %d on %s by %s\n", mflag ? "ON" : "OFF", 
         fileid, _currbrd.oi.name, my_userid());

  return(chmod(fname, mode) ? S_SYSERR : S_OK);
}

local_bbs_delete_message(fileid)
SHORT fileid;
{
  FILENODE *node;
  PATH fname;
  HEADER hdr;
  int is_my_post;

  if (_currbrd.btype != BOARD_MAIL && _currbrd.btype != BOARD_POST) 
    return S_INVALID;

  node = _bcache_find(fileid);
  fileid_to_fname(_currbrd.bdir, fileid, fname);
  if (node == NULL) return S_NOTFOUND;

  read_headers(fname, &hdr);
  is_my_post = is_me(hdr.owner);

  if (!(_currbrd.oi.flags & OPEN_MANAGE)) {
    if (!is_my_post) return S_DENIED;
  }

  if (unlink(fname)) return S_SYSERR;

  if (_currbrd.btype == BOARD_MAIL && !test_readbit(&_currbrd.ri, fileid)) {
    notify_new_mail(_currbrd.oi.name, -1);
  }

  if (_currbrd.btype == BOARD_POST) {
    set_count(_currbrd.bdir, fileid, 0);
    if (!is_my_post) {
      bbslog(2, "DELETEPOST '%s' (%s) on %s by %s\n", hdr.title, hdr.owner,
           _currbrd.oi.name, my_userid());
    }
  }
  return S_OK;
}

local_bbs_update_message(fileid, newfile)
SHORT fileid;
char *newfile;
{
  FILENODE *node;
  PATH fname;
  struct utimbuf utbuf;

  if (_currbrd.btype != BOARD_POST) 
    return S_INVALID;

  if (!(_currbrd.oi.flags & OPEN_MANAGE))
    return S_DENIED;
  
  node = _bcache_find(fileid);
  fileid_to_fname(_currbrd.bdir, fileid, fname);
  if (node == NULL) return S_NOTFOUND;

  /* Touch the message back to its original posting time */
  utbuf.actime = 0;
  utbuf.modtime = node->mtime;
  if (utime(fname, &utbuf)) return S_SYSERR;

  bbslog(2, "EDITMSG %d on %s by %s\n", fileid, _currbrd.oi.name, my_userid());
  return S_OK;
}

local_bbs_delete_range(start, finis, count)
SHORT start;
SHORT finis;
SHORT *count;
{
  FILENODE *node;
  PATH fname;
  SHORT indx = 0;

  if (_currbrd.btype != BOARD_MAIL && _currbrd.btype != BOARD_POST) 
    return S_INVALID;

  if (!(_currbrd.oi.flags & OPEN_MANAGE))
    return S_DENIED;

  *count = 0;
  for (node = _currbrd.bcache; node && (indx++ < finis); node = node->next) {
    if (indx < start) continue;
    if (node->flags & FILE_MARKED) continue;
    if (_currbrd.btype == BOARD_MAIL && (node->flags & FILE_UNREAD)) continue;
    fileid_to_fname(_currbrd.bdir, node->fileid, fname);
    if (unlink(fname) == 0) (*count)++;
  }

  if (_currbrd.btype == BOARD_POST)
    bbslog(2, "DELETERANGE %d-%d on %s by %s\n", start, finis, 
          _currbrd.oi.name, my_userid());

  return S_OK;
}

local_bbs_forward_message(fileid)
SHORT fileid;
{
  FILENODE *node;
  PATH fname;
  HEADER hdr;
  char cmd[80];
  char *tfile;
  int rc;

  if (_currbrd.btype != BOARD_MAIL && _currbrd.btype != BOARD_POST) 
    return S_INVALID;
  
  node = _bcache_find(fileid);
  fileid_to_fname(_currbrd.bdir, fileid, fname);
  if (node == NULL) return S_NOTFOUND;
  read_headers(fname, &hdr);

  if ((tfile = tmpnam(NULL)) == NULL)
    return S_INVALID;

  sprintf(cmd, "/usr/local/bin/hcode -ki < %s > %s", fname, tfile);
  system(cmd);
  rc = mail_file_to_outside(tfile, hdr.title, 0);
  unlink (tfile);
  return (rc);
}

fname_to_pathname(fname, buf)
char *fname;
char *buf;
{
  strcpy(buf, _currbrd.bdir);
  strcat(buf, "/");
  strcat(buf, fname);
}

local_bbs_download(fname, protoname, path)
char *fname;
char *protoname;
char *path;
{
  PATH fullname;
  FILE *fp;

  if (_currbrd.btype != BOARD_FILE) return S_DENIED;
  fname_to_pathname(fname, fullname);

  if ((fp = fopen(fullname, "r")) == NULL) return S_NOTFOUND;
  fclose(fp);

  if (protoname == NULL && path != NULL) {
    /* Special case -- just return the filename */
    strcpy(path, fullname);
    return S_OK;
  }
  else return (do_download(_currbrd.bdir, fname, protoname));
}

local_bbs_forward_file(fname)
char *fname;
{
  PATH fullname;
  TITLE title;

  if (_currbrd.btype != BOARD_FILE) return S_DENIED;
  fname_to_pathname(fname, fullname);
  sprintf(title, "%s: %s", _currbrd.oi.name, fname);
  return (mail_file_to_outside(fullname, title, !is_text_file(fullname)));
}

/* This is used by bbs_visit_board */

_mark_all_as_read(bname)
char *bname;
{
  if (_currbrd.btype == BOARD_POST && !strcmp(_currbrd.oi.name, bname)) {
    FILENODE *node;
    get_filelist_ids(_currbrd.bdir, &_currbrd.ri);
    time((time_t *)&_currbrd.ri.stamp);
    for (node = _currbrd.bcache; node != NULL; node = node->next) {
      node->flags &= ~FILE_UNREAD;
    }
    time(&_currbrd.bsync);
  }
  else {
    PATH bdir;
    READINFO ri;
    get_board_directory(bname, bdir);    
    get_filelist_ids(bdir, &ri);
    time((time_t *)&ri.stamp);
    set_bitfile_ent(bname, &ri);
  }
  return S_OK;
}  

/* This is used by bbs_enum_boards to do the counts */

_board_count(board, rinfo)
BOARD *board;
READINFO *rinfo;
{
  PATH bdir, fname;
  char *fnamebase;
  DIR *dp;
  struct dirent *dent;
  struct stat stbuf;
  SHORT fileid;

  board->totalposts = board->newposts = board->ownedposts = 0;
  board->lastpost = 0;
  
  get_board_directory(board->name, bdir);
  if ((dp = opendir(bdir)) == NULL) {
    return S_SYSERR;
  }
              
  strcpy(fname, bdir);
  strcat(fname, "/");
  fnamebase = fname+strlen(fname);

  while ((dent = readdir(dp)) != NULL) {
    strcpy(fnamebase, dent->d_name);
    fileid = hex2SHORT(dent->d_name);
    if (fileid > 0 && fileid <= BBS_MAX_FILES && stat(fname, &stbuf) == 0) {
      if (stbuf.st_size > 0) {
        (board->totalposts)++;
        if (!test_readbit(rinfo, fileid)) (board->newposts)++;
        if ((LONG)stbuf.st_mtime > board->lastpost)
          board->lastpost = (LONG)stbuf.st_mtime;
      }
      /* 
         To test and increment board->ownedposts, we'd have to read the 
         headers and compare the owner to our userid. In the interest of
         speed, I'm not doing that, for now. 
      */
    }
  }

  closedir(dp);
  return S_OK;
}

LONG get_count(dir, id)
char *dir;
SHORT id;
{
  FILE *fp;
  char cmap[256];
  LONG count;

  sprintf(cmap, "%s/%s", dir, COUNTMAP_FILE);
  if ((fp = fopen(cmap, "r+")) == NULL)
  {
    set_cmap(dir);
    return 0;
  }
  if (fseek(fp, id * sizeof(LONG), SEEK_SET) == -1)
    {
      fclose(fp);
      return 0;
    }
  if (fread(&count, sizeof(LONG), 1, fp) == -1)
    {
      fclose(fp);
      return 0;
    }
  fclose(fp);
  return count;
}

static void set_count(dir, id, count)
char *dir;
SHORT id;
LONG count;
{
  char cmap[256];
  int fd;

  sprintf(cmap, "%s/%s", dir, COUNTMAP_FILE);
  if ((fd = open(cmap, O_RDWR)) == -1)
  {
     set_cmap(dir);
     if ((fd = open(cmap, O_RDWR)) == -1)
       return;
  }
  if (lseek(fd, id * sizeof(LONG), SEEK_SET) == -1)
    {
      close(fd);
      return;
    }
  while (lockf (fd, F_LOCK, sizeof(LONG)) == -1 && errno == EINTR);

  write(fd, &count, sizeof(LONG));
  lseek(fd, id * sizeof(LONG), SEEK_SET);
  lockf(fd, F_ULOCK, sizeof(LONG));
  close(fd);
  return;
}

static void inc_count(dir, id)
char *dir;
SHORT id;
{
  set_count(dir, id, (get_count(dir, id) + 1));
}

void set_cmap(dir)
char *dir;
{
  char cmap_file[256];

  sprintf(cmap_file, "%s/%s", dir, COUNTMAP_FILE);

  if (access(cmap_file, F_OK) == -1)
    {
      FILE *fp;
      COUNTMAP cmap;

      if ((fp = fopen(cmap_file, "w")) == NULL)
	return;
      memset(cmap, '\0', sizeof(COUNTMAP));
      fwrite (cmap, sizeof (COUNTMAP), 1, fp);
      fclose(fp);
      return;
    }
}
me, &stbuf))
    return S_NOTFOUND;
  else node->flags &= ~FILE_UNREAD;

  if (!test_readbit(&_currbrd.ri, fileid)) {
    set_readbit(&_currbrd.ri, fileid);
    if (_currbrd.btype == BOARD_MAIL)
      notify_new_mail(_currbrd.oi.name, -1);
  }

  strcpy(fname, myfname);
  return S_OK;  
}

local_bbs_mark_mesDarkNET-1.08/gram.y                                                                                    644   21270   21270        12274  5715557226   7235                                                                                                                                                                                                                                                                                                                                                                      %token ENVIRONMENT
%token MENU 
%token STRING
%token COMMAND
%token OBRACE
%token CBRACE
%token COMMA 
%token OPAREN
%token CPAREN
%token ID_NAME
%token INTEGER
%token ERROR

%{
#include <stdio.h>
#include "client.h"

extern char *get_yytext() ;
extern int yyleng ;
%}

%start commands

%union {
  int ival ;
  char * sval ;
  NMENUITEM *mival ;
  NMENU *mval ;
}

%type <ival> integer name ident
%type <sval> string
%type <mival> menulist menuitem command commandentry

%%

commands :
    | commands menudef
    | error

menudef :  MENU string COMMA string COMMA string COMMA string OBRACE menulist CBRACE
{
    NMENU *mkmenu(), *mp ;

    if(mp = mkmenu($10)) {
        mp->menu_id = $2 ;
	mp->kmenu_id = NULL;
        mp->menu_title = $4 ;
        mp->kmenu_title = NULL;
        mp->menu_prompt = $6 ;
        mp->kmenu_prompt = NULL;
        mp->menu_default = $8 ;
        pushmenu(mp) ;
    }
}
| MENU string COMMA string COMMA string COMMA string COMMA string COMMA string COMMA string OBRACE menulist CBRACE
{
    NMENU *mkmenu(), *mp ;

    if(mp = mkmenu($16)) {
        mp->menu_id = $2 ;
        mp->kmenu_id = $4 ;
        mp->menu_title = $6 ;
	mp->kmenu_title = $8;
        mp->menu_prompt = $10 ;
        mp->kmenu_prompt = $12 ;
        mp->menu_default = $14 ;
        pushmenu(mp) ;
    }
}
| ENVIRONMENT OPAREN string CPAREN
{
    extern char *default_env ;
    default_env = $3 ;
    parse_default() ;
}

menulist : menuitem
{
    $$ = $1 ;
}
      | menulist menuitem
{
    if($1)
      $2->next = $1 ;
    $$ = $2 ;
}

menuitem : OPAREN string COMMA string COMMA string COMMA ident COMMA commandentry COMMA string CPAREN
{
    register NMENUITEM *mip ;

    if(mip = $10) {
        mip->name = $2 ;
	mip->kname = NULL;
        mip->default_action = $4 ;
        mip->error_action = $6 ;
        mip->enabled = $8 ;
        mip->help = $12 ;
	mip->khelp = NULL;
    }
    $$ = mip ;
}
| OPAREN string COMMA string COMMA string COMMA ident COMMA commandentry COMMA string COMMA string CPAREN
{
    register NMENUITEM *mip ;

    if(mip = $10) {
        mip->name = $2 ;
	mip->kname = NULL;
        mip->default_action = $4 ;
        mip->error_action = $6 ;
        mip->enabled = $8 ;
        mip->help = $12 ;
        mip->khelp = $14 ;
    }
    $$ = mip ;
}
| OPAREN string COMMA string COMMA string COMMA string COMMA ident COMMA commandentry COMMA string COMMA string CPAREN
{
    register NMENUITEM *mip ;

    if(mip = $12) {
        mip->name = $2 ;
	mip->kname = $4;
        mip->default_action = $6 ;
        mip->error_action = $8 ;
        mip->enabled = $10 ;
        mip->help = $14 ;
        mip->khelp = $16 ;
    }
    $$ = mip ;
}

ident: integer
{ $$ = $1 ; }
| name
{ $$ = $1 ; }

command : COMMAND
{
    NMENUITEM *mkmenuitem() ;
    char buf[512] ;
    strncpy(buf,get_yytext(),yyleng) ;
    buf[yyleng] = '\0' ;

    $$ = mkmenuitem(buf+1) ;
}

commandentry: command
{ $$ = $1; }
   | command string
{
    NMENUITEM *mip = $1 ;

    if(mip)
      mip->action_arg = $2 ;
    $$ = mip ;
}
string : STRING
{
    char *mkstring() ;
    char *ExpandString() ;
    char buf[512] ;
    
    strncpy(buf,get_yytext(),yyleng) ;
    buf[yyleng-1] = '\0' ;
    $$ = mkstring(ExpandString(buf+1)) ;
}

integer : INTEGER
{
    int atoi() ;

    $$ = atoi(get_yytext()) ;
}

name : ID_NAME
{
    int convert_cmd_to_int() ;
    char buf[512] ;
    
    strncpy(buf,get_yytext(),yyleng) ;
    buf[yyleng] = '\0' ;
    $$ = convert_cmd_to_int(buf) ;
}
%%

char *mkstring(s)
register char *s ;
{
    register char *p ;

    p = (char *) malloc(strlen(s)+1) ;
    strcpy(p,s) ;
    return p ;
}

menuerror()
{
    do_echo("WARNING, invalid function in Menu definition\n") ;
    return 0 ;
}

NMENUITEM *
mkmenuitem(s)
char *s ;
{
    NMENUITEM *mip ;
    extern int line_num ;
    extern int (*findfunc())() ;
    if(!(mip = (NMENUITEM *) malloc(sizeof(NMENUITEM))))
      return NULL ;
    memset(mip, '\0', sizeof(NMENUITEM)) ;
    if(!(mip->action_func = findfunc(s))) {
        char buf[512] ;
        sprintf(buf,"WARNING, invalid function in menu file\nfunction = '%s' LINE %d\n",s,line_num) ;
        do_echo(buf) ;
        mip->action_func = menuerror ;
    }
    return mip ;
}

int
getmenuindex(t)
unsigned int t ;
{
    t = (t | 0x20) - 'a' ;
    return t % MAXMENUSZ ;
}

NMENU *
mkmenu(mip)
NMENUITEM *mip ;
{
    NMENU *mp ;
    NMENUITEM *tp ;

    if(!(mp = (NMENU *)malloc(sizeof(NMENU))))
      return NULL ;
    memset(mp,'\0',sizeof(NMENU)) ;
    mp->commlist = mip ;
    for(tp = mip;tp;tp = tp->next) {
        register int menuindex = GetMenuIndex(*(tp->name)) ;
        if(mp->menucommands[menuindex]) {
            char buf[512] ;
            extern int line_num ;
            sprintf(buf,
         "Warning Menu command %s attempting to use filled slot!\nLINE %d\n",
                    tp->name,line_num) ;
            do_echo(buf) ;
            continue ;
        }
        mp->menucommands[menuindex] = tp ;
    }
    return mp ;
}

NMENU *bigMenuList = NULL ;

pushmenu(mp)
NMENU *mp ;
{
    NMENUITEM *mip = NULL ;
    NMENUITEM *tmp, *next ;
    
    for(tmp=mp->commlist;tmp;tmp = next) {
        next = tmp->next ;
        tmp->next = mip ;
        mip = tmp ;
    }
    mp->commlist = mip ;
    mp->next = bigMenuList ;
    bigMenuList = mp ;
}

                                                                                                                                                                                                                                                                                                                                    DarkNET-1.08/headers.c                                                                                 644   21270   21270        13710  5747642516   7672                                                                                                                                                                                                                                                                                                                                                                      
/*
Eagles Bulletin Board System
Copyright (C) 1994, Ray Rocker, rrrocker@rock.b11.ingr.com
                                rock@seabass.st.usm.edu
                                72673.2105@compuserve.com

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "server.h"
#include <time.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>


#define HEADER_TAG_SIZE 11
#define HEADERSIZE      80  /* must be greater than HEADER_TAG_SIZE+TITLELEN */

static char *day_of_week[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
static char *mon_of_year[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };

read_headers(fname, hdr)
char *fname;
HEADER *hdr;
{
  char buf[HEADERSIZE];
  FILE *fp;
  char *hdrdata, *space;

  memset(hdr->owner, '\0', sizeof(hdr->owner));
  memset(hdr->title, '\0', sizeof(hdr->title));
  
  fp = fopen(fname, "r");
  if (fp == NULL) return S_SYSERR;

  hdrdata = buf+HEADER_TAG_SIZE;
  while (fgets(buf, sizeof buf, fp)) {
    strip_trailing_space(buf);
    if (buf[0] == '\0') break;
    else if (!strncmp(buf, "From: ", 6)) {
      if (space = strchr(hdrdata, ' ')) *space = '\0';
      strncpy(hdr->owner, hdrdata, NAMELEN);
    }
    else if (!strncmp(buf, "Posted By: ", 11)) {
      if (space = strchr(hdrdata, ' ')) *space = '\0';
      strncpy(hdr->owner, hdrdata, NAMELEN);
    }
    else if (!strncmp(buf, "Title: ", 7))
      strncpy(hdr->title, hdrdata, TITLELEN);
    else if (!strncmp(buf, "Subject: ", 9))
      strncpy(hdr->title, hdrdata, TITLELEN);
  }

  fclose(fp);
  return S_OK;
}

struct writetostruct {
  int fd;
  char *buf;
};

write_to_header(indx, userid, info)
int indx;
char *userid;
struct writetostruct *info;
{
  int i;
  int len = strlen(info->buf);
  int needed = strlen(userid)+3;
  if ((HEADERSIZE - len) < needed) {
    strcat(info->buf, ",\n");
    write(info->fd, info->buf, len+2);
    for (i=0; i<HEADER_TAG_SIZE; i++) info->buf[i] = ' ';
    info->buf[HEADER_TAG_SIZE] = '\0';
  }
  else if (len > HEADER_TAG_SIZE) strcat(info->buf, ", ");
  strcat(info->buf, userid);
  return S_OK;
}  

/* What a mess. I should use stdio. */

write_mail_headers(fd, hdr, username, list)
int fd;
HEADER *hdr;
char *username;
NAMELIST list;
{
  char fmt[40];
  char fmt2[40];
  char hdrline[HEADERSIZE];
  time_t now = time(NULL);
  struct writetostruct tostruct;
  struct tm *curr_t;
  
  sprintf(fmt, "%%-%ds", HEADER_TAG_SIZE);

  sprintf(hdrline, fmt, "From:");
  strcat(hdrline, hdr->owner);
  strcat(hdrline, " (");
  strcat(hdrline, username);         /* hdrline is big enough */
  strcat(hdrline, ")\n");
  write(fd, hdrline, strlen(hdrline));

  sprintf(hdrline, fmt, "Subject:");
  strcat(hdrline, hdr->title);       /* again, hdrline is big enough */
  strcat(hdrline, "\n");
  write(fd, hdrline, strlen(hdrline));

  tzset();				/* let's set the timezone - dkim */
  curr_t = localtime(&now);
  sprintf(fmt2, "%%-%ds%%s %%s %%.2d %%2.2d:%%2.2d:%%2.2d %%d %%s\n", HEADER_TAG_SIZE);
  sprintf(hdrline, fmt2,
	"Date:",
	day_of_week[curr_t->tm_wday],
	mon_of_year[curr_t->tm_mon],
	curr_t->tm_mday,
	curr_t->tm_hour, curr_t->tm_min, curr_t->tm_sec,
	curr_t->tm_year + 1900,
#if LINUX == 1
	tzname[curr_t->tm_isdst]);
#else
	curr_t->tm_zone);
#endif

  write(fd, hdrline, strlen(hdrline));

  sprintf(hdrline, fmt, "To:");
  tostruct.fd = fd;
  tostruct.buf = hdrline;
  apply_namelist(list, write_to_header, &tostruct);
  if (strlen(hdrline) > HEADER_TAG_SIZE) {
    strcat(hdrline, "\n");
    write(fd, hdrline, strlen(hdrline));
  }
  write(fd, "\n", 1);
}

write_post_headers(fd, hdr, username, bname)
int fd;
HEADER *hdr;
char *username;
char *bname;
{
  char fmt[40];
  char fmt2[40];
  char hdrline[HEADERSIZE];
  time_t now = time(NULL);
  struct writetostruct tostruct;
  struct tm *curr_t;
  
  sprintf(fmt, "%%-%ds", HEADER_TAG_SIZE);

  sprintf(hdrline, fmt, "Posted By:");
  strcat(hdrline, hdr->owner);
  strcat(hdrline, " (");
  strcat(hdrline, username);         /* hdrline is big enough */
  strcat(hdrline, ") on '");
  strcat(hdrline, bname);
  strcat(hdrline, "'\n");
  write(fd, hdrline, strlen(hdrline));

  sprintf(hdrline, fmt, "Title:");
  strcat(hdrline, hdr->title);       /* again, hdrline is big enough */
  strcat(hdrline, "\n");
  write(fd, hdrline, strlen(hdrline));

  tzset();				/* just to make sure - dkim */
  curr_t = localtime(&now);
  sprintf(fmt2, "%%-%ds%%s %%s %%.2d %%2.2d:%%2.2d:%%2.2d %%d %%s\n", HEADER_TAG_SIZE);
  sprintf(hdrline, fmt2,
	"Date:",
	day_of_week[curr_t->tm_wday],
	mon_of_year[curr_t->tm_mon],
	curr_t->tm_mday,
	curr_t->tm_hour, curr_t->tm_min, curr_t->tm_sec,
	curr_t->tm_year + 1900,
#if LINUX == 1
	tzname[curr_t->tm_isdst]);
#else
	curr_t->tm_zone);
#endif

  write(fd, hdrline, strlen(hdrline));
  write(fd, "\n", 1);
}

/* This one is used by the client side */

parse_to_list(list, fname, myname)
NAMELIST *list;
char *fname;
char *myname;
{
  FILE *fp;
  char header[HEADERSIZE];
  char *ptr, *id;
  int gotit = 0;

  if ((fp = fopen(fname, "r")) == NULL) return;
  while (fgets(header, sizeof header, fp) && header[0] != '\n') {
    if (!gotit && strncmp(header, "To: ", 4)) continue;
    if (gotit && strncmp(header, "    ", 4)) break;
    gotit = 1;
    ptr = header+4;
    while (id = strtok(ptr, " \t\n,")) {
      ptr = NULL;
      if (strcmp(id, myname) && !is_in_namelist(*list, id))
        add_namelist(list, id, NULL);
    }
  }
  fclose(fp);
  sort_list(list);
}

                                                        DarkNET-1.08/home.c                                                                                    644   21270   21270         2460  5647532323   7160                                                                                                                                                                                                                                                                                                                                                                      
/*
Eagles Bulletin Board System
Copyright (C) 1994, Ray Rocker, rrrocker@rock.b11.ingr.com
                                rock@seabass.st.usm.edu
                                72673.2105@compuserve.com

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include <stdio.h>
#include <stdlib.h>
#include "osdeps.h"

#define BBSHOMEENV "BBSHOME"

/*
   This function is used by the local bbs client and all utilities
   to chdir to the bbs home directory.
*/

home_bbs(dir)
char *dir;
{
  char *bbshome;
  if (dir != NULL) bbshome = dir;
  else {
    bbshome = getenv(BBSHOMEENV);
    if (bbshome == NULL) {
      /* We must be there already. */
      return 0;
    }
  }
  return (chdir(bbshome));
}
  
  
      
                                                                                                                                                                                                                DarkNET-1.08/init.c                                                                                    644   21270   21270        17734  5744032744   7225                                                                                                                                                                                                                                                                                                                                                                      
/*
Eagles Bulletin Board System
Copyright (C) 1994, Ray Rocker, rrrocker@rock.b11.ingr.com
                                rock@seabass.st.usm.edu
                                72673.2105@compuserve.com

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "server.h"
#include <malloc.h>

int bbslib_user = BBSLIB_DEFAULT;

SERVERDATA server;
extern USERDATA user_params;

static char *perm_strs[PERMBIT_MAX+1];
static LONG perm_table[MAX_CLNTCMDS];

static char *mode_strs[BBS_MAX_MODE+1];
static char mode_chars[BBS_MAX_MODE+1];

char mode_pageable[BBS_MAX_MODE+1];

#define PERMSTRFILE	"etc/permstrs"
#define ACCESSFILE	"etc/access"
#define CONFIGFILE	"etc/bbconfig"
#define MODEFILE        "etc/modes"
#define	MODEXFILE	"etc/modes.x"

/*ARGSUSED*/
_init_modes_func(indx, rec, arg)
int indx;
char *rec;
void *arg;
{
  /*
     Modes file format:
     mode-val:mode-char:mode-string:allow-page
  */
  char buf[10];
  int mode, len;
  strip_trailing_space(rec);
  rec = _extract_quoted(rec, buf, sizeof(buf));
  mode = atoi(buf);
  if (mode >= 0 && mode <= BBS_MAX_MODE) {
    if (mode_strs[mode]) {
	free(mode_strs[mode]);
	mode_strs[mode] = NULL;
    }
    rec = _extract_quoted(rec, buf, sizeof(buf));
    mode_chars[mode] = *buf;
    rec = _extract_quoted(rec, buf, sizeof(buf));
    len = strlen(buf)+1;
    if ((mode_strs[mode] = (char *)malloc(len)) == NULL) return ENUM_QUIT;
    strcpy(mode_strs[mode], buf);  
    if (*rec == 'N' || *rec == 'n')
       mode_pageable[mode] = 'N';
  }  
  return S_OK;
}

init_mode_strs_chars()
{
  int count;
  extern int lang;

  if (lang)
    _record_enumerate(MODEXFILE, 0, _init_modes_func, NULL);
  else
    _record_enumerate(MODEFILE, 0, _init_modes_func, NULL);
  return S_OK;
}

/*ARGSUSED*/
_init_strs_func(indx, rec, arg)
int indx;
char *rec;
void *arg;
{
  int len;
  strip_trailing_space(rec);
  len = strlen(rec)+1;
  if ((perm_strs[indx] = (char *)malloc(len)) == NULL) return ENUM_QUIT;
  strcpy(perm_strs[indx], rec);  
  return (indx == PERMBIT_MAX ? ENUM_QUIT : S_OK);
}

init_perm_strs()
{
  int count;
  count = _record_enumerate(PERMSTRFILE, 0, _init_strs_func, NULL);
  for (; count<=PERMBIT_MAX; count++) {
    if ((perm_strs[count] = (char *)malloc(9)) != NULL)
      strcpy(perm_strs[count], "(unused)");      
  }
  return S_OK;
}

/*ARGSUSED*/
_init_perms_func(indx, rec, arg)
int indx;
char *rec;
void *arg;
{
  char *str, *equals;
  int i;
  perm_table[indx] = 0;
  strip_trailing_space(rec);
  if ((equals = strchr(rec, '=')) != NULL) {
    equals++;
    str = strtok(equals, " \t,");
    do {
      if (!strcmp(str, "ALL")) {
        perm_table[indx] = PERM_ALL;
        break;
      }
      for (i=0; i<=PERMBIT_MAX; i++) {
        if (perm_strs[i] && !strcmp(perm_strs[i], str))
	{
          perm_table[indx] |= PERMBIT(i);
	  break;
	}
      }
      rec = NULL;
    } while (str = strtok(NULL, " \t,"));
  }
  return (indx == MAX_CLNTCMDS-1 ? ENUM_QUIT : S_OK);
}

init_perms()
{
  int count;
  count = _record_enumerate(ACCESSFILE, 0, _init_perms_func, NULL);
  for (; count<MAX_CLNTCMDS; count++) {
    perm_table[count] = 0;
  }
  return S_OK;
}

/*ARGSUSED*/
_init_config_func(indx, rec, arg)
int indx;
char *rec;
void *arg;
{
  char *equals;
  int i;
  strip_trailing_space(rec);

  if ((equals = strchr(rec, '=')) == NULL) return S_OK;
  *equals++ = '\0';
  strip_trailing_space(rec);
  strip_trailing_space(equals);
/*
  while (*rec && isspace(*rec)) rec++;
  while (*equals && isspace(*equals)) equals++;
*/
  while (*rec && myisspace(*rec)) rec++;
  while (*equals && myisspace(*equals)) equals++;

  if (!strcasecmp(rec, "new")) {
    if (toupper(*equals) == 'Y') server.newok = 1;
  }
  else if (!strcasecmp(rec, "users")) {
    i = atoi(equals);
    if (i > 0) server.maxusers = i;
  }
  else if (!strcasecmp(rec, "usertablesize")) {
    i = atoi(equals);
    if (i > 0) server.maxutable = i;
  }
  else if (!strcasecmp(rec, "name")) {
    strncpy(server.name, equals, BBSNAMELEN);
  }
  else if (!strcasecmp(rec, "logfile")) {
    strncpy(server.logfile, equals, PATHLEN);
  }
  else if (!strcasecmp(rec, "loglevel")) {
    i = atoi(equals);
    if (i >= 0 && i < LOG_LEVEL_MAX) server.loglevel = i;
  }
  else if (!strcasecmp(rec, "mailer")) {
    strncpy(server.mailbin, equals, PATHLEN);
  }
  else if (!strcasecmp(rec, "encoder")) {
    strncpy(server.encodebin, equals, PATHLEN);
  }
  else if (!strcasecmp(rec, "logons")) {
    i = atoi(equals);
    if (i >= 0) server.maxlogons = i;
  }
  else if (!strcasecmp(rec, "siglines")) {
    i = atoi(equals);
    if (i >= 0) server.maxsiglines = i;
  }
  else if (!strcasecmp(rec, "showreal")) {
    if (toupper(*equals) == 'Y') server.queryreal = 1;
  }
  else if (!strcasecmp(rec, "timeout")) {
    i = atoi(equals);
    if (i >= 0) server.idletimeout = i;
  }
  return S_OK;
}

init_config()
{
  _record_enumerate(CONFIGFILE, 0, _init_config_func, NULL);
  return S_OK;
}

_determine_access(mask, access)
LONG mask;
char *access;
{
  int i;
  memset(access, '0', MAX_CLNTCMDS);
  for (i=0; i<MAX_CLNTCMDS; i++) {
    if (mask == 0) access[i] = (perm_table[i] == PERM_ALL ? '1' : '0');
    else access[i] = (perm_table[i] & mask ? '1' : '0');
  }
  return S_OK;
}  

_has_access(cmd)
LONG cmd;
{
  if (cmd < 0 || cmd >= MAX_CLNTCMDS) return 0;
  return(user_params.access[cmd] == '1');
}

_they_have_access(cmd, mask)
LONG cmd;
LONG mask;
{
  if (cmd < 0 || cmd >= MAX_CLNTCMDS) return 0;
  if (mask == 0) return(perm_table[cmd] == PERM_ALL);
  else return(perm_table[cmd] & mask);
}

local_bbs_initialize()
{
  char loghdr[16];
  char *ident;
  FILE *fp;
  if ((fp = fopen(CONFIGFILE, "r")) == NULL) {
    /* We're in the wrong directory, probably. */
    return S_NOTFOUND;
  }
  fclose(fp);
  umask(0007);
  init_perm_strs();
  init_perms();
  server.newok = 0;
  server.loglevel = LOG_LEVEL_DEFAULT;
  server.maxusers = 80;
  server.maxutable = 80;
  server.maxlogons = 0;
  server.maxsiglines = 4;
  server.queryreal = 0;
  server.idletimeout = 0;
  strcpy(server.name, "The Unknown BBS");
  strcpy(server.logfile, "log");
  sprintf(server.tempfile, "tmp/bbs%05d", getpid());
  strcpy(server.mailbin, "/usr/lib/sendmail");
  strcpy(server.encodebin, "/usr/bin/uuencode");
  if (server.maxutable < server.maxusers) 
    server.maxutable = server.maxusers;
  init_config();
  open_bbslog(server.logfile, server.loglevel);
  ident = (bbslib_user == BBSLIB_BBSD ? "BBSD" : "LOCAL");
  sprintf(loghdr, "%s(%05d)", ident, getpid());
  set_log_header(loghdr);
  if (utable_attach(server.maxusers) != S_OK) {
    close_bbslog();
    return S_SYSERR;
  }
  return S_OK;
}

local_bbs_disconnect()
{
  local_logout();
  close_bbslog();
  unlink(server.tempfile);
  utable_detach(0);
  return S_OK;
}
  
local_bbs_connect(host, port, bbsinfo)
char *host;
SHORT port;
BBSINFO *bbsinfo;
{
  strcpy(bbsinfo->boardname, server.name);
  bbsinfo->majver = SERVER_VERSION_MAJ;
  bbsinfo->minver = SERVER_VERSION_MIN;
  bbsinfo->newok = server.newok;
  return S_OK;
}

local_bbs_get_permstrings(ppstrs)
char **ppstrs;
{
  int i;
  for (i=0; i<=PERMBIT_MAX; i++) {
    ppstrs[i] = perm_strs[i];
  }
  return S_OK;
}

local_bbs_get_modestrings(pmstrs)
char **pmstrs;
{
  int i;
  for (i=0; i<=BBS_MAX_MODE; i++) {
/*
    pmstrs[i] = (mode_strs[i] == NULL ? "" : mode_strs[i]);
*/
    pmstrs[i] = mode_strs[i];
  }
  return S_OK;
}

local_bbs_get_modechars(mchars)
char *mchars;
{
  int i;
  for (i=0; i<=BBS_MAX_MODE; i++) {
    mchars[i] = (mode_chars[i] == '\0' ? ' ': mode_chars[i]);
  }
  return S_OK;
}
                                    DarkNET-1.08/log.c                                                                                     644   21270   21270         4610  5647532323   7010                                                                                                                                                                                                                                                                                                                                                                      
/*
Eagles Bulletin Board System
Copyright (C) 1994, Ray Rocker, rrrocker@rock.b11.ingr.com
                                rock@seabass.st.usm.edu
                                72673.2105@compuserve.com

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "server.h"
#include <time.h>
#include <unistd.h>
#if WANTS_VARARGS_H
# include <varargs.h>
#else
# include <stdarg.h>
#endif

PATH bbs_logfile;
int bbs_loglevel;
char bbs_logsource[16];
FILE *bbs_log;

open_bbslog(logfile, loglevel)
char *logfile;
int loglevel;
{
  if (logfile == NULL) return S_INVALID;
  strncpy(bbs_logfile, logfile, PATHLEN-1);
  bbs_log = fopen(bbs_logfile, "a");
  if (bbs_log == NULL) {
      return S_SYSERR;
  }
  bbs_loglevel = loglevel;
  return S_OK;
}

close_bbslog()
{
  fclose(bbs_log);
  return S_OK;
}

void
set_log_header(str)
char *str;
{
  char *p = str;
  int indx = 0;
  memset(bbs_logsource, ' ', 15);
  while (p && *p && indx < 16) {
    bbs_logsource[indx++] = *p++;
  }                       
  bbs_logsource[15] = '\0';
}

void
#if WANTS_VARARGS_H
bbslog(va_alist)
va_dcl
#else
bbslog(int level, char *fmt, ...)
#endif
{
  va_list args;
  time_t now;
  char timestr[40];
#if WANTS_VARARGS_H
  int level;
  char *fmt;
#endif

#if WANTS_VARARGS_H
  va_start(args);
  level = va_arg(args, int);
  fmt = va_arg(args, char *);
#else
  va_start(args, fmt);
#endif
  
  if (level > bbs_loglevel) {
    va_end(args);
    return;
  }

  fseek(bbs_log, 0, SEEK_END);
  if (fprintf(bbs_log, "%-16s ", bbs_logsource) == EOF) {
    close_bbslog();
    open_bbslog(bbs_logfile, bbs_loglevel);
    fprintf(bbs_log, "%-16s ", bbs_logsource);
  }
  time(&now);
  strftime(timestr, sizeof timestr, "%x %X", localtime(&now));
  fprintf(bbs_log, "%s ", timestr);    
  vfprintf(bbs_log, fmt, args);
  fflush(bbs_log);
  va_end(args);
}
                                                                                                                        DarkNET-1.08/login.c                                                                                   644   21270   21270        33356  5751535713   7372                                                                                                                                                                                                                                                                                                                                                                      
/*
Eagles Bulletin Board System
Copyright (C) 1994, Ray Rocker, rrrocker@rock.b11.ingr.com
                                rock@seabass.st.usm.edu
                                72673.2105@compuserve.com

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "server.h"
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#if NEXTSTEP == 1
# include <sys/stat.h>
#endif

#if USES_UTMPX
# include <utmpx.h>
# undef UTMP_FILE
# define UTMP_FILE UTMPX_FILE
#else
# include <utmp.h>
# ifndef UTMP_FILE
#  define UTMP_FILE "/etc/utmp"
# endif
#endif

#define LOGONFILE "etc/logons"

typedef struct _LOGONDATA {
  NAME userid;
  SHORT logonlimit;
} LOGONDATA;

USERDATA user_params;
int user_number = -1;

extern SERVERDATA server;
extern char mode_pageable[];

SHORT
my_real_mode()
{
  return (user_params.u.mode & ~MODE_FLG_NOPAGE);
}

SHORT
my_mode()
{
  return (user_params.u.mode & ~MODE_FLG_NOPAGE);
}

set_real_mode(mode)
SHORT mode;
{
  utable_get_record(user_number, &user_params);
  switch (mode) {
  case 0: 
    /* Magic value: clear the non-pageable flag */
    user_params.u.mode &= ~MODE_FLG_NOPAGE;
    break;
  case 1:
    /* Magic value: set the non-pageable flag */
    user_params.u.mode |= MODE_FLG_NOPAGE;
    break;
  default:
    user_params.u.mode = mode;
    if (mode_pageable[mode] == 'N') user_params.u.mode |= MODE_FLG_NOPAGE;
  }
  utable_set_record(user_number, &user_params);
  return S_OK;
}  

my_utable_slot()
{
  return user_number;
}

_has_perms(mask)
LONG mask;
{
  return(user_params.perms & mask);
}

is_me(userid)
char *userid;
{
  return(!strcasecmp(userid, user_params.u.userid));
}

char *
my_userid()
{
  return user_params.u.userid;
}

char *
my_username()
{
  return user_params.u.username;
}

char *
my_host()
{
  return user_params.u.fromhost;
}

int
my_flag(flag)
SHORT flag;
{
  return (user_params.u.flags & flag);
}

get_remote_host(host)
char *host;
{
  int fd;
#if USES_UTMPX
  struct utmpx ut;
#else
  struct utmp ut;
#endif
  int uthostlen = sizeof ut.ut_host;
  char *tt = ttyname(0);
  if (uthostlen > HOSTLEN) uthostlen = HOSTLEN;
  if (tt == NULL) tt = "???";
  if (!strncmp(tt, "/dev/", 5)) tt+=5;
  if ((fd = open(UTMP_FILE, O_RDONLY)) != -1) {
    while (read(fd, &ut, sizeof ut) == sizeof ut) {
#if SUNOS == 1
      if (!strcmp(tt, ut.ut_line)) {
#else
      if (!strcmp(tt, ut.ut_line) && ut.ut_type != DEAD_PROCESS) {
#endif
        memset(host, 0, HOSTLEN);
        if (ut.ut_host[0] == '\0') strcpy(host, "localhost");
        else strncpy(host, ut.ut_host, uthostlen);
        close(fd);
        return S_OK;
      }
    }
    close(fd);
    strcpy(host, "localhost");
    return S_NOTFOUND;
  }
  strcpy(host, "localhost");
  return S_SYSERR;
}

get_client_host(host)
char *host;
{
  struct sockaddr_in sin;
  int sinsize = sizeof(sin);
  struct hostent *hent;
  if (getsockname(0, (struct sockaddr *)&sin, &sinsize) == -1) {
    strcpy(host, "unknown");
    return S_SYSERR;
  }
  hent = gethostbyaddr((char *)&sin.sin_addr.s_addr, 
                       sizeof(sin.sin_addr.s_addr), AF_INET);
  if (hent == NULL) {
    char *netaddr = inet_ntoa(sin.sin_addr);
    if (netaddr == NULL) strcpy(host, "unknown");
    else strncpy(host, netaddr, HOSTLEN);            
  }
  else {
    strncpy(host, hent->h_name, HOSTLEN);
  }
  return S_OK;
}

_logent_to_data(rec, ldata)
char *rec;
LOGONDATA *ldata;
{
  rec =_extract_quoted(rec, ldata->userid, sizeof(ldata->userid));
  ldata->logonlimit = atoi(rec);
  return S_OK;
}

/*ARGSUSED*/
_count_logons(indx, udata, ctr)
int indx;
USERDATA *udata;
int *ctr;
{
  (*ctr)++;
  return S_OK;
}

logon_limit_exceeded(userid)
char *userid;
{
  LOGONDATA ldata;
  int rc, online = 0;
  rc = _record_find(LOGONFILE, _match_first, userid, _logent_to_data, &ldata);
  if (rc != S_OK) ldata.logonlimit = server.maxlogons;
  if (ldata.logonlimit == 0) return 0;    /* 0 means unlimited */
  utable_enumerate(0, userid, _count_logons, &online);  
  if (online >= ldata.logonlimit) return 1;
  return 0;
}

/*ARGSUSED*/
_userid_to_pid(indx, udata, pid)
int indx;
USERDATA *udata;
LONG *pid;
{
  *pid = udata->u.pid;
  return ENUM_QUIT;
}

kick_previous_logon(userid)
char *userid;
{
  LONG pid = 0;
  utable_enumerate(0, userid, _userid_to_pid, &pid);
  if (pid > 0) {
    if (kill(pid, SIGTERM) == 0) return 0;
  }
  return -1;
}

local_bbs_login(userid, passwd, kick, loginfo)
char *userid;
char *passwd;
SHORT kick;
LOGININFO *loginfo;
{
  ACCOUNT acct;
  OPENINFO oinfo;
  int usernum;
  
  if (user_number != -1) {
    /* Already logged in! */
    return S_DENIED;
  }

  if (user_params.u.fromhost[0] == '\0') {
    if (bbslib_user == BBSLIB_BBSD)
      get_client_host(user_params.u.fromhost);
    else
      get_remote_host(user_params.u.fromhost);
  }

  memset(&acct, '\0', sizeof(acct));
  if (_lookup_account(userid, &acct) != S_OK) {
    bbslog(1, "BADUSERID %s from %s\n", userid, user_params.u.fromhost);
    return S_INVALID;
  }

  if (!is_passwd_good(acct.passwd, passwd)) {
    bbslog(1, "BADPASSWORD %s from %s\n", userid, user_params.u.fromhost);
    return S_INVALID;
  }

  if (acct.flags & FLG_DISABLED) {
    return S_DISABLED;
  }

  _determine_access(acct.perms, user_params.access);

  if (logon_limit_exceeded(acct.userid)) {
    if (acct.flags & FLG_SHARED) return S_DENIED;
    if (kick) kick_previous_logon(acct.userid);
    else return S_TEMPFAIL;
  }

  if (utable_lock_record(&user_number) != S_OK) {
    return S_FULL;
  }

  strcpy(loginfo->userid, acct.userid);
  strcpy(loginfo->username, acct.username);
  if (*acct.editor)
    strcpy(loginfo->editor, acct.editor);
  else
    strcpy(loginfo->editor, "builtin");
  if (*acct.terminal)
    strcpy(loginfo->terminal, acct.terminal);
  else
    strcpy(loginfo->terminal, "vt100");
  if (acct.lang[0] != '\0' && strcmp(acct.lang, "Kr") == 0)
    loginfo->lang = 1;
  else
    loginfo->lang = 0;
  loginfo->flags = acct.flags & ~(FLG_EXEMPT | FLG_DISABLED);
  loginfo->idletimeout = _has_access(C_NOTIMEOUT) ? 0 : server.idletimeout;
  memcpy(loginfo->access, user_params.access, sizeof(loginfo->access));
  get_lastlog_time(acct.userid, &loginfo->lastlogin);
  get_lastlog_host(acct.userid, loginfo->fromhost);

  strcpy(user_params.u.userid, acct.userid);
  strcpy(user_params.u.username, acct.username);
  user_params.u.pid = getpid();
  user_params.u.flags = acct.flags;
  user_params.u.mode = M_UNDEFINED;
  user_params.usermode = M_UNDEFINED;
  user_params.perms = acct.perms;

  if (local_bbs_open_mailbox(&oinfo) == S_OK) {
    user_params.newmailmsgs = oinfo.newmsgs;
    local_bbs_close_board();
  }

  utable_set_record(user_number, &user_params);

  set_lastlog(user_params.u.userid, user_params.u.fromhost);

  bbslog(1, "LOGIN %s %s\n", user_params.u.userid, user_params.u.fromhost);
  return S_OK;
}

local_logout()
{
  if (user_number != -1) {
    utable_get_record(user_number, &user_params);

    if (bbslib_user == BBSLIB_DEFAULT) {
      if (user_params.u.mode == M_CHAT) {
        local_bbs_exit_chat();
      }
      else if (user_params.u.mode == M_TALK) {
        local_bbs_exit_talk();
      }
    }

    utable_free_record(user_number);
    bbslog(1, "LOGOUT %s\n", user_params.u.userid);
  }
  return S_OK;
}  

local_bbs_newlogin(acct, loginfo)
ACCOUNT *acct;
LOGININFO *loginfo;
{
  int rc;

  if (server.newok == 0) return S_DENIED;

  rc = local_bbs_add_account(acct, 0);
  if (rc != S_OK) return rc;

  rc = local_bbs_login(acct->userid, acct->passwd, 0, loginfo);
  return rc;
}

local_bbs_check_mail()
{
  utable_get_record(user_number, &user_params);
  return (user_params.newmailmsgs ? S_EXISTS : S_OK);  
}

local_bbs_set_mode(mode)
SHORT mode;
{
  utable_get_record(user_number, &user_params);
  switch (mode) {
  case 0: 
    /* Magic value: clear the non-pageable flag */
    user_params.usermode &= ~MODE_FLG_NOPAGE;
    break;
  case 1:
    /* Magic value: set the non-pageable flag */
    user_params.usermode |= MODE_FLG_NOPAGE;
    break;
  default:
    user_params.usermode = mode;
    if (mode_pageable[mode] == 'N') user_params.usermode |= MODE_FLG_NOPAGE;
  }
  utable_set_record(user_number, &user_params);
  return S_OK;
}

local_bbs_set_passwd(passwd)
char *passwd;
{
  ACCOUNT acct;
  strncpy(acct.passwd, passwd, PASSLEN);
  return (_set_account(user_params.u.userid, &acct, MOD_PASSWD));
}

local_bbs_set_username(uname)
char *uname;
{
  ACCOUNT acct;
  utable_get_record(user_number, &user_params);
  strncpy(user_params.u.username, uname, UNAMELEN);
  utable_set_record(user_number, &user_params);
  strncpy(acct.username, uname, UNAMELEN);
  return(_set_account(user_params.u.userid, &acct, MOD_USERNAME));
}

local_bbs_set_terminal(term)
char *term;
{
  ACCOUNT acct;
  strncpy(acct.terminal, term, UNAMELEN);
  return (_set_account(user_params.u.userid, &acct, MOD_TERMINAL));
}

local_bbs_set_email(email)
char *email;
{
  ACCOUNT acct;
  strncpy(acct.email, email, MAILLEN);
  return (_set_account(user_params.u.userid, &acct, MOD_EMAIL));
}

local_bbs_set_protocol(protoname)
char *protoname;
{
  ACCOUNT acct;
  strncpy(acct.protocol, protoname, NAMELEN);
  return (_set_account(user_params.u.userid, &acct, MOD_PROTOCOL));
}

local_bbs_set_editor(editor)
char *editor;
{
  ACCOUNT acct;
  strncpy(acct.editor, editor, NAMELEN);
  return (_set_account(user_params.u.userid, &acct, MOD_EDITOR));
}

local_bbs_owninfo(acct)
ACCOUNT *acct;
{
  return (local_bbs_get_userinfo(user_params.u.userid, acct));
}

local_bbs_toggle_cloak()
{
  ACCOUNT acct;
  int mode = my_real_mode();
  if (mode == M_TALK || mode == M_PAGE || mode == M_CHAT || mode == M_IRC) {
    /* We don't allow cloak to be toggled in these modes */
    return(S_ILLEGAL);
  }    
  utable_get_record(user_number, &user_params);
  user_params.u.flags ^= FLG_CLOAK;
  bbslog(2, "CLOAK %s %s\n", user_params.u.flags & FLG_CLOAK ? "ON" : "OFF",
         user_params.u.userid);
  utable_set_record(user_number, &user_params);
  acct.flags = FLG_CLOAK;
  return(_set_account(user_params.u.userid, &acct, _TOGGLE_FLAGS));
}

local_bbs_set_pager(pageroff, override)
SHORT pageroff;
SHORT override;
{
  ACCOUNT acct;

  acct.flags = 0;
  pageroff = (pageroff ? 1 : 0);
  override = (override ? 1 : 0);

  utable_get_record(user_number, &user_params);

  if ((user_params.u.flags & FLG_NOPAGE ? 1 : 0) != pageroff)
    acct.flags |= FLG_NOPAGE;
  if ((user_params.u.flags & FLG_NOOVERRIDE ? 1 : 0) != override)
    acct.flags |= FLG_NOOVERRIDE;

  if (acct.flags == 0)
    return S_OK;

  user_params.u.flags ^= acct.flags;

  utable_set_record(user_number, &user_params);
  return(_set_account(user_params.u.userid, &acct, _TOGGLE_FLAGS));
}

local_bbs_set_plan(fname)
char *fname;
{
  PATH planfile;
  int rc = 0;
  local_bbs_get_plan(user_params.u.userid, planfile);
  if (fname == NULL) {
    unlink(planfile);
  }
  else if (strcmp(planfile, fname)) {
    rc = copy_file(fname, planfile, 0600, 0);
  }
  return (rc == 0 ? S_OK : S_SYSERR);
}

local_bbs_set_signature(fname)
char *fname;
{
  PATH sigfile;
  int rc = 0;
  local_bbs_get_signature(sigfile);
  if (fname == NULL) {
    unlink(sigfile);
  }
  else if (strcmp(sigfile, fname)) {
    rc = copy_file(fname, sigfile, 0600, 0);
  }
  return (rc == 0 ? S_OK : S_SYSERR);
}

_enum_users(indx, info, en)
int indx;
USERDATA *info;
struct enumstruct *en;
{
  int pageok = 1;
  if ((info->u.flags & FLG_CLOAK) && !_has_access(C_SEECLOAK))
    return S_OK;

  /* Assumption: real mode will never be M_UNDEFINED and unpageable */
  if (info->u.mode == M_UNDEFINED) info->u.mode = info->usermode;
  if (info->u.mode & MODE_FLG_NOPAGE) {
    info->u.mode &= ~MODE_FLG_NOPAGE;
    pageok = 0;
  }

  if (pageok) pageok = has_page_permission(info);
  info->u.flags &= ~(FLG_EXEMPT);
  info->u.flags &= ~(FLG_NOPAGE | FLG_NOOVERRIDE);
  if (!pageok) info->u.flags |= FLG_NOPAGE;
  if (en->fn(indx, &info->u, en->arg) == ENUM_QUIT) return ENUM_QUIT;
  return S_OK;
}

local_bbs_enum_users(chunk, startrec, userid, enumfn, arg)
SHORT chunk;
SHORT startrec;
char *userid;
int (*enumfn)();
void *arg;
{
  struct enumstruct en;
  en.fn = enumfn;
  en.arg = arg;
  utable_enumerate(startrec, userid, _enum_users, &en);
  return S_OK;
}

_enum_user_names(indx, info, list)
int indx;
USERDATA *info;
NAMELIST *list;
{
  if ((info->u.flags & FLG_CLOAK) && !_has_access(C_SEECLOAK))
    return S_OK;
  if (!is_in_namelist(*list, info->u.userid)) 
    add_namelist(list, info->u.userid, NULL);
  return S_OK;
}

local_bbs_usernames(list)
NAMELIST *list;
{
  static time_t lastupdate = 0;
  if (!utable_test_flush(lastupdate)) {
    return S_NOUPDATE;
  }
  create_namelist(list, MAXUTABLE);
  utable_enumerate(0, NULL, _enum_user_names, list);
  sort_list(list);
  return S_OK;
}

local_bbs_kick_user(pid)
LONG pid;
{
  USERDATA udata;
  if (utable_find_record(pid, &udata) != S_OK) return S_NOTFOUND;
  if ((udata.perms & PERM_SYSOP) && !_has_perms(PERM_SYSOP)) {
    return S_DENIED;
  }
  bbslog(2, "KICK %s by %s\n", udata.u.userid, user_params.u.userid);
  if (kill(pid, SIGTERM) == -1) return S_SYSERR;
  else return S_OK;
}  

_mail_adjust(indx, info, adjval)
int indx;
USERDATA *info;
int *adjval;
{
  info->newmailmsgs += *adjval;
  utable_set_record(indx, info);
  return S_OK;
}

notify_new_mail(userid, adjust)
char *userid;
int adjust;
{
  utable_enumerate(0, userid, _mail_adjust, &adjust);
}
                                                                                                                                                                                                                                                                                  DarkNET-1.08/menu.l                                                                                    644   21270   21270         1112  5651020347   7167                                                                                                                                                                                                                                                                                                                                                                      %{
#include "client.h"
#include "y.tab.h"
char *get_yytext() { return yytext ; }
extern int line_num ;
%}

%%
[Ee]nvironment |
ENVIRONMENT    {return ENVIRONMENT;}
[Mm]enu |
MENU           {return MENU;}
\,             {return COMMA;}
\{             {return OBRACE;}
\}             {return CBRACE;}
\(             {return OPAREN;}
\)             {return CPAREN;}
\"[^"\n]*\"    {return STRING;}
\$[a-zA-Z.]+   {return COMMAND;}
[a-zA-Z_]+     {return ID_NAME;}
[0-9]+         {return INTEGER;}
[ \t] ;
\n             {line_num++; }
\/\/.* ;
\#.* ;
.              {return ERROR ; }
%%


                                                                                                                                                                                                                                                                                                                                                                                                                                                      DarkNET-1.08/menus.c                                                                                   644   21270   21270        22307  5751540112   7370                                                                                                                                                                                                                                                                                                                                                                      
/*
Eagles Bulletin Board System
Copyright (C) 1994, Ray Rocker, rrrocker@rock.b11.ingr.com
                                rock@seabass.st.usm.edu
                                72673.2105@compuserve.com

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "client.h"
#include <ctype.h>

char permtab[MAX_CLNTCMDS];
char *currentboard = currboard;

/*
   Read menus are still hardcoded. We should fix this one day.
*/

int MainReadHelp(), MailReadHelp();
int MailDisplay(), MailDelete(), MailDelRange();
int MailReply(), GroupReply(), Forward(), SequentialRead();
int FileMenu(), FileHelp(), FileReadHelp();
int ReadMenuSelect();
int PostDisplay(), PostDelete(), PostMessage(), PostDelRange(), PostMark();
int PostEdit();
int FileDownload(), FileView(), FileReadMenuProto();
int FileReceive(), FileReadMenuSelect(), FileForward();

READMENUITEM mainreadlist[] = {
	{
	'r',             PostDisplay,       0,           C_READMSG,
        "r               Read current message\n",
	"r               ±ÛÀÐ±â\n"
	},
	{
	' ',             PostDisplay,       0,           C_READMSG,
        "<space>         Read current message\n",
	"<space>         ±ÛÀÐ±â\n"
	},
        {
	CTRL('P'),       PostMessage,       OPEN_POST,   C_POST,
	"CTRL-P          Post a message on this board\n",
	"CTRL-P          ±Û¾²±â\n"
	},
	{
	's',		 ReadMenuSelect,    0,           C_BNAMES,
	"s               Select a new board\n",
	"s               °è½ÃÆÇ ¼±ÅÃ\n"
	},
	{
	'S',		 SequentialRead,    0,           C_ENUMHDRS,
	"S               Sequentially read new messages from cursor\n",
	"S               Â÷·Ê´ë·Î »õ±ÛÀÐ±â\n"
	},
	{
        'd',             PostDelete,        0,           C_DELMSG,
        "d               Delete current message (if owned)\n",
	"d               ÀÚ±â±Û Áö¿ì±â\n"
	},
	{
	'D',             PostDelRange,      OPEN_MANAGE, C_DELRANGE,
	"D               Delete range of messages\n",
	"D               ±Û ¹üÀ§ÁöÁ¤ÇØ¼­ Áö¿ì±â\n"
	},
	{
	'm',		 PostMark,	    OPEN_MANAGE, C_MARKMSG,
	"m               Mark message for non-deletion\n",
	"m               Áö¿ìÁö ¾Ê°Ô Ç¥½ÃÇÏ±â\n"
	},
	{
	'E',		 PostEdit,	    0,		 C_REPLACEMSG,
	"E               Edit a post\n",
	"E               ±Û ¼öÁ¤ÇÏ±â\n"
	},
	{
	'F',             Forward,           0,           C_FORWARDMSG,
        "F               Forward post to your home mailbox\n",
	"F               ±Û email ·Î °¡Á®°¡±â\n"
	},
	{
        'h',             MainReadHelp,      0,           0,
        "h               Get this help screen\n",
	"h               µµ¿ò¸»\n"
	},
	{
        CTRL('J'),       MainReadHelp,      0,           0,
        NULL,
	NULL
	},
	{
        '\0',            NULL,              0,           0,
        NULL,
	NULL
	}
};

READMENUITEM mailreadlist[] = {
	{
	'r',             MailDisplay,       0,           C_READMSG,
        "r               Read current message\n",
	"r               ÆíÁö ÀÐ±â\n"
	},
	{
        'R',             MailReply,         OPEN_POST,   C_MAIL,
	"R               Reply to sender of current message\n",
	"R               ÆíÁö ´äÀåÇÏ±â\n"
	},
	{
	'G',             GroupReply,        OPEN_POST,   C_MAIL,
        "G               Reply to sender and all other recipients\n", 
	"G               º¸³½ÀÌ¿Í ´Ù¸¥ ¸ðµç ¼ö½ÅÀÚ¿¡°Ô ´äÀåÇÏ±â\n"
	},
	{
        'd',             MailDelete,        OPEN_MANAGE, C_DELMSG,
        "d               Delete current message\n",
	"d               ÆíÁö Áö¿ì±â\n"
	},
	{
	'D',             MailDelRange,      OPEN_MANAGE, C_DELRANGE,
	"D               Delete range of mail messages\n",
	"D               ¹üÀ§ÁöÁ¤ÇØ¼­ ÆíÁö Áö¿ì±â\n"
	},
	{
	'F',             Forward,           0,           C_FORWARDMSG,
        "F               Forward mail to your home mailbox\n",
	"F               email ·Î ÆíÁö °¡Á®°¡±â\n"
	},
	{
        'h',             MailReadHelp,      0,           0,
        "h               Get this help screen\n",
	"h               µµ¿ò¸»\n"
	},
	{
        CTRL('J'),       MailReadHelp,      0,           0,
        NULL, NULL
	},
	{
        '\0',            NULL,              0,           0,
        NULL, NULL
	}
};

READMENUITEM filereadlist[] = {
#if !REMOTE_CLIENT
	{
        't',             FileReadMenuProto, 0,           C_SETPROTO,
        "t               Set download protocol\n",
	"t               ´Ù¿î·Îµå ÇÁ·ÎÅäÄÝ Á¤ÇÏ±â\n"
	},
	{
        'v',             FileView,          0,           C_DOWNLOAD,
	"v               View a text file\n",
	"v               ÅØ½ºÆ® È­ÀÏ ³»¿ë º¸±â\n"
	},
#endif
	{
        'r',             FileReceive,       0,           C_DOWNLOAD,
        "r               Recieve (download) selected file\n",
	"r               ¼±ÅÃÇÑ È­ÀÏ ´Ù¿î·Îµå ÇÏ±â\n"
	},
	{
	'F',             FileForward,       0,           C_FORWARDFILE,
        "F               Mail file to yourself -- uuencodes if binary\n",
        "F               email ·Î °¡Á®°¡±â\n"
	},
	{
        's',             FileReadMenuSelect, 0,          C_FBNAMES,
        "s               Select a new file board\n",
	"s               È­ÀÏº¸µå ¼±ÅÃÇÏ±â\n"
	},
	{
        'h',             FileReadHelp,      0,           0,
        "h               Get this help screen\n",
	"h               µµ¿ò¸»\n"
	},
	{
        CTRL('J'),       FileReadHelp,      0,           0,
        NULL,
	NULL
	},
	{
        '\0',            NULL,              0,           0,
        NULL,
	NULL
	}
};

DoReadHelp(p, flags)
READMENUITEM *p ;
int flags;
{
  extern int lang;
  while(p->cmdkey) {
    if (HasReadMenuPerm(p->openaccess, flags) && HasPerm(p->permaccess))
      {
	if (lang && p->khelpstr)
	  {
	    prints(p->khelpstr);
	  }
	else
	  {
	    if (p->helpstr)
	      prints(p->helpstr);
	  }
      }
    p++ ;
  }
}

MovementReadHelp()
{
  extern int lang;

  standout();
  if (lang)
    prints("Ä¿¼­ µ¿ÀÛ ¸í·É\n");
  else
    prints("Movement Commands\n");
  standend();
  if (lang)
  {
    prints("p               ÀÌÀü ±Û·Î\n");
    prints("n               ´ÙÀ½ ±Û·Î\n");
    prints("P               ÀÌÀü ÆäÀÌÁö·Î\n");
    prints("N               ´ÙÀ½ ÆäÀÌÁö·Î\n");
    prints("## <cr>         ÁöÁ¤µÈ ±Û·Î\n");
    prints("$               ¸¶Áö¸· ±Û·Î\n");
  }
  else
  {
    prints("p               Previous Message\n");
    prints("n               Next Message\n");
    prints("P               Previous Page\n");
    prints("N               Next Page\n");
    prints("## <cr>         Goto Message ##\n");
    prints("$               Goto Last Message\n");
  }
}

MiscReadHelp()
{
  extern int lang;

  if (lang)
  {
    prints("CTRL-L          È­¸é ´Ù½Ã±×¸®±â\n");
    prints("e               ±ÜÀÐ±â ¸Þ´º¿¡¼­ ³ª°¡±â\n");
  }
  else
  {
    prints("CTRL-L          Redraw Screen\n");
    prints("e               EXIT Read Menu\n");
  }
}

ReadMenuHelp(title, list, flags)
char *title;
READMENUITEM *list;
int flags;
{
  extern int lang;
  clear();
  standout();
  prints(title);
  standend();
  move(2,0);
  MovementReadHelp();
  prints("\n");
  standout();
  if (lang)
    prints("±âÅ¸ ¸í·Éµé\n");
  else
    prints("Miscellaneous Commands\n");
  standend();
  DoReadHelp(list, flags);
  MiscReadHelp();
  pressreturn();
  clear();
  return FULLUPDATE;    
}

/*ARGSUSED*/
MailReadHelp(hptr, curr, num, flags)
void *hptr;
LONG curr, num, flags;
{
  extern int lang;
  int rc;

  if (lang)
    rc = ReadMenuHelp("¿ìÃ¼Åë ÀÐ±â µµ¿ò¸»\n", mailreadlist, flags);
  else
    rc = ReadMenuHelp("Mail Read Menu Help Screen\n", mailreadlist, flags);
  return (rc);
}

/*ARGSUSED*/
MainReadHelp(hptr, curr, num, flags)
void *hptr;
LONG curr, num, flags;
{
  extern int lang;
  int rc;
  
  if (lang)
    rc = ReadMenuHelp("±Û ÀÐ±â µµ¿ò¸»\n", mainreadlist, flags);
  else
    rc = ReadMenuHelp("Read Menu Help Screen\n", mainreadlist, flags);

  return (rc);
}

/*ARGSUSED*/
FileReadHelp(hptr, curr, num, flags)
void *hptr;
LONG curr, num, flags;
{
  extern int lang;
  int rc;

  if (lang)
    rc = ReadMenuHelp("È­ÀÏÀü¼Û µµ¿ò¸»\n", filereadlist, flags);
  else
    rc = ReadMenuHelp("Download Menu Help Screen\n", filereadlist, flags);
  return (rc);
}

NotImpl()
{
  extern int lang;

  clear();
  if (lang)
    prints("ÀÌ ±â´ÉÀº ¾ÆÁ÷ ÁØºñ°¡ ¾ÈµÇ¾ú½À´Ï´Ù.\n");
  else
    prints("This function is not yet implemented.\n");
  pressreturn();
  return FULLUPDATE;
}

EndMenu()
{
  return EXITMENU;
}

SetPermTable()
{
  memcpy(permtab, myinfo.access, MAX_CLNTCMDS);
}

HasPerm(perm)
int perm;
{
  if (perm == 0) return 1;
  else if (perm < 0 || perm >= MAX_CLNTCMDS) return 0;
  else return (permtab[perm]-'0');
}

HasReadMenuPerm(perm, flags)
int perm, flags;
{
  if (perm == 0) return 1;
  else return (perm & flags);
}

int
MenuGetch()
{
  char c;
  while (1) {
    c = igetch();
    if (myisprint(c)) break;
    if (c == '\r' || c == '\n' || c == '\010' || c == '\177') {
      c = '\n';
      break;
    }
    if (c == CTRL('L')) {
      redoscr() ;  
    }
  }
  return c;
}
  0,           0,
        NULL,
	NULL
	}
};

READMENUITEM mailreadlist[] = {
	{
	'r',             MailDisplay,       0,           C_READMSG,
        "r               Read current message\n",
	"r               ÆíÁö ÀÐ±â\n"
	},
	{
        'R',             MailReply,         OPEN_POST,   C_MAIL,
	"R               RDarkNET-1.08/misc.c                                                                                    644   21270   21270         5214  5747644675   7202                                                                                                                                                                                                                                                                                                                                                                      
/*
Eagles Bulletin Board System
Copyright (C) 1994, Ray Rocker, rrrocker@rock.b11.ingr.com
                                rock@seabass.st.usm.edu
                                72673.2105@compuserve.com

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "server.h"
#include <errno.h>



/* Miscellaneous server functions. */

#define HOME        "home"

get_home_directory(userid, buf)
char *userid;
char *buf;
{
  strcpy(buf, HOME);
  strcat(buf, "/");
  strcat(buf, userid);
}

#define MAILDIR     "mail"

get_mail_directory(userid, buf)
char *userid;
char *buf;
{
  get_home_directory(userid, buf);
  strcat(buf, "/");
  strcat(buf, MAILDIR);
}

#define PLANFILE    "plan"

local_bbs_get_plan(userid, buf)
char *userid;
char *buf;
{
  get_home_directory(userid, buf);
  strcat(buf, "/");
  strcat(buf, PLANFILE);
  return S_OK;
}

#define SIGFILE     "signature"

local_bbs_get_signature(buf)
char *buf;
{
  get_home_directory(my_userid(), buf);
  strcat(buf, "/");
  strcat(buf, SIGFILE);
  return S_OK;
}

#define BOARDHOME  "boards"

get_board_directory(bname, buf)
char *bname;
char *buf;
{
  strcpy(buf, BOARDHOME);
  strcat(buf, "/");
  strcat(buf, bname);
  return S_OK;
}

#define ISSUEFILE   "etc/issue"

local_bbs_get_issue(buf)
char *buf;
{
  strcpy(buf, ISSUEFILE);
  return S_OK;
}

#define INFOFILE   "etc/info"

local_bbs_get_info(buf)
char *buf;
{
  strcpy(buf, INFOFILE);
  return S_OK;
}

#define GNUFILE    "etc/COPYING"

local_bbs_get_license(buf)
char *buf;
{
  strcpy(buf, GNUFILE);
  return S_OK;
}

#define WELCFILE   "etc/welcome"

local_bbs_get_welcome(buf)
char *buf;
{
  strcpy(buf, WELCFILE);
  return S_OK;
}

local_bbs_set_welcome(buf)
char *buf;
{
  int rc = 0;
  if (buf == NULL) {
    unlink(WELCFILE);
  }
  else if (strcmp(WELCFILE, buf)) {
    rc = copy_file(buf, WELCFILE, 0660, 0);
  }
  return (rc == 0 ? S_OK : S_SYSERR);
}

#if SUNOS == 1
char *strerror(errno)
int errno;
{
   extern int sys_nerr;
   extern char *sys_errlist[];

   if (errno >= 0 && errno < sys_nerr)
      return (sys_errlist[errno]);
   return NULL;
}
#endif
                                                                                                                                                                                                                                                                                                                                                                                    DarkNET-1.08/modes.c                                                                                   644   21270   21270         2551  5742134154   7334                                                                                                                                                                                                                                                                                                                                                                       
/*
Eagles Bulletin Board System
Copyright (C) 1994, Ray Rocker, rrrocker@rock.b11.ingr.com
                                rock@seabass.st.usm.edu
                                72673.2105@compuserve.com

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "client.h"

char *global_modestrs[BBS_MAX_MODE+1];
char global_modechars[BBS_MAX_MODE+1];

char *
ModeToString(mode)
SHORT mode;
{
  if (global_modestrs[0] == NULL) {
    bbs_get_modestrings(global_modestrs);
  }
  if (mode <= BBS_MAX_MODE) {
    return(global_modestrs[mode]);
  }
  return("");
}

char
ModeToChar(mode)
SHORT mode;
{
  if (global_modechars[0] == '\0') {
    bbs_get_modechars(global_modechars);
  }
  if (mode <= BBS_MAX_MODE) {
    return(global_modechars[mode]);
  }
  return(' ');
}
                                                                                                                                                       DarkNET-1.08/modes.h                                                                                   644   21270   21270         2734  5731470537   7352                                                                                                                                                                                                                                                                                                                                                                      
/*
Eagles Bulletin Board System
Copyright (C) 1994, Ray Rocker, rrrocker@rock.b11.ingr.com
                                rock@seabass.st.usm.edu
                                72673.2105@compuserve.com

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/


/* 
   Legal values for the mode field in a userec structure, to tell what
   a user is doing. Some of these are set by the server but by the client
   because this is a transaction-based system for the most part.
*/

#define M_EMPTY		0    /* Empty slot in utable */
#define M_CONNECTING	1    
#define M_UNDEFINED     2

#define M_MAIL          3
#define M_READING       4
#define M_POSTING       5
#define M_ULDL          6
#define M_CHAT          7
#define M_MONITOR       8
#define M_TALK          9
#define M_PAGE         10
#define	M_IRC	       11
#define	M_FTP	       12
#define	M_VOTE	       13
#define	M_ROUTING      14
                                    DarkNET-1.08/name.c                                                                                    644   21270   21270        10746  5751533042   7171                                                                                                                                                                                                                                                                                                                                                                      
/*
	Too slow.. rewrote everything!

	Daeshik Kim

	hellcat@korea.slip.umd.edu
	dkim@hq.si.net
*/

/*
Eagles Bulletin Board System
Copyright (C) 1994, Ray Rocker, rrrocker@rock.b11.ingr.com
                                rock@seabass.st.usm.edu
                                72673.2105@compuserve.com

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "common.h"
#include <malloc.h>

static int nodecmp(i,j)
NAMENODE *i;
NAMENODE *j;
{
  register unsigned char *s1, *s2;
  register int xor;

  s1=i->word;
  s2=j->word;


  for (;*s1||*s2; s1++, s2++) {
    if (!*s1 || !*s2)
	return (*s2 - *s1);
    if (*s1 == *s2)
	continue;
    if (myisalpha(*s1) && myisalpha(*s2)) {
	xor = *s1 ^ *s2;
	if (xor != 32 && xor != 0)
	  return (*s1 - *s2);
    } else {
	return (*s1 - *s2);
    }
  }
  return (0);
}

void sort_list(list)
NAMELIST *list;
{
  /* empty */
  if (list == NULL || *list == NULL || (*list)->size == 0 || (*list)->last == 0)
    return;

  qsort((*list)->data, (*list)->size, sizeof(NAMENODE), nodecmp);
}

void
free_namelist(list)
NAMELIST *list;
{
  register NAMENODE *trav;

  if (list == NULL || *list == NULL)
    return;
  free((*list)->data);
  *list = NULL;
  return;
}

void
create_namelist(list, size)
NAMELIST *list;
int size;
{
  NAMELIST ptr;

  if (list && *list)
  {
    free_namelist(list);
  }
  ptr = (NAMELIST)malloc(sizeof(*ptr));
  ptr->data = (NAMENODE*)calloc(size, sizeof(NAMENODE));
  ptr->size = size;
  ptr->last = 0;
  *list = ptr;
}

add_namelist(list, name, name_before)
NAMELIST *list;
char *name;
char *name_before;
{
  register int size, last;
  register NAMENODE *data;

  if (*list == NULL)
    return S_SYSERR;

  data = (*list)->data;
  size = (*list)->size;
  last = (*list)->last;

  if (last >= size)
    return S_SYSERR;

  if (name && *name)
  {
    strcpy(data[last].word, name);
  }
  else
  {
    *data[last].word = '\0';
  }
    
  ((*list)->last)++;
  return 0;
}

remove_namelist(list, name)
NAMELIST *list;
char *name;
{
  NAMENODE *prev = NULL;
  register NAMENODE *curr;
  register int i, size, last;

  if (list == NULL || *list == NULL || (*list)->size <= 0 || (*list)->last <=0)
    return S_NOTFOUND;

  curr = (*list)->data;
  size = (*list)->size;
  last = (*list)->last;

  for (i=0; i<last && strcasecmp(curr[i].word,name); i++);

  if (i >= last)
    return S_NOTFOUND;

  *curr[i].word = '\0';

  ((*list)->last)--;
  sort_list(list);
  return S_OK;
}

is_in_namelist(list, name)
NAMELIST list;
char *name;
{
  register NAMENODE *ptr;
  register int i, size;

  if (list == NULL || name == NULL || *name == '\0')
    return 0;
  for (i=0, size=list->last, ptr = list->data; i<size; i++) {
    if (!strcasecmp(ptr[i].word, name))
      return 1;
  }
  return 0;
}

apply_namelist(list, fptr, arg)
NAMELIST list;
int (*fptr)();
void *arg;
{
  register int i, size;
  register NAMENODE *ptr;

  for(i=0, size=list->last, ptr=list->data; i<size && ptr; i++)
    (*fptr)(i, ptr[i].word, arg);
  return i;
}

/*ARGSUSED*/
static int _write_list_element(indx, name, fp)
int indx;
char *name;
FILE *fp;
{
  fprintf(fp, "%s\n", name);
  return S_OK;
}

write_namelist(fname, list)
char *fname;
NAMELIST list;
{
  FILE *fp;

  if (list == NULL) unlink(fname);
  else {
    if ((fp = fopen(fname, "w")) == NULL) {
      return S_SYSERR;
    }
    apply_namelist(list, _write_list_element, fp);
    fclose(fp);
  }
  return S_OK;
}

read_namelist(fname, list)
char *fname;
NAMELIST *list;
{
  FILE *fp;
  char rec[NAMELEN+1];	/* this should be enough for reading user names */
  register char *ptr;

  create_namelist(list, MAX_TMP);

  if ((fp = fopen (fname, "r")) == NULL)
    return S_SYSERR;

  while (fgets(rec, NAMELEN, fp)) {
    if (*rec == '#' || myisspace(*rec)) continue;
    for (ptr = rec; (*ptr) && (!myisspace(*ptr)); ptr++);
    *ptr = '\0';
    if (!is_in_namelist(*list, rec)) {
      add_namelist(list, rec, NULL);
    }
  }
  fclose(fp);

  sort_list(list);
  return S_OK;
}
                          DarkNET-1.08/netmail.c                                                                                 644   21270   21270         7440  5715562045   7664                                                                                                                                                                                                                                                                                                                                                                      
/*
Eagles Bulletin Board System
Copyright (C) 1994, Ray Rocker, rrrocker@rock.b11.ingr.com
                                rock@seabass.st.usm.edu
                                72673.2105@compuserve.com

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "server.h"
#include <ctype.h>

/* For the bbs name and tempfile */
extern SERVERDATA server;

is_valid_address(addr)
char *addr;
{
  if (*addr == '\0') return 0;   /* blank */
  while (*addr) {
    if (!isalnum(*addr) && strchr(".%!@:;-_+[]", *addr) == NULL)
      return 0;
    addr++;
  }
  return 1;
}

LONG
mail_to_outside (fname, title, to)
char *fname;
char *title;
char *to;
{
  FILE *fp;
  ACCOUNT acct;
  PATH execbuf;
  int rc;
  char *base;

  if ((fp = fopen(fname, "r")) == NULL) return S_NOTFOUND;
  fclose(fp);

  if (local_bbs_owninfo(&acct) != S_OK) return S_SYSERR;
  if (!is_valid_address(to)) return S_INVALID;
  if ((fp = fopen (server.tempfile, "w")) == NULL) return S_SYSERR;

  /* Write headers! */
  fprintf(fp, "Subject: %s (fwd)\n", title);
  fprintf(fp, "To: %s\n", to);
  fprintf(fp, "X-Sent-By: %s (%s) on The UnderB\n", acct.userid, acct.username);
  fprintf(fp, "X-Disclaimer: (%s) is not responsible for the contents of this message.\n", server.name);  
  fprintf(fp, "\n*** Forwarded file follows ***\n\n");
  fflush(fp);
  rc = append_file(fileno(fp), fname);
  fclose(fp);
  if (rc != 0) {
    unlink(server.tempfile);
    return S_SYSERR;
  }
  strcpy(execbuf, server.mailbin);
  strcat(execbuf, " ");
  strcat(execbuf, to);
  bbslog(3, "EMAIL '%s' to %s by %s\n", title, to, acct.userid);
  rc = execute(execbuf, NULL, server.tempfile, "/dev/null", "/dev/null", NULL);
  unlink(server.tempfile);
  return (rc == 0 ? S_OK : S_SYSERR);
}

LONG
mail_file_to_outside(fname, title, is_binary)
char *fname;
char *title;
int is_binary;
{
  FILE *fp;
  ACCOUNT acct;
  PATH execbuf;
  int rc;
  char *base;

  if ((fp = fopen(fname, "r")) == NULL) return S_NOTFOUND;
  fclose(fp);

  if (local_bbs_owninfo(&acct) != S_OK) return S_SYSERR;

  if (!is_valid_address(acct.email)) return S_INVALID;

  if ((fp = fopen(server.tempfile, "w")) == NULL) return S_SYSERR;

  /* Write headers! */
  fprintf(fp, "Subject: %s (fwd)\n", title);
  fprintf(fp, "To: %s\n", acct.email);
  fprintf(fp, "X-Forwarded-By: %s (%s)\n", acct.userid, acct.username);
  fprintf(fp, "X-Disclaimer: %s is not responsible for the contents of this message.\n", server.name);  
  fprintf(fp, "\n*** Forwarded file follows ***\n\n");

  fflush(fp);
  if (is_binary) {
    fclose(fp);
    base = strrchr(fname, '/');
    if (base) base++;
    else base = fname;
    strcpy(execbuf, server.encodebin);
    strcat(execbuf, " ");
    strcat(execbuf, base);
    rc = execute(execbuf, NULL, fname, server.tempfile, "/dev/null", NULL, 1);
  }
  else {
    rc = append_file(fileno(fp), fname);
    fclose(fp);
  }
  
  if (rc != 0) {
    unlink(server.tempfile);
    return S_SYSERR;
  }

  strcpy(execbuf, server.mailbin);
  strcat(execbuf, " ");
  strcat(execbuf, acct.email);
  bbslog(3, "FORWARD '%s' to %s by %s\n", title, acct.email, acct.userid);
  rc = execute(execbuf, NULL, server.tempfile, "/dev/null", "/dev/null", NULL);
  unlink(server.tempfile);
  return (rc == 0 ? S_OK : S_SYSERR);
}
                                                                                                                                                                                                                                DarkNET-1.08/nmenus.c                                                                                  644   21270   21270        31714  5751474431   7562                                                                                                                                                                                                                                                                                                                                                                      
/*
Eagles Bulletin Board System
Copyright (C) 1994, Ray Rocker, rrrocker@rock.b11.ingr.com
                                rock@seabass.st.usm.edu
                                72673.2105@compuserve.com

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#define	AD_FILE_KR	"etc/ad.dkim.kr"
#define	AD_FILE_EN	"etc/ad.dkim.en"

#define	MAX_HELP_LEN		80
#define	HELP_MENU_START_LINE	3

#include "client.h"
#include <ctype.h>
#include <malloc.h>

extern LOGININFO myinfo;
extern char *currentboard;
char *_menudesc_file;

/* New Menu Function */

int GetMenuIndex(t)
unsigned int t ;
{
    t = (t | 0x20) - 'a' ;
    return t % MAXMENUSZ ;
}

char InterpretMenuAction(action) 
char *action;
{
  if(action[0] != '$')
    return action[0] ;
  if(bbs_check_mail())
    return action[2] ;
  return action[1] ;
}

extern NMENU *bigMenuList ;

NMENU *menuEnt[MAXMENUDEPTH] ;
int currMenuEnt = -1 ;


/*ARGSUSED*/
int 
NDoMenu(menu_name)
char *menu_name ;
{
  int found, update = FULLUPDATE;
  char oldcmd = 'h', cmd ;
  int comm_loc, len;
  NMENU *msp ;
  NMENUITEM *item = NULL ;
  char buf[45];
  extern int lang;
  
  for(msp = bigMenuList;msp;msp=msp->next)
    if(!strcmp(menu_name,msp->menu_id))
      break ;
  if(!msp || currMenuEnt == MAXMENUDEPTH)
    return 0 ;
  currMenuEnt++ ;
  menuEnt[currMenuEnt] = msp ;
  if (myinfo.lastlogin == 0 || BITISSET(myinfo.flags, FLG_SHARED)) cmd = 'H';
  else cmd = InterpretMenuAction(msp->menu_default) ;
  while (update != EXITMENU) {
      if (PagePending()) {
          if (Answer()) update = FULLUPDATE;
      }
      if (update == FULLUPDATE || update == PARTUPDATE) {
          update == FULLUPDATE ? clear() : move(0,0);
          if(!strcmp(msp->menu_title,"*")) {
            extern BBSINFO serverinfo ;
	    standout();
            prints("%s",serverinfo.boardname) ;
	    standend();
            clrtoeol();
	    refresh();
          } else {
	    standout();
	    if (lang && msp->kmenu_title && *msp->kmenu_title) {
		prints("%s", msp->kmenu_title);
	    } else {
		prints("%s",msp->menu_title);
	    }
	    standend();
            clrtoeol();
	    refresh();
	  }
          move(0, t_columns - 45);
          if (currentboard[0] == '\0') {
	    c_msg(INFO_NO_BOARD_SELECTED, FALSE);
          } else {
	    if (lang)
              prints("* ÇöÀç º¸µå : %s *", currentboard);
	    else
              prints("* Current Board: %s *", currentboard);
	  }
          move(1,0);
	  if (lang && msp->kmenu_prompt && *msp->kmenu_prompt) {
	    register int i;
	    register char *p;

	    prints("%s",msp->kmenu_prompt);
	    for (p=msp->kmenu_prompt, i=0; (*p); i++, p++);
	    comm_loc = i;
	  } else {
	    prints("%s",msp->menu_prompt);
	    comm_loc = strlen(msp->menu_prompt) ;
	  }
          clrtoeol();
      }
      if (bbs_check_mail()) {
	  move(0, t_columns - 13);
          standout();
	  c_msg(INFO_MAIL, FALSE);
          standend();
          clrtoeol();
          refresh();
      }
      while(cmd != '\n') {
          item = msp->menucommands[GetMenuIndex(cmd)] ;
          if(item != NULL && HasPerm(item->enabled)) {
              move(1,comm_loc);
	      len = comm_loc;
              standout();
	      if (lang && item->kname && *item->kname) {
		prints("%s", item->kname) ;
		len += strlen(item->kname);
	      } else {
		prints("%s", item->name) ;
		len += strlen(item->name);
	      }
	      standend();
              clrtoeol();

	      sprintf(buf, "[%s/%s/%s]",
			myinfo.editor, myinfo.terminal, myinfo.username);
	      move (1, t_columns - strlen(buf) - 1);
	      prints(buf);
              move(1, len);
          } else {
              bell();
              cmd = oldcmd;
          }
          oldcmd = cmd;
          cmd = MenuGetch();
          if (!isalpha(cmd) && cmd != '\n') {
              bell();
              cmd = oldcmd;
          }
      }
      item = msp->menucommands[GetMenuIndex(oldcmd)] ;
      if (item != NULL) {
          update = (item->action_func)(item->action_arg);
          BITCLR(update, FETCHNEW | NEWDIRECT);     
          if (update & MENUERROR) 
            cmd = InterpretMenuAction(item->error_action);
          else 
            cmd = InterpretMenuAction(item->default_action) ;
      }
  }
  currMenuEnt-- ;
  return FULLUPDATE;
}

do_help()
{
    NMENU *mp ;
    NMENUITEM *mip ;
    char *ptr1, *ptr2;
    int i, j, k;
    FILE *fp = NULL;
    char buf[MAX_HELP_LEN+1];
    char del[MAX_HELP_LEN+1];
    extern int lang;

    if(currMenuEnt < 0)
      return ;

    mp = menuEnt[currMenuEnt] ;
    i = HELP_MENU_START_LINE;

    if (lang) {
      if (mp->kmenu_id && *mp->kmenu_id) {
	sprintf(buf, "====<%s %s>====", mp->kmenu_id, "¸Þ´º µµ¿ò¸»");
      } else {
        sprintf(buf, "====<%s %s>====", mp->menu_id, "¸Þ´º µµ¿ò¸»");
      }
    } else {
      sprintf(buf, "====<%s %s>====", mp->menu_id, "Menu Help Screen");
    }

    move(i++,0) ;
    clrtobot();
    prints("%s", buf);

    for(mip=mp->commlist;
	i < (t_lines - HELP_MENU_START_LINE) && mip ;
	mip=mip->next)
    {
      if(HasPerm(mip->enabled)) {
	if (lang)
	  ptr1 = mip->khelp;
	else
	  ptr1 = mip->help;

	/* remove leading space if any*/
	for (; (*ptr1)&&(*ptr1 == ' '); ptr1++);

	strcpy(buf, ptr1);

	/* remove trailing space if any*/
	ptr2 = buf + strlen(buf);
	for (ptr2--; (*ptr2) && (*ptr2 == ' '); ptr2--);
	*(ptr2+1) = '\0';

	move (i++, 0);
	prints("%c", buf[0]) ;
	standout();
	prints("%c", buf[1]) ;
	standend();
	prints("%s", &buf[2]) ;
      }
    }

    move (i++, 0);
    prints("====<%s>====", version[lang]);

    /* this gatta be ONE line ad. for now - DKIM */
    if (lang)
      fp = fopen(AD_FILE_KR, "r");
    else
      fp = fopen(AD_FILE_EN, "r");
    if (fp) {
      if (fgets(buf, MAX_HELP_LEN, fp)) {
	buf[strlen(buf)-1] = '\0';

	move (i++, 0);
	clrtoeol();
	move (i++, 0);
	prints(buf);
      }
      fclose(fp);
    }
    move (i, 0);
    clrtobot();
    return PARTUPDATE;
}

do_echo(s)
char *s ;
{
    clear() ;
    prints("%s",s) ;
    pressreturn() ;
    return FULLUPDATE ;
}

exec_func(s)
char *s ;
{
    int i ;
    char buf[4096] ;
    char *p, *q ;
    SHORT mode ;
    
    parse_default() ;
    strncpy(buf,s,sizeof(buf)) ;
    p=strchr(buf,':') ;
    if(p) {
      *p='\0' ;
      q=strchr(p+1,':') ;
      if(q) {
            *q='\0';
            mode = atoi(q+1);            
      }
      parse_environment(p+1) ;
    }
      
    if (mode > 1) bbs_set_mode(mode);
    clear() ;
    refresh() ;
    i = do_exec(buf,NULL,0) ;
    clear() ;
    if (mode > 1) bbs_set_mode(M_UNDEFINED);
    return FULLUPDATE ;
}
 
exec_func_w_pause(s)
char *s ;
{
    int i ;
    
    char buf[4096] ;
    char *p, *q ;
    SHORT mode ;

    parse_default() ;
    strncpy(buf,s,sizeof(buf)) ;
    p=strchr(buf,':') ;
    if(p) {
        *p='\0' ;
        q=strchr(p+1,':') ;
        if(q) {
            *q='\0';
            mode = atoi(q+1);            
        }
        parse_environment(p+1) ;
    }
      
    if (mode > 1) bbs_set_mode(mode) ;
    clear() ;
    refresh() ;
    i = do_exec(buf,NULL,0) ;
    pressreturn() ;
    clear() ;
    if (mode > 1) bbs_set_mode(M_UNDEFINED) ;
    return FULLUPDATE ;
}

int do_pipe_more() ;

int revised_pipe_more(s)
char *s ;
{
    char buf[4096] ;
    char *p ;
    
    parse_default() ;
    strncpy(buf,s,sizeof(buf)) ;
    p=strchr(buf,':') ;
    if(p) {
        *p='\0' ;
        parse_environment(p+1) ;
    }
      
    do_pipe_more(buf) ;
}

struct funcs {
    char *funcname ;
    int (*funcptr)() ;
} ;

int NotImpl(), EndMenu(), XyzMenu(), AdminMenu(), MailMenu(), TalkMenu();
int MainHelp(), XyzHelp(), AdminHelp(), MailHelp(), TalkHelp();
int ShowDate(), Welcome(), BoardInfo(), GnuInfo(), EditWelcome();
int MainReadHelp(), MailReadHelp();
int FileMenu(), FileHelp(), FileReadHelp();
int AllUsers(), OnlineUsers(), SetPasswd(), SetUsername(), SetAddress();
int ShortList(), Monitor();
int SetTermtype(), ShowOwnInfo(), AddAccount(), DeleteAccount();
int SetUserData(), SetUserPerms(), ToggleCloak(), ToggleExempt();
int Query(), QueryEdit();
int MailSend(), GroupSend(), ReadNewMail(), MailRead();
int NetMailSend();
int MailDisplay(), MailDelete(), MailDelRange();
int MailReply(), GroupReply(), Forward();
int Visit(), BoardCounts(), Zap(), ReadNew(), SequentialRead();
int Boards(), SelectBoard(), AddBoard(), DeleteBoard(), ChangeBoard();
int SetBoardMgrs();
int FtpPost(), Post(),  MainRead(), ReadMenuSelect();
int PostDisplay(), PostDelete(), PostMessage(), PostDelRange(), PostMark();
int PostEdit();
int FileBoards(), FileSelect(), FileDownload();
int FileUpload(), FileReceive(), FileReadMenuSelect();
int Chat(), Kick(), Talk(), SetPager(), SetOverrides(), Irc();
int Routing();
int SignatureEdit();
#if !REMOTE_CLIENT
int SelectEditor(), SelectProtocol(), FileReadMenuProto(), FileView();
#endif
int SetLang(), DeleteMe(), Xit();

struct funcs funclist[] = {
    "exec", exec_func,
    "exec.pause", exec_func_w_pause,
    "exec.more", revised_pipe_more,
    "echo", do_echo,
    "NotImpl",NotImpl,
    "EndMenu",EndMenu,
    "Help",do_help,
    "Menu",NDoMenu,
    "ShowDate",ShowDate,
    "Welcome", Welcome,
    "BoardInfo",BoardInfo,
    "GnuInfo",GnuInfo,
    "EditWelcome",EditWelcome,
    "AllUsers",AllUsers,
    "OnlineUsers",OnlineUsers,
    "SetPasswd",SetPasswd,
    "SetUsername",SetUsername,
    "SetAddress",SetAddress,
    "ShortList",ShortList,
    "Monitor",Monitor,
    "SetTermtype",SetTermtype,
    "ShowOwnInfo",ShowOwnInfo,
    "AddAccount",AddAccount,
    "DeleteAccount",DeleteAccount,
    "SetUserData",SetUserData,
    "SetUserPerms",SetUserPerms,
    "ToggleCloak",ToggleCloak,
    "ToggleExempt",ToggleExempt,
    "Query",Query,
    "QueryEdit",QueryEdit,
    "MailSend",MailSend,
    "NetMailSend",NetMailSend,
    "GroupSend",GroupSend,
    "ReadNewMail",ReadNewMail,
    "MailRead",MailRead,
    "Visit",Visit,
    "BoardCounts",BoardCounts,
    "Zap",Zap,
    "ReadNew",ReadNew,
    "Boards",Boards,
    "SelectBoard",SelectBoard,
    "AddBoard",AddBoard,
    "DeleteBoard",DeleteBoard,
    "ChangeBoard",ChangeBoard,
    "SetBoardMgrs",SetBoardMgrs,
    "Post",Post,
    "FtpPost",FtpPost,
    "MainRead",MainRead,
    "FileBoards",FileBoards,
    "FileSelect",FileSelect,
    "FileDownload",FileDownload,
#if !REMOTE_CLIENT
    "SelectProtocol",SelectProtocol,
#endif
    "FileUpload",FileUpload,
    "Irc",Irc,
    "Routing", Routing,
    "Chat",Chat,
    "Kick",Kick,
    "Talk",Talk,
    "SetPager",SetPager,
    "SetOverrides",SetOverrides,
#if !REMOTE_CLIENT
    "SelectEditor",SelectEditor,
#endif
    "SignatureEdit",SignatureEdit,
    "SetLang", SetLang,
    "DeleteMe", DeleteMe,
    "Xit", Xit,
    NULL,NULL
} ;

    
int (*findfunc(s))()
char *s ;
{
    int i ;
    
    for(i=0;funclist[i].funcname;i++)
      if(!strcmp(funclist[i].funcname,s))
        return funclist[i].funcptr ;
    return NULL ;
}

#if !REMOTE_CLIENT

/* NOTE: This MUST agree with ACCESSFILE location in init.c */
#define ACCESSFILE "etc/access" 

char *funcstrings[MAX_CLNTCMDS];

form_function_list()
{
    FILE *fp;
    int i;
    char buf[1024], *equals;
    for (i=0; i<MAX_CLNTCMDS; i++) funcstrings[i] = NULL;
    i = 0;
    if ((fp = fopen(ACCESSFILE, "r")) != NULL) {
      while (i<MAX_CLNTCMDS && fgets(buf, sizeof buf, fp) != NULL) {
        if (*buf == '#' || isspace(*buf)) continue;
        if ((equals = strchr(buf, '=')) != NULL) {
          *equals = '\0';
          if ((funcstrings[i] = (char *)malloc(strlen(buf)+1)) != NULL)
	    strcpy(funcstrings[i], buf);
	}
	i++;
      }
      fclose(fp);
    }
}

free_function_list()
{
    int i;
    for (i=0; i<MAX_CLNTCMDS; i++)
      if (funcstrings[i] != NULL) free(funcstrings[i]);
}

convert_cmd_to_int(s) 
char *s;
{
    int i ;
    
    for (i=0; i<MAX_CLNTCMDS; i++) {
      if (funcstrings[i] == NULL) continue;
      if (!strcmp(funcstrings[i], s)) return i;
    }
    fprintf(stderr, "does not grok '%s'\n", s);
    sleep(2);
    return -1;
}

#else /* REMOTE_CLIENT */

convert_cmd_to_int(s)
char *s;
{
    /* In the remote client, we're assuming numbers will be here */
    return 0;
}

#endif /* !REMOTE_CLIENT */

int line_num ;

ParseMenu()
{
    FILE *fp ;
    extern FILE *yyin ;
    
    if((fp = fopen(_menudesc_file,"r")) == NULL) {
        perror("open menu file") ;
        return -1 ;
    }
#if !REMOTE_CLIENT
    form_function_list();    
#endif
    yyin = fp ;
    line_num = 1 ;
    yyparse() ;
    fclose(fp) ;
#if !REMOTE_CLIENT
    free_function_list();
#endif
    return 0;
}

yywrap()
{
    return 1 ;
}

yyerror()
{
    char buf[512] ;
    sprintf(buf,"syntax error in '%s' %d.\n",_menudesc_file,line_num) ;
    do_echo(buf) ;
}
currMenuEnt < 0)
      return ;

    mp = menuEnt[cuDarkNET-1.08/osdeps.h                                                                                  644   21270   21270         7152  6044621571   7531                                                                                                                                                                                                                                                                                                                                                                      
/*
Eagles Bulletin Board System
Copyright (C) 1994, Ray Rocker, rrrocker@rock.b11.ingr.com
                                rock@seabass.st.usm.edu
                                72673.2105@compuserve.com

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

/* 
   All operating system dependent stuff should go here.
   If your OS has already been ported to, pick it below and you do not
   have to edit any other source files.
   If not you'll have to figure out the right settings and maybe add some.
*/

#define LINUX		0 	/* Linux 1.0 */
#define SUNOS           1	/* SunOS version 4.x */
#define SOLARIS         0       /* SunOS version 5.x */
#define AIX             0       /* IBM AIX 3.2.x */
#define OSF             0       /* DEC OSF/1 (LINUX works too) */
#define NEXTSTEP        0       /* NeXTStep 3.2 -- also uses #ifdef NeXT */
#define AUX             0       /* Apple A/UX */
#define UNIXWARE        0       /* Novell's UnixWare (SVR4) */
#define ULTRIX          0       /* Ultrix 4.3 (LINUX works too) */

#define NO_STRCASECMP	1

/* 
   LONG must be a 4-byte quantity, SHORT must be a 2-byte quantity 
*/

typedef unsigned LONG;		/* 32-bit unsigned */
typedef unsigned short SHORT;	/* 16-bit unsigned */

/* 
   If your C library does not have flock(2) define NO_FLOCK.
*/

#if SOLARIS || AIX || UNIXWARE
# define NO_FLOCK 1             /* No flock, must use lockf */
#else
# define NO_FLOCK 0
#endif

/*
   If your C library does not have vfork(2) define NO_VFORK.
*/

#if AIX || SGI || AUX
# define NO_VFORK 1
#endif

/* 
   If your system does not support the System V termio interface
   (you need BSD sgtty.h etc.), define NO_TERMIO.
*/

#if NEXTSTEP
# define NO_TERMIO 1
#endif

/* 
   If your C library does not have the setpgid(3) function, define 
   NO_SETPGID to make it use setpgrp(3).
*/

#if NEXTSTEP
# define NO_SETPGID 1
#endif

/* 
   If your C library does not have strcasecmp(3) and strncasecmp(3)
   you can define this. Or, #define strcasecmp and strncasecmp to
   whatever case-insensitive strcmp functions you do have.

#if UNIXWARE
# define NO_STRCASECMP 1
#endif
*/

/* 
   Do you want varargs or stdarg? Stdarg is the default, define this
   if your compiler uses varargs.
*/

#if SUNOS || SOLARIS || NEXTSTEP
# define WANTS_VARARGS_H 1
#endif

/*
   Do you have a <sys/select.h> header file and need it?
*/

#if AIX
# define USES_SYS_SELECT_H 1
#endif

/* 
   Does your system support shared memory? (shmget(2), shmat(2), shmdt(2))
   If no, define this symbol. If shared memory is optional in your kernel
   and you don't have it, it's ok to leave this undefined.
*/

#if NEXTSTEP
# define NO_SHARED_MEMORY 1
#endif

/* 
   System V usually doesn't give the remote host in the utmp file.
   Many of them have a utmpx file which does include this field.
*/

#if SOLARIS || UNIXWARE
# define USES_UTMPX 1
#endif

/*
   If crypt(3) is declared in unistd.h, good. If it's missing use this.
*/

#if SUNOS || SOLARIS || AIX || AUX
# define NEEDS_CRYPT_DECLARED 1
#endif

/* Function prototyping */

#ifndef __P
# define __P(x) ()
#endif

                                                                                                                                                                                                                                                                                                                                                                                                                      DarkNET-1.08/passwd.c                                                                                  644   21270   21270         3662  5647532324   7537                                                                                                                                                                                                                                                                                                                                                                      
/*
Eagles Bulletin Board System
Copyright (C) 1994, Ray Rocker, rrrocker@rock.b11.ingr.com
                                rock@seabass.st.usm.edu
                                72673.2105@compuserve.com

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/


#include "common.h"
#include <time.h>
#if NEEDS_CRYPT_DECLARED
char *crypt __P((char *, char *));
#else
# include <unistd.h>
#endif

#define REALPASSLEN 8   /* number of significant characters */

is_passwd_good(crypted, clear)
char *crypted;
char *clear;
{
  char *pw;
  char copy[REALPASSLEN+1];
  memset(copy, 0, sizeof copy);
  strncpy(copy, clear, REALPASSLEN);
  pw = crypt(copy, crypted);    
  return (!strcmp(pw, crypted));  
}

void
encrypt_passwd(crypted, clear)
char *crypted;
char *clear;
{
  char copy[REALPASSLEN+1];
  char saltc[2];
  time_t now;
  char *pw;
  int i;
  if (*clear == '\0') {
    *crypted = '\0';
    return;
  }
  memset(copy, 0, sizeof copy);
  strncpy(copy, clear, REALPASSLEN);    
  time(&now);
  saltc[0] = (char)(now & 000177);
  saltc[1] = (char)((now >> 7) & 000177);
  for (i=0; i<2; i++) {
    if (saltc[i] < 0x2e) saltc[i]+=0x41;
    if (saltc[i] > 0x39 && saltc[i] < 0x41) saltc[i]-=0x7;
    if (saltc[i] > 0x5a && saltc[i] < 0x61) saltc[i]+=0x6;
    if (saltc[i] > 0x7a) saltc[i]-=0x5;
  }
  pw = crypt(copy, saltc);
  strncpy(crypted, pw, PASSLEN);
}
 __P((char *, char *));
#else
# include <unistd.h>
#endif

#define REALPASSLENDarkNET-1.08/perms.h                                                                                   644   21270   21270         2616  5651100327   7354                                                                                                                                                                                                                                                                                                                                                                      
/*
Eagles Bulletin Board System
Copyright (C) 1994, Ray Rocker, rrrocker@rock.b11.ingr.com
                                rock@seabass.st.usm.edu
                                72673.2105@compuserve.com

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/


/* 
   Defines the bits that correspond to each permission. The permission bits
   used by the system are defined here, and their names are in the permstrs
   file.
*/

#define PERMBIT(n)	(1 << n)
#define PERMBIT_MAX     31

#define PERM_NONE       0
#define PERM_ALL        ~0

/* PERM_DEFAULT is given to each new account upon creation */
#define PERM_DEFAULT    PERMBIT(0) | PERMBIT(1) | PERMBIT(2) | PERMBIT(3)

/* The bit to denote Sysop permission */
#define PERM_SYSOP	PERMBIT(4)
#define PERM_ACCTMGR	PERMBIT(5)
#define PERM_BRDMGR	PERMBIT(6)
                                                                                                                  DarkNET-1.08/readbits.c                                                                                644   21270   21270        15531  5647532324  10051                                                                                                                                                                                                                                                                                                                                                                      
/*
Eagles Bulletin Board System
Copyright (C) 1994, Ray Rocker, rrrocker@rock.b11.ingr.com
                                rock@seabass.st.usm.edu
                                72673.2105@compuserve.com

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "server.h"
#include <time.h>

/* readbits file format:
bname       :ordr:stampxxx:10101010...

if bname is empty, the readbits are for Mail.
*/

#define BIT_BNAME_OFFSET  0
#define BIT_ORDER_OFFSET  (BIT_BNAME_OFFSET+NAMELEN+1)
#define BIT_STAMP_OFFSET  (BIT_ORDER_OFFSET+5)
#define BIT_DATA_OFFSET   (BIT_STAMP_OFFSET+9)
 
#define READBITFILE "readbits"

get_readbit_file(userid, buf)
char *userid;
char *buf;
{
  get_home_directory(userid, buf);
  strcat(buf, "/");
  strcat(buf, READBITFILE);
}

expand_bitent(bitent, ba)
char *bitent;    /* The readbit data */
char *ba;        /* char array of size READBITSIZE, filled */
{
  char *eob;
  char currval;
  int currct = 0;
  char scratch[10];

  for (eob = ba+READBITSIZE-1; *eob == '0' && eob > ba; eob--);
  eob++;

  for (currval = *ba; ba <= eob; ba++) {
    if (*ba == currval) currct++;
    else {
      if (currct <= 4) {
        memset(scratch, 0, sizeof scratch);
        for (; currct; currct--) scratch[currct-1] = currval;
      }
      else sprintf(scratch, "%c[%d]", currval, currct);
      strcpy(bitent, scratch);
      bitent += strlen(scratch);
      currct = 1;
      currval = *ba;
    }
  }
  *bitent = '\0';
}

compress_bitent(bitent, ba)
char *bitent;     /* The readbit data */
char *ba;         /* char array of size READBITSIZE, empty */
{
  int ct;
  char *rbrkt;

  memset(ba, '0', READBITSIZE);

  while (*bitent && *bitent != '\n') {
    if (*(bitent+1) == '[') {
      if (rbrkt = strchr(bitent, ']')) *rbrkt = '\0';
      for (ct = atoi(bitent+2); ct; ct--) *ba++ = *bitent;
      if (rbrkt) {
	*rbrkt = ']';
        bitent = rbrkt;
      }
    }
    else {
      *ba++ = *bitent;
    }
    bitent++;
  }
}

parse_readinfo(rec, rinfo)
char *rec;
READINFO *rinfo;
{
  rinfo->stamp = hex2LONG(rec+BIT_STAMP_OFFSET);
  compress_bitent(rec+BIT_DATA_OFFSET, rinfo->bits);
  return S_OK;
}

parse_readorder(rec, order)
char *rec;
SHORT *order;
{
  *order = hex2SHORT(rec+BIT_ORDER_OFFSET);
  return S_OK;
}

get_bitfile_ent(bname, rinfo)
char *bname;
READINFO *rinfo;
{
  int rc;
  PATH bitfile;

  get_readbit_file(my_userid(), bitfile);

  memset(rinfo->bits, '0', READBITSIZE);
  rinfo->stamp = 0;

  rc = _record_find(bitfile, _match_first, bname, parse_readinfo, rinfo);
  return rc;
}

struct _bitsetstruct {
  char *bname;
  SHORT *order;
  READINFO *rinfo;
};

format_readinfo(rec, info)
char *rec;
struct _bitsetstruct *info;
{
  if (info->bname) {
    memset(rec+BIT_BNAME_OFFSET, ' ', NAMELEN);
    memcpy(rec+BIT_BNAME_OFFSET, info->bname, strlen(info->bname));
    rec[BIT_ORDER_OFFSET-1] = ':';
  }

  if (info->order) {
    SHORTcpy(rec+BIT_ORDER_OFFSET, *(info->order));
    rec[BIT_STAMP_OFFSET-1] = ':';
  }
    
  if (info->rinfo) {
    LONGcpy(rec+BIT_STAMP_OFFSET, info->rinfo->stamp);
    rec[BIT_DATA_OFFSET-1] = ':';
    expand_bitent(rec+BIT_DATA_OFFSET, info->rinfo->bits);
    strcat(rec, "\n");
  }
  return S_OK;
}              

/* This can GO AWAY if I ever fix _record_replace to only pass two args */

update_readinfo(newrec, oldrec, info)
char *newrec;

char *oldrec;
struct _bitsetstruct *info;
{
  strcpy(newrec, oldrec);
  return (format_readinfo(newrec, info));
}

set_bitfile_ent(bname, rinfo)
char *bname;
READINFO *rinfo;
{
  int rc;
  struct _bitsetstruct bs;
  PATH bitfile;

  if (my_flag(FLG_SHARED)) return 0;

  get_readbit_file(my_userid(), bitfile);

  bs.bname = NULL;
  bs.order = NULL;
  bs.rinfo = rinfo;

  rc = _record_replace(bitfile, _match_first, bname, update_readinfo, &bs);
  
  if (rc == S_NOTFOUND) {
    SHORT order = READ_ORDER_UNSET;
    bs.bname = bname;    
    bs.order = &order;
    rc = _record_add(bitfile, _match_first, bname, format_readinfo, &bs);
  }

  return rc;
}
    
set_readbit(rinfo, fileid)
READINFO *rinfo;
SHORT fileid;
{
  if (fileid <= 0 || fileid > READBITSIZE) return S_INVALID;
  rinfo->bits[fileid-1] = '1';
  return S_OK;
}

clear_all_readbits(rinfo)
READINFO *rinfo;
{
  memset(rinfo->bits, '0', sizeof(rinfo->bits));
  return S_OK;
}

test_readbit(rinfo, fileid)
READINFO *rinfo;
SHORT fileid;
{
  if (fileid <= 0 || fileid > READBITSIZE) return 0;
  return (rinfo->bits[fileid-1] == '1');
}

get_read_order(bname, order)
char *bname;
SHORT *order;
{
  int rc;
  PATH bitfile;

  get_readbit_file(my_userid(), bitfile);
  *order = READ_ORDER_UNSET;

  rc = _record_find(bitfile, _match_first, bname, parse_readorder, order);
  return rc;
}

set_read_order(bname, order)
char *bname;
SHORT order;
{
  int rc;
  struct _bitsetstruct bs;
  PATH bitfile;

  if (my_flag(FLG_SHARED)) return 0;

  get_readbit_file(my_userid(), bitfile);

  bs.bname = NULL;
  bs.order = &order;
  bs.rinfo = NULL;

  rc = _record_replace(bitfile, _match_first, bname, update_readinfo, &bs);
  
  if (rc == S_NOTFOUND) {
    READINFO rinfo;
    rinfo.stamp = 0;
    clear_all_readbits(&rinfo);
    bs.bname = bname;    
    bs.rinfo = &rinfo;
    rc = _record_add(bitfile, _match_first, bname, format_readinfo, &bs);
  }

  return rc;
}
    
/*ARGSUSED*/
fix_readbit_entry(indx, rec, ncs)
int indx;
char *rec;
struct namechange *ncs;
{
  int rc;
  PATH bitfile;
  NAME userid;
  struct _bitsetstruct bs;

  /* Sleazy way to get the userid out of the passfile record */
  memset(userid, 0, sizeof userid);
  strncpy(userid, rec, NAMELEN);
  strip_trailing_space(userid);

  get_readbit_file(userid, bitfile);
  
  if (ncs->newname == NULL)
    rc = _record_delete(bitfile, _match_first, ncs->oldname);
  else {
    bs.rinfo = NULL;
    bs.order = NULL;
    bs.bname = ncs->newname;
    rc = _record_replace(bitfile, _match_first, ncs->oldname,
		         update_readinfo, &bs);
  }
 
  return rc;
}    

#define NOZAP_FILE "nozap"

local_bbs_zap_board(bname, dozap)
char *bname;
SHORT dozap;
{
  int rc;
  PATH nzfile;
  FILE *fp;
  SHORT neworder = dozap ? READ_ORDER_ZAPPED : READ_ORDER_UNSET;

  get_board_directory(bname, nzfile);
  strcat(nzfile, "/");
  strcat(nzfile, NOZAP_FILE);
  if (dozap && ((fp = fopen(nzfile, "r")) != NULL)) {
    fclose(fp);
    return S_ILLEGAL;
  }

  rc = set_read_order(bname, neworder);

  return (rc == S_OK ? S_OK : S_NOTFOUND);
}
t = atoi(bitent+2); ct; ct--) *ba++ = *bitent;
      if (rbrkt) {
	*rbrkt = ']';
        bitent = rbrkt;
      }
    }
    else {
      *ba++ = *bitent;
    }
    biteDarkNET-1.08/talk.c                                                                                    644   21270   21270        23044  5733463064   7205                                                                                                                                                                                                                                                                                                                                                                      
/*
Eagles Bulletin Board System
Copyright (C) 1994, Ray Rocker, rrrocker@rock.b11.ingr.com
                                rock@seabass.st.usm.edu
                                72673.2105@compuserve.com

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "server.h"
#include <sys/time.h>
#include <signal.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <ctype.h>

#if USES_SYS_SELECT_H
# include <sys/select.h>
#endif

#ifndef INADDR_LOOPBACK
# define INADDR_LOOPBACK 0x7f000001
#endif

#define PAGE_INTERVAL 20      /* How often the page signal is sent */

int talkfd = -1;
int cloak_save;
USERDATA talk_theirdata, talk_mydata;

local_bbs_talk(pid, fd, sockp)
LONG pid;
LONG fd;
LONG *sockp;
{
  int s, sinlen, nfds, rc;
  struct sockaddr_in sin;
  fd_set readfds;
  struct timeval tv;
  char cbuf[256];
  SHORT mymode;

  mymode = my_real_mode();
  if (mymode == M_CHAT || mymode == M_TALK || mymode == M_IRC) {
    return S_ILLEGAL;
  }

  if (mymode != M_PAGE) {
    /* You can't page yourself! */
    if (pid == getpid()) return S_EXISTS;

    if (utable_find_record(pid, &talk_theirdata) != S_OK) return S_NOTFOUND;

    if (!has_page_permission(&talk_theirdata)) return S_INVALID;

    /* Don't interrupt an upload or download. */
    if (talk_theirdata.u.mode & MODE_FLG_NOPAGE) return S_TEMPFAIL;  
    /* Also if the client says it's not in a place where it can hear you. */ 
    if (talk_theirdata.usermode & MODE_FLG_NOPAGE) return S_TEMPFAIL;

    if ((s = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
      bbslog(0, "ERROR local_bbs_talk: socket failed\n");
      return S_SYSERR;
    }

    memset(&sin, 0, sizeof sin);
    sin.sin_family = PF_INET;
    sin.sin_addr.s_addr = INADDR_ANY;
    if (bind(s, (struct sockaddr *)&sin, sizeof sin) == -1) {
      close(s);
      bbslog(0, "ERROR local_bbs_talk: bind failed\n");
      return S_SYSERR;
    }
    sinlen = sizeof sin;
    if (getsockname(s, (struct sockaddr *)&sin, &sinlen) == -1) {
      close(s);
      bbslog(0, "ERROR local_bbs_talk: getsockname failed\n");
      return S_SYSERR;
    }
    if (listen(s, 1) == -1) {
      close(s);
      bbslog(0, "ERROR local_bbs_talk: listen failed\n");
      return S_SYSERR;
    }

    set_real_mode(M_PAGE);
    utable_get_record(my_utable_slot(), &talk_mydata);
    talk_mydata.destpid = pid;
    talk_mydata.port = (SHORT)htons(sin.sin_port);
    utable_set_record(my_utable_slot(), &talk_mydata);
    talkfd = s;
      
    bbslog(4,"PAGE %s by %s\n",talk_theirdata.u.userid,talk_mydata.u.userid);
  }

/*
  if (kill(pid, SIGUSR1) == -1) {
*/
  if (kill(pid, SIGUSR2) == -1) {
    local_bbs_exit_talk();
    return S_SYSERR;
  }

  nfds = (talkfd > fd ? talkfd+1 : fd+1);
  while (1) {
    tv.tv_sec = PAGE_INTERVAL;
    tv.tv_usec = 0;
    FD_ZERO(&readfds);
    FD_SET(talkfd, &readfds);
    FD_SET(fd, &readfds);
    rc = select(nfds, &readfds, NULL, NULL, &tv);
    switch (rc) {
    case -1:
      if (errno != EINTR) {
	local_bbs_exit_talk();
        bbslog(0, "ERROR local_bbs_talk: select failed\n");
        return S_SYSERR;
      }
      break;
    case 0:
      return S_CMDTIMEOUT;
    default:
      if (FD_ISSET(talkfd, &readfds)) {
	int talksock;
        sinlen = sizeof sin;
	talksock = accept(talkfd, (struct sockaddr *)&sin, &sinlen);
        if (talksock == -1 || recv(talksock, cbuf, 1, 0) != 1) {
          local_bbs_exit_talk();
          bbslog(0, "ERROR local_bbs_talk: accept or recv failed\n");
	  return S_SYSERR;
	}
        if (cbuf[0] != 'y') {
	  local_bbs_exit_talk();
          bbslog(4, "PAGE REFUSED from %s by %s\n", 
		 talk_mydata.u.userid, talk_theirdata.u.userid);
	  return S_DENIED;
	}
        set_real_mode(M_TALK);
        utable_get_record(my_utable_slot(), &talk_mydata);
        talk_mydata.port = 0;

        /* Force pager's cloak setting to match pagee's cloak setting */
        if ((talk_mydata.u.flags & FLG_CLOAK) != 
            (talk_theirdata.u.flags & FLG_CLOAK)) {
          cloak_save = (talk_mydata.u.flags & FLG_CLOAK) ? 1 : -1;
          talk_mydata.u.flags ^= FLG_CLOAK;
        }
        utable_set_record(my_utable_slot(), &talk_mydata);
        bbslog(4, "PAGE ACCEPTED from %s by %s\n", 
	       talk_mydata.u.userid, talk_theirdata.u.userid);
	*sockp = (LONG)talksock;
	return S_OK;
      }        
      else if (FD_ISSET(fd, &readfds)) {
	int i, cc = read(fd, cbuf, sizeof cbuf);
        if (cc <= 0) {
	  local_bbs_exit_talk();
	  return S_SYSERR;
	}
        for (i=0; i<cc; i++) 
	  if (cbuf[i] == 3 || cbuf[i] == 4) {
	    local_bbs_exit_talk();
	    return S_DISABLED;
	  }
      }
    }
  }  
  /*NOTREACHED*/
  return 0;
}  
  
local_bbs_exit_talk()
{
  USERDATA udata;
  if (talkfd == -1) return S_OK;
  close(talkfd);
  talkfd = -1;
  utable_get_record(my_utable_slot(), &udata);
  udata.destpid = 0;
  udata.port = 0;
  if (cloak_save) {
    if (cloak_save > 0) udata.u.flags |= FLG_CLOAK;
    else udata.u.flags &= ~FLG_CLOAK;
    cloak_save = 0;
  }
  utable_set_record(my_utable_slot(), &udata);
  
  set_real_mode(M_UNDEFINED);
  return S_OK;
}  

/*ARGSUSED*/
_find_whos_paging(indx, udata, urec)
int indx;
USERDATA *udata;
USEREC *urec;
{
  if (udata->destpid == urec->pid && udata->port != 0) {
    memcpy(urec, &udata->u, sizeof(*urec));
    /* Kludge: pass port back in flags field. */
    urec->flags = udata->port;
    return ENUM_QUIT;
  }
  return S_OK;
}

local_bbs_get_talk_request(urec, paddr, pport)
USEREC *urec;
LONG *paddr;      /* may be NULL */
SHORT *pport;     /* may be NULL */
{
  memset(urec, 0, sizeof(*urec));
  urec->pid = getpid();
  utable_enumerate(0, NULL, _find_whos_paging, urec);
  if (urec->userid[0] == '\0') {
    urec->pid = 0;    
    return S_NOTFOUND;
  }      
  if (paddr) *paddr = (LONG)htonl(INADDR_LOOPBACK);
  if (pport) *pport = urec->flags;
  urec->flags = 0;
  return S_OK;
}

_get_answer_socket(addr, port, psock)
LONG addr;
SHORT port;
LONG *psock;
{
  int s;
  struct sockaddr_in sin;
  SHORT mymode;

  mymode = my_real_mode();
  if (mymode == M_CHAT || mymode == M_IRC || mymode == M_TALK) {
    return S_EXISTS;
  }

  if ((s = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
    return S_SYSERR;
  }
    
  memset(&sin, 0, sizeof sin);
  sin.sin_family = PF_INET;
  sin.sin_port = ntohs((unsigned short)port);
  sin.sin_addr.s_addr = (unsigned long)addr;

  if (connect(s, (struct sockaddr *)&sin, sizeof sin) == -1) {
    close(s);
    return S_SYSERR;
  }

  *psock = (LONG)s;
  return S_OK;
}  

local_bbs_refuse_page(addr, port)
LONG addr;
SHORT port;
{
  int rc, sock;
  char shaddup = 'n';
  rc = _get_answer_socket(addr, port, &sock);
  if (rc != S_OK) return rc;
  if (send(sock, &shaddup, 1, 0) != 1) return S_SYSERR;
  close(sock);
  return S_OK;
}

local_bbs_accept_page(addr, port, psock)
LONG addr;
SHORT port;
LONG *psock;
{
  int rc, sock;
  char talktome = 'y';
  rc = _get_answer_socket(addr, port, &sock);
  if (rc != S_OK) return rc;
  if (send(sock, &talktome, 1, 0) != 1) return S_SYSERR;
  set_real_mode(M_TALK);
  talkfd = sock;
  /* 
     (maybe) TODO: get destpid and port, set in utable record.
     Will have to do this before enum_users can return info about
     who is talking to whom.
  */     
  *psock = (LONG)sock;
  return S_OK;
}

/* Override list stuff */

#define OVERRIDE_FILE  "overrides"

get_override_file(userid, buf)
char *userid;
char *buf;
{
  get_home_directory(userid, buf);
  strcat(buf, "/");
  strcat(buf, OVERRIDE_FILE);
}

is_on_override_list(userid)
char *userid;
{
  PATH buf;
  get_override_file(userid, buf);
  if (_record_find(buf, _match_full, my_userid(), NULL, NULL) == S_OK) 
    return 1;
  else return 0;
}

local_bbs_set_overrides(list)
NAMELIST list;
{
  PATH buf;
  FILE *fp;
  get_override_file(my_userid(), buf);
  return (write_namelist(buf, list));
}

local_bbs_get_overrides(list)
NAMELIST *list;
{
  PATH buf;
  get_override_file(my_userid(), buf);
  return (read_namelist(buf, list));
}

/* Returns 1 if current user can page user, 0 if not */

has_page_permission(udata)
USERDATA *udata;
{
  int noovers, noothers;

  if (!_they_have_access(C_TALKACCEPT, udata->perms)) return 0;

  if (_has_perms(PERM_SYSOP)) return 1;

  noovers = udata->u.flags & FLG_NOOVERRIDE;
  noothers = udata->u.flags & FLG_NOPAGE;

  if (noovers && noothers) return 0;
  if (!noovers && !noothers) return 1;

  if (is_on_override_list(udata->u.userid)) {
    if (noovers) return 0;
  }
  else {
    if (noothers) return 0;
  }
  return 1;
}

#if FULL_USER_DELETE
/* For fixing override files when users get deleted or their names changed */

/*ARGSUSED*/
fix_override_entry(indx, rec, ncs)
int indx;
char *rec;
struct namechange *ncs;
{
  PATH overfile;
  NAME userid;

  /* Sleazy way to get the userid out of the passfile record */
  memset(userid, 0, sizeof userid);
  strncpy(userid, rec, NAMELEN);
  strip_trailing_space(userid);

  get_override_file(userid, overfile);
  
  if (ncs->newname == NULL)
    _record_delete(overfile, _match_full, ncs->oldname);
  else _record_replace(overfile, _match_full, ncs->oldname,
                       _change_name, ncs->newname);
  return S_OK;
}    
#endif
FLG_CLOAK) ? 1 : -1;
          talk_mydata.u.flags ^= FLG_CLOAK;
        }
        utable_set_record(my_utable_slot(), &talk_mydata);
        bbslog(4, "PAGE ACCEPTED from %s by %s\n", 
	       talk_mydata.u.userid, talk_theirdata.u.userid);
	*sockp = (LONG)talksock;
	return S_OK;
      }        
      else if (FD_ISSET(fd, &readfds)) {
	int i, cc = read(fd, cbuf, sizeof cbuf);
        if (cc <= 0) {
	  local_bbs_exit_talk();
	  return S_SYSERR;
	}
        for (i=0; i<cc;DarkNET-1.08/readmenu.c                                                                                644   21270   21270        30140  5741711301  10032                                                                                                                                                                                                                                                                                                                                                                      
/*
Eagles Bulletin Board System
Copyright (C) 1994, Ray Rocker, rrrocker@rock.b11.ingr.com
                                rock@seabass.st.usm.edu
                                72673.2105@compuserve.com

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

/*
   Adapted from Pirates BBS 1.8 "read.c"
   Copyright (C) 1990, Edward Luke, lush@Athena.EE.MsState.EDU
*/

#include "client.h"
#include <malloc.h>
#include <time.h>

#define MAIL_KEEP_NAME " $MAIL "

int BoardType;

extern READMENUITEM mailreadlist[], mainreadlist[], filereadlist[];

extern OpenMailbox(), CloseMailbox();
extern OpenBoard(), CloseBoard();
extern OpenFileBoard(), CloseFileBoard();
extern LONG get_count();

#define PUTCURS   move(4+locmem->crs_line-locmem->top_line,0);prints(">");
#define RMVCURS   move(4+locmem->crs_line-locmem->top_line,0);prints(" ");

HEADER *headers = NULL;

struct keeploc {
    int btype;
    char *key ;
    int top_line ;
    int crs_line ;
    struct keeploc *next ;
} ;

struct keeploc *
getkeep(btype,s,def_topline,def_cursline)
char *s ;
LONG def_topline, def_cursline;
{
  static struct keeploc *keeplist = NULL ;
  struct keeploc *p ;

  for(p = keeplist; p!= NULL; p = p->next) {
    if(p->btype == btype && !strcmp(s,p->key))
      return p ;
  }
  p = (struct keeploc *) malloc(sizeof (*p)) ;
  p->btype = btype;
  p->key = (char *) malloc(strlen(s)+1) ;
  strcpy(p->key,s) ;
  p->top_line = def_topline ;
  p->crs_line = def_cursline ;
  p->next = keeplist ;
  keeplist = p ;
  return p ;
}

void
fixkeep(locmem, maxline, def_lines)
struct keeploc *locmem;
int maxline;
int def_lines;
{
  if (maxline < locmem->top_line) {
    if ((locmem->top_line = maxline - def_lines) < 1)
      locmem->top_line = 1;
  }
  if (maxline < locmem->crs_line) locmem->crs_line = maxline;
}

MailMenuTitle()
{
  register int i, j;
  char buf[256];
  extern int lang;

  clear();
  move(0,0);
  if (lang) {
    prints("ÆíÁö ÀÐ±â ¸Þ´º\n");
    prints("(n)[´ÙÀ½ ÆíÁö]     (p)[ÀÌÀüÆíÁö]     (r)[ÀÐ±â]     (e)[³ª°¡±â]\n");
    prints("(<¹øÈ£>-<¸®ÅÏ>) ÁöÁ¤ÇÑ ¹øÈ£·Î °¡±â      ($) ¸¶Áö¸· ÆíÁö·Î    (h) µµ¿ò¸»\n");
    sprintf(buf, "  ENT Å©±â %-8s %-12s %-49s","  ¾ðÁ¦","  ´©°¡","  Á¦¸ñ");
  } else {
    prints("Interactive Read Menu                (FOR Mail)\n") ;
    prints("(n)ext Message     (p)revious Message     (r)ead Message     (e)xit Read Menu\n");  
    prints("(##<cr>) go to message ##      ($) go to last message     (h) Get Help Screen\n");
    sprintf(buf, "  ENT SIZE %-8s %-12s %-49s","Date","From","Subject") ;
  }
  for (i=strlen(buf), j=t_columns-1; i<j; i++)
    buf[i] = ' ';
  buf[i] = '\0';
  standout();
  prints("%s\n", buf);
  standend();
  clrtobot();
}

ReadMenuTitle()
{
  register int i, j;
  char buf[256];
  extern int lang;

  clear();
  move(0,0);
  if (lang) {
    prints("±ÛÀÐ±â                                             ÇöÀçº¸µå: '%s'\n",currboard) ;
    prints("(n)[´ÙÀ½ ±Û]     (p)[ÀÌÀü ±Û]     (r)[ÀÐ±â]     (e)[³ª°¡±â]\n");
    prints("(<¹øÈ£>-<¸®ÅÏ>) ÁöÁ¤ÇÑ ¹øÈ£·Î °¡±â      ($) ¸¶Áö¸· ±Û·Î    (h) µµ¿ò¸»\n");
    sprintf(buf, "  ENT Å©±â %-8s %-12s %-6s %-42s","  ¾ðÁ¦", "  ´©°¡", "Á¶È¸¼ö", "  Á¦¸ñ") ;
  } else {
    prints("Interactive Read Menu                              Current Board '%s'\n",currboard) ;
    prints("(n)ext Message     (p)revious Message     (r)ead Message     (e)xit Read Menu\n");
    prints("##<cr> go to message ##     <CTRL-P> post a message     (h) Get a HELP screen\n");
    sprintf(buf, "  ENT SIZE %-8s %-12s %-6s %-42s","Date", "Owner", "Read #", " Title") ;
  }
  for (i=strlen(buf), j=t_columns-1; i<j; i++)
    buf[i] = ' ';
  buf[i] = '\0';
  standout();
  prints("%s\n", buf);
  standend();
  clrtobot() ;
}

FileMenuTitle()
{
    clear();
    move(0,0);
    prints("Interactive Download Menu                          Current Board '%s'\n",currfileboard) ;
    prints("(n)ext File      (p)revious File      (v)iew File      (e)xit Download Menu\n");
    prints("##<cr> go to file ##          (r)ecieve file          (h) Get a HELP screen\n");
    prints("  ENT T  SIZE  %s\n","Filename") ;
    clrtobot() ;
}

struct get_recs_struct {
  SHORT want;
  SHORT got;
};

GetRecsFunc(indx, hdr, info)
int indx;
HEADER *hdr;
struct get_recs_struct *info;
{
  if (info->got >= info->want) return ENUM_QUIT;
  memcpy(&headers[info->got], hdr, sizeof(HEADER));
  info->got++;
  return S_OK;
}  

MenuGetRecords(first_line, num_lines)
int first_line, num_lines;
{
  int result;
  struct get_recs_struct gr;
  gr.want = (SHORT)num_lines;
  gr.got = 0;
  first_line--;
  result = bbs_enum_headers(gr.want, (SHORT)first_line, 0, GetRecsFunc, &gr);
  return (result == S_OK ? (int)gr.got : 0);
}

MenuDrawScreen(first_line, num_lines)
int first_line, num_lines;
{
  int i, k;
  char c;
  char buf[TITLELEN+40];
  char dir[256];
  char date[9];
  struct tm *tm;
  time_t clock;

  move(4,0) ;
  for (i=0; i<num_lines; i++) {
    if (BoardType == BOARD_FILE) {
      c = (BITISSET(headers[i].flags, FILE_BINARY) ? 'B' : 'A');
    } else {
      if (headers[i].flags & FILE_MARKED)
	c = (BITISSET(headers[i].flags, FILE_UNREAD) ? 'M' : 'm');
      else
	c = (BITISSET(headers[i].flags, FILE_UNREAD) ? 'N' : ' ');
    }

    clock = headers[i].mtime;
    tm = localtime(&clock);
    sprintf(date,"%2.2d/%2.2d/%2.2d", tm->tm_mon+1, tm->tm_mday, tm->tm_year%100);
    
    k = (headers[i].size + 512) / 1024;
    switch (BoardType) {
    case BOARD_FILE:
      sprintf(buf, " %4d %c %2dk %s", first_line+i, c, k, date, headers[i].title);  
      break;
    case BOARD_POST:
      sprintf(dir, "boards/%s", currboard);
      sprintf(buf, " %4d %c %2dk %-8s %-12s %4d %s", first_line+i, c, k, date,
	         headers[i].owner,
		 get_count(dir, headers[i].fileid),
		 headers[i].title);
      break;
    default:
      sprintf(buf, " %4d %c %2dk %-8s %-12s %s", first_line+i, c, k, date,
	         headers[i].owner, headers[i].title);
      break;
    }
    if(strlen(buf) >= 79) {
      buf[78] = '^' ;
      buf[79] = '\0' ;
    }
    prints("%s\n", buf) ;
  }
}

ReadMenu(openfn, closefn, fetchfn, titlefn, drawfn, keepname, rcmdlist)
int (*openfn)();
int (*closefn)();
int (*fetchfn)();
int (*titlefn)();
int (*drawfn)();
char *keepname;
READMENUITEM *rcmdlist;
{
  char lbuf[11];
  int lbc, i, ch;
  struct keeploc *locmem;
  int screen_len = t_lines - 5;
  int num_entries;
  int last_line;
  int openflags;
  int mode = DONOTHING;
  
  if (headers)
  {
    free (headers);
  }
  headers = (HEADER *)calloc(screen_len, sizeof(*headers));
  
  (*titlefn)();
  last_line = (*openfn)(&openflags, 0, NULL);
  if (last_line == -1) {
    c_msg(ERR_PERM, TRUE);
    return 0;
  }
  if(last_line == 0) {
    c_msg(ERR_NOTHING, TRUE);
    (*closefn)();
    return 0;
  }
  
  locmem = getkeep(BoardType, keepname,
	   (last_line-screen_len+1 < 1)?1:last_line-screen_len+1,last_line) ;
  
  fixkeep(locmem, last_line, screen_len-3);
  num_entries = (*fetchfn)(locmem->top_line, screen_len);
  (*drawfn)(locmem->top_line, num_entries);
  
  PUTCURS ;
  lbc = 0 ;
  while((ch = igetch()) != EOF) {
    if (PagePending()) {
      Answer();
      mode = FULLUPDATE;
      goto endofloop;
    }
    if(myisdigit(ch)) {
      if(lbc < 9)
	lbuf[lbc++] = ch ;
      goto endofloop ;
    }
    if(ch != '\n' && ch != '\r')
      lbc = 0 ;
    switch(ch) {
      int val ;
    case 'q':
    case 'e':
      mode = EXITMENU;
      break ;
    case '\n':
    case '\r':
      if(lbc == 0)
	break ;
      lbuf[lbc] = '\0' ;
      val = atoi(lbuf) ;
      lbc = 0 ;
      if(val > last_line)
	val = last_line ;
      if(val <= 0)
	val = 1 ;
      if(val >= locmem->top_line && val < locmem->top_line+screen_len) {
	RMVCURS ;
	locmem->crs_line = val ;
	PUTCURS ;
	continue ;
      }
      locmem->top_line = val - 10 ;
      if(locmem->top_line <= 0)
	locmem->top_line = 1 ;
      locmem->crs_line = val ;
      mode = PARTUPDATE | FETCHNEW;
      goto endofloop ;
    case 'p':
      if(locmem->crs_line == locmem->top_line) {
	if(locmem->crs_line == 1) {
	  bell() ;
	  break ;
	}
	locmem->top_line -= screen_len - 2 ;
	if(locmem->top_line <= 0)
	  locmem->top_line = 1 ;
	locmem->crs_line-- ;
	mode = PARTUPDATE | FETCHNEW;
	break ;
      }
      RMVCURS ;
      locmem->crs_line-- ;
      PUTCURS ;
      break ;
    case CTRL('L'):
      redoscr() ;
      break ;
    case 'n':
      if(locmem->crs_line == last_line) {
	bell() ;
	break ;
      }
      if(locmem->crs_line+1 == locmem->top_line+screen_len) {
	locmem->top_line += screen_len - 2 ;
	locmem->crs_line++ ;
	mode = PARTUPDATE | FETCHNEW;
	break ;
      }
      RMVCURS ;
      locmem->crs_line++ ;
      PUTCURS ;
      break ;
    case 'N':
      if(locmem->top_line + screen_len - 1 >= last_line) {
	bell() ;
	break ;
      }
      locmem->top_line += screen_len - 1 ;
      locmem->crs_line = locmem->top_line ;
      mode = PARTUPDATE | FETCHNEW;
      break ;
    case 'P':
      if(locmem->top_line == 1) {
	bell() ;
	break ;
      }
      locmem->top_line -= screen_len - 1 ;
      if(locmem->top_line <= 0)
	locmem->top_line = 1 ;
      locmem->crs_line = locmem->top_line ;
      mode = PARTUPDATE | FETCHNEW;
      break ;
    case '$':
      if(last_line < locmem->top_line + screen_len) {
	RMVCURS ;
	locmem->crs_line = last_line ;
	PUTCURS ;
	break ;
      }
      locmem->top_line = last_line - screen_len + 1 ;
      if(locmem->top_line <= 0)
	locmem->top_line = 1 ;
      locmem->crs_line = last_line ;
      mode = PARTUPDATE | FETCHNEW;
      break ;
    default:
      for(i = 0; rcmdlist[i].cmdfunc != NULL; i++) {
	if(rcmdlist[i].cmdkey == ch && 
           HasReadMenuPerm(rcmdlist[i].openaccess, openflags) &&
	   HasPerm(rcmdlist[i].permaccess)) {
	  mode = (*(rcmdlist[i].cmdfunc))
	    (&headers[locmem->crs_line - locmem->top_line],
	     locmem->crs_line, last_line, openflags);
	  break ;
	}
      }
      if(rcmdlist[i].cmdfunc == NULL)
	bell();
      break ;
    }
  endofloop:
    if (mode & (FETCHNEW | NEWDIRECT)) {
      if (mode & NEWDIRECT) (*closefn)();
      last_line = (*openfn)(&openflags, 0, NULL);
      if (mode & NEWDIRECT)
	locmem = getkeep(BoardType, keepname,
			 (last_line-screen_len < 1)?1:last_line-screen_len+1,
			 last_line) ;
      fixkeep(locmem, last_line, screen_len-3);
      num_entries = (*fetchfn)(locmem->top_line, screen_len);
    }
    if (mode & (FULLUPDATE | PARTUPDATE)) {
      if (mode & FULLUPDATE) {
	clear() ;
	(*titlefn)();
      }
      if(last_line <= 0) {
	c_msg(ERR_NOTHING, TRUE);
	num_entries = 0 ;
	break;
      }
      (*drawfn)(locmem->top_line, num_entries);
      if(locmem->crs_line > last_line)
	locmem->crs_line = last_line ;
      clrtobot() ;
      PUTCURS ;
    }
    if(mode == EXITMENU || num_entries == 0)
      break ;
    mode = DONOTHING ;
  }
  (*closefn)();
  clear() ;
  return 0;
}

MailRead()
{
  BoardType = BOARD_MAIL;
  bbs_set_mode(M_MAIL);
  ReadMenu(OpenMailbox, CloseMailbox, MenuGetRecords, MailMenuTitle, 
	   MenuDrawScreen, MAIL_KEEP_NAME, mailreadlist);
  bbs_set_mode(M_UNDEFINED);  
  return PARTUPDATE;
}

MainRead()
{
  extern int lang;

  if (*currboard == '\0')
    {
      move(2,0);
      clrtobot();
      move(3,0);
      c_msg(ERR_NOT_SELECTED, TRUE);
    }
  else
    {
      BoardType = BOARD_POST;
      bbs_set_mode(M_READING);
      ReadMenu(OpenBoard, CloseBoard, MenuGetRecords, ReadMenuTitle,
		MenuDrawScreen, currboard, mainreadlist);
      bbs_set_mode(M_UNDEFINED);
    }
  return PARTUPDATE;
}

FileDownload()
{
  if (*currfileboard == '\0') {
    move(2,0);
    clrtobot();
    move(3,0);
    c_msg(ERR_NOT_SELECTED, TRUE);
  }
  else {
    BoardType = BOARD_FILE;
    ReadMenu(OpenFileBoard, CloseFileBoard, MenuGetRecords, FileMenuTitle,
    	     MenuDrawScreen, currfileboard, filereadlist);
  }
  return PARTUPDATE;
}
j; i++)
    buf[i] = ' ';
  buf[i] = '\0';
  standout();
  prints("%s\n", buf);
  standend();
  clrtobot() ;
}

FileMenuTitle()
{
    clear();
    move(0,0);
    prints("Interactive Download Menu                          Current Board '%s'\n",currfileboard) ;
    prints("(n)ext File      (p)revious File      (v)iew File      (e)xit Download Menu\n");
    prints("##<cr> go to file ##          (r)ecieve file       DarkNET-1.08/readnew.c                                                                                 644   21270   21270        17106  5743111102   7661                                                                                                                                                                                                                                                                                                                                                                      
/*
Eagles Bulletin Board System
Copyright (C) 1994, Ray Rocker, rrrocker@rock.b11.ingr.com
                                rock@seabass.st.usm.edu
                                72673.2105@compuserve.com

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "client.h"

/* Flags for Read New */
#define NEW_READ	001
#define NEW_PASS	002
#define NEW_SKIP	004
#define NEW_VISIT       010
#define NEW_QUIT	020

/* Are we reading mail or posts? */
#define FILE_TYPE_MAIL	1
#define FILE_TYPE_POST	2

extern int OpenMailbox(), CloseMailbox(), MailDisplay();
extern int CloseMailbox(), CloseBoard(), PostDisplay();
extern char *Ctime();

struct readnewstruct {
  int nummsgs;
  int numread;
  int openflags;
  int dispflags;
  int excode;
  char *thread;
};

ReadNewMessage(type, hptr, numleft, options, openflags)
int type;
HEADER *hptr;
int numleft;
int options;
int openflags;
{
  char ans[2], promptstr[80];
  extern int lang;

  clear();
  if (numleft > 0) {
    if (type == FILE_TYPE_MAIL) {
      if (lang)
	prints("[»õÆíÁö %d °³°¡ ³²¾Ò½À´Ï´Ù]\n", numleft);
      else
	prints("[%d new mail message%s left]\n", numleft, numleft==1?"":"s");
    } else {
      if (lang)
	prints("[»õ±Û %d °³°¡ '%s' º¸µå¿¡ ³²¾Ò½À´Ï´Ù]\n", numleft, currboard);
      else
	prints("[%d new message%s left on board '%s']\n", numleft, numleft==1?"":"s", currboard);
    }
  }

  if (lang) {
    prints("%s:%s (½Ã°£:%s) (%d ¹ÙÀÌÆ®)\n", 
	 (type == FILE_TYPE_MAIL ? "ÆíÁö¹ß¼ÛÀÎ" : "±Û¾´ÀÌ"),
	 hptr->owner, Ctime((time_t *)&hptr->mtime), hptr->size);
    prints("Á¦¸ñ: %s", hptr->title);

    strcpy(promptstr, "[R]-ÀÐ±â, [P]-³Ñ¾î°¡, ");
    if (BITISSET(options, NEW_SKIP)) strcat(promptstr, "[S]-´ÙÀ½º¸µå·Î, ");
    if (BITISSET(options, NEW_VISIT)) strcat(promptstr, "[V]-ÀÐÀº°É·Î, ");
    strcat(promptstr, " [Q]-³¡? [R]: ");

  } else {
    prints("%s %s on %s (%d bytes)\n", 
	 (type == FILE_TYPE_MAIL ? "Mail from" : "Posted by"),
	 hptr->owner, Ctime((time_t *)&hptr->mtime), hptr->size);
    prints("Subject: %s", hptr->title);

    strcpy(promptstr, "Read, Pass, ");
    if (BITISSET(options, NEW_SKIP)) strcat(promptstr, "SkipBoard, ");
    if (BITISSET(options, NEW_VISIT)) strcat(promptstr, "Visit, ");
    strcat(promptstr, "or Quit? [R]: ");

  }
  
  getdata(3, 0, promptstr, ans, sizeof(ans), DOECHO, 0);
  
  if (*ans == 'Q' || *ans == 'q')
    return NEW_QUIT;
  if (*ans == 'P' || *ans == 'p')
    return NEW_PASS;
  if (BITISSET(options, NEW_SKIP) && (*ans == 'S' || *ans == 's'))
    return NEW_SKIP;
  if (BITISSET(options, NEW_VISIT) && (*ans == 'V' || *ans == 'v'))
    return NEW_VISIT;
  
  if (type == FILE_TYPE_MAIL) MailDisplay(hptr, 0, 0, openflags);
  else if (type == FILE_TYPE_POST) PostDisplay(hptr, 0, 0, openflags);
  return NEW_READ;
}

NewMailReadfn(indx, hdr, info)
int indx;
HEADER *hdr;
struct readnewstruct *info;
{
  info->excode = ReadNewMessage(FILE_TYPE_MAIL, hdr, info->nummsgs,
                                  0,info->openflags);
  if (info->nummsgs > 0) info->nummsgs--;
  if (info->excode == NEW_QUIT) return ENUM_QUIT;
  return S_OK;
}  

ReadNewMail()
{
  struct readnewstruct rns;
  int servresp;
  clear();
  bbs_set_mode(M_MAIL);
  rns.nummsgs = OpenMailbox(&rns.openflags, 1, &servresp);
  if (servresp != S_OK) {
    c_msg(ERR_FILE, TRUE);
    pressreturn();
  } else if (rns.nummsgs == 0) {
    c_msg(ERR_NOTHING, TRUE);
    CloseMailbox();
    pressreturn();
  } else {
    bbs_enum_headers(10, 0, 1, NewMailReadfn, &rns);
    CloseMailbox();
  }
  bbs_set_mode(M_UNDEFINED);
  return FULLUPDATE;
}

IsSameThread(title1, title2)
char *title1;
char *title2;
{
  /* Function to see if two posts are in the same thread */
  if (!strncasecmp(title1, "Re: ", 4)) title1 += 4;
  if (!strncasecmp(title2, "Re: ", 4)) title2 += 4;
  return (!strcasecmp(title1, title2));
}    

NewPostReadfn(indx, hdr, info)
int indx;
HEADER *hdr;
struct readnewstruct *info;
{
  if (info->thread != NULL && !IsSameThread(info->thread, hdr->title)) {
    info->excode = NEW_PASS;      
  }
  else {
    info->excode = ReadNewMessage(FILE_TYPE_POST, hdr, info->nummsgs,
                                info->dispflags, info->openflags);
    if (info->nummsgs > 0) info->nummsgs--;
  }

  if (info->excode == NEW_READ) (info->numread)++;
  if (info->excode == NEW_QUIT || info->excode == NEW_VISIT ||
      info->excode == NEW_SKIP) return ENUM_QUIT;

  return S_OK;
}  

/*ARGSUSED*/
SequentialRead(hptr, currmsg, numrecs, openflags)
HEADER *hptr;
int currmsg, numrecs, openflags;
{
  char ans[7];
  TITLE threadtitle;
  struct readnewstruct rns;
  extern int lang;

  rns.nummsgs = -1;
  rns.numread = 0;
  rns.openflags = openflags;
  rns.dispflags = NEW_VISIT;
  clear();

  if (lang) {
    if (getdata(0, 0, "(N)-»õ±ÛÀÐ±â / (F)-ÇöÀç ±Û thread ÂÉÂ÷°¡±â? [N]: ",
          ans, sizeof ans, DOECHO, 1) == -1) return FULLUPDATE;
  } else {
    if (getdata(0, 0, "Read (N)ew messages or (F)ollow current thread? [N]: ",
          ans, sizeof ans, DOECHO, 1) == -1) return FULLUPDATE;
  }
    
  if (*ans == 'F' || *ans == 'f') {
    strncpy(threadtitle, hptr->title, sizeof threadtitle);
    rns.thread = threadtitle;
  }
  else rns.thread = NULL;

  if (currmsg) currmsg--;
  bbs_enum_headers(10, currmsg, rns.thread==NULL?1:0, NewPostReadfn, &rns);
  if (rns.excode == NEW_VISIT) {
    rns.numread++;  /* to force FETCHNEW */
    bbs_visit_board(currboard);
  }
  return (rns.numread ? (FULLUPDATE | FETCHNEW) : FULLUPDATE);
}

/*ARGSUSED*/
ReadNewPosts(indx, board, disp)
int indx;
BOARD *board;
int *disp;
{
  int openflags, newmsgs;
  struct readnewstruct rns;
  char msgbuf[80], ans[4];
  static int i;

  clear();
  move(t_lines/2, t_columns/2-2);
/*
  c_msg(INFO_SCANNING, FALSE);
  prints (" [%s]", board->name);
*/
  switch (i) {
  case 0:
    prints("----");
    i++;
    break;
  case 1:
    prints("\\\\\\\\");
    i++;
    break;
  case 2:
    prints("||||");
    i++;
    break;
  case 3:
    prints("////");
    i = 0;
    break;
  }
  refresh();

  memset(currboard, '\0', sizeof currboard);
  strncpy(currboard, board->name, sizeof currboard);
  newmsgs = OpenBoard(&openflags, 1, NULL);
  if (newmsgs > 0) {
    rns.nummsgs = newmsgs;
    rns.numread = 0;
    rns.openflags = openflags;
    rns.dispflags = NEW_SKIP | NEW_VISIT;
    rns.thread = NULL;
    bbs_enum_headers(10, 0, 1, NewPostReadfn, &rns);
     *disp = rns.excode;
    if (*disp == NEW_VISIT) {
      bbs_visit_board(currboard);
    }
  }
  CloseBoard();
  return (*disp == NEW_QUIT ? ENUM_QUIT : S_OK);
}

ReadNew()
{
  NAME savecurr;
  int disp = NEW_READ;
  extern int lang;
  
  bbs_set_mode(M_READING);  

  /* Save the currboard, 'cuz we're gonna meddle with it */
  strcpy(savecurr, currboard);
  
  /* Now read the unzapped boards in sequence */
  clear();
  move(t_lines/2, t_columns/2-10);
  c_msg(INFO_SCANNING, FALSE);
  refresh();

  bbs_enum_boards(10, 0, BE_UNZAPPED, ReadNewPosts, &disp);

  clear();
  if (disp == NEW_QUIT)
      c_msg(INFO_QUIT, TRUE);
  else
      c_msg(INFO_DONE, TRUE);

  /* restore currbrd */
  strcpy(currboard, savecurr);
  bbs_set_mode(M_UNDEFINED);
  pressreturn();
  return FULLUPDATE;
}
*)&hptr->mtime), hptr->size);
    prints("Á¦¸ñ: %s", hptr->title);

    strcpy(promptstr, "[R]-ÀÐ±â, [P]-³Ñ¾î°¡, ");
    if (BITISSET(options, NEW_SKIP)) strcat(promptstr, "[S]-´ÙÀ½º¸µå·Î, ");
    if (BITISSET(options, NEW_VISIT)) strcat(promptstr, "[V]-ÀÐÀº°É·Î, ");
    strcat(promptstr, " [Q]-³¡? [R]: ");

  } else {
    prints("%s %s on %s (%d bytes)\n", 
	 (type == FILE_TYPE_MAIL ? "Mail from" : "Posted by"),
	 hptr->owner, Ctime((timDarkNET-1.08/record.c                                                                                  644   21270   21270        15516  5747644656   7552                                                                                                                                                                                                                                                                                                                                                                      
/*
Eagles Bulletin Board System
Copyright (C) 1994, Ray Rocker, rrrocker@rock.b11.ingr.com
                                rock@seabass.st.usm.edu
                                72673.2105@compuserve.com

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/


#include "server.h"
#include <ctype.h>
#include <unistd.h>

#if NO_FLOCK == 1
# define LOCK(fp)   lockf(fileno(fp), F_LOCK, 0)
# define UNLOCK(fp) lockf(fileno(fp), F_ULOCK, 0)
#else
# include <sys/file.h> 
# define LOCK(fp)   flock(fileno(fp), LOCK_EX)
# define UNLOCK(fp) flock(fileno(fp), LOCK_UN)
#endif

/*
#define IS_COMMENT(s) (*s == '#' || isspace(*s))
*/
#define IS_COMMENT(s) (*s == '#' || myisspace(*s))

#define BBS_MAX_RECORD 4096

_match_first(rec, fld)
char *rec;
char *fld;
{
  register char c1, c2;
  while (*fld) {
    c1 = *fld++;
    c2 = *rec++;
    if (c1 == c2) continue;
    if (myislower(c1)) c1 = toupper(c1);
    if (myislower(c2)) c2 = toupper(c2);
    if (c1 != c2) return S_OK;
  }
  return ((*rec == ' ' || *rec == ':') ? S_EXISTS : S_OK);
}

_match_full(rec, fld)
char *rec;
char *fld;
{
  register char c1, c2;
  while (*fld) {
    c1 = *fld++;
    c2 = *rec++;
    if (c1 == c2) continue;
    if (myislower(c1)) c1 = toupper(c1);
    if (myislower(c2)) c2 = toupper(c2);
    if (c1 != c2) return S_OK;
  }
  return ((*rec == '\n' || *rec == '\0') ? S_EXISTS : S_OK);
}

/*ARGSUSED*/
_change_name(newrec, oldrec, newname)
char *newrec;
char *oldrec;
char *newname;
{
  sprintf(newrec, "%s\n", newname);
  return S_OK;
}

char *
_append_quoted(rec, str)
char *rec;
char *str;
{
  while (*str) {
    if (*str == ':' || *str == '\\') *rec++ = '\\';
    *rec++ = *str++;
  }
  *rec++ = ':';
  *rec = '\0';
  return rec;
}

char *
_extract_quoted(rec, str, len)
char *rec;
char *str;
int len;
{
  len--;    /* leave space for terminating null */
  while (*rec != ':' && *rec != '\n' && *rec != '\0') {
    if (*rec == '\\') rec++;
    if (len) {
      *str++ = *rec;
      len--;
    }
    rec++;
  }
  *str = '\0';
  if (*rec == ':') rec++;
  return rec;
}

_record_add(fname, testf, targ, formatf, farg)
char *fname;
int (*testf)();
void *targ;
int (*formatf)();
void *farg;
{
  FILE *fp;
  char rec[BBS_MAX_RECORD];
  int rc;

  if ((fp = fopen(fname, "r+")) == NULL) {
    if ((fp = fopen(fname, "w")) == NULL) {
      return S_SYSERR;
    }
  }

  LOCK(fp);        
  
  if (testf) {
    while (fgets(rec, sizeof rec, fp)) {
      if (IS_COMMENT(rec)) continue;
      rc = testf(rec, targ);
      if (rc != S_OK) {
        UNLOCK(fp);
        fclose(fp);
        return rc;
      }
    }
  }

  rc = formatf(rec, farg);
  if (rc != S_OK) {
    UNLOCK(fp);
    fclose(fp);
    return rc;
  }

  fseek(fp, 0, SEEK_END);
  fputs(rec, fp);
  UNLOCK(fp);
  fclose(fp);
  return S_OK;
}      

_do_record_delete(fname, testf, targ, single)
char *fname;
int (*testf)();
void *targ;
int single;
{
  FILE *fp;
  char rec[BBS_MAX_RECORD];
  int rc, len;
  unsigned delsz = 0, savesz = 0;

  if ((fp = fopen(fname, "r+")) == NULL) {
    return S_NOTFOUND;
  }

  LOCK(fp);        
  
  while (fgets(rec, sizeof rec, fp)) {
    len = strlen(rec);

    if (IS_COMMENT(rec) || (single && delsz)) rc = S_OK;
    else rc = testf(rec, targ);

    if (rc == S_OK) {
      savesz += len;
      if (delsz) {
        fseek(fp, -(delsz+len), SEEK_CUR);
        fputs(rec, fp);
        fseek(fp, delsz, SEEK_CUR);
      }        
    }
    else {
      delsz += len;
    }
  }                        

  if (savesz == 0) unlink(fname);
  else if (delsz) ftruncate(fileno(fp), savesz);
  UNLOCK(fp);
  fclose(fp);
  return (delsz ? S_OK : S_NOTFOUND);
}      

_record_delete(fname, testf, targ)
char *fname;
int (*testf)();
void *targ;
{
  return (_do_record_delete(fname, testf, targ, 1));
}

_record_delete_many(fname, testf, targ)
char *fname;
int (*testf)();
void *targ;
{
  return (_do_record_delete(fname, testf, targ, 0));
}

_record_find(fname, testf, targ, formatf, farg)
char *fname;
int (*testf)();
void *targ;
int (*formatf)();
void *farg;
{
  FILE *fp;
  char rec[BBS_MAX_RECORD];
  int rc;

  if ((fp = fopen(fname, "r")) == NULL) {
    return S_NOTFOUND;
  }

  while (fgets(rec, sizeof rec, fp)) {
    if (IS_COMMENT(rec)) continue;
    rc = testf(rec, targ);
    if (rc != S_OK) {
      if (formatf) rc = formatf(rec, farg);
      else rc = S_OK;
      fclose(fp);
      return rc;
    }
  }

  fclose(fp);
  return S_NOTFOUND;
}      

_record_enumerate(fname, start, enumf, earg)
char *fname;
int start;
int (*enumf)();
void *earg;
{
  FILE *fp;
  char rec[BBS_MAX_RECORD];
  int indx = 0;

  if ((fp = fopen(fname, "r")) == NULL) {
    return 0;
  }

  while (fgets(rec, sizeof rec, fp)) {
    if (IS_COMMENT(rec)) continue;
    if (indx >= start) {
      if (enumf(indx, rec, earg) == ENUM_QUIT) break;
    }
    indx++;
  }

  fclose(fp);
  return indx;
}      

/* This is one UGLY function, but it's as neat as I can make it! */

_record_replace(fname, testf, targ, replf, rarg)
char *fname;
int (*testf)();
void *targ;
int (*replf)();
void *rarg;
{
  FILE *fp;
  char rec[BBS_MAX_RECORD];
  char newrec[BBS_MAX_RECORD];
  char scratch[BBS_MAX_RECORD];
  int rc = S_OK, len, newlen, difflen, chunk;
  int savesz = 0;

  if ((fp = fopen(fname, "r+")) == NULL) {
    return S_NOTFOUND;
  }

  LOCK(fp);        
  
  while (rc == S_OK && fgets(rec, sizeof rec, fp)) {
    len = strlen(rec);

    if (IS_COMMENT(rec)) rc = S_OK;
    else rc = testf(rec, targ);

    if (rc == S_OK) savesz += len;
  }

  if (rc == S_OK) {
    UNLOCK(fp);
    fclose(fp);
    return S_NOTFOUND;
  }

  rc = replf(newrec, rec, rarg);
  if (rc != S_OK) {
    UNLOCK(fp);
    fclose(fp);
    return rc;  
  }
  newlen = strlen(newrec);
  difflen = len - newlen;
  
  if (difflen) chunk = fread(rec, 1, sizeof rec, fp);
  else chunk = 0;

  fseek(fp, -(chunk+len), SEEK_CUR);
  fputs(newrec, fp);

  if (difflen) {
    savesz += newlen;
    while (chunk) {
      len = chunk+difflen;
      newlen = chunk;
      memcpy(scratch, rec, chunk);

      if (len > 0) {
        fseek(fp, len, SEEK_CUR);
        chunk = fread(rec, 1, sizeof rec, fp);
      }
      else chunk = len = 0;
      
      fseek(fp, -(chunk+len), SEEK_CUR);
      fwrite(scratch, 1, newlen, fp);                
      savesz += newlen;
    }      
    ftruncate(fileno(fp), savesz);
  }

  UNLOCK(fp);
  fclose(fp);
  return S_OK;
}      

r(c2);
    if (c1 != c2) return S_OK;
  }
  return ((*rec == '\n' || *rec == '\0') ? S_EXISTS : S_OK);
}

/*ARGSUSED*/
_change_name(newrec, oldrec, newname)
char *newrec;
char *oDarkNET-1.08/retval.h                                                                                  644   21270   21270         3123  5715564001   7521                                                                                                                                                                                                                                                                                                                                                                      
/*
Eagles Bulletin Board System
Copyright (C) 1994, Ray Rocker, rrrocker@rock.b11.ingr.com
                                rock@seabass.st.usm.edu
                                72673.2105@compuserve.com

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/


/*
   Return values for the bbs library functions. Used all over in the server.
*/

#define S_OK		0
#define S_SYSERR	1
#define S_DENIED	2
#define S_NOTFOUND	3
#define S_EXISTS	4
#define S_INVALID       5
#define S_FULL          6
#define S_NOUPDATE      7
#define S_DISABLED      8
#define S_UNAVAILABLE   9
#define S_ILLEGAL       10
#define S_TEMPFAIL      11
#define S_BADPACKET     12
#define S_TIMEOUT       13
#define S_CMDTIMEOUT    14
#define S_BADPATH       15

#define S_GETFILE       101
#define S_PUTFILE       102

/* 
   ENUM_QUIT is never returned by the library functions, but is to be
   returned by the functions called by the enumeration-type library
   functions when they want to quit enumerating.
*/

#define ENUM_QUIT	666


                                                                                                                                                                                                                                                                                                                                                                                                                                             DarkNET-1.08/server.h                                                                                  644   21270   21270        10716  5715564072   7570                                                                                                                                                                                                                                                                                                                                                                      
/*
Eagles Bulletin Board System
Copyright (C) 1994, Ray Rocker, rrrocker@rock.b11.ingr.com
                                rock@seabass.st.usm.edu
                                72673.2105@compuserve.com

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/


#include "common.h"
#include "perms.h"

/* 
   Header file of stuff just of use to the server side, which is for now
   just libbbs. 
*/

#define SERVER_VERSION_MAJ	0
#define SERVER_VERSION_MIN	1

/* This userid owns posts/mail that have no headers */

#define SYSOP_ACCOUNT "SYSOP"

typedef struct _USERDATA {
  USEREC u;
  LONG perms;
  ACCESSCODES access;
  int newmailmsgs;     /* easy (You have mail.) checking */
  SHORT usermode;
  SHORT port;          /* this and destpid are for Talk */
  LONG destpid;        /* this tells who I am paging */
} USERDATA;

typedef struct _SERVERDATA {
  BBSNAME name;
  PATH logfile;
  PATH tempfile;
  PATH mailbin;
  PATH encodebin;
  int maxusers;
  int maxutable;
  int newok;
  int loglevel;
  int maxlogons;
  int idletimeout;
  int maxsiglines;
  int queryreal;
} SERVERDATA;

#define LOG_LEVEL_MAX     10
#define LOG_LEVEL_DEFAULT 1

/* 
   Maximum number of files per board. Be careful not to extend this beyond
   BBS_MAX_RECORD in record.c! The readbits files will break things if so.
*/

#define BBS_MAX_FILES  2048

#define READBITSIZE BBS_MAX_FILES   /* future plan: BBS_MAX_FILES / 8 */

typedef struct _READINFO {
  LONG stamp;
  char bits[READBITSIZE];
} READINFO;
  
/*
   Read order is not implemented at this time, but it can be added later
   without ill effect.
*/

#define READ_ORDER_ZAPPED     0xffff   /* means board is zapped */
#define READ_ORDER_UNSET      0x0000   /* not zapped, or unzapped */

struct enumstruct {
  int (*fn)();
  void *arg;
  SHORT flags;
};

struct namechange {
  char *oldname;
  char *newname;
};

/* This mask must encompass all the MOD_* flags for account in common.h */
#define MOD_ACCOUNT_MASK 0x0FFF

#define _MOD_PERMS     0x8000
#define _TOGGLE_FLAGS  0x4000
#define _TOGGLE_FLAG   0x2000

/* Server stuff for chat. */
#define PATH_CHATD     "bin/chatd"
#define PATH_CHATPORT  "etc/.chatport"
#define PATH_CHATPID   "etc/.chatpid"

/* Are we an ordinary program or bbsd? */
#define BBSLIB_DEFAULT  0
#define BBSLIB_BBSD     1
extern int bbslib_user;

int _match_first __P((char *, char *));
int _match_full __P((char *, char *));
int _change_name __P((char *, char *, char *));
char *_append_quoted __P((char *, char *));
char *_extract_quoted __P((char *, char *, int));
int _record_add __P((char *, int(), void *, int(), void *));
int _record_delete __P((char *, int(), void *));
int _record_delete_many __P((char *, int(), void *));
int _record_find __P((char *, int(), void *, int(), void *));
int _record_enumerate __P((char *, int, int(), void *));
int _record_replace __P((char *, int(), void *, int(), void *));

int get_bitfile_ent __P((char *, READINFO *));
int set_bitfile_ent __P((char *, READINFO *));
int clear_all_readbits __P((READINFO *));
int set_readbit __P((READINFO *, SHORT));
int test_readbit __P((READINFO *, SHORT));

#if NO_SHARED_MEMORY
# define utable_attach f_utable_attach
# define utable_detach f_utable_detach
# define utable_lock_record f_utable_lock_record
# define utable_free_record f_utable_free_record
# define utable_get_record f_utable_get_record
# define utable_set_record f_utable_set_record
# define utable_find_record f_utable_find_record
# define utable_enumerate f_utable_enumerate
#endif

int utable_attach __P((int));
int utable_detach __P((int));
int utable_lock_record __P((int *));
int utable_free_record __P((int));
int utable_get_record __P((int, USERDATA *));
int utable_set_record __P((int, USERDATA *));
int utable_find_record __P((LONG, USERDATA *));
int utable_enumerate __P((int, char *, int(), void *));

SHORT my_real_mode __P((void));
char *my_userid __P((void));
char *my_username __P((void));
char *my_host __P((void));

TH logfile;
  PATH tempfile;
  PATH mailbin;
  PATDarkNET-1.08/system.c                                                                                  644   21270   21270        23603  5751542010   7564                                                                                                                                                                                                                                                                                                                                                                      
/*
Eagles Bulletin Board System
Copyright (C) 1994, Ray Rocker, rrrocker@rock.b11.ingr.com
                                rock@seabass.st.usm.edu
                                72673.2105@compuserve.com

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "client.h"
#include <string.h>
#include <fcntl.h>
#include <time.h>

#if REMOTE_CLIENT
extern char *editor;
extern char *pager;
extern char *shell;
#endif

static char *day_of_week[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
static char *mon_of_year[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};

ShowDate()
{
  time_t now;
  extern int lang;
  extern char *Ctime __P((time_t *));

  move(2,0);
  clrtobot();
  move(3,0);

  time(&now);

  if (lang)
    prints("ÇöÀç ½Ã°£: %s", Ctime(&now));
  else
    prints("Date and time on this system: %s", Ctime(&now));
  return PARTUPDATE;
}

/* 
   The builtin more should be improved a bit. I decided to leave it
   non-configurable because (a) no one has complained loudly, and (b)
   why bother with all that forking and execing when reading posts.
*/

More(filename, promptend)
char *filename;
int promptend; 
{
  return (more(filename, promptend));
}

#if !REMOTE_CLIENT
SelectEditor()
{
  NAME editorname;
  NAMELIST editorlist = NULL;
  extern LOGININFO myinfo;
  extern int lang;

  move(2,0);
  clrtobot();
  bbs_enum_editors(&editorlist);
  if (editorlist == NULL) {
    c_msg(ERR_NOTHING, TRUE);
    pressreturn();
    return FULLUPDATE;
  }

  if (lang)
    namecomplete(editorlist, "ÆíÁý±â¸¦ °í¸£¼¼¿ä: ", editorname);
  else
    namecomplete(editorlist, "Select editor: ", editorname);

  if (editorname[0] == '\0') return FULLUPDATE;
  else if (!is_in_namelist(editorlist, editorname)) {
    move(4,0);
    c_msg(ERR_NOT_EXIST, TRUE);
    free_namelist(&editorlist);
    pressreturn();
    return FULLUPDATE;
  }
  if (*editorname)
    strcpy(myinfo.editor, editorname);
  else
    strcpy(myinfo.editor, "builtin");
  bbs_set_editor(editorname);
  free_namelist(&editorlist);
  return FULLUPDATE;
}
#endif

Edit(filename)
char *filename;
{
  int rc;
  int done = 0;
#if !REMOTE_CLIENT
  ACCOUNT acct;
  PATH editbin;
  PATH editorenv;
  PATH execbuf;
  char ans[2];

  acct.editor[0] = '\0';
  bbs_owninfo(&acct);
  if (acct.editor[0] != '\0') {
    if (bbs_get_editor(acct.editor, editbin, editorenv) == S_OK) {
      extern int lang;

      sprintf(editorenv, "TERM=%s", acct.terminal);
      if (editorenv[0] != '\0') parse_environment(editorenv);
      if (strcmp(acct.editor, "PICO") == 0 || strcmp(acct.editor, "pico") == 0) {
	if (lang)
          sprintf(execbuf, "%s -t -k %s", editbin, filename);
	else
          sprintf(execbuf, "%s -t %s", editbin, filename);
      } else {
        if (strcmp(acct.editor, "VI") == 0 || strcmp(acct.editor, "vi") == 0) {
          sprintf(execbuf, "%s -s %s", editbin, filename);
	} else {
          sprintf(execbuf, "%s %s", editbin, filename);
	}
      }
      while (!done) {
	bbs_set_mode(1);    /* Magic value to block paging */
	rc = do_exec(execbuf, NULL, 0);
	bbs_set_mode(0);    /* Magic value to allow paging */
	clear();
	if (rc) {
	  c_msg(ERR_EXEC, TRUE);
	  unlink (filename);
	  pressreturn();
	  return (rc);
	}
	if (lang)
	  getdata(0,0,"(S)°¥¹«¸®, (A)Ãë¼Ò, (E)ÆíÁý? [S]: ",ans,sizeof(ans),DOECHO,0);
	else
	  getdata(0,0,"(S)ave, (A)bort, (E)dit? [S]: ",ans,sizeof(ans),DOECHO,0);
	switch (ans[0]) {
	case 'E': case 'e':
	  break;
	case 'A': case 'a':
	  unlink(filename);
	  rc = 1;
	  done = 1;
	  break;
	default:
	  rc = 0;
	  done = 1;
	  break;
	}
      }
      if (lang)
        getdata(0,0,"Á¤¸» ¾µ±î¿ä? (Y/N)? [Y]: ",ans, 2, DOECHO, 0);
      else
        getdata(0,0,"Post it? (Y/N)? [Y]: ",ans, 2, DOECHO, 0);
      if (*ans == 'N' || *ans == 'n')
	return (-1);
      return (0);
    } else {
      clear();
      c_msg(ERR_NOT_EXIST, TRUE);
      pressreturn();
    }
  }
  rc = vedit(filename);
  return (rc);
#else /* REMOTE_CLIENT */
  char buf[MAXCOMSZ];
  char ans[9];
  if (editor == NULL) {
    return(vedit(filename));
  }
  sprintf(buf, "%s %s", editor, filename);
  while (!done) {    
    rc = do_exec(buf, NULL, 0);
    clear();
    if (rc == -1) {
      c_msg(ERR_EXEC, TRUE);
      pressreturn();
      break;
    }
    if (lang)
      getdata(0,0,"(C)-°è¼Ó, (A)-Ãë¼Ò, (E)-ÆíÁý? [C]: ",ans,sizeof(ans),DOECHO,0);
    else
      getdata(0,0,"(C)-Continue, (A)-Abort, (E)-Edit? [C]: ",ans,sizeof(ans),DOECHO,0);
    switch (ans[0]) {
    case 'E': case 'e':
      break;
    case 'A': case 'a':
      unlink(filename);
      rc = done = 1;
      break;
    default:
      rc = 0;
      done = 1;
    }
  }
  return rc; 
#endif
}
 
#if REMOTE_CLIENT
ShellEscape()
{
  clear();
  do_exec(shell, NULL, 0);
  return FULLUPDATE;
}
#endif

Welcome()
{
  PATH welcfile;
  clear();
  if (bbs_get_welcome(welcfile) != S_OK || More(welcfile, 1)) {
    c_msg(ERR_FAILURE, TRUE);
    pressreturn();
  }
  return FULLUPDATE;
}
    
EditWelcome()
{
  PATH welcfile;
  if (bbs_get_welcome(welcfile) != S_OK) {
    c_msg(ERR_FAILURE, TRUE);
    pressreturn();
    return FULLUPDATE;
  }
  switch (Edit(welcfile)) {
  case -1:
    break;
  case 1:
    move(1,0);
    c_msg(ERR_FAILURE, TRUE);
    pressreturn();
    break;        
  case 0:
    move(1,0);
    if (bbs_set_welcome(welcfile) == S_OK)
      c_msg(INFO_CHANGED, TRUE);
    else
      c_msg(ERR_FAILURE, TRUE);
    pressreturn();
  }
  return FULLUPDATE;
}

BoardInfo()
{   
  PATH infofile;
  FILE *fp1, *fp2;
  int c;
  extern int lang;

  if (bbs_get_info(infofile) != S_OK) {
    c_msg(ERR_FILE, TRUE);
    pressreturn();
  }
  if ((fp2 = fopen(c_tempfile, "w")) == NULL) {
    c_msg(ERR_FILE, TRUE);
    pressreturn();
  }
  fprintf(fp2, "\t\t%s\n\n", version[lang]);
  if ((fp1 = fopen(infofile, "r")) == NULL) {
    fclose(fp2);
    c_msg(ERR_FILE, TRUE);
    pressreturn();
  }
  while ((c=getc(fp1)) != EOF)
    putc(c, fp2);
  fclose(fp1);
  fclose(fp2);

  clear();
  if (More(c_tempfile, 1)) {
    c_msg(ERR_FAILURE, TRUE);
    unlink(c_tempfile);
    pressreturn();
  }
  unlink(c_tempfile);
  return FULLUPDATE;
}

GnuInfo()
{   
  PATH gnufile;
  clear();
  if (bbs_get_license(gnufile) != S_OK || More(gnufile, 1)) {
    c_msg(ERR_FAILURE, TRUE);
    pressreturn();
  }
  return FULLUPDATE;
}

#define MAXLINELEN 256

CopyMessageBody(dest, src)
char *dest, *src;
{
  int LINELEN;
  char buf[MAXLINELEN], overflow[MAXLINELEN];
  FILE *ofp, *ifp;
  int ch, lastch = 0;
  int i, inbody = 0, newline = 1, overflowed = 0;
  char *space;

  LINELEN = t_columns;

  if ((ofp = fopen(dest, "w")) == NULL) return -1;
  if ((ifp = fopen(src, "r")) == NULL) {
    fclose(ofp);
    return -1;
  }

  while ((ch = fgetc(ifp)) != EOF) {
    if (!inbody) {
      if (ch == '\n' && lastch == '\n') inbody = 1;
      else lastch = ch;
      continue;
    }
    if (newline) {
      newline = 0;
      if (overflowed) {
        memcpy(buf, overflow, LINELEN);
        overflowed = 0;
      }              
      else memset(buf, 0, LINELEN);
      i = strlen(buf);
    }
    buf[i++] = ch;
    if (i > LINELEN-4 && ch != '\n') {
      if ((space = strrchr(buf, ' ')) != NULL) {
        *space++ = '\0';
        memset(overflow, 0, LINELEN);
        strcpy(overflow, space);
        overflowed = 1;        
      }
      fprintf(ofp, "%s\n", buf);
      newline = 1;
    }
    if (ch == '\n') {
      fprintf(ofp, "%s", buf);
      newline = 1;
    }
  }
  fclose(ifp);
  fclose(ofp);
}

AnnotateMessageBody(dest, src)
char *dest, *src;
{
  int LINELEN;
  char buf[MAXLINELEN], overflow[MAXLINELEN];
  FILE *ofp, *ifp;
  int ch, lastch = 0;
  int i, inbody = 0, newline = 1, overflowed = 0;
  char *space;

  LINELEN = t_columns;

  if ((ofp = fopen(dest, "w")) == NULL) return -1;
  if ((ifp = fopen(src, "r")) == NULL) {
    fclose(ofp);
    return -1;
  }

  while ((ch = fgetc(ifp)) != EOF) {
    if (!inbody) {
      if (ch == '\n' && lastch == '\n') inbody = 1;
      else lastch = ch;
      continue;
    }
    if (newline) {
      fprintf(ofp, "> ");
      newline = 0;
      if (overflowed) {
        memcpy(buf, overflow, LINELEN);
        overflowed = 0;
      }              
      else memset(buf, 0, LINELEN);
      i = strlen(buf);
    }
    buf[i++] = ch;
    if (i > LINELEN-4 && ch != '\n') {
      if ((space = strrchr(buf, ' ')) != NULL) {
        *space++ = '\0';
        memset(overflow, 0, LINELEN);
        strcpy(overflow, space);
        overflowed = 1;        
      }
      fprintf(ofp, "%s\n", buf);
      newline = 1;
    }
    if (ch == '\n') {
      fprintf(ofp, "%s", buf);
      newline = 1;
    }
  }
  fclose(ifp);
  fclose(ofp);
}

filecopy(dest, src)
char *dest, *src;
{
  int ifd, ofd, rc = 0, cc;
  char buf[1024];
  if ((ofd = open(dest, O_WRONLY | O_CREAT, 0600)) == -1)
    return -1;
  if ((ifd = open(src, O_RDONLY)) == -1)
    {
      close(ofd);
      return -2;
    }
  while (cc = read(ifd, buf, sizeof(buf)))
    if (write(ofd, buf, cc) != cc) {
      rc = -3;
      break;
    }
  close(ofd);
  close(ifd);
  return rc;
}

#if REMOTE_CLIENT
SaveFile(fname)
char *fname;
{
  char savename[PATHLEN];
  clear();
  getdata(0, 0, "Save to file: ", savename, sizeof(savename), DOECHO, 0);
  if (savename[0] == '\0')
    {
      c_msg(INFO_CANCELLED, TRUE);
    }
  else
    switch(filecopy(savename, fname))
      {
      case -3:
      case -2:
      case -1:
	c_msg(ERR_FILE, TRUE);
	break;
      case 0:
	c_msg(INFO_SAVED, TRUE);
      }
}
#endif
0,0,"(S)ave, (A)bort, (E)dit? [S]: ",ans,sizeof(ans),DOECHO,0);
	switch (ans[0]) {
	case 'E': case 'e':
	  break;
	case 'A': DarkNET-1.08/uldl.c                                                                                    644   21270   21270        14375  5735705234   7221                                                                                                                                                                                                                                                                                                                                                                      
/*
Eagles Bulletin Board System
Copyright (C) 1994, Ray Rocker, rrrocker@rock.b11.ingr.com
                                rock@seabass.st.usm.edu
                                72673.2105@compuserve.com

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "server.h"
#include <unistd.h>

#define PROTOFILE "etc/protos"

/* 
   The PROTOFILE lists the available protocols for uploading/downloading.
   Format is:

   protoname:send-binary:receive-binary
*/

typedef struct _PROTOCOL {
  NAME name;
  PATH sendbin;
  PATH recvbin;
  SHORT recv_pipe;
} PROTOCOL;

protoent_to_proto(rec, proto)
char *rec;
PROTOCOL *proto;
{
  proto->recv_pipe = 0;
  rec = _extract_quoted(rec, proto->name, sizeof(proto->name));
  rec = _extract_quoted(rec, proto->sendbin, sizeof proto->sendbin);
  if (*rec == '|') {
    proto->recv_pipe = 1;
    rec++;
  }    
  _extract_quoted(rec, proto->recvbin, sizeof(proto->recvbin));
  return S_OK;
}

_lookup_protocol(pname, proto)
char *pname;
PROTOCOL *proto;
{
  int rc;
  memset(proto, 0, sizeof *proto);
  rc = _record_find(PROTOFILE, _match_first, pname, protoent_to_proto, proto);
  return rc;
}

/*ARGSUSED*/
static int _fill_protonames(indx, rec, list)
int indx;
char *rec;
NAMELIST *list;
{
  PROTOCOL proto;
  protoent_to_proto(rec, &proto);
  add_namelist(list, proto.name, NULL);
  return S_OK;
}

local_bbs_protonames(list)
NAMELIST *list;
{
  create_namelist(list, MAXPROTO);
  _record_enumerate(PROTOFILE, 0, _fill_protonames, list);  
  sort_list(list);
  return S_OK;
}

#define ULDLFILE  "etc/ftplist"

/* 
   The ULDLFILE lists the directories available for upload/download.
   Format, for now, is:

   boardname:directory:description
*/

#define UPLOADBOARD "UPLOAD"

/*
   This is a special entry in the ULDLFILE which, if present, specifies
   the directory for uploads to go to. Downloading from it is not allowed.
*/

ftpent_to_board(rec, board)
char *rec;
BOARD *board;
{
  PATH bdir;  /* thrown away in this function */
  rec = _extract_quoted(rec, board->name, sizeof(board->name));
  rec = _extract_quoted(rec, bdir, sizeof bdir);
  rec = _extract_quoted(rec, board->description, sizeof(board->description));
  rec = _extract_quoted(rec, board->kdescription, sizeof(board->kdescription));
  return S_OK;
}

ftpent_to_dir(rec, dir)
char *rec;
char *dir;
{
  NAME bname;  /* thrown away in this function */
  rec = _extract_quoted(rec, bname, sizeof(bname));
  rec = _extract_quoted(rec, dir, PATHLEN+1);
  return S_OK;
}

_lookup_ftpent(bname, board)
char *bname;
BOARD *board;
{
  int rc;
  memset(board, 0, sizeof *board);
  rc = _record_find(ULDLFILE, _match_first, bname, ftpent_to_board, board);
  if (!strcmp(board->name, UPLOADBOARD)) return S_NOTFOUND;
  return rc;
}

get_fileboard_directory(bname, dir)
char *bname;
char *dir;
{
  int rc;
  dir[0] = '\0';
  rc = _record_find(ULDLFILE, _match_first, bname, ftpent_to_dir, dir);
  return rc;
}

_enum_fileboards(indx, rec, en)
int indx;
char *rec;
struct enumstruct *en;
{
  BOARD board;
  memset(&board, '\0', sizeof board);
  ftpent_to_board(rec, &board);
  if (!strcmp(board.name, UPLOADBOARD)) return S_OK;
  if (en->fn(indx, &board, en->arg) == ENUM_QUIT) return ENUM_QUIT;
  return S_OK;
}

/*ARGSUSED*/
local_bbs_enum_fileboards(chunk, startrec, enumfn, arg)
SHORT chunk;
SHORT startrec;
int (*enumfn)();
void *arg;
{
  struct enumstruct en;
  en.fn = enumfn;
  en.arg = arg;
  _record_enumerate(ULDLFILE, startrec, _enum_fileboards, &en);
  return S_OK;
}

static int _fill_fileboardnames(indx, rec, list)
int indx;
char *rec;
NAMELIST *list;
{
  BOARD board;
  ftpent_to_board(rec, &board);
  if (strcmp(board.name, UPLOADBOARD)) {
    add_namelist(list, board.name, NULL);
  }
  return S_OK;
}

local_bbs_fileboardnames(list)
NAMELIST *list;
{
  create_namelist(list, MAXFILEBOARD);
  _record_enumerate(ULDLFILE, 0, _fill_fileboardnames, list);  
  sort_list(list);
  return S_OK;
}

_is_valid_fname(fname)
char *fname;
{
  /* To make sure no one tries to pull hanky panky, like asking to download
     /etc/passwd...*/

  if (strchr(fname, '/')) return 0;
  if (fname[0] == '\0' || fname[0] == '.') return 0;
  return 1;
}

local_bbs_upload(path, fname, protoname)
char *path;
char *fname;
char *protoname;
{
  int rc;
  char *outf = NULL;
  PROTOCOL proto;
  PATH execbuf;
  PATH upldir;

  if (get_fileboard_directory(UPLOADBOARD, upldir) != S_OK) {
    return S_DENIED;
  }

  if (protoname == NULL && path != NULL) {
    /* Special case -- just return the filename */
    strcpy(path, upldir);
    strcat(path, "/");
    strcat(path, fname);
    return S_OK;
  }

  if (_lookup_protocol(protoname, &proto) != S_OK)
    return S_INVALID;

  if (proto.recvbin[0] == '\0')
    return S_INVALID;

  if (!_is_valid_fname(fname)) return S_INVALID;

  strcpy(execbuf, proto.recvbin);
  if (!proto.recv_pipe) {
    strcat(execbuf, " ");
    strcat(execbuf, fname);
  }
  else outf = fname;

  bbslog(3, "UPLOAD %s proto %s by %s\n", fname, proto.name, my_userid());

  set_real_mode(M_ULDL);
  rc = execute(execbuf, upldir, NULL, outf, NULL, NULL, 0);
  set_real_mode(M_UNDEFINED);
      
  return (rc == 0 ? S_OK : S_SYSERR);
}

do_download(dir, fname, protoname)
char *dir;
char *fname;
char *protoname;
{
  int rc;
  PROTOCOL proto;
  PATH execbuf;

  if (_lookup_protocol(protoname, &proto) != S_OK)
    return S_INVALID;

  if (proto.sendbin[0] == '\0')
    return S_INVALID;

  if (!_is_valid_fname(fname)) return S_INVALID;

  strcpy(execbuf, proto.sendbin);
  strcat(execbuf, " ");
  strcat(execbuf, fname);

  bbslog(3, "DOWNLOAD %s proto %s by %s\n", fname, proto.name, my_userid());

  set_real_mode(M_ULDL);
  rc = execute(execbuf, dir, NULL, NULL, NULL, NULL, 0);
  set_real_mode(M_UNDEFINED);
      
  return (rc == 0 ? S_OK : S_SYSERR);
}
c, board->kdescription, sizeof(board->kdescription));
  return S_OK;
}

ftpent_to_dir(rec, dir)
char *rec;
char *dir;
{
  NAME bname;  /* thrown away in this function */
  rec = _extract_quoted(rec, bname, sizeof(bname));
  rec = _extract_quoted(rec, dir, PATDarkNET-1.08/utable.c                                                                                  644   21270   21270        27640  5747644636   7547                                                                                                                                                                                                                                                                                                                                                                      
/*
Eagles Bulletin Board System
Copyright (C) 1994, Ray Rocker, rrrocker@rock.b11.ingr.com
                                rock@seabass.st.usm.edu
                                72673.2105@compuserve.com

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "server.h"
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#if NO_FLOCK == 1
# define LOCK(fd)   lockf(fd, F_LOCK, 0)
# define UNLOCK(fd) lockf(fd, F_ULOCK, 0)
#else
# include <sys/file.h> 
# define LOCK(fd)   flock(fd, LOCK_EX)
# define UNLOCK(fd) flock(fd, LOCK_UN)
#endif

#ifndef NO_SHARED_MEMORY
# include <sys/ipc.h>
# include <sys/shm.h>

int _utable_in_shared_memory = 1;
#endif

#define USERFLUSH       ".uflush"

/* Maximum number of active users, set by utable_attach. */
int utable_sz = 0;

extern SERVERDATA server;

/*
   First the file implementation of the user table. Systems which do not
   support shared memory must use this. Also systems which do support
   it as a kernel option (Linux, SunOS, others?) can fall back to this
   if their kernel isn't set up for it.
*/

#define UTABLEFILE       "etc/.utable"

f_utable_attach(numusers)
int numusers;
{
  int fd;
  if (utable_sz != 0) return S_EXISTS;
  if ((fd = open(UTABLEFILE, O_RDWR | O_CREAT, 0600)) == -1) {
    bbslog(0, "ERROR f_utable_attach: cannot open %s\n", UTABLEFILE);
    return S_SYSERR;
  }
  utable_sz = numusers;
  close(fd);
  return S_OK;
}

/*ARGSUSED*/
f_utable_detach(destroy)
int destroy;
{
  return S_OK;
}

f_utable_lock_record(precnum)
int *precnum;
{
  int i, fd, rc;
  USERDATA data;
  if (utable_sz == 0) return S_NOTFOUND;

  if ((fd = open(UTABLEFILE, O_RDWR)) == -1) {
    bbslog(0, "ERROR f_utable_lock_record: cannot open %s\n", UTABLEFILE);
    return S_SYSERR;
  }

  LOCK(fd);
  for (i=0; i<utable_sz; i++) {
    rc = read(fd, &data, sizeof data);
    if (rc == sizeof data) {
      if (data.u.mode == M_EMPTY || kill(data.u.pid, 0) == -1) {
        lseek(fd, -sizeof(USERDATA), SEEK_CUR);
        break;
      }
    }
    else if (rc >= 0) {
      lseek(fd, -rc, SEEK_CUR);
      break;
    }
    else {
      bbslog(0, "ERROR f_utable_lock_record: read failed\n");
      UNLOCK(fd);
      close(fd);
      return S_SYSERR;
    }
  }
  
  if (i < utable_sz) {
    memset(&data, 0, sizeof data);
    data.u.mode = M_CONNECTING;
    rc = write(fd, &data, sizeof data);
    if (precnum && rc == sizeof data) *precnum = i;
    UNLOCK(fd);
    close(fd);
    return (rc == sizeof data ? S_OK : S_SYSERR);
  }

  UNLOCK(fd);
  close(fd);
  return S_FULL;
}

f_utable_free_record(recnum)
int recnum;
{
  int fd;
  struct stat stbuf;
  USERDATA data;
  int offset = recnum*(sizeof(USERDATA));  

  if (utable_sz == 0) return S_NOTFOUND;
  if (recnum < 0 || recnum > utable_sz-1) return S_INVALID;
  memset(&data, 0, sizeof data);
  data.u.mode = M_EMPTY;

  if ((fd = open(UTABLEFILE, O_WRONLY)) == -1) {
    bbslog(0, "ERROR f_utable_free_record: cannot open %s\n", UTABLEFILE);
    return S_SYSERR;
  }
  fstat(fd, &stbuf);
  if (offset >= stbuf.st_size) {
    close(fd);
    return S_INVALID;
  }
  lseek(fd, offset, SEEK_SET);
  if (write(fd, &data, sizeof(data)) != sizeof(data)) {
    close(fd);
    return S_SYSERR;
  }
  close(fd);
  touch_flush(USERFLUSH);
  return S_OK;
}

f_utable_get_record(recnum, buf)
int recnum;
USERDATA *buf;
{
  int fd;
  struct stat stbuf;
  USERDATA data;
  int offset = recnum*(sizeof(USERDATA));  
  if (utable_sz == 0) return S_NOTFOUND;
  if (recnum < 0 || recnum > utable_sz-1) return S_INVALID;
  if ((fd = open(UTABLEFILE, O_RDONLY)) == -1) {
    bbslog(0, "ERROR f_utable_get_record: cannot open %s\n", UTABLEFILE);
    return S_SYSERR;
  }
  fstat(fd, &stbuf);
  if (offset >= stbuf.st_size) {
    close(fd);
    return S_INVALID;
  }
  lseek(fd, offset, SEEK_SET);
  if (read(fd, &data, sizeof(data)) != sizeof(data)) {
    close(fd);
    return S_SYSERR;
  }
  close(fd);
  if (data.u.mode == M_EMPTY) return S_INVALID;
  memcpy(buf, &data, sizeof(*buf));
  return S_OK;
}

f_utable_set_record(recnum, buf)
int recnum;
USERDATA *buf;
{
  int fd;
  struct stat stbuf;
  USERDATA data;
  int offset = recnum*(sizeof(USERDATA));  
  if (utable_sz == 0) return S_NOTFOUND;
  if (recnum < 0 || recnum > utable_sz-1) return S_INVALID;
  if ((fd = open(UTABLEFILE, O_RDWR)) == -1) {
    bbslog(0, "ERROR f_utable_set_record: cannot open %s\n", UTABLEFILE);
    return S_SYSERR;
  }
  fstat(fd, &stbuf);
  if (offset >= stbuf.st_size) {
    close(fd);
    return S_INVALID;
  }
  lseek(fd, offset, SEEK_SET);
  if (read(fd, &data, sizeof(data)) != sizeof(data)) {
    close(fd);
    return S_SYSERR;
  }
  if (data.u.mode == M_EMPTY) {
    close(fd);
    return S_INVALID;
  }
  lseek(fd, -sizeof(USERDATA), SEEK_CUR);
  if (write(fd, buf, sizeof(*buf)) != sizeof(*buf)) {
    close(fd);
    return S_SYSERR;
  }
  close(fd);
  if (strcmp(data.u.userid, buf->u.userid)) {
    touch_flush(USERFLUSH);
  }
  return S_OK;
}

f_utable_find_record(pid, buf)
LONG pid;
USERDATA *buf;
{
  int fd;
  USERDATA data;
  if (utable_sz == 0) return S_NOTFOUND;
  if ((fd = open(UTABLEFILE, O_RDONLY)) == -1) {
    return S_NOTFOUND;
  }
  while (read(fd, &data, sizeof data) == sizeof data) {
    if (data.u.mode == M_EMPTY) continue;
    if (data.u.pid == pid) {
      if (buf) memcpy(buf, &data, sizeof(*buf));
      close(fd);
      return S_OK;
    }
  }
  close(fd);
  return S_NOTFOUND;
}

f_utable_enumerate(startrec, userid, func, arg)
int startrec;
char *userid;
int (*func)();
void *arg;
{
  int fd, indx, retval = 0;
  USERDATA udata;
  if (utable_sz == 0) return S_NOTFOUND;
  if (startrec < 0 || startrec > utable_sz-1) return S_INVALID;
  if ((fd = open(UTABLEFILE, O_RDONLY)) == -1) {
    return S_OK;
  }
  indx = startrec;
  lseek(fd, indx*sizeof(udata), SEEK_SET);
  while (indx < utable_sz && retval != ENUM_QUIT) {
    if (read(fd, &udata, sizeof udata) != sizeof udata) break;
    if (udata.u.mode != M_EMPTY &&
        udata.u.mode != M_CONNECTING &&
        kill(udata.u.pid, 0) == 0 &&
        (userid == NULL || !strcasecmp(userid, udata.u.userid))) { 
      retval = (*func)(indx, &udata, arg);
    }
    indx++;
  }
  close(fd);
  return S_OK;
}

#ifndef NO_SHARED_MEMORY

/* Shared memory implementation of the user table. */

# define KEY_BBS_MIN     90
# define KEY_BBS_MAX     100
# define KEYFILE         "etc/.shmkey"

USERDATA *utableptr = NULL;

int utable_shmid = -1;

_read_shmkey()
{
  FILE *fp;
  char buf[8];
  int key = -1;
  if ((fp = fopen(KEYFILE, "r")) != NULL) {
    if (fgets(buf, sizeof buf, fp) != NULL) key = atoi(buf);
    fclose(fp);
  }
  return key;      
}  

_write_shmkey(key)
int key;
{
  FILE *fp;
  char buf[8];
  if ((fp = fopen(KEYFILE, "w")) != NULL) {
    sprintf(buf, "%05d\n", key);
    fputs(buf, fp);
    fclose(fp);
  }
  return (fp == NULL ? -1 : 0);
}  

utable_attach(numusers)
int numusers;
{
  int key, i, created = 0;
  int memsize;
  if (utableptr) return S_EXISTS;
  memsize = sizeof(USERDATA)*server.maxutable;
  key = _read_shmkey();
  if (key == -1) {
    key = KEY_BBS_MIN;
    while (key < KEY_BBS_MAX && !created) {
      if ((utable_shmid = shmget(key, memsize, 0600|IPC_CREAT)) == -1) key++;
      else created = 1;
    }
  }
  else {
    utable_shmid = shmget(key, memsize, 0600);
    if (utable_shmid == -1 && errno == ENOENT) {
      created = 1;
      utable_shmid = shmget(key, memsize, 0600|IPC_CREAT);
    }
  }

  if (utable_shmid == -1) {
#if FORCE_SHARED_MEMORY
    bbslog(0, "ERROR utable_attach: shmget failed\n");
    return S_SYSERR;
#else
    _utable_in_shared_memory = 0;
    return (f_utable_attach(numusers));
#endif
  }

  utableptr = (USERDATA *)shmat(utable_shmid, NULL, 0);
  if (utableptr == NULL || utableptr == (USERDATA *)-1) {
    utable_detach(1);
#if FORCE_SHARED_MEMORY
    bbslog(0, "ERROR utable_attach: shmat failed\n");
    return S_SYSERR;
#else
    _utable_in_shared_memory = 0;
    return(f_utable_attach(numusers));
#endif
  }
  utable_sz = numusers;
  if (created) {
    _write_shmkey(key);
    memset(utableptr, 0, memsize);
    for (i=0; i<server.maxutable; i++) utableptr[i].u.mode = M_EMPTY;
  }

  return S_OK;
}

utable_detach(destroy)
int destroy;
{
  if (!_utable_in_shared_memory) 
    return f_utable_detach(destroy);
  if (utableptr == NULL) return S_NOTFOUND;

  if (shmdt((char *)utableptr) == -1) {
    bbslog(0, "ERROR utable_detach: shmdt failed\n");
    return S_SYSERR;
  }

  utableptr = NULL;

  if (destroy) {
    if (shmctl(utable_shmid, IPC_RMID, (struct shmid_ds *)NULL) == -1)
      return S_DENIED;
  }

  return S_OK;
}

utable_lock_record(precnum)
int *precnum;
{
  int i;
  if (!_utable_in_shared_memory) 
    return f_utable_lock_record(precnum);
  if (utableptr == NULL) return S_NOTFOUND;
  for (i=0; i<utable_sz; i++) {
    if (utableptr[i].u.mode == M_EMPTY || kill(utableptr[i].u.pid, 0) == -1) {
      memset(&utableptr[i], 0, sizeof(utableptr[i]));
      utableptr[i].u.mode = M_CONNECTING;
      if (precnum) *precnum = i;
      return S_OK;
    }
  }

  return S_FULL;
}
            
utable_free_record(recnum)
int recnum;
{
  if (!_utable_in_shared_memory) 
    return f_utable_free_record(recnum);
  if (utableptr == NULL) return S_NOTFOUND;

  if (recnum < 0 || recnum > utable_sz-1) return S_INVALID;

  utableptr[recnum].u.mode = M_EMPTY;
  touch_flush(USERFLUSH);
  return S_OK;
}

utable_get_record(recnum, buf)
int recnum;
USERDATA *buf;
{
  if (!_utable_in_shared_memory) 
    return f_utable_get_record(recnum, buf);
  if (utableptr == NULL) return S_NOTFOUND;

  if (recnum < 0 || recnum > utable_sz-1) return S_INVALID;
  if (utableptr[recnum].u.mode == M_EMPTY) return S_INVALID;
  memcpy(buf, &utableptr[recnum], sizeof(*buf));
  return S_OK;
}

utable_set_record(recnum, buf)
int recnum;
USERDATA *buf;
{
  if (!_utable_in_shared_memory) 
    return f_utable_set_record(recnum, buf);
  if (utableptr == NULL) return S_NOTFOUND;

  if (recnum < 0 || recnum > utable_sz-1) return S_INVALID;
  if (utableptr[recnum].u.mode == M_EMPTY) return S_INVALID;
  if (strcmp(utableptr[recnum].u.userid, buf->u.userid)) {
    touch_flush(USERFLUSH);
  }
  memcpy(&utableptr[recnum], buf, sizeof(*buf));
  return S_OK;
}

utable_find_record(pid, buf)
LONG pid;
USERDATA *buf;
{
  int recnum;
  if (!_utable_in_shared_memory) 
    return f_utable_find_record(pid, buf);
  if (utableptr == NULL) return S_NOTFOUND;

  for (recnum = 0; recnum < utable_sz; recnum++) {
    if (utableptr[recnum].u.mode == M_EMPTY) continue;
    if (utableptr[recnum].u.pid == pid) {
      if (buf) memcpy(buf, &utableptr[recnum], sizeof(*buf));
      return S_OK;
    }
  }
  return S_NOTFOUND;
}

utable_enumerate(startrec, userid, func, arg)
int startrec;
char *userid;
int (*func)();
void *arg;
{
  int indx, retval = 0;
  USERDATA udata;
  if (!_utable_in_shared_memory) 
    return f_utable_enumerate(startrec, userid, func, arg);
  if (utableptr == NULL) return S_NOTFOUND;

  if (startrec < 0 || startrec >= utable_sz) return S_INVALID;
  indx = startrec;
  while (indx < utable_sz && retval != ENUM_QUIT) {
    if (utableptr[indx].u.mode != M_EMPTY &&
        utableptr[indx].u.mode != M_CONNECTING &&
        kill(utableptr[indx].u.pid, 0) == 0 &&
        (userid == NULL || !strcasecmp(userid, utableptr[indx].u.userid))) { 
      memcpy(&udata, &utableptr[indx], sizeof udata);
      retval = (*func)(indx, &udata, arg);
    }
    indx++;
  }
  return S_OK;
}

#endif /* NO_SHARED_MEMORY */

utable_test_flush(lastupdate)
time_t lastupdate;
{
  return (test_flush(USERFLUSH, lastupdate));
}


                                                                                                DarkNET-1.08/util.c                                                                                    644   21270   21270        16463  5747645245   7246                                                                                                                                                                                                                                                                                                                                                                      
/*
Eagles Bulletin Board System
Copyright (C) 1994, Ray Rocker, rrrocker@rock.b11.ingr.com
                                rock@seabass.st.usm.edu
                                72673.2105@compuserve.com

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "common.h"
#include <ctype.h>
#if NEXTSTEP == 1
# include <sys/dir.h>
# include <sys/dirent.h>
#else
# include <dirent.h>
#endif
#include <fcntl.h>
#include <time.h>
#include <sys/stat.h>
#if NEXTSTEP == 1
# define S_ISDIR(mode)   (((mode) & (_S_IFMT)) == (_S_IFDIR))
#endif


static char *day_of_week[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
static char *mon_of_year[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
/* Miscellaneous useful functions */
#if NO_STRCASECMP == 1
#if LINUX == 1
int strcasecmp __P ((__const char *s1, __const char *s2))
#else
strcasecmp(s1,s2)
register unsigned char *s1,*s2 ;
#endif
{
  register int xor;

  if (s1 == NULL || s2 == NULL)
    return s1 - s2;

  for(; *s1 || *s2; s1++,s2++) {
    if (!*s1 || !*s2)
	return ((unsigned char)*s1 - (unsigned char)*s2);
    if (*s1 == *s2)
      continue;
    if (myisalpha(*s1) && myisalpha(*s2)) {
      xor = *s1 ^ *s2;
      if (xor != 32 && xor!= 0)
	return ((unsigned char)*s1 - (unsigned char)*s2);
    } else {
      return ((unsigned char)*s1 - (unsigned char)*s2);
   }
  }
  return 0;
}

#if LINUX == 1
int strncasecmp __P ((__const char *s1, __const char *s2, size_t n))
#else
strncasecmp(s1,s2,n)
register char *s1,*s2 ;
register int n ;
#endif
{
  register int i, xor;

  if (s1 == NULL || s2 == NULL)
    return s1 - s2;

  for (i=0; i<n; i++, s1++, s2++) {
    if (*s1 == *s2)
      continue;
    if (myisalpha(*s1) && myisalpha(*s2)) {
      xor = *s1 ^ *s2;
      if (xor != 32 && xor!= 0)
	return ((unsigned char)*s1 - (unsigned char)*s2);
    } else {
      return ((unsigned char)*s1 - (unsigned char)*s2);
    }
  }
  return 0;
}
#endif

void
strip_trailing_space(str)
char *str;
{
  char *eos;
  if (str == NULL || *str == '\0') return;
  eos = str+strlen(str)-1;
  while (eos >= str && myisspace(*eos))
    *eos-- = '\0';
}

is_directory(fname)
char *fname;
{
  struct stat stbuf;
  if (stat(fname, &stbuf) == 0 && S_ISDIR(stbuf.st_mode)) return 1;
  return 0;
}

recursive_rmdir(dir)
char *dir;
{
  PATH fname;
  DIR *dp;
  struct dirent *dent;

  if ((dp = opendir(dir)) == NULL) {
    return -1;
  }
              
  while ((dent = readdir(dp)) != NULL) {
    if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
      continue;
    sprintf(fname, "%s/%s", dir, dent->d_name);
    if (is_directory(fname)) recursive_rmdir(fname);
    else unlink(fname);
  }

  closedir(dp);
  if (rmdir(dir)) return -1;
  else return 0;
}

/* I want to strangle whoever decided that ctime should return a string 
   with a FREAKING NEWLINE on the end. */

char *
Ctime(t)
time_t *t;
{
  static char ctbuf[40];
  char *ct;
  struct tm *curr_t;

  tzset();
  curr_t = localtime(t);
  sprintf(ctbuf, "%s %s %.2d %2.2d:%2.2d:%2.2d %d %s",
	        day_of_week[curr_t->tm_wday],
        mon_of_year[curr_t->tm_mon],
        curr_t->tm_mday,
        curr_t->tm_hour, curr_t->tm_min, curr_t->tm_sec,
        curr_t->tm_year + 1900,
#if LINUX == 1
        tzname[curr_t->tm_isdst]);
#else
        curr_t->tm_zone);
#endif
  return ctbuf;
}

is_valid_userid(userid)
char *userid;
{
  int len = strlen(userid);
  if (len < 2) return 0;
  if (!isalpha(userid[0]) && !ishangul(userid[0])) return 0;
  if (!isalnum(userid[len-1]) && !ishangul(userid[len-1])) return 0;
  while (*userid) {
    if (!isalnum(*userid) && !ishangul(*userid)) {
      if (*userid != '-' && *userid != '_') return 0;
      if (!isalnum(*(userid-1))) return 0;
    }    
    userid++;
  }
  return 1;
}
    
is_valid_password(passwd)
char *passwd;
{
  if (!passwd || !*passwd) return 0;
  return 1;
}

is_valid_boardname(bname)
char *bname;
{
  int len = strlen(bname);
  if (len < 1) return 0;
  while (*bname) {
    if (!isalnum(*bname) && !ishangul(*bname)) return 0;
    bname++;
  }
  return 1;
}

/* 
   Append contents of fname to open file descriptor fd.
   fd is assumed to be pointing at end-of-file.
   fd is left open by this function.
*/

append_file(fd, fname)
int fd;
char *fname;
{
  char buf[4096];
  int bytes;
  int nfd = open(fname, O_RDONLY);
  if (nfd == -1) return -1;
  
  while ((bytes = read(nfd, buf, sizeof buf)) && bytes != -1) {
    write(fd, buf, bytes);
  }
  close(nfd);
  return 0;
}

copy_file(src, dest, fmode, append)
char *src, *dest;
int fmode, append;
{
  int omode, fd, rc;
  omode = (append ? O_WRONLY|O_APPEND|O_CREAT : O_WRONLY|O_TRUNC|O_CREAT);
  if ((fd = open(dest, omode, fmode)) == -1) return -1;
  rc = append_file(fd, src);
  close(fd);
  return rc;
}

LONG
hex2LONG(str)
char *str;
{
  char c;  
  int i;
  LONG val = 0;
  for (i=0; i<8; i++) {
    val <<= 4;
    c = tolower(str[i]);
    if (c >= '0' && c <= '9') val += (c-'0');
    else if (c >= 'a' && c <= 'f') val += (c-'a'+10);
    else return 0;
  }
  return val;
}        

SHORT
hex2SHORT(str)
char *str;
{
  char c;  
  int i;
  SHORT val = 0;
  for (i=0; i<4; i++) {
    val <<= 4;
    c = tolower(str[i]);
    if (c >= '0' && c <= '9') val += (c-'0');
    else if (c >= 'a' && c <= 'f') val += (c-'a'+10);
    else return 0;
  }
  return val;
}        

char *
LONGcpy(str, lval)
char *str;
LONG lval;
{
  char nbuf[9];
  sprintf(nbuf, "%08x", lval);
  memcpy(str, nbuf, 8);
  return (str+8);
}
  
char *
SHORTcpy(str, sval)
char *str;
SHORT sval;
{
  char nbuf[5];
  sprintf(nbuf, "%04x", sval);
  memcpy(str, nbuf, 4);
  return (str+4);
}

touch_flush(flushf)
char *flushf;
{
  int fd = open(flushf, O_WRONLY | O_CREAT, 0600);
  if (fd == -1) return -1;
  write(fd, "NEW\n", 5);
  close(fd);
  return 0;
}

test_flush(flushf, t)
char *flushf;
time_t t;
{
  struct stat stbuf;
  if (stat(flushf, &stbuf) != 0) return 1;
  return (stbuf.st_mtime >= t);
}

char *ascii_exts [] = {
   "c", "h", "txt", "pl", "cpp", "p", "f", "pas", "bas", "cxx", NULL
};

char *binary_exts [] = {
   "z", "gz", "tar", "zip", "zoo", "arc", "arj", "gif", "o", "obj", "a",
   "exe", "com", "lib", "dll", "wav", "cur", "ani", "jpg", "tif", "bin",
   NULL
};

is_text_file(path)
char *path;
{
  int fd, cc, i;
  char buf[1024];
  char *dot, **cp;

  /* Look for common extensions first and make assumptions, wise we hope */
  if (dot = strrchr(path, '.')) {
    dot++;
    for (cp = ascii_exts; *cp != NULL; cp++)
      if (!strcasecmp(dot, *cp)) return 1;
    for (cp = binary_exts; *cp != NULL; cp++)
      if (!strcasecmp(dot, *cp)) return 0;
  }

  if ((fd = open(path, O_RDONLY)) == -1) return 0;
  cc = read(fd, buf, sizeof buf);
  close(fd);
  if (cc == -1) return 0;
  for (i=0; i<cc; i++) {
    if (!myisprint(buf[i]) && !myisspace(buf[i])) return 0;
  }
  return 1;  
}        
                                                                                                                                                                                                             DarkNET-1.08/mkftplist.pl                                                                              755   21270   21270         5660  5647532325  10450                                                                                                                                                                                                                                                                                                                                                                      #!/usr/bin/perl
# mkftplist.pl
#
# Perl script to generate the Eagles BBS ftplist file.
# Ray Rocker
# Initial revision: June 4, 1994
#
# This program must be run from the bbs home directory if BBSHOME is not
# defined in the environment; it will not complete if the etc/ftplist 
# is not found.
#
# Usage: mkftplist.pl <root-dir>
# Adds an entry for every directory under <root-dir> to the ftplist if one 
# does not exist. The name of the file board defaults to the basename of the 
# directory. Conflicts will be resolved if possible by appending things, 
# and warnings will be generated when this happens.
#

$ftplist = "etc/ftplist";
$oldlist = "etc/ftplist.bak";
$newlist = "etc/ftplist.new";

$argc = @ARGV;
if ($argc < 1) {
  die "Usage: mkftplist.pl <root-dir>";
}
$rootdir = $ARGV[0];

$homedir = $ENV{"BBSHOME"};
if ("$homedir" ne "") {
  chdir($homedir) || die "Cannot chdir to $homedir: $!";
}

open(FTPLIST, "$ftplist") || die "Cannot open $ftplist for reading: $!";
while (<FTPLIST>) {
  if (/^#/ || /^\s/) {
    next;
  }
  ($bname, $bdir, $comment) = split(/:/);
  if (! -d $bdir) {
    print "$bdir is not a directory, removing\n";
  }
  else {
    $ftp{$bdir} = $bname;
    push(@bnames, $bname);
  }
}

&Recurse($rootdir);

seek(FTPLIST, 0, 0) || die "Cannot seek $ftplist to beginning: $!";

open(NEWFTPLIST, ">$newlist") || die "Cannot open $newlist for writing: $!";
while (<FTPLIST>) {
  if (/^#/ || /^\s/) {
    print NEWFTPLIST "$_";
    next;
  }
  ($bname, $bdir, $comment) = split(/:/);
  if ($ftp{$bdir}) {
    print NEWFTPLIST "$_";
    $ftp{$bdir} = "";
  }
}

close(FTPLIST);

while (@pair = each %ftp) {
  if ($pair[1]) {
    print NEWFTPLIST "$pair[1]:$pair[0]:\n";
  }
}

close(NEWFTPLIST);
rename($ftplist, $oldlist) || die "Cannot rename $ftplist to $oldlist: $!\n";
if (!rename($newlist, $ftplist)) {
  print STDERR "Cannot move $newlist to $ftplist: $!\n";
  print STDERR "Leaving old ftplist intact.\n";
  rename($oldlist, $ftplist);
}

sub Recurse {
  local($dir) = $_[0];
  local(*DHANDLE);
  local($fullname);
  local($file);
  
  if (opendir(DHANDLE, $dir)) {
    while ($file = readdir(DHANDLE)) {
      if ($file =~ /^[.]{1,2}$/) {
        next;
      }
      $fullname = "$dir/$file";
      if (! -d $fullname) {
        next;
      }
      &Recurse($fullname);      
      if (!($ftp{$fullname})) {
        &Resolve($file);
        $ftp{$fullname} = $file;
        push(@bnames, $file);
      }
    }      
    closedir(DHANDLE);
  }
}  

sub Resolve {
  local($origfile) = $_[0];
  local($origcopy) = substr($origfile, 0, 12);
  local($tempfile) = $origcopy;
  local($hitcount) = 1;
  while (grep("$tempfile" eq "$_", @bnames)) {
    $tempfile = $origcopy.$hitcount;
    if (length($tempfile) > 12) {
      chop($origcopy);
      $hitcount = 1;
      $tempfile = $origcopy.$hitcount;
    }    
    $hitcount++;
  }
  if ($origfile ne $tempfile) {
    print STDERR "Warning: $fullname is board $tempfile\n";
    $file = $tempfile;
  }
}





                                                                                DarkNET-1.08/pbbs/                                                                                     755   21270   21270            0  6044661520   6715                                                                                                                                                                                                                                                                                                                                                                      DarkNET-1.08/pbbs/io.c                                                                                 644   21270   21270        22130  5742136045   7576                                                                                                                                                                                                                                                                                                                                                                      /*
    Pirate Bulletin Board System
    Copyright (C) 1990, Edward Luke, lush@Athena.EE.MsState.EDU
    Eagles Bulletin Board System
    Copyright (C) 1992, Raymond Rocker, rocker@rock.b11.ingr.com
                        Guy Vega, gtvega@seabass.st.usm.edu
                        Dominic Tynes, dbtynes@seabass.st.usm.edu

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 1, or (at your option)
    any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include <stdio.h>
#include "osdeps.h"
#include "io.h"
#include "myctype.h"
#include <sys/types.h>
#include <signal.h>
#include <ctype.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <errno.h>

#if USES_SYS_SELECT_H
# include <sys/select.h>
#endif

extern int input_active;

#define OBUFSIZE  (4096)
#define IBUFSIZE  (256)

char outbuf[OBUFSIZE] ;
int obufsize = 0 ;

char inbuf[IBUFSIZE] ;
int ibufsize = 0 ;
int icurrchar = 0 ;

oflush()
{
    if(obufsize)
      write(1,outbuf,obufsize) ;
    obufsize = 0 ;
}

output(s,len)
char *s ;
{
    /* Invalid if len >= OBUFSIZE */

    if(obufsize+len > OBUFSIZE) {  /* doin a oflush */
        write(1,outbuf,obufsize) ;
        obufsize = 0 ;
    }
    memcpy(outbuf+obufsize,s,len) ;
    obufsize+=len ;
}

ochar(c)
{
    if(obufsize > OBUFSIZE-1) {  /* doin a oflush */
        write(1,outbuf,obufsize) ;
        obufsize = 0 ;
    }
    outbuf[obufsize++] = c ;
}

int i_newfd = 0;
struct timeval i_to, *i_top = NULL ;
int (*flushf)() = NULL ;

#if 0
int serversock = 0;
int in_child = 0;
int (*sockf)() = NULL;

add_serversock(fd)
int fd;
{
    serversock = fd;
}

add_servhandler(func)
int (*func)();
{
    sockf = func;
}
#endif

add_io(fd,timeout)
int fd ;
int timeout ;
{
    i_newfd = fd ;
    if(timeout) {
        i_to.tv_sec = timeout ;
        i_to.tv_usec = 0 ;
        i_top = &i_to ;
    } else i_top = NULL ;
}

add_flush(flushfunc)
int (*flushfunc)() ;
{
    flushf = flushfunc ;
}

num_in_buf()
{
    return icurrchar - ibufsize ;
}

int
igetch()
{
igetagain:
    if(ibufsize == icurrchar) {
        fd_set readfds ;
        struct timeval to ;
        int nfds, sr ;

        to.tv_sec = 0 ;
        to.tv_usec = 0 ;
        FD_ZERO(&readfds) ;
        nfds = 1;
#if 0
        if (!in_child) 
#endif
	    FD_SET(0,&readfds) ;
        if(i_newfd) {
            FD_SET(i_newfd,&readfds) ;
	    nfds = i_newfd+1;
        }
#if 0
	if(serversock) {
	    FD_SET(serversock,&readfds);
            if (serversock >= nfds) nfds = serversock+1;
        }
#endif
        if((sr = select(nfds, &readfds, NULL, NULL, &to)) <= 0) {
            if(flushf)
                (*flushf)() ;
            if(dumb_term)
                oflush() ;
            else
                refresh() ;
selectagain:
            FD_ZERO(&readfds) ;
            nfds = 1;
#if 0
            if (!in_child)
#endif
  	        FD_SET(0,&readfds) ;
            if(i_newfd) {
                FD_SET(i_newfd,&readfds) ;
  	        nfds = i_newfd+1;
	    }
#if 0
	    if (serversock) {
		FD_SET(serversock,&readfds);
                if (serversock >= nfds) serversock+1;
            }
#endif
            while((sr = select(nfds, &readfds, NULL, NULL, i_top)) <0) {
                if(errno == EINTR) {
#if 0
                    if (in_child) return (I_SIGNAL);
		    else 
#endif
		      continue ;
		}
                else {
                    perror("select") ;
                    fprintf(stderr,"abnormal select conditions\n") ;
                    return -1 ;
                }
            }
            if(sr == 0)
                return I_TIMEOUT ;
        }
#if 0
        if(serversock && FD_ISSET(serversock,&readfds)) {
	    if (sockf) {
	  	(*sockf)(serversock);
		goto selectagain;
	    }
            else return I_OTHERDATA ;
        }
#endif
        if(i_newfd && FD_ISSET(i_newfd,&readfds)) {
            return I_OTHERDATA ;
        }
        while((ibufsize = read(0,inbuf,IBUFSIZE)) <= 0) {
            if(ibufsize == 0)
                generic_abort() ;
            if(ibufsize < 0 && errno != EINTR)
                generic_abort() ;
        }
        icurrchar = 0 ;
    }
    input_active = 1;
    switch(inbuf[icurrchar]) {
      case CTRL('L'):
        redoscr() ;
        icurrchar++ ;
        goto igetagain ;
      default:
        break ;
    }
    return inbuf[icurrchar++] ;
}

getdata(line,col,prompt,buf,len,echo,cancel)
int line,col ;
char *prompt, *buf ;
int len, echo, cancel ;
{
    int ch ;
    int clen = 0 ;
    int x,y ;
    extern unsigned char scr_cols ;

    if(prompt) {
        move(line,col) ;
        prints("%s",prompt) ;
    }
    if(dumb_term) {
        while(clen < len - 1 && (ch = igetch()) != '\r') {
	    if((ch == CTRL('C') || ch == CTRL('D')) && cancel)
              return -1 ;
            if(ch == '\n')
              break ;
            if(ch == '\177' || ch == CTRL('H')) {
                if(clen == 0) {
                    bell() ;
                    continue ;
                }
                clen-- ;
                if(echo) {
                    ochar(CTRL('H')) ;
                    ochar(' ') ;
                    ochar(CTRL('H')) ;
                }
                continue ;
            }
            if(!myisprint(ch)) {
                if(echo)
                  bell() ;
                continue ;
            }
            if(clen >= len-1) {
                if(echo)
                  bell() ;
                continue ;
            }
            buf[clen++] = ch ;
            if(echo)
              ochar(ch) ;
        }
        buf[clen] = '\0' ;
        prints("\n") ;
        oflush() ;
        return clen ;
    }
    clrtoeol() ;
    getyx(&y,&x) ;
    while(clen < len - 1 && (ch = igetch()) != '\r') {
        if((ch == CTRL('C') || ch == CTRL('D')) && cancel)
          return -1 ;
        if(ch == '\n')
          break ;
        if(ch == '\177' || ch == CTRL('H')) {
            if(clen == 0) {
                bell() ;
                continue ;
            }
            clen-- ;
            if(echo) {
                move(y,x+clen) ;
                prints(" ") ;
                move(y,x+clen) ;
            }
            continue ;
        }
        if(!myisprint(ch)) {
            bell() ;
            continue ;
        }
        if(x+clen >= scr_cols || clen >= len-1) {
            bell() ;
            continue ;
        }
        buf[clen++] = ch ;
        if(echo)
          prints("%c",ch) ;
    }
    buf[clen] = '\0' ;
    if(echo)
      prints("\n") ;
    refresh() ;
    return clen ;
}

getdata_echo(line,col,prompt,buf,len,echo,echochar,cancel)
int line,col ;
char *prompt, *buf ;
int len, echo, echochar, cancel ;
{
    int ch ;
    int clen = 0 ;
    int x,y ;
    extern unsigned char scr_cols ;

    if(prompt) {
        move(line,col) ;
        prints("%s",prompt) ;
    }
    if(dumb_term) {
        while((ch = igetch()) != '\r') {
	    if((ch == CTRL('C') || ch == CTRL('D')) && cancel)
              return -1 ;
            if(ch == '\n')
              break ;
            if(ch == '\177' || ch == CTRL('H')) {
                if(clen == 0) {
                    bell() ;
                    continue ;
                }
                clen-- ;
                if(echo) {
                    ochar(CTRL('H')) ;
                    ochar(' ') ;
                    ochar(CTRL('H')) ;
                }
                continue ;
            }
            if(!myisprint(ch)) {
                if(echo)
                  bell() ;
                continue ;
            }
            if(clen >= len-1) {
                if(echo)
                  bell() ;
                continue ;
            }
            buf[clen++] = ch ;
            if(echo)
              ochar(ch);
	    else
              ochar(echochar) ;
        }
        buf[clen] = '\0' ;
        prints("\n") ;
        oflush() ;
        return clen ;
    }
    clrtoeol() ;
    getyx(&y,&x) ;
    while((ch = igetch()) != '\r') {
        if((ch == CTRL('C') || ch == CTRL('D')) && cancel)
          return -1 ;
        if(ch == '\n')
          break ;
        if(ch == '\177' || ch == CTRL('H')) {
            if(clen == 0) {
                bell() ;
                continue ;
            }
            clen-- ;
            if(echo) {
                move(y,x+clen) ;
                prints(" ");
                move(y,x+clen) ;
            }
            continue ;
        }
        if(!myisprint(ch)) {
            bell() ;
            continue ;
        }
        if(x+clen >= scr_cols || clen >= len-1) {
            bell() ;
            continue ;
        }
        buf[clen++] = ch ;
        if(echo)
          prints("%c",ch) ;
	else
          prints("%c",echochar) ;
    }
    buf[clen] = '\0' ;
    prints("\n") ;
    refresh() ;
    return clen ;
}
                                                                                                                                                                                                                                                                                                                                                                                                                                        DarkNET-1.08/pbbs/more.c                                                                               644   21270   21270        12171  5751272545  10143                                                                                                                                                                                                                                                                                                                                                                      /*
    Pirate Bulletin Board System
    Copyright (C) 1990, Edward Luke, lush@Athena.EE.MsState.EDU
    Eagles Bulletin Board System
    Copyright (C) 1992, Raymond Rocker, rocker@rock.b11.ingr.com
                        Guy Vega, gtvega@seabass.st.usm.edu
                        Dominic Tynes, dbtynes@seabass.st.usm.edu

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 1, or (at your option)
    any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include <stdio.h>
#include "osdeps.h"
#include "io.h"
#include "myctype.h"
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>

int
readln(fp,buf)
FILE *fp ;
char *buf ;
{
    int i, j, k ;
    int ch ;
    int bytes ;
    extern int t_columns;

    i = 0 ;
    bytes = 0 ;
    while((ch = getc(fp)) != EOF) {
        bytes++ ;
        if(ch == '\n') {
            buf[i] = '\0' ;
            return bytes ;
        }
        if(ch == '\t') {
          k = (8 - (i % 8));
          if(k == 0) k = 8;
          for(j=0;j<k;j++) {
            buf[i++] = ' ';
            if(i == t_columns) {
              buf[i] = '\0' ;
              return bytes ;
            }
          }
        }
        if(myisprint(ch))
            buf[i++] = ch ;
        if(i == t_columns) {
            buf[i] = '\0' ;
            return bytes ;
        }
    }
    if(i == 0)
      return 0 ;
    else {
        buf[i] = '\0' ;
        return bytes ;
    }
}

int
more(filename,promptend)
char *filename ;
{
    FILE *fp ;
    int ch ;
    int i, j ;
    int viewed, pos ;
    long tsize ;
    struct stat st ;
    int numbytes ;
    int pagebreaks[1024];
    int pageno, linectr;
    char buf[129] ;
    char **page;
    extern int t_lines ;
    memset(pagebreaks, 0, sizeof(pagebreaks));

    if((fp = fopen(filename,"r")) == NULL) {
        return -1;
    }
    if(fstat(fileno(fp), &st)) {
        return -1;
    }
    tsize = st.st_size ;
    clear() ;

    if ((page = (char**)calloc(t_lines, sizeof(char*))) == NULL)
	return -1;
    for (i=0; i<t_lines-1; i++) {
	if ((page[i] = (char*) calloc (1, 129)) == NULL) {
	    for (; (i); i--) {
		if (page[i]) {
		    free(page[i]);
		    page[i] = NULL;
		}
	    }
	    free(page);
	    page = NULL;
	    return -1;
	}
    }

    i = 0 ;
    pos = 0 ;
    viewed = 0 ;
    pageno = linectr = 0;

    numbytes = readln(fp,buf) ;
    do {
        if(!numbytes)
          break ;
        viewed += numbytes ;
        if(pos == t_lines - 1) {
	    move (0, 0);
	    clrtobot();
	    for (j=1; j<pos; j++) {
		prints("%s\n", page[j]);
		if (*page[j])
		    strcpy(page[j-1], page[j]);
		else
		   *page[j-1] = '\0';
	    }
            pos-- ;
        }
        prints("%s\n",buf) ;
	if (*buf)
	    strcpy(page[pos], buf);
	else
	    *page[pos] = '\0';
        i++ ;
        pos++ ;
        if (++linectr == t_lines) {
            if (++pageno < 1024) pagebreaks[pageno] = viewed;
            linectr = 0;
        }
        numbytes = readln(fp,buf) ;
        if(!numbytes)
          break ;
        if(i == t_lines-1) {
            move(t_lines-1,0) ;
            if(!dumb_term) {
		extern int lang;

                standout() ;
		if (lang)
                  prints("-- ´õ -- (%d%%)",(viewed*100)/tsize) ;
		else
                  prints("--More-- (%d%%)",(viewed*100)/tsize) ;
                standend() ;
            } else
              bell() ;
            while((ch = igetch()) != EOF) {
                if(ch == ' ') {
                    move(t_lines-1,0) ;
                    clrtobot() ;
                    refresh() ;
                    i = 1 ;
                    break ;
                }
                if(ch == 'q') {
                    move(t_lines-1,0) ;
                    clrtobot() ;
                    refresh() ;
                    fclose(fp) ;
		    for (j=0; j<t_lines-1; j++) {
		      free(page[j]);
		    }
		    free(page);
                    return  0;
                }
                if(ch == '\r') {
                    move(t_lines-1,0) ;
                    clrtobot() ;
                    refresh() ;
                    i = t_lines-2 ;
                    break ;
                }
                if(ch == 'b') {
		    if (pageno >= 1 && pageno < 1024 && viewed < tsize) {
		        pageno--;
			viewed = pagebreaks[pageno];
		        fseek(fp, viewed, SEEK_SET);
			move(t_lines-1,0);
			clrtobot();
			i = linectr = 0;
			numbytes = readln(fp, buf);
			break;
		    }
                }
                bell() ;
            }
        }
    } while(numbytes) ;
    fclose(fp) ;
    move(t_lines-1,0) ;
    if(promptend)
      pressreturn() ;
    for (j=0; j<t_lines-1; j++) {
      free(page[j]);
    }
    free(page);
    return 0 ;
}
                                                                                                                                                                                                                                                                                                                                                                                                       DarkNET-1.08/pbbs/screen.c                                                                             644   21270   21270        34671  5731470362  10464                                                                                                                                                                                                                                                                                                                                                                      /*
    Pirate Bulletin Board System
    Copyright (C) 1990, Edward Luke, lush@Athena.EE.MsState.EDU
    Eagles Bulletin Board System
    Copyright (C) 1992, Raymond Rocker, rocker@rock.b11.ingr.com
                        Guy Vega, gtvega@seabass.st.usm.edu
                        Dominic Tynes, dbtynes@seabass.st.usm.edu

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 1, or (at your option)
    any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include <stdio.h>
#include "osdeps.h"
#include "io.h"
#include "screen.h"
#include "myctype.h"
#include <varargs.h>
#include <malloc.h>

extern char clearbuf[] ;
extern char cleolbuf[] ;
extern char scrollrev[] ;
extern char strtstandout[] ;
extern char endstandout[] ;
extern int clearbuflen ;
extern int cleolbuflen ;
extern int scrollrevlen ;
extern int strtstandoutlen ;
extern int endstandoutlen ;

extern int automargins ;

#define o_clear()     output(clearbuf,clearbuflen)
#define o_cleol()     output(cleolbuf,cleolbuflen) 
#define o_scrollrev() output(scrollrev,scrollrevlen)
#define o_standup()   output(strtstandout,strtstandoutlen)
#define o_standdown() output(endstandout,endstandoutlen)

int scrint = 0 ;
unsigned char scr_lns, scr_cols ;
unsigned char cur_ln = 0, cur_col = 0 ;
unsigned char roll ;
int scrollcnt ;
unsigned char docls ;
unsigned char downfrom ;
int standing = 0 ;


static struct screenline *big_picture = NULL ;

static int init_screen(slns,scols)
{
    scr_lns = slns ;
    scr_cols = MIN(scols,LINELEN) ;
    big_picture = (struct screenline *) calloc(scr_lns,
                                               sizeof(struct screenline)) ;
    for(slns=0;slns<scr_lns;slns++) {
        big_picture[slns].mode = 0 ;
        big_picture[slns].len = 0 ;
        big_picture[slns].oldlen = 0 ;
      }
    scrint = 1;
    docls = 1 ;
    downfrom = 0 ;
    roll = 0 ;
}

initscr()
{
    if (dumb_term)
	return 0;

    if (big_picture)
    {
	free(big_picture);
	big_picture = NULL;
    }
    init_screen(t_lines,t_columns) ;
    return 0;
}

fullscreen()
{
    return (scrint);
}

int tc_col, tc_line ;

rel_move(was_col,was_ln,new_col,new_ln)
{
    extern int ochar();
    extern char *BC ;

    if(new_ln >= t_lines  || new_col >= t_columns)
      return ;
    tc_col = new_col ;
    tc_line = new_ln ;
    if((new_col == 0) && (new_ln == was_ln+1)) {
        ochar('\n') ;
        if(was_col != 0)
          ochar('\r') ;
        return ;
    }
    if((new_col == 0) && (new_ln == was_ln)) {
        if(was_col != 0)
          ochar('\r') ;
        return ;
    }
    if(was_col == new_col && was_ln == new_ln)
      return ;
    if(new_col == was_col - 1 && new_ln == was_ln) {
        if(BC)
          tputs(BC,1,ochar) ;
        else
          ochar(CTRL('H'));
        return ;
    }
    
    do_move(new_col,new_ln,ochar) ;
}


standoutput(buf,ds,de,sso,eso)
char *buf ;
int ds,de,sso,eso ;
{
    int st_start, st_end ;

    if(eso <= ds || sso >= de) {
        output(buf+ds,de-ds) ;
        return ;
    }
    st_start = MAX(sso,ds) ;
    st_end = MIN(eso,de) ;
    if(sso > ds)
      output(buf+ds,sso-ds) ;
    o_standup() ;
    output(buf+st_start,st_end-st_start) ;
    o_standdown() ;
    if(de > eso)
      output(buf+eso,de-eso) ;
}

redoscr()
{
    register int i,j ;
    int ochar() ;
    register struct screenline *bp = big_picture ;

    if(dumb_term)
      return ;
    o_clear() ;
    tc_col = 0 ;
    tc_line = 0 ;
    for(i=0;i<scr_lns;i++) {
        j = (i+roll)%scr_lns ;
        if(bp[j].len == 0)
            continue ;
        rel_move(tc_col,tc_line,0,i) ;
        if(bp[j].mode&STANDOUT)
          standoutput(bp[j].data,0,bp[j].len,bp[j].sso,bp[j].eso) ;
        else 
          output(bp[j].data,bp[j].len) ;
        tc_col+=bp[j].len ;
        if(tc_col >= t_columns) {
            if(!automargins) {
                tc_col -= t_columns ;
                tc_line++ ;
                if(tc_line >= t_lines)
                  tc_line = t_lines - 1 ;
            }  else
              tc_col = t_columns-1 ;
        }
        bp[j].mode &= ~(MODIFIED) ;
        bp[j].oldlen = bp[j].len ;
    }
    rel_move(tc_col,tc_line,cur_col,cur_ln) ;
    docls = 0 ;
    scrollcnt = 0 ;
    oflush() ;
}

refresh()
{
    register int i,j ;
    register struct screenline *bp = big_picture ;
    extern int automargins ;
    extern int scrollrevlen ;

    if(dumb_term)
      return ;
    if(num_in_buf() != 0)
      return ;
    if((docls) || (abs(scrollcnt) >= (scr_lns-3)) ) {
        redoscr() ;
        return ;
    }
    if(scrollcnt < 0) {
        if(!scrollrevlen) {
            redoscr() ;
            return ;
        }
        rel_move(tc_col,tc_line,0,0) ;
        while(scrollcnt < 0) {
            o_scrollrev() ;
            scrollcnt++ ;
        }
    }
    if(scrollcnt > 0) {
        rel_move(tc_col,tc_line,0,t_lines-1) ;
        while(scrollcnt > 0) {
            ochar('\n') ;
            scrollcnt-- ;
        }
    }
    for(i=0;i<scr_lns;i++) {
        j = (i+roll)%scr_lns ;
        if(bp[j].mode&MODIFIED && bp[j].smod < bp[j].len) {
            bp[j].mode &= ~(MODIFIED) ;
            if(bp[j].emod >= bp[j].len)
              bp[j].emod = bp[j].len - 1 ;
            rel_move(tc_col,tc_line,bp[j].smod,i) ;
            if(bp[j].mode&STANDOUT)
              standoutput(bp[j].data,bp[j].smod,bp[j].emod+1,
                          bp[j].sso,bp[j].eso) ;
            else 
              output(&bp[j].data[bp[j].smod],bp[j].emod-bp[j].smod+1) ;
            tc_col = bp[j].emod+1 ;
            if(tc_col >= t_columns) {
                if(automargins) {
                    tc_col -= t_columns ;
                    tc_line++ ;
                    if(tc_line >= t_lines)
                      tc_line = t_lines - 1 ;
                } else
                  tc_col = t_columns-1 ;
            }
        }
        if(bp[j].oldlen > bp[j].len) {
            rel_move(tc_col,tc_line,bp[j].len,i) ;
            o_cleol() ;
        }
        bp[j].oldlen = bp[j].len ;
    }
    rel_move(tc_col,tc_line,cur_col,cur_ln) ;
    oflush() ;
}

clear()
{
    register int i ;

    if(dumb_term)
      return ;
    roll = 0 ;
    docls = 1 ;
    downfrom = 0 ;
    for(i=0 ;i<scr_lns;i++) {
        big_picture[i].mode = 0 ;
        big_picture[i].len = 0 ;
        big_picture[i].oldlen = 0 ;
    }
    move(0,0) ;
}

clrtoeol()
{
    register struct screenline *slp ;

    if(dumb_term)
      return ;
    standing = 0 ;
    slp = &big_picture[((cur_ln+roll)%scr_lns)] ;
    if(cur_col <= slp->sso)
      slp->mode &= ~STANDOUT ;
    if(cur_col > slp->oldlen) {
        register int i ;
        for(i=slp->len;i<=cur_col;i++)
          slp->data[i] = ' ' ;
    }
    slp->len = cur_col ;
}

clrtobot()
{
    register int i ;

    if(dumb_term)
      return ;
    for(i=cur_ln; i<scr_lns;i++) {
        big_picture[(i+roll)%scr_lns].mode = 0 ;
        big_picture[(i+roll)%scr_lns].len = 0 ;
        if(big_picture[(i+roll)%scr_lns].oldlen > 0)
          big_picture[(i+roll)%scr_lns].oldlen = 255 ;
    }
}

clrstandout()
{
    register int i ;
    if(dumb_term)
      return ;
    for(i=0;i<scr_lns;i++)
      big_picture[i].mode &= ~(STANDOUT) ;
}

static char nullstr[] = "(null)" ;

move(y,x)
{
    cur_col = x ;
    cur_ln = y ;
}

getyx(y,x)
int *y,*x ;
{
    *y = cur_ln ;
    *x = cur_col ;
}

outc(c)
register unsigned char c ;
{
    register struct screenline *slp ;

/*
    c &= 0x7f ;
*/
    if(dumb_term) {
/*
        if(!isprint(c)) {
*/
        if(!myisprint(c)) {
            if(c == '\n') {
                ochar('\r') ;
                ochar('\n') ;
                return ;
            }
            ochar('*') ;
            return ;
        }
        ochar(c) ;
        return ;
    }
    slp = &big_picture[((cur_ln+roll)%scr_lns)] ;
/*
    if(!isprint(c)) {*/  /* deal with non-printables */
    if(!myisprint(c)) {  /* deal with non-printables */
        if(c == '\n' || c == '\r') {  /* do the newline thing */
            if(standing) {
                slp->eso = MAX(slp->eso,cur_col) ;
                standing = 0 ;
            }
            if(cur_col > slp->len) {
                register int i ;
                for(i=slp->len;i<=cur_col;i++)
                  slp->data[i] = ' ' ;
            }
            slp->len = cur_col ;
            cur_col = 0 ;
            if(cur_ln < scr_lns)
              cur_ln++ ;
            return ;
        }
        c = '*' ; /* else substitute a '*' for non-printable */
    }
    if(cur_col >= slp->len) {
        register int i ;
        for(i=slp->len;i<cur_col;i++)
          slp->data[i] = ' ';
        slp->data[cur_col] = '\0' ;
        slp->len = cur_col+1 ;
    }
    if(slp->data[cur_col] != c) {
        if((slp->mode & MODIFIED) != MODIFIED)
          slp->smod = (slp->emod = cur_col) ;
        slp->mode |= MODIFIED ;
        if(cur_col > slp->emod)
          slp->emod = cur_col ;
        if(cur_col < slp->smod)
          slp->smod = cur_col ;
    }
    slp->data[cur_col] = c ;
    cur_col++ ;
    if(cur_col >= scr_cols) {
        if(standing && slp->mode&STANDOUT) {
            standing = 0 ;
            slp->eso = MAX(slp->eso,cur_col) ;
        }
        cur_col = 0 ;
        if(cur_ln < scr_lns)
          cur_ln++ ;
    }
}

outs(str)
register char *str ;
{
	while(*str != '\0')
		outc(*str++) ;
}

outns(str,n)
register char *str ;
register int n ;
{
    for(;n>0;n--)
      outc(*str++) ;
}


addch(ch)
{
    outc(ch) ;
}

scroll()
{
    if(dumb_term) {
        prints("\n") ;
        return ;
    }
    scrollcnt++ ;
    roll = (roll+1)%scr_lns ;  /* subtract one from roll mod scr_lns*/
    move(scr_lns-1,0) ;
    clrtoeol() ;
}

rscroll()
{
    if(dumb_term) {
        prints("\n\n") ;
        return ;
    }
    scrollcnt-- ;
    roll = (roll+(scr_lns-1))%scr_lns ;
    move(0,0) ;
    clrtoeol() ;
}

standout()
{
    register struct screenline *slp ;

    if(dumb_term  || !strtstandoutlen)
      return ;
    if(!standing) {
        slp = &big_picture[((cur_ln+roll)%scr_lns)] ;
        standing = 1 ;
        slp->sso = cur_col ;
        slp->eso = cur_col ;
        slp->mode |= STANDOUT ;
    }
}

standend()
{
    register struct screenline *slp ;

    if(dumb_term || !strtstandoutlen)
      return ;
    if(standing) {
        slp = &big_picture[((cur_ln+roll)%scr_lns)] ;
        standing= 0 ;
        slp->eso = MAX(slp->eso,cur_col) ;
    }
}

int dec[] = {1000000000,100000000,10000000,1000000,100000,10000,1000,100,10,1} ;
 
prints(va_alist)
va_dcl
{
	va_list ap ;
	register char *fmt ;
    char *bp ;
	register int i, count, hd, indx ;

	va_start(ap) ;
	fmt = va_arg(ap, char *) ;
	while(*fmt != '\0')
      {
          if(*fmt == '%')
            {
                int sgn = 1 ;
                int val = 0 ;
                int len,negi ;

                fmt++ ;
                while(*fmt == '-') {
                    sgn *= -1 ;
                    fmt++ ;
                }
                while(myisdigit(*fmt)) {
                    val *= 10 ;
                    val += *fmt - '0' ;
                    fmt++ ;
                }
                switch(*fmt)
                  {
                    case 's':
                      bp = va_arg(ap, char *) ;
                      if(bp == NULL)
                        bp = nullstr ;
                      if(val) {
                          register int slen = strlen(bp) ;
                          if(val <= slen)
                            outns(bp,val) ;
                          else if(sgn > 0) {
                              for(slen=val-slen;slen > 0; slen--)
                                outc(' ') ;
                              outs(bp) ;
                          } else {
                              outs(bp) ;
                              for(slen=val-slen;slen > 0; slen--)
                                outc(' ') ;
                          }
                      } else outs(bp) ;
                      break ;
                    case 'd':
                      i = va_arg(ap, int) ;

                      negi = 0 ;
                      if(i < 0)
                        {
                            negi = 1 ;
                            i *= -1 ;
                        }
                      for(indx=0;indx < 10;indx++)
                        if(i >= dec[indx])
                          break ;
                      if(i == 0)
                        len = 1 ;
                      else
                        len = 10 - indx ;
                      if(negi)
                        len++ ;
                      if(val >= len && sgn > 0) {
                          register int slen ;
                          for(slen = val-len;slen>0;slen--)
                            outc(' ') ;
                      }
                      if(negi)
                        outc('-') ;
                      hd = 1, indx = 0;
                      while(indx < 10)
                        {
                            count = 0 ;
                            while(i >= dec[indx])
                              {
                                  count++ ;
                                  i -= dec[indx] ;
                              }
                            indx++ ;
                            if(indx == 10)
                              hd = 0 ;
                            if(hd && !count)
                              continue ;
                            hd = 0 ;
                            outc('0'+count) ;
                        }
                      if(val >= len && sgn < 0) {
                          register int slen ;
                          for(slen = val-len;slen>0;slen--)
                            outc(' ') ;
                      }
                      break ;
                    case 'c':
                      i = va_arg(ap, int) ;
                      outc(i) ;
                      break ;
                    case '\0':
                      goto endprint ;
                    default:
                      outc(*fmt) ;
                      break ;
                  }
                fmt++ ;
                continue ;
            }
          
          outc(*fmt) ;
          fmt++ ;
      }
  endprint:
    
	return ;
}
,tc_line,cur_col,cur_ln) ;
    oflush() ;
}

clear()
{
    register intDarkNET-1.08/pbbs/stuff.c                                                                              644   21270   21270        21045  5745573365  10337                                                                                                                                                                                                                                                                                                                                                                      /*
    Pirate Bulletin Board System
    Copyright (C) 1990, Edward Luke

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 1, or (at your option)
    any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.


    Email address:
    lush@Athena.EE.MsState.EDU
*/

#include <stdio.h>
#include <sys/param.h>
#include <signal.h>
#include <malloc.h>
#include <fcntl.h>
#include <errno.h>
#include "osdeps.h"
#include "io.h"

#define MAXENVS (200)

#if NO_VFORK
#define vfork fork
#endif

#if 0
extern int in_child;     /* to let igetch() know when to select on fd 0 */
int gotsigchld;          /* for communication with SIGCHLD handler */
#endif

int g_child_pid = -1;

dumbreturn()
{
    int ch ;
    extern int lang;

    if (lang)
      prints("°è¼Ó ÇÏ½Ã·Á¸é [RETURN] À» Ä¡¼¼¿ä") ;
    else
      prints("Press [RETURN] to continue") ;
    while((ch = igetch()) != EOF)
        if(ch == '\n' || ch == '\r')
    	    break ;
}

pressreturn()
{
    char c[2] ;
    extern int lang;

    if (dumb_term) return (dumbreturn());
    if (lang)
      getdata(t_lines-1,0,"°è¼Ó ÇÏ½Ã·Á¸é [RETURN] À» Ä¡¼¼¿ä",c,2,NOECHO,0) ;
    else
      getdata(t_lines-1,0,"Press [RETURN] to continue",c,2,NOECHO,0) ;
    move(t_lines-1,0) ;
    clrtoeol() ;
    refresh() ;
    return 0 ;
}

bell()
{
    fprintf(stderr,"%c",CTRL('G')) ;
}

char *bbsenv[MAXENVS] ;
int numbbsenvs = 0 ;
 
bbssetenv(env,val)
char *env, *val ;
{
    register int i,len ;
 
    if(numbbsenvs == 0)
      bbsenv[0] = NULL ;
    len = strlen(env) ;
    for(i=0;bbsenv[i];i++)
      if(!strncasecmp(env,bbsenv[i],len) && bbsenv[i][len] == '=')
        break ;
    if(i>=MAXENVS)
      return -1 ;
    if(bbsenv[i])
      free(bbsenv[i]) ;
    else
      bbsenv[++numbbsenvs] = NULL ;
    bbsenv[i] = (char *)malloc(strlen(env)+strlen(val)+2) ;
    strcpy(bbsenv[i],env) ;
    strcat(bbsenv[i],"=") ;
    strcat(bbsenv[i],val) ;
}

#define LOOKFIRST  (0)
#define LOOKLAST   (1)
#define QUOTEMODE  (2)

static int timeout_occurred;
static void timeout_handler()
{
	timeout_occurred = 1;
	alarm(0);
}

do_exec(com,wd,timeout)
char *com, *wd ;
int timeout;
{
    char path[MAXFILELEN] ;
    char pcom[MAXCOMSZ] ;
    char *arglist[MAXARGS] ;
    register int i,len ;
    register int argptr ;
    int status, pid, w ;
    int pmode ;
    int saved_alarm ;
    void (*isig)(), (*qsig)(), (*asig)();
    extern int errno;

    strncpy(pcom,com,MAXCOMSZ) ;
    len = MIN(strlen(com)+1,MAXCOMSZ) ;
    pmode = LOOKFIRST ;
    for(i=0,argptr=0;i<len;i++) {
        if(pcom[i] == '\0')
          break ;
        if(pmode == QUOTEMODE) {
            if(pcom[i] == '\"') {
                pmode = LOOKFIRST ;
                pcom[i] = '\0' ;
                continue ;
            }
            continue ;
        }
        if(pcom[i] == '\"') {
            pmode = QUOTEMODE ;
            arglist[argptr++] = &pcom[i+1] ;
            if(argptr+1 == MAXARGS)
              break ;
            continue ;
        }
        if(pmode == LOOKFIRST)
          if(pcom[i] != ' ') {
              arglist[argptr++] = &pcom[i] ;
              if(argptr+1 == MAXARGS)
                break ;
              pmode = LOOKLAST ;
          } else continue ;
        if(pcom[i] == ' ') {
            pmode = LOOKFIRST ;
            pcom[i] = '\0' ;
        }
    }
    arglist[argptr] = NULL ;
    if(argptr == 0)
      return -1 ;
    strncpy(path,arglist[0],MAXFILELEN) ;
    refresh();
    reset_tty() ;
    saved_alarm = alarm(0);
    if((pid = vfork()) == 0) {
        if(wd)
          if(chdir(wd)) {
              fprintf(stderr,"Unable to chdir to '%s'\n",wd) ;
              exit(-1) ;
          }
        if(numbbsenvs == 0)
          bbsenv[0] = NULL ;
        execve(path,arglist,bbsenv) ;
        fprintf(stderr,"EXECVP FAILED... path = '%s'\n",path) ;
        exit(-1) ;
    }
    g_child_pid = pid;
    isig = signal(SIGINT, SIG_IGN);
    qsig = signal(SIGQUIT, SIG_IGN);
    asig = signal(SIGALRM, timeout_handler);

    if (timeout)
	alarm(timeout);

    errno = 0;
    if ((w = wait(&status)) != pid) {
	if (timeout_occurred) {
	  kill (pid, SIGTERM);
	}
    }

    if (saved_alarm)
	alarm(saved_alarm);

    signal(SIGINT, isig) ;
    signal(SIGQUIT, qsig) ;
    signal(SIGALRM, asig);
    g_child_pid = -1;
    restore_tty() ;
    if (w == -1) {
	if (timeout_occurred)
	    return -2;
	return -1;
    }
    return(status) ;
}

#define BINDIR "bin/"

do_pipe_more(com)
char *com ;
{
    char path[MAXPATHLEN] ;
    char pcom[MAXCOMSZ] ;
    char *arglist[MAXARGS] ;
    register int i,len ;
    register int argptr ;
    register char *lparse ;
    int status, pid, w, fd[2] ;
    int pmode ;
    int saved_alarm ;
    void (*isig)(), (*qsig)() ;
    extern int t_lines ;
    char buf[256] ;
    int buflen, bufchar ;
    strncpy(path,BINDIR,MAXPATHLEN) ;
    strncpy(pcom,com,MAXCOMSZ) ;
    len = MIN(strlen(com)+1,MAXCOMSZ) ;
    pmode = LOOKFIRST ;
    for(i=0,argptr=0;i<len;i++) {
        if(pcom[i] == '\0')
          break ;
        if(pmode == QUOTEMODE) {
            if(pcom[i] == '\001') {
                pmode = LOOKFIRST ;
                pcom[i] = '\0' ;
                continue ;
            }
            continue ;
        }

        if(pcom[i] == '\001') {
            pmode = QUOTEMODE ;
            arglist[argptr++] = &pcom[i+1] ;
            if(argptr+1 == MAXARGS)
              break ;
            continue ;
        }
        if(pmode == LOOKFIRST)
          if(pcom[i] != ' ') {
              arglist[argptr++] = &pcom[i] ;
              if(argptr+1 == MAXARGS)
                break ;
              pmode = LOOKLAST ;
          } else continue ;
        if(pcom[i] == ' ') {
            pmode = LOOKFIRST ;
            pcom[i] = '\0' ;
        }
    }
    arglist[argptr] = NULL ;
    if(argptr == 0)
      return -1 ;
    if(*arglist[0] == '/')
      strncpy(path,arglist[0],MAXPATHLEN) ;
    else
      strncat(path,arglist[0],MAXPATHLEN) ;
    if(pipe(fd) < 0) {
        perror("Pipe!") ;
        return -1 ;
    }
    saved_alarm = alarm(0);
    if((pid = vfork()) == 0) {
        close(fd[0]) ;
        close(0) ;
        open("/dev/null",O_RDONLY,0) ;
        dup2(fd[1],1) ;
        close(fd[1]) ;
        if(numbbsenvs == 0)
          bbsenv[0] = NULL ;
        execve(path,arglist,bbsenv) ;
        fprintf(stderr,"EXECV FAILED... path = '%s'\n",path) ;
        exit(-1) ;
    }
    close(fd[1]) ;
    buflen = 0 ;
    bufchar = 0 ;
    while(YEA) {
        int ch ;
        int chars ;
 
        move(3,0) ;
        clrtobot();
        for(i=3;i<t_lines-1;i++) {
            chars = 0 ;
            while(YEA) {
                if(bufchar == buflen) {
                    buflen = read(fd[0], buf, sizeof(buf)) ;
                    if(buflen <= 0) {
                        buflen = -1 ;
                        break ;
                    }
                    bufchar = 0 ;
                }
                while(bufchar!=buflen && buf[bufchar] != '\n') {
                    outc(buf[bufchar++]) ;
                    if(++chars == 78) {
                        outc('\n') ;
                        break ;
                    }
                }
                if(chars == 78)
                  break ;
                if(buf[bufchar] == '\n') {
                    outc(buf[bufchar++]) ;
                    break ;
                }
            }
            if(buflen == -1)
              break ;
        }
        if(buflen == -1 || i != t_lines-1)
          break ;
        standout() ;
        prints("-- More --") ;
        standend() ;
        clrtoeol() ;
        while((ch = igetch()) != EOF) {
            if(ch == '\n' || ch == '\r' || ch == ' ')
              break ;
            if(ch == 'q') {
                move(t_lines-1,0) ;
                clrtoeol() ;
                goto outahere ;
            }
            bell() ;
        }
    }
  outahere:
 
    clrtobot() ;
    close(fd[0]) ;
            
    isig = signal(SIGINT, SIG_IGN) ;
    qsig = signal(SIGQUIT, SIG_IGN) ;
    while((w = wait(&status)) != pid && w != 1)
      /* NULL STATEMENT */ ;
    if (saved_alarm) alarm(0);
    signal(SIGINT, isig) ;
    signal(SIGQUIT, qsig) ;
    return((w == -1)? w: status) ;
}
         if(argptr+1 == MAXARGS)
                break ;
              pmode = LOOKLAST ;
          } else continue ;
        if(pcom[i] == ' ') {
            pmode = LOOKFIRST ;
            pcom[i] = '\0' ;
        }
    }
    arglist[argptr] = NULL ;
    if(argptr == 0)
      return -1 ;
    strncpy(path,arglist[0],MAXFILELEN) ;
    refresh();
    reset_tty() ;
    saved_alarm = alarm(0);
    if((pid = vfork()) == 0) {
        if(wd)
          if(chdir(wd)) {
         DarkNET-1.08/pbbs/term.c                                                                               644   21270   21270        16000  5747642601  10142                                                                                                                                                                                                                                                                                                                                                                      /*
    Pirate Bulletin Board System
    Copyright (C) 1990, Edward Luke, lush@Athena.EE.MsState.EDU
    Eagles Bulletin Board System
    Copyright (C) 1992, Raymond Rocker, rocker@rock.b11.ingr.com
                        Guy Vega, gtvega@seabass.st.usm.edu
                        Dominic Tynes, dbtynes@seabass.st.usm.edu

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 1, or (at your option)
    any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include <stdio.h>
#include "osdeps.h"
#if NO_TERMIO
# include <sgtty.h>
#else
# include <termio.h>
#endif

#if NO_TERMIO

struct sgttyb tty_state, tty_new ;

get_tty()
{   
    if(gtty(1,&tty_state) < 0) {
        return(-1) ;
    }
    return 1 ;
}
  
init_tty()
{
    bcopy(&tty_state, &tty_new, sizeof(tty_new)) ;
    tty_new.sg_flags |= RAW ;
    tty_new.sg_flags &= ~(TANDEM|CBREAK|LCASE|ECHO|CRMOD) ;
    stty(1,&tty_new) ;
}

reset_tty()
{
    stty(1,&tty_state) ;
}
    
restore_tty()
{
    stty(1,&tty_new) ;
}

#else /* ! NO_TERMIO */

extern char *tgetstr();

struct termio tty_state, tty_new;

get_tty()
{
    if(ioctl(1,TCGETA,&tty_state) < 0) {
        return -1;
    }
#if LINUX == 1
    /* Hopefully temporary workaround for buggy login program. */
    tty_state.c_oflag |= OPOST;
    tty_state.c_iflag |= BRKINT;
    tty_state.c_lflag |= ISIG;
    tty_state.c_cc[VMIN] = 1;
#endif
    return 0;
}

init_tty()
{
    memcpy(&tty_new, &tty_state, sizeof(tty_new));
    tty_new.c_iflag &= IXANY;
    tty_new.c_iflag &= ~(ISTRIP);
    tty_new.c_oflag &= ~(OPOST | OLCUC | OCRNL);
    tty_new.c_lflag &= ~(ICANON | ISIG | XCASE | ECHO);
    tty_new.c_lflag |= TOSTOP;
    tty_new.c_cflag &= ~(PARENB | PARODD);
    tty_new.c_cflag |= CS8;
    tty_new.c_cc[VMIN] = 1;
    tty_new.c_cc[VTIME] = 0;
    if (ioctl(1,TCSETA,&tty_new) == -1) printf("ioctl failed\n");
}

reset_tty()
{
    ioctl(1,TCSETA,&tty_state) ;
}

restore_tty()
{
    ioctl(1,TCSETA,&tty_new) ;
}

#endif /* ! NO_TERMIO */

term_ok(term)
char *term;
{
   char tbuf[1024];
   if (tgetent(tbuf, term) != 1) return 0;
   return 1; 
}

#define TERMCOMSIZE (256)

int dumb_term = 1 ;

char clearbuf[TERMCOMSIZE] ;
int clearbuflen ;

char cleolbuf[TERMCOMSIZE] ;
int cleolbuflen ;

char cursorm[TERMCOMSIZE] ;
char *cm ;

char scrollrev[TERMCOMSIZE] ;
int scrollrevlen ;

char strtstandout[TERMCOMSIZE] ;
int strtstandoutlen ;

char endstandout[TERMCOMSIZE] ;
int endstandoutlen ;

int t_lines = 24;
int t_columns = 80 ;

int automargins ;

char *outp ;
int  *outlp ;

outcf(ch)
char ch ;
{
    if(*outlp >= TERMCOMSIZE)
        return ;
    (*outlp)++ ;
    *outp++ = ch ;
}

#include <sys/time.h>
#include <signal.h>

#define	TIMEOUT		30
#define	EMULATIONS	1

static char *getsize[EMULATIONS] =
	{
	"\0337\033[r\033[999;999H\033[6n",
	};

static char *size[EMULATIONS] = { "\033[%d;%dR" };
static char *restore[EMULATIONS] = { "\0338" };

static int readstring(fp, buf, str)
    register FILE *fp;
    register char *buf;
    char *str;
{
    register int last, c;
    struct itimerval it;
    extern int generic_abort();

    signal(SIGALRM, (void (*)())generic_abort);
    bzero((char *)&it, sizeof(struct itimerval));
    it.it_value.tv_sec = TIMEOUT;
    setitimer(ITIMER_REAL, &it, (struct itimerval *)NULL);
    if ((c = getc(fp)) == 0233) {   /* meta-escape, CSI */
        *buf++ = c = '\033';
        *buf++ = '[';
    } else
        *buf++ = c;
    if(c != *str) {
	generic_abort();
    }
    last = str[strlen(str) - 1];
    while((*buf++ = getc(fp)) != last) ;
    bzero((char *)&it, sizeof(struct itimerval));
    setitimer(ITIMER_REAL, &it, (struct itimerval *)NULL);
    *buf = 0;
}

term_init(term)
char *term ;
{
    extern char PC, *UP, *BC ;
    extern short ospeed ;
    static char UPbuf[TERMCOMSIZE] ;
    static char BCbuf[TERMCOMSIZE] ;
    static char buf[4096] ;
    char sbuf[4096] ;
    char *sbp, *s ;
    char *tgetstr() ;

#if NO_TERMIO
    ospeed = tty_state.sg_ospeed ;
#else
    ospeed = tty_state.c_cflag & CBAUD ;
#endif
    if(tgetent(buf, term) != 1)
        return -1;
    sbp = sbuf ;
    s = tgetstr("pc", &sbp) ; /* get pad character */
    if(s)
        PC = *s ;

    if (strcmp(term, "xterm") == 0 ||
	strcmp(term, "vt220") == 0 ||
	strcmp(term, "vt200") == 0 ||
	strcmp(term, "vt102") == 0 ||
	strcmp(term, "iyagi") == 0 ||
	strcmp(term, "vt52") == 0) { /* let's try this */

#if LINUX == 1
	struct winsize ws;
#else
	struct ttysize ts;
#endif
	int tty;
	int emu;
	int rows, cols;
	FILE *ttyfp;
	char buf[BUFSIZ];

	emu = 0;	/* currently only for xterm */
	ttyfp = fopen("/dev/tty", "r+");
	tty = fileno(ttyfp);
	write (tty, getsize[0], strlen(getsize[0]));
	readstring(ttyfp, buf, size[0]);
	if (strcmp(term, "iyagi") == 0)
		sscanf (buf, size[emu], &cols, &rows);
	else
		sscanf (buf, size[emu], &rows, &cols);
	write(tty, restore[emu], strlen(restore[emu]));
#if LINUX == 1
	if (ioctl (tty, TIOCGWINSZ, &ws) != -1) {
	  ws.ws_row = rows;
	  ws.ws_col = cols;
	  ioctl (tty, TIOCSWINSZ, &ws);
	}
#else
	if (ioctl (tty, TIOCGSIZE, &ts) != -1) {
	  ts.ts_lines = rows;
	  ts.ts_cols = cols;
	  ioctl (tty, TIOCSSIZE, &ts);
	}
#endif
	t_lines = rows;
	t_columns = cols;
    } else {
      t_lines = tgetnum("li") ;
      t_columns = tgetnum("co") ;
    }
    automargins = tgetflag("am") ;
    outp = clearbuf ;         /* fill clearbuf with clear screen command */
    outlp = &clearbuflen ;
    clearbuflen = 0 ;
    sbp = sbuf ;
    s = tgetstr("cl", &sbp) ;
    if(s)
        tputs(s,t_lines, outcf) ;
    outp = cleolbuf ;         /* fill cleolbuf with clear to eol command */
    outlp = &cleolbuflen ;
    cleolbuflen = 0 ;
    sbp = sbuf ;
    s = tgetstr("ce",&sbp) ;
    if(s)
        tputs(s,1,outcf) ;
    outp = scrollrev ;
    outlp = &scrollrevlen ;
    scrollrevlen = 0 ;
    sbp = sbuf ;
    s = tgetstr("sr",&sbp) ;
    if(s)
        tputs(s,1,outcf) ;
    outp = strtstandout ;
    outlp = &strtstandoutlen ;
    strtstandoutlen = 0 ;
    sbp = sbuf ;
    s = tgetstr("so",&sbp) ;
    if(s)
        tputs(s,1,outcf) ;
    outp = endstandout ;
    outlp = &endstandoutlen ;
    endstandoutlen = 0 ;
    sbp = sbuf ;
    s = tgetstr("se",&sbp) ;
    if(s)
        tputs(s,1,outcf) ;
    sbp = cursorm ;
    cm = tgetstr("cm",&sbp) ;
    if(cm)
        dumb_term = 0 ;
    else
        dumb_term = 1 ;
    sbp = UPbuf ;
    UP = tgetstr("up",&sbp) ;
    sbp = BCbuf ;
    BC = tgetstr("bc",&sbp) ;
    if(dumb_term) {
        t_lines = 24 ;
        t_columns = 80 ;
    }
    return 0;
}

do_move(destcol,destline,outc)
int destcol,destline ;
int (*outc)() ;
{
    tputs(tgoto(cm,destcol,destline), 1, outc) ;
}


DarkNET-1.08/pbbs/vedit.c                                                                              644   21270   21270        44054  5751540521  10311                                                                                                                                                                                                                                                                                                                                                                      /*
    Pirate Bulletin Board System
    Copyright (C) 1990, Edward Luke, lush@Athena.EE.MsState.EDU
    Eagles Bulletin Board System
    Copyright (C) 1992, Raymond Rocker, rocker@rock.b11.ingr.com
                        Guy Vega, gtvega@seabass.st.usm.edu
                        Dominic Tynes, dbtynes@seabass.st.usm.edu

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 1, or (at your option)
    any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include <stdio.h>
#include "osdeps.h"
#include <sys/stat.h>
#include "io.h"
#include "edit.h"
#include "myctype.h"

struct textline *firstline = NULL;
struct textline *lastline = NULL;

struct textline *currline = NULL;
int currpnt = 0;

struct textline *top_of_win = NULL;
int curr_window_line;
int redraw_everything;

static void vedit_help ();

void
indigestion (i)
{
  fprintf (stderr, "SERIOUS INTERNAL INDIGESTION CLASS %d\n", i);
}

struct textline *
back_line (pos, num)
     struct textline *pos;
{
  while (num-- > 0)
    if (pos && pos->prev)
      pos = pos->prev;
  return pos;
}

struct textline *
forward_line (pos, num)
     struct textline *pos;
{
  while (num-- > 0)
    if (pos && pos->next)
      pos = pos->next;
  return pos;
}

int
getlineno ()
{
  int cnt = 0;
  struct textline *p = currline;

  while (p != top_of_win)
    {
      if (p == NULL)
	break;
      cnt++;
      p = p->prev;
    }
  return cnt;
}

char *
killsp (s)
     char *s;
{
  while (*s == ' ')
    s++;
  return s;
}

struct textline *
alloc_line ()
{
  extern void *malloc ();
  register struct textline *p;

  p = (struct textline *) malloc (sizeof (*p));
  if (p == NULL)
    {
      indigestion (13);
      generic_abort ();
    }
  p->next = NULL;
  p->prev = NULL;
  p->data[0] = '\0';
  p->len = 0;
  return p;
}

/*
  Appends p after line in list.  keeps up with last line as well.
 */

void
append (p, line)
     register struct textline *p, *line;
{
  p->next = line->next;
  if (line->next)
    line->next->prev = p;
  else
    lastline = p;
  line->next = p;
  p->prev = line;
}

/*
  delete_line deletes 'line' from the list and maintains the lastline, and
  firstline pointers.
 */
void
delete_line (line)
     register struct textline *line;
{
  if (!line->next && !line->prev)
    {
      line->data[0] = '\0';
      line->len = 0;
      return;
    }
  if (line->next)
    line->next->prev = line->prev;
  else
    lastline = line->prev;
  if (line->prev)
    line->prev->next = line->next;
  else
    firstline = line->next;
  free (line);
}

/*
  split splits 'line' right before the character pos
 */
void
split (line, pos)
     register struct textline *line;
     register int pos;
{
  register struct textline *p = alloc_line ();

  if (pos > line->len)
    {
      free (p);
      return;
    }
  p->len = line->len - pos;
  line->len = pos;
  strcpy (p->data, (line->data + pos));
  *(line->data + pos) = '\0';
  append (p, line);
  if (line == currline && pos <= currpnt)
    {
      currline = p;
      currpnt -= pos;
      curr_window_line++;
    }
  redraw_everything = YEA;
}

/*
  join connects 'line' and the next line.  It returns true if:

  1) lines were joined and one was deleted
  2) lines could not be joined
  3) next line is empty

  returns false if:

  1) Some of the joined line wrapped
 */

int
join (line)
     register struct textline *line;
{
  register int ovfl;

  if (!line->next)
    return YEA;
  if (*killsp (line->next->data) == '\0')
    return YEA;
  ovfl = line->len + line->next->len - WRAPMARGIN;
  if (ovfl < 0)
    {
      strcat (line->data, line->next->data);
      line->len += line->next->len;
      delete_line (line->next);
      return YEA;
    }
  else
    {
      register char *s;
      register struct textline *p = line->next;

      s = p->data + p->len - ovfl - 1;
      while (s != p->data && *s == ' ')
	s--;
      while (s != p->data && *s != ' ')
	s--;
      if (s == p->data)
	return YEA;
      split (p, (s - p->data) + 1);
      if (line->len + p->len >= WRAPMARGIN)
	{
	  indigestion (0);
	  return YEA;
	}
      join (line);
      p = line->next;
      if (p->len >= 1 && p->len + 1 < WRAPMARGIN)
	{
	  if (p->data[p->len - 1] != ' ')
	    {
	      strcat (p->data, " ");
	      p->len++;
	    }
	}
      return NA;
    }
}

void
insert_char (ch)
     register int ch;
{
  register int i;
  register char *s;
  register struct textline *p = currline;
  int wordwrap = YEA;

  if (currpnt > p->len)
    {
      indigestion (1);
      return;
    }
  for (i = p->len; i >= currpnt; i--)
    p->data[i + 1] = p->data[i];
  p->data[currpnt] = ch;
  p->len++;
  currpnt++;
  if (p->len < WRAPMARGIN)
    return;
  s = p->data + (p->len - 1);
  while (s != p->data && *s == ' ')
    s--;
  while (s != p->data && *s != ' ')
    s--;
  if (s == p->data)
    {
      wordwrap = NA;
      s = p->data + (p->len - 2);
    }
  split (p, (s - p->data) + 1);
  p = p->next;
  if (wordwrap && p->len >= 1)
    {
      i = p->len;
      if (p->data[i - 1] != ' ')
	{
	  p->data[i] = ' ';
	  p->data[i + 1] = '\0';
	  p->len++;
	}
    }
  while (!join (p))
    {
      p = p->next;
      if (p == NULL)
	{
	  indigestion (2);
	  break;
	}
    }
}

void
insert_hangul (buf)
     char buf[];
{
  register int i;
  register char *s;
  register struct textline *p = currline;
  int wordwrap = YEA;

  if (currpnt > p->len)
    {
      indigestion (1);
      return;
    }
  for (i = p->len; i >= currpnt; i--)
    p->data[i + 2] = p->data[i];
  p->data[currpnt] = buf[0];
  p->data[currpnt+1] = buf[1];
  p->len += 2;
  currpnt += 2;
  if (p->len < WRAPMARGIN)
    return;
  s = p->data + (p->len - 1);
  while (s != p->data && *s == ' ')
    s--;
  while (s != p->data && *s != ' ')
    s--;
  if (s == p->data)
    {
      wordwrap = NA;
      s = p->data + (p->len - 2);
    }
  split (p, (s - p->data) + 1);
  p = p->next;
  if (wordwrap && p->len >= 1)
    {
      i = p->len;
      if (p->data[i - 1] != ' ')
	{
	  p->data[i] = ' ';
	  p->data[i + 1] = '\0';
	  p->len++;
	}
    }
  while (!join (p))
    {
      p = p->next;
      if (p == NULL)
	{
	  indigestion (2);
	  break;
	}
    }
}

void
delete_char ()
{
  register int i;

  if (currline->len == 0)
    return;
  if (currpnt >= currline->len)
    {
      indigestion (1);
      return;
    }
  for (i = currpnt; i != currline->len; i++)
    currline->data[i] = currline->data[i + 1];
  currline->len--;
}

void
delete_hangul ()
{
  register int i;

  if (currline->len < 2)
    return;
  if (currpnt >= currline->len)
    {
      indigestion (1);
      return;
    }
  for (i = currpnt; i != currline->len; i++)
    currline->data[i] = currline->data[i + 2];
  currline->len -= 2;
}

void
vedit_init ()
{
  register struct textline *p = alloc_line ();

  firstline = p;
  lastline = p;
  currline = p;
  currpnt = 0;
  top_of_win = p;
  curr_window_line = 0;
  redraw_everything = NA;
}

void
read_file (filename)
     char *filename;
{
  FILE *fp;
  int ch, state;
  char buf[2];

  if (currline == NULL)
    vedit_init ();
  if ((fp = fopen (filename, "r+")) == NULL)
    {
      if ((fp = fopen (filename, "w+")) != NULL)
	{
	  fclose (fp);
	  return;
	}
      indigestion (4);
      generic_abort ();
    }
  state = 0;
  while ((ch = getc (fp)) != EOF)
    {
      if (ishangul(ch))
	{
	  switch (state) {
	  case 0:
	    state = 1;
	    buf[0] = ch;
	    break;
	  case 1:
	    state = 0;
	    buf[1] = ch;
	    insert_hangul(buf);
	    break;
	  }
	}
      else
	{
	  if (myisprint (ch))
	    insert_char (ch);
	  else if (ch == '\n')
	    split (currline, currpnt);
	  state = 0;
	}
    }
  fclose (fp);
}

#define KEEP_EDITING -2

int
write_file (filename)
     char *filename;
{
  FILE *fp;
  struct textline *p = firstline;
  char abort[6];
  int aborted = 0;
  extern int lang;

  if (lang)
    getdata (0, 0, "(S)°¥¹«¸®, (A)Ãë¼Ò, (E)ÆíÁý? [S]: ", abort, 6, DOECHO, NULL, 0);
  else
    getdata (0, 0, "(S)ave, (A)bort, or (E)dit? [S]: ", abort, 6, DOECHO, NULL, 0);

  if (abort[0] == 'a' || abort[0] == 'A')
    {
      struct stat stbuf;
      if (stat (filename, &stbuf) || stbuf.st_size == 0)
	unlink (filename);
      aborted = -1;
    }
  else if (abort[0] == 'e' || abort[0] == 'E')
    return KEEP_EDITING;
  firstline = NULL;
  if (!aborted)
    {
      if ((fp = fopen (filename, "w")) == NULL)
	{
	  indigestion (5);
	  generic_abort ();
	}
    }
  while (p != NULL)
    {
      struct textline *v = p->next;
      if (!aborted)
	if (p->next != NULL || p->data[0] != '\0')
	  fprintf (fp, "%s\n", p->data);
      free (p);
      p = v;
    }
  if (!aborted)
    fclose (fp);
  currline = NULL;
  lastline = NULL;
  firstline = NULL;
  return aborted;
}

void
display_buffer ()
{
  register struct textline *p;
  register int i;

  for (p = top_of_win, i = 0; i < 24; i++)
    {
      move (i, 0);
      if (p)
	{
	  prints ("%s", p->data);
	  p = p->next;
	}
      else
	prints ("~");
      clrtoeol ();
    }
  return;
}

#define ESCAPE  (01)
#define VTKEYS  (02)
#define NORMAL  (00)

int vedit (filename)
     char *filename;
{
  int ch;
  int foo;
  int lastcharindent = -1;
  int mode = NORMAL;
  int firstkey = YEA;
  int state = 0;
  char buf[2];

  read_file (filename);
  top_of_win = firstline;
  currline = firstline;
  curr_window_line = 0;
  currpnt = 0;
  clear ();
  display_buffer ();
  move (t_lines - 1, 0);
  standout ();
  prints ("Type Ctrl-Z for help\n");
  standend ();
  move (curr_window_line, currpnt);
  while ((ch = igetch ()) != EOF)
    {
      if (firstkey)
	{
	  firstkey = NA;
	  move (0, 0);
	  clrtoeol ();
	  prints ("~\n~");
	}
      if (ch & 0x80)
	mode = NORMAL;
      switch (mode)
	{
	case ESCAPE:
	  switch (ch)
	    {
	    case '[':
	      mode = VTKEYS;
	      break;
	    case '>':
	      top_of_win = back_line (lastline, 23);
	      currline = lastline;
	      curr_window_line = getlineno ();
	      currpnt = 0;
	      redraw_everything = YEA;
	      mode = NORMAL;
	      break;
	    case '<':
	      top_of_win = firstline;
	      currline = top_of_win;
	      currpnt = 0;
	      curr_window_line = 0;
	      redraw_everything = YEA;
	      mode = NORMAL;
	      break;
	    case 'v':
	    case 'V':
	      top_of_win = back_line (top_of_win, 22);
	      currline = top_of_win;
	      currpnt = 0;
	      curr_window_line = 0;
	      redraw_everything = YEA;
	      mode = NORMAL;
	      break;
	    default:
	      bell ();
	      mode = NORMAL;
	      break;
	    }
	  state = 0;
	  break;
	case VTKEYS:
	  switch (ch)
	    {
	    case 'A':
	      ch = CTRL ('P');
	      break;
	    case 'B':
	      ch = CTRL ('N');
	      break;
	    case 'C':
	      ch = CTRL ('F');
	      break;
	    case 'D':
	      ch = CTRL ('B');
	      break;
	    default:
	      bell ();
	      mode = NORMAL;
	      break;
	    }
	  state = 0;
	  if (mode == NORMAL)
	    break;
	  mode = NORMAL;
	default:
	  if (ishangul(ch))
	    {
	      switch (state) {
	      case 0:
		state = 1;
		buf[0] = ch;
		break;
	      case 1:
		state = 0;
		buf[1] = ch;
		insert_hangul(buf);
		break;
	      } 
	      lastcharindent = -1;
	    }
	  else
	    {
	      state = 0;
	      if (myisprint (ch))
		{
		  insert_char (ch);
		  lastcharindent = -1;
		}
	      else
		{
		  switch (ch)
		    {
		    case CTRL ('P'):
		      if (lastcharindent == -1)
			lastcharindent = currpnt;
		      if (!currline->prev)
			{
			  bell ();
			  break;
			}
		      curr_window_line--;
		      currline = currline->prev;
		      currpnt = (currline->len > lastcharindent) ? lastcharindent : currline->len;
		      if (currpnt > 1)
			{
			  if (isHan(currline->data, currpnt) == 2)
			    currpnt--;
			}
		      break;
		    case CTRL ('N'):
		      if (lastcharindent == -1)
			lastcharindent = currpnt;
		      if (!currline->next)
			{
			  bell ();
			  break;
			}
		      currline = currline->next;
		      curr_window_line++;
		      currpnt = (currline->len > lastcharindent) ? lastcharindent : currline->len;
		      if (currpnt > 1)
			{
			  if (isHan(currline->data, currpnt) == 2)
			    currpnt--;
			}
		      break;
		    default:
		      lastcharindent = -1;
		      switch (ch)
			{
			case CTRL ('F'):
			  if (currline->len == currpnt)
			    {
			      if (!currline->next)
				{
				  bell ();
				  break;
				}
			      currpnt = 0;
			      curr_window_line++;
			      currline = currline->next;
			      break;
			    }
			  currpnt++;
			  if (currpnt < currline->len &&
			      isHan(currline->data, currpnt) == 2)
			     currpnt++;
			  break;
			case CTRL ('B'):
			  if (currpnt == 0)
			    {
			      if (!currline->prev)
				{
				  bell ();
				  break;
				}
			      curr_window_line--;
			      currline = currline->prev;
			      currpnt = currline->len;
			      break;
			    }
			  currpnt--;
			  if (currpnt > 0 &&
			      isHan(currline->data, currpnt) == 2)
			    {
			      currpnt --;
			    }
			  break;
			case CTRL ('G'):
			  clear ();
			  redraw_everything = YEA;
			  break;
			case CTRL ('Z'):
			  vedit_help ();
			  break;
			case CTRL ('V'):
			  {
			    struct textline *temp = forward_line (top_of_win, 22);
			    if (temp == lastline)
			      {
				bell ();
				break;
			      }
			    top_of_win = temp;
			  }
			  currline = top_of_win;
			  curr_window_line = 0;
			  currpnt = 0;
			  redraw_everything = YEA;
			  break;
			case CTRL ('A'):
			  currpnt = 0;
			  break;
			case CTRL ('E'):
			  currpnt = currline->len;
			  break;
			case CTRL ('X'):
			case CTRL ('W'):
			  clear ();
			  foo = write_file (filename);
			  if (foo != KEEP_EDITING)
			    return foo;
			case '\r':
			case '\n':
			  split (currline, currpnt);
			  break;
			case '\177':
			case CTRL ('H'):
			  if (currpnt == 0)
			    {
			      struct textline *p;
			      
			      if (!currline->prev)
				{
				  bell ();
				  break;
				}
			      curr_window_line--;
			      currline = currline->prev;
			      currpnt = currline->len;
			      if (*killsp (currline->next->data) == '\0')
				{
				  delete_line (currline->next);
				  redraw_everything = YEA;
				  break;
				}
			      
			      p = currline;
			      while (!join (p))
				{
				  p = p->next;
				  if (p == NULL)
				    {
				      indigestion (2);
				      generic_abort ();
				    }
				}
			      redraw_everything = YEA;
			      break;
			    }
			  currpnt--;
			  switch(isHan(currline->data, currpnt)) {
			  case 0:
			  case 1:
			    delete_char();
			    break;
			  case 2:
			    if (currpnt > 0) {
			      currpnt--;
			      delete_hangul();
			    } else {
			      delete_char();
			    }
			    break;
			  }
			  break;
			case CTRL ('D'):
			  if (currline->len == currpnt)
			    {
			      struct textline *p = currline;
			      
			      while (!join (p))
				{
				  p = p->next;
				  if (p == NULL)
				    {
				      indigestion (2);
				      generic_abort ();
				    }
				}
			      redraw_everything = YEA;
			      break;
			    }
			  switch (isHan(currline->data, currpnt)) {
			  case 0:
			  case 2:
			    delete_char ();
			    break;
			  case 1:
			    if (currline->len > 1)
			      delete_hangul();
			    else
			      delete_char();
			    break;
			  }
			  break;
			case CTRL ('K'):
			  if (currline->len == 0)
			    {
			      struct textline *p = currline->next;
			      
			      if (!p)
				{
				  p = currline->prev;
				  if (!p)
				    {
				      bell ();
				      break;
				    }
				  curr_window_line--;
				}
			      if (currline == top_of_win)
				top_of_win = p;
			      delete_line (currline);
			      currline = p;
			      redraw_everything = YEA;
			      break;
			    }
			  if (currline->len == currpnt)
			    {
			      struct textline *p = currline;
			      
			      while (!join (p))
				{
				  p = p->next;
				  if (p == NULL)
				    {
				      indigestion (2);
				      generic_abort ();
				    }
				}
			      redraw_everything = YEA;
			      break;
			    }
			  currline->len = currpnt;
			  currline->data[currpnt] = '\0';
			  break;
			case '\033':	/* ESC */
			  mode = ESCAPE;
			  break;
			default:
			  bell ();
			  break;
			}
		    }
		}
	    }
	  break;
	}
      if (curr_window_line == -1)
	{
	  curr_window_line = 0;
	  if (!top_of_win->prev)
	    {
	      indigestion (6);
	      bell ();
	    }
	  else
	    {
	      top_of_win = top_of_win->prev;
	      rscroll ();
	    }
	}
      if (curr_window_line == 24)
	{
	  curr_window_line = 23;
	  if (!top_of_win->next)
	    {
	      indigestion (7);
	      bell ();
	    }
	  else
	    {
	      top_of_win = top_of_win->next;
	      scroll ();
	    }
	}
      move (curr_window_line, 0);
      prints ("%s", currline->data);
      clrtoeol ();
      if (redraw_everything)
	display_buffer ();
      redraw_everything = NA;
      move (curr_window_line, currpnt);
    }
  return 0;
}

char *helptxt[] =
{
  "\01General Commands:",
  "Ctrl-X  Save and Exit (or Ctrl-W)",
  "Ctrl-L  Redraw Screen",
  "Ctrl-Z  Call up this help screen",
  "",
  "\01Cursor and Movement Commands:",
  "Ctrl-F  Forward character",
  "Ctrl-B  Backward character",
  "Ctrl-P  Previous line",
  "Ctrl-N  Next line",
  "Ctrl-V  Next Page",
  "ESC v   Previous Page",
  "ESC >   Goto end of file",
  "ESC <   Goto beginning of file",
  "Ctrl-A  Beginning of line",
  "Ctrl-E  End of line",
  "",
  "\01Deletion Commands:",
  "Ctrl-D  Delete character at cursor",
  "Ctrl-K  Delete to end of line",
  NULL};

static void vedit_help ()
{
  int i, off = 0, pos = 2;

  clear ();
  standout ();
  prints ("Editor Help Screen --------------------------------------- Press Any Key to Exit");
  standend ();
  for (i = 0; helptxt[i]; i++)
    {
      move (pos, off);
      if (helptxt[i][0] == '\01')
	{
	  standout ();
	  prints ("%s", &helptxt[i][1]);
	  standend ();
	}
      else
	prints ("%s", helptxt[i]);
      clrtoeol ();
      pos++;
    }
  move (23, 0);
  igetch ();
  clear ();
  redraw_everything = YEA;
}
   case '>':
	      top_of_win = back_line (lastline, 23);
	      currline = lastline;
	      curr_window_line = getlineno ();
	      currpnt = 0;
	      redraw_everything = YEA;
	      mode = NORMAL;
	      break;
	    case '<':
	      top_of_win = firstline;
	      currline = top_of_win;
	      currpnt = 0;
	      curr_window_line = 0;
	      redraw_everything = YEA;
	      mode = NORMAL;
	      break;
	    case 'v':
	    case 'V':
	      top_of_win = back_line DarkNET-1.08/pbbs/edit.h                                                                               644   21270   21270         2221  5647532325  10105                                                                                                                                                                                                                                                                                                                                                                      /*
    Pirate Bulletin Board System
    Copyright (C) 1990, Edward Luke, lush@Athena.EE.MsState.EDU
    Eagles Bulletin Board System
    Copyright (C) 1992, Raymond Rocker, rocker@rock.b11.ingr.com
                        Guy Vega, gtvega@seabass.st.usm.edu
                        Dominic Tynes, dbtynes@seabass.st.usm.edu

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 1, or (at your option)
    any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#define WRAPMARGIN (80)


struct textline {
    struct textline *prev ;
    struct textline *next ;
    int len ;
    char data[WRAPMARGIN + 1] ;
} ;

t (C) 1992, Raymond Rocker, rocker@rock.b11.ingr.com
                        Guy Vega, gtvega@seabass.st.usm.edu
                        Dominic Tynes, dbtynes@seabass.st.usm.edu

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either DarkNET-1.08/pbbs/io.h                                                                                 644   21270   21270         3410  5742136130   7556                                                                                                                                                                                                                                                                                                                                                                      /*
    Pirate Bulletin Board System
    Copyright (C) 1990, Edward Luke, lush@Athena.EE.MsState.EDU
    Eagles Bulletin Board System
    Copyright (C) 1992, Raymond Rocker, rocker@rock.b11.ingr.com
                        Guy Vega, gtvega@seabass.st.usm.edu
                        Dominic Tynes, dbtynes@seabass.st.usm.edu

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 1, or (at your option)
    any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#ifndef MIN
#define MIN(a,b) ((a<b)?a:b)
#endif

#ifndef MAX
#define MAX(a,b) ((a>b)?a:b)
#endif
 
#define DOECHO (1)      /* Flags to getdata input function */
#define NOECHO (0)

#define I_TIMEOUT   (-2)        /* Used for the getchar routine select call */
#define I_OTHERDATA (0xA0)      /* interface */
#define I_SIGNAL    (-4)

#define MAXCOMSZ   (1024) /* Maximum length of do_exec command */
#define MAXFILELEN (80)   /* Maximum length of the executable file name */
#define MAXARGS    (40)   /* Maximum number of args to a do_exec command */

#ifndef CTRL
#define CTRL(x)	(x&037)
#endif

#define YEA     1
#define NA      0

#if AUX
# define clear aux_clear
#endif

extern int dumb_term;
extern int t_lines;
extern int t_columns;
extern int scrint;
extern int g_child_pid;
                                                                                                                                                                                                                                                        DarkNET-1.08/pbbs/screen.h                                                                             644   21270   21270         3367  5731476424  10454                                                                                                                                                                                                                                                                                                                                                                      /*
    Pirate Bulletin Board System
    Copyright (C) 1990, Edward Luke, lush@Athena.EE.MsState.EDU
    Eagles Bulletin Board System
    Copyright (C) 1992, Raymond Rocker, rocker@rock.b11.ingr.com
                        Guy Vega, gtvega@seabass.st.usm.edu
                        Dominic Tynes, dbtynes@seabass.st.usm.edu

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 1, or (at your option)
    any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

/* Maximum Screen width in chars */
#define LINELEN (256)

/* Line buffer modes             */
#define MODIFIED (1)   /* if line has been modifed, output to screen   */
#define STANDOUT (2)   /* if this line has a standout region */

struct screenline {
    unsigned char oldlen ;       /* previous line length              */
    unsigned char len ;          /* current length of line            */
    unsigned char mode ;         /* status of line, as far as update  */
    unsigned char smod ;         /* start of modified data            */
    unsigned char emod ;         /* end of modified data              */
    unsigned char sso ;          /* start stand out */
    unsigned char eso ;          /* end stand out */
    unsigned char data[LINELEN] ;
} ;
                                                                                                                                                                                                                                                                         DarkNET-1.08/pbbs/hangul.c                                                                             644   21270   21270         1270  5733560133  10426                                                                                                                                                                                                                                                                                                                                                                      /*
 * Hangul.C for some editor functions.
 *
 * Programmed by Abraxas (Jeong-Hun Moon)
 * Program Date: Oct 14, 1994 (Fri)
 * Programed for.. Hana BBS.
 *
 * Version: 0.1 (Not programmed yet)
 */

#include <stdio.h>

/*
 * Function:  int isHan(char *string, int index)
 * Return Value:
 *      0 : if string[index] is simple ascii.
 *      1 : if string[index] is 1st char of hangul.
 *      2 : if string[index] is 2nd char of hangul.
 */

int
isHan(str, index)
	char	*str;
	int	index;
{
	int	i = 0;
	if(index < 0 || index >= strlen(str))
		return 0;
	for(;index >= 0; str++, index--) {
		if(!((*str) & 0x80))
			i = 0;		/* clear status */
		else if(i == 1) i = 2;
		else i = 1;
	}
	return i;
}
                                                                                                                                                                                                                                                                                                                                        DarkNET-1.08/config/                                                                                   755   21270   21270            0  6044657544   7247                                                                                                                                                                                                                                                                                                                                                                      DarkNET-1.08/config/COPYING                                                                            644   21270   21270        43252  5736655626  10423                                                                                                                                                                                                                                                                                                                                                                                          GNU GENERAL PUBLIC LICENSE
                       Version 2, June 1991

 Copyright (C) 1989, 1991 Free Software Foundation, Inc.
                          675 Mass Ave, Cambridge, MA 02139, USA
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.

                             Preamble

  The licenses for most software are designed to take away your
freedom to share and change it.  By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users.  This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it.  (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.)  You can apply it to
your programs, too.

  When we speak of free software, we are referring to freedom, not
price.  Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.

  To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.

  For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have.  You must make sure that they, too, receive or can get the
source code.  And you must show them these terms so they know their
rights.

  We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.

  Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software.  If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.

  Finally, any free program is threatened constantly by software
patents.  We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary.  To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.

  The precise terms and conditions for copying, distribution and
modification follow.

                    GNU GENERAL PUBLIC LICENSE
   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

  0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License.  The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language.  (Hereinafter, translation is included without limitation in
the term "modification".)  Each licensee is addressed as "you".

Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope.  The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.

  1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.

You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.

  2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:

    a) You must cause the modified files to carry prominent notices
    stating that you changed the files and the date of any change.

    b) You must cause any work that you distribute or publish, that in
    whole or in part contains or is derived from the Program or any
    part thereof, to be licensed as a whole at no charge to all third
    parties under the terms of this License.

    c) If the modified program normally reads commands interactively
    when run, you must cause it, when started running for such
    interactive use in the most ordinary way, to print or display an
    announcement including an appropriate copyright notice and a
    notice that there is no warranty (or else, saying that you provide
    a warranty) and that users may redistribute the program under
    these conditions, and telling the user how to view a copy of this
    License.  (Exception: if the Program itself is interactive but
    does not normally print such an announcement, your work based on
    the Program is not required to print an announcement.)

These requirements apply to the modified work as a whole.  If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works.  But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.

Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.

In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.

  3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:

    a) Accompany it with the complete corresponding machine-readable
    source code, which must be distributed under the terms of Sections
    1 and 2 above on a medium customarily used for software interchange; or,

    b) Accompany it with a written offer, valid for at least three
    years, to give any third party, for a charge no more than your
    cost of physically performing source distribution, a complete
    machine-readable copy of the corresponding source code, to be
    distributed under the terms of Sections 1 and 2 above on a medium
    customarily used for software interchange; or,

    c) Accompany it with the information you received as to the offer
    to distribute corresponding source code.  (This alternative is
    allowed only for noncommercial distribution and only if you
    received the program in object code or executable form with such
    an offer, in accord with Subsection b above.)

The source code for a work means the preferred form of the work for
making modifications to it.  For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable.  However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.

If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.

  4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License.  Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.

  5. You are not required to accept this License, since you have not
signed it.  However, nothing else grants you permission to modify or
distribute the Program or its derivative works.  These actions are
prohibited by law if you do not accept this License.  Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.

  6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions.  You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.

  7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License.  If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all.  For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.

If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.

It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices.  Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.

This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.

  8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded.  In such case, this License incorporates
the limitation as if written in the body of this License.

  9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time.  Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.

Each version is given a distinguishing version number.  If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation.  If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.

  10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission.  For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this.  Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.

                            NO WARRANTY

  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.

  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.

                       END OF TERMS AND CONDITIONS

        Appendix: How to Apply These Terms to Your New Programs

  If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.

  To do so, attach the following notices to the program.  It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.

    <one line to give the program's name and a brief idea of what it does.>
    Copyright (C) 19yy  <name of author>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

Also add information on how to contact you by electronic and paper mail.

If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:

    Gnomovision version 69, Copyright (C) 19yy name of author
    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
    This is free software, and you are welcome to redistribute it
    under certain conditions; type `show c' for details.

The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License.  Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.

You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary.  Here is a sample; alter the names:

  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
  `Gnomovision' (which makes passes at compilers) written by James Hacker.

  <signature of Ty Coon>, 1 April 1989
  Ty Coon, President of Vice

This General Public License does not permit incorporating your program into
proprietary programs.  If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library.  If this is what you want to do, use the GNU Library General
Public License instead of this License.
), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.

  6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or DarkNET-1.08/config/access                                                                             644   21270   21270        20154  5751546476  10547                                                                                                                                                                                                                                                                                                                                                                      # This is the bbs access file. For each function in libbbs.a, and a few
# more, a line here is required to tell the bbs what permissions are
# necessary to access each function. Be sure not to delete any of the 
# non-comments or no one will have access to some functions.
#
# For each function:
# ALL means all users can do this, regardless of permission bits.
# NONE means no users can do this. Not even Sysops.
# Strings from the permstrs file (see it for more info) are used to 
# restrict access to users with those permissions. For example the sysop
# functions have "Sysop". You can list more than one, separated by commas.
# 
#
# C_INIT         0   Initialize the bbs (read in the bbconfig file)
Initialize=ALL
# C_CONNECT      1   Connect to the bbs
Connect=ALL
# C_DISCONNECT   2   Disconnect from the bbs
Disconnect=ALL
# C_ISSUE        3   Read the issue file
GetIssue=ALL
# C_WELCOME      4   Read the welcome screen
GetWelcome=ALL
#
# Note: NEWLOGIN should stay ALL here. This is actually controlled in
# bbconfig file; if "new=yes" is not in it the NEWLOGIN command will be
# denied anyway.
#
# C_NEWLOGIN     5   Create a new account at the login prompt
NewLogin=ALL
# C_LOGIN        6   Log into the bbs
Login=ALL
# C_ADDACCT      7   Add an account from the Admin Menu
AddAccount=AccountMgr
# C_DELACCT      8   Delete an account
DeleteAccount=AccountMgr
# C_QUERY        9   Query an account
Query=ALL
# C_OWNINFO     10   Get complete info for your own account
GetOwnInfo=ALL
# C_GETACCT     11   Get complete info on any account
GetAnyInfo=AccountMgr
# C_SETMODE     12   Set your mode (Reading, Posting, Chat, etc.)
SetMode=ALL
# C_SETPASSWD   13   Change your password
SetPassword=ALL
# C_SETUSERNAME 14   Change your username
SetUsername=ALL
# C_SETTERMINAL 15   Change your terminal type
SetTerminal=ALL
# C_SETEMAIL    16   Change your email address
SetAddress=ALL
# C_SETPERMS    17   Change permissions for any account
SetPermissions=Sysop
# C_SETACCT     18   Set information for any account
SetAccountInfo=AccountMgr
# C_ALLUSERS    19   List all accounts 
AllUsers=ALL
# C_USERS       20   List all logged-in users
Users=ALL
# C_ALLNAMES    21   Get list of all account userids
AllNames=ALL
# C_NAMES       22   Get list of all logged-in userids
Names=ALL
# C_INFOFILE    23   Read the bbs information file
GetInfoFile=ALL
# C_GNUFILE     24   Read the GNU General Public License
GetGNUFile=ALL
# C_GETPLAN     25   Read any user's plan
GetPlan=ALL
# C_SETPLAN     26   Set your own plan
SetPlan=ALL
# C_CLOAK       27   Hide from other users
Cloak=Cloak
# C_EXEMPT      28   Mark an account as exempt from user cleans
ExemptUser=AccountMgr
# C_GETPERMSTRS 29   Get the list of permission names
GetPermStrings=AccountMgr,BoardMgr
# C_CHKMAIL     30   Check to see if you have unread mail
CheckMail=ALL
# C_MAIL        31   Send mail to other bbs users
SendMail=ALL
# C_OPENMAIL    32   Open for own mailbox for reading
OpenMail=ALL
# C_CLOSEBRD    33   Close a mailbox, board, or file board
CloseBoard=ALL
# C_ENUMHDRS    34   Get mail or post header information
EnumHeaders=ALL
# C_READMSG     35   Read a mail message or post
ReadMessage=ALL
#
# Note: DELMSG, DELRANGE, MARKMSG, and REPLACEMSG should remain accessible
# to ALL in this file, unless you want these functions to be inaccessible 
# to the per-board Managers. A user must have Manager permission when opening
# a board for these rights to be granted.
#
# C_DELMSG      36   Delete a mail message or post
DeleteMessage=ALL
# C_DELRANGE    37   Delete a range of mail messages or posts
DeleteRange=ALL
# C_MARKMSG     38   Mark a post for non-deletion
MarkMessage=ALL
# C_SETWELCOME  39   Modify or delete the welcome screen
EditWelcome=WelcomeMgr
# C_ADDBOARD    40   Create a new board for posting
AddBoard=BoardMgr
# C_DELBOARD    41   Delete a board and all posts on it
DeleteBoard=BoardMgr
# C_GETBOARD    42   Get information about a board
GetBoardInfo=ALL
# C_SETBOARD    43   Set information about a board
SetBoardInfo=BoardMgr
# C_ENUMBRDS    44   Return information about all boards
EnumBoards=ALL
# C_BNAMES      45   Get a list of all board names
BoardNames=ALL
# C_VISITBRD    46   Mark all posts on a board or boards as read
VisitBoard=ALL
# C_POST        47   Post a message on a board
Post=ALL
# Note: Since each board has its own access masks in the boardlist,
# things like OPENBRD, GETBOARD, ENUMBRDS, etc. will only reveal the
# boards to which the user has access. OPENBRD and TESTBRD return to 
# the user flags telling if they have Post or Manager access.
#
# C_OPENBRD     48   Open a public board for reading
OpenBoard=ALL
# C_TESTBRD     49   Find out whether you can post on or manage a board
TestBoard=ALL
# C_REPLACEMSG  50   Edit a message on a board (see note above)
ReplaceMessage=ALL
# C_ZAPBOARD    51   Mark a board to not be scanned for new messages
ZapBoard=ALL
# C_GETBMGRLIST 52   Get list of managers for a board
GetBoardMgrs=BoardMgr
# C_SETBMGRLIST 53   Set list of managers for a board
SetBoardMgrs=BoardMgr
# C_ENUMFBRDS   54   Return information about all file boards
EnumFileBoards=ALL
# C_FBNAMES     55   Get a list of all file board names
FileBoardNames=ALL
# C_OPENFBRD    56   Open a file board for viewing or downloading
OpenFileBoard=ALL
# C_PROTONAMES  57   Get a list of all protocol names for UL/DL
ProtocolNames=ALL
# C_SETPROTO    58   Set your protocol for UL/DL
SetProtocol=ALL
# C_UPLOAD      59   Upload a file, if an UPLOAD board is configured
Upload=NONE
# C_DOWNLOAD    60   Download a file from the open file board
Download=ALL
# NOTE: The chat client doesn't support read-only chat, nor honor the
# value of C_EXITCHAT for obvious reasons. C_EXITCHAT and C_CHATLINE
# are available to whoever has C_CHAT.
#
# C_CHAT        61   Enter the Chat system
Chat=ALL
# C_EXITCHAT    62   Exit the Chat system
ExitChat=ALL
# C_CHATLINE    63   Send a line to the chat daemon
TalkInChat=ALL
# C_KICK        64   Kick a logged-in user off of the system
Kick=Sysop
# C_TALK        65   Page another user for private talk
Page=ALL
# C_EXITTALK    66   Exit a private talk
EndTalk=ALL
# C_GETTALKREQ  67   Find out who is paging you
GetPageRequest=ALL
# C_TALKACCEPT  68   Accept a page
AcceptPage=ALL
# C_TALKREFUSE  69   Refuse a page
RefusePage=ALL
# C_SETPAGER    70   Set your paging status
SetPager=ALL
# C_GETOVERLIST 71   Get your override/deny list for paging
GetOverrides=ALL
# C_SETOVERLIST 72   Set your override/deny list for paging
SetOverrides=ALL
# C_FORWARDMSG  73   Forward a message to your email address
ForwardMessage=ALL
# C_FORWARDFILE 74   Forward a file to your email address
ForwardFile=ALL
#
# These next three should be NONE if you aren't offering any editors
# except the builtin one to local users (see editors file).
#
# C_SETEDITOR   75   Set your editor for mailing/posting
SetEditor=ALL
# C_GETEDITOR   76   Get the name of your last selected editor
GetEditor=NONE
# C_ENUMEDITORS 77   List all editors available through the bbs
EnumEditors=NONE
# C_GETSIGFILE  78   Signature file for mail/posts
GetSignature=ALL
# C_SETSIGFILE  79   Signature file
SetSignature=ALL
# 
# These do not correspond to commands, but are used by the server for
# filtering the information returned by some commands.
#
# C_SEEALLAINFO 80   See account flags in bbs_query, etc.
SeeAllAccountInfo=AccountMgr
# C_SEEALLBINFO 81   See board permission masks in bbs_get_board, etc.
SeeAllBoardInfo=BoardMgr
# C_ALLBOARDMGR 82   Have manager permission on all boards automatically.
ManageAllBoards=BoardMgr
# C_SEECLOAK    83   See cloaked users in bbs_enum_users, etc.
SeeCloaked=SeeCloak
# C_SEEREALNAME 84   See real names in bbs_query IF showreal is enabled.
SeeRealName=Basic-1
# C_NOTIMEOUT   85   Immunity to the local client's idle timer
NoIdleTimeout=Sysop
# C_IRC		86
Irc=ALL
# C_SETLANG	87
SetLang=ALL
# C_DELME	88
DeleteMe=ALL
# C_XIT        89
Xit=ALL
# C_SENDMAIL   90
NetMailSend=ALL
# C_FTPPOST    91
FtpPost=ALL
# C_ROUTING	92
Routing=ALL
# C_ADMINMENU   93
# C_FILEMENU    94
# C_MAILMENU    95
# C_TALKMENU    96
# C_XYZMENU     97
# C_GETMODESTRS 98
# C_GETMODECHRS 99

#
# More can go here, for use in configurable menus.
# ONLY ADD NEW ENTRIES BELOW THIS POINT!
#
AdminMenu=Sysop,AccountMgr,BoardMgr
ShellEscape=Sysop
# etc.
Mgr
# C_GETPERMSTRS 29   Get the list of permission names
GetPermStrings=AccountMgr,BoardMgr
# C_CHKMAIL     30   Check to see if you have unread mail
CheckMail=ALL
# C_MAIL        31   Send mail to other bbs users
SendMail=ALL
# C_OPENMAIL    32   Open for own mailbox for reading
OpenMail=ALL
# C_CLOSEBRD    33   Close a mailbox, board, or file board
CloseBoard=ALL
# C_ENUMHDRS    34   Get mail or poDarkNET-1.08/config/bbconfig                                                                           644   21270   21270         4712  6044657256  11034                                                                                                                                                                                                                                                                                                                                                                      # This is the main bbs config file. It MUST exist or the bbs will not run.
#
# Startup information is given here in name=value form. The things you
# specify here are:
#
# name: The name of your bbs. Up to 40 chars. Default=The Unknown BBS.
# new: If yes, users can enter 'new' at the login prompt and create
#      their own accounts. Otherwise they can't. Default=no.
# users: How many users can log in at once. Base this on the capacity
#      of your system, mainly on RAM. Default=80.
#      NOTE: If you INCREASE this number, you must kill ALL bbs processes
#      and remove the shared memory segment. If you have an "ipcrm" utility
#      that is best, or rebooting will work.
# logfile: The location of the bbs log file. Default=~/log.
# loglevel: Controls what events get written to the logfile. Default=1.
#      Higher numbers mean more logging.
#      System errors are always logged.
#      Level 1: Logins, logouts, and account creations
#      Level 2: Administrative actions
#      Level 3: Posts, uploads, downloads, forwards.
#      Level 4: Entries to chat/talk.
# logons: The number of times users can log onto the bbs at once.
#      Zero means unlimited. Use entries in the ~/etc/logons file to
#      override this default value.
# siglines: The maximum number of lines from a signature file to be appended
#      to posts and mail. If zero, signature is not appended.
#      Default=4.
# showreal: If yes, the real name of a user is returned with a Query.
#      Default=no. If yes, can be further restricted with the SeeRealName
#      setting in the access file.
# timeout: After this many minutes of no input, the local client may time 
#      out and boot a user. This is imprecise and the actual time before 
#      boot may range from 1 to 2 times this value. In Monitor mode, the
#      timeout is exactly 2 times this value. Default is 0, meaning no idle 
#      timeout. May be overridden with the NoIdleTimeout setting in the
#      access file. 
# mailer: The mail program (and flags) to use for forwarding.
#      Default=/usr/lib/sendmail. Adding the -odq flag (queue instead of 
#      deliver immediately) can be a big help if much forwarding is done.
# encoder: Needed if you have binary files in your file section and want
#      to allow forwarding of them. Put the path to uuencode here.
#
name=The DarkNET BBS
new=yes
users=60
usertablesize=60
logfile=log
loglevel=4
logons=0
siglines=8
showreal=no
timeout=60
mailer=/usr/lib/sendmail
encoder=/usr/bin/uuencode
                                                      DarkNET-1.08/config/ad.dark.en                                                                         644       0       1           62  6044657544  10673                                                                                                                                                                                                                                                                                                                                                                      Today's Ad:          Welcome to DarkNET, K.E.R.I.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              DarkNET-1.08/config/boardlist                                                                          644   21270   21270          364  5736664763  11235                                                                                                                                                                                                                                                                                                                                                                      # This is the list of public message boards on the bbs. DO NOT edit this
# file by hand unless you know what you are doing! The Admin Menu has
# functions for managing this file safely.
#
# To add a board, select (N)ew Board on the Admin menu.
                                                                                                                                                                                                                                                                            DarkNET-1.08/config/chatconfig                                                                         644   21270   21270          765  5736655626  11362                                                                                                                                                                                                                                                                                                                                                                      # This is an optional configuration file used by the chat daemon.
# 
# mainroom: allows the name of the main chat room to be set. Default=main.
# operators: list of chat "super-ops", separated by commas or spaces.
#   Operators can kick out troublemakers from any room, and see/enter all
#   locked and secret rooms.
# restricted: list of restricted accounts that cannot use /join, /rooms,
#   or see users in rooms besides the main room.
#
#mainroom=main
#operators=SYSOP,anotherop
#restricted=guest
           DarkNET-1.08/config/chathlp.txt                                                                        644   21270   21270         2266  5736655626  11534                                                                                                                                                                                                                                                                                                                                                                      # This is the main Chat client help file, used by the /h command.
# Blank lines do get displayed. Don't use tabs in here.
#

/me <text>       Action: display <text> as an action
/c               Clear: reset screen to initial state
/e <text>        Exit: leave chat (also CTRL-C)
/f [+,-][ls]     Flags: set or unset room flags (Op only)
/h               Help: get this help message
/i <nick>        Invite: give <nick> a key to the room (Op only)
/j <room>        Join: join a new or existing room
/k <nick>        Kick: boot <nick> back to main room (Op only)
/l <range>       List: verbose list of logged-in users
/m <nick> <text> Message: send <text> privately to <nick>
/n <nick>        Nick: change your chatid to <nick>
/o <nick>        Op: make <nick> an Op in this room (Op only)
/q <userid>      Query: query an account on the bbs
/r               Rooms: list all active rooms, except secret rooms
/u <range>       Users: compact list of logged-in users
/w <range>       Who: list all users in chat, excluding secret rooms
/whoin <room>    WhoIn: Same as /w but only list one room
/whois <nick>    WhoIs: Identify a nick or all nicks by chatid
/x               Xtra Help: yet another help screen
                                                                                                                                                                                                                                                                                                                                          DarkNET-1.08/config/chatxhlp.txt                                                                       644   21270   21270         1176  5736655626  11723                                                                                                                                                                                                                                                                                                                                                                      # This is the extra Chat client help file, used by the /x command.
# Blank lines do get displayed. Don't use tabs in here.
#

INPUT LINE EDITING CONTROLS:
Ctrl-A     Beginning of line
Ctrl-B     Backward one character
Ctrl-D     Delete character under cursor
Ctrl-E     End of line
Ctrl-F     Forward one character
Ctrl-H     Delete character before cursor
Ctrl-U     Clear entire line
Ctrl-W     Delete word under or prior to cursor
ESC B      Backward one word
ESC F      Forward one word

ROOM FLAGS used with /f command:
l          Locked: Only users invited with /i can enter
s          Secret: Room and users invisible to /u and /w
                                                                                                                                                                                                                                                                                                                                                                                                  DarkNET-1.08/config/editors                                                                            644   21270   21270         2066  6044657514  10731                                                                                                                                                                                                                                                                                                                                                                      # This is the optional editor config file. You can offer alternate editors
# to the builtin one here if you like.
#
# WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
# DO NOT put your favorite shell editors here. Most editors can do lots
# of things you do NOT want bbs users to do! Like: escape to a shell,
# pipe shell commands, write or bring up files other than the one they're 
# editing. Your bbs can be BLOWN AWAY quite easily. You should only install 
# editors here that you have modified to be safe. You have been warned.
#
# The builtin editor need only be uncommented if there are other choices too.
# The builtin editor is always used as the default.
#
# The environment field uses the same format and substitution rules for 
# %I, %U, %T, %E, %H as described in the menu.desc file.
#
# Format: <editor-name>:<full-path-with-flags>:<environment>:<comment>
#
#builtin:::Builtin editor (no path or environment needed)
builtin:::Builtin editor (no path or environment needed)
PICO:/usr1/bbs/bin/pico::Pico Editor
VI:/usr1/bbs/bin/vi::VI Editor
                                                                                                                                                                                                                                                                                                                                                                                                                                                                          DarkNET-1.08/config/ftplist                                                                            644   21270   21270         1040  5736655626  10745                                                                                                                                                                                                                                                                                                                                                                      # This is the list of directories that contain files for uploading and
# downloading. At this time you must set it up by hand. The format of
# records in this file is:
#
# board-name:full-directory-path:optional-description-of-files
#
# The special board-name UPLOAD designates the directory uploads go to.
# You can point a download directory to it too if you like.
#
# Examples:
#
# EaglesBBS:/usr/src/eagles-bbs.3.0:Eagles BBS 3.0 source
# UPLOAD:/usr/bbs/files/incoming:
# Source:/usr/bbs/files/source:You can quote colons like this\: see.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                DarkNET-1.08/config/info                                                                               644   21270   21270         1257  6044657676  10225                                                                                                                                                                                                                                                                                                                                                                      The DarkNET BBS                       Version 1.0
Copyright (C) 1995                    Yoo-Eup Hyung

Under Bulletin Board System           Version 1.0
Copyright (C) 1995                    Daeshik Kim

Based in part on:
Eagles Bulletin Board System          Version: 3.0-BETA
Copyright (C) 1992-1994               Raymond R. Rocker
Pirate Bulletin Board System          Version: 1.00
Copyright (C) 1990                    Edward A. Luke

This BBS comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to distribute it under
certain conditions as described in the GNU GENERAL PUBLIC LICENSE.
Use the (G)nu command in the (X)yz menu to find out more information.
                                                                                                                                                                                                                                                                                                                                                 DarkNET-1.08/config/issue                                                                              644   21270   21270          245  6044657737  10374                                                                                                                                                                                                                                                                                                                                                                                 ==============================
              @@  ¾ÆÀÌ±¸ ¾î¼­¿ÀÀÌ¼Ò¿¹!
           ==============================
           DarkNet Bulletin Board Service
                                                                                                                                                                                                                                                                                                                                                           DarkNET-1.08/config/logons                                                                             644   21270   21270          716  5736655626  10552                                                                                                                                                                                                                                                                                                                                                                      # The logons file specifies the number of times each user may logon to
# the bbs at once. It is here so that the default "logons" value in
# the bbconfig file may be overridden for certain users. For instance,
# you may allow unlimited logons by default, but set a guest account
# to a limited number in this file. Or allow only one logon for normal
# users with a higher logon limit for sysops given here.
#
# Format: userid:logon-limit
#
# guest:5  
# SYSOP:0
                                                  DarkNET-1.08/config/menu.desc                                                                          644   21270   21270        36226  6044663001  11152                                                                                                                                                                                                                                                                                                                                                                      # This file contains a description of the menu hierarchy.

# Set Up the Default Environment

Environment("TERM=%T,BBS_USERID=%I,BBS_USERNAME=%U,SHELL=/bin/false")

# The Environment Variables can be changed upon execution of a command with
# $exec, $exec.pause, or $exec.more by including the environment string
# in the execution command seperated by a colon, for example to have
# a menu entry execute the vi editor and reset the terminal type to
# a specific type you would use:
# $exec "/usr/ucb/vi:TERM=ansi"
#
#  Percent characters in all strings of this menu indicate substitution
#  directives.  %T substitutes the Terminal Type, %I the BBS User Id,
#  %U the BBS User Name, %E the selected editor, and %H the host from
#  which the user is logged in.

# menu "menu name", "titlestring", "menu prompt", "default action" {
#  [command list]
# }
# A "*" in the titlestring field will be substituted by the bbs name.

#
# For every action in this list is a string.  Normally the string is the
# command name that you want to execute for that particular case, for example
# a defalut action of "Help" means that the Help command will be the default
# command when you enter this menu.  You can also make the action string
# be a function of the "new mail waiting" status.  This is indicated by
# action strings that start with a '$' character.  When the action string
# begins with a '$' the first character following the $ indicates the default
# action for when no mail is waiting, and the second character indicates
# the command for when mail is waiting.  For example in the following
# menu code the default action of "$NM" means that when you first enter
# the bbs you get a "New" action when no mail is waiting, and a 
# "Mail" action for when there is mail waiting.
# 
menu "Main", "¸ÞÀÎ", "The DarkNET BBS", "´ÙÅ©³Ý", "Command: ", "¹» ÇÒ±î: ", "$NM" {
# Each Command entry is enclosed in parens and is a list of
# the following:
# Command Name, Default Next Command, Next Command on Error,
# Permission required to use this command, Function to execute this
# command (may include one text string as argument), and 
# finally the help string for the command.
("Select",  "º¸µå°í¸£±â (S)", "Read",    "Select",   BoardNames,    $SelectBoard,
"(S)-Select      [Set current board]",
"(S)-°í¸£±â      [º¸µåºÎÅÍ °ñ¸£¼¼¿ä]")
("Boards",  "º¸µå¸®½ºÆÃ (B)", "Select",  "Boards",   EnumBoards,  $Boards,
"(B)-Boards      [List boards on system]",
"(B)-º¸µåÁ¾·ù    [¾î¶² º¸µå°¡ ÀÖ³ª?]")
("Count",   "±Û¼¼±â (C)", "Select",  "Boards",   EnumBoards,  $BoardCounts,
"(C)-Count       [Count posts by board]",
"(C)-±Û¼¼±â      [±Û º¸µåº°·Î ¼¼¾î º¸½Ç·¡¿ä?]")
("Post",    "±Û¾²±â (P)", "Read",    "Read",     Post,      $Post,
"(P)-Post        [Post a message on current board]",
"(P)-±Û¾²±â      [¼±ÅÃÇÑ º¸µå¿¡ ±Û Á» ¿Ã·Á¿ä]")
("FtpPost", "FTP ±Û¾²±â (F)", "Read",    "Select",     FtpPost,      $FtpPost,
"(F)-FtpPost     [Post a message on curr. board via FTP]",
"(F)tp-±Û¾²±â    [¼±ÅÃÇÑ º¸µå¿¡ ±Û Á» ¿Ã·Á¿ä via FTP]")
("Read",    "±ÛÀÐ±â (R)", "Read",    "Post",     OpenBoard,   $MainRead,
"(R)-Read        [Enter multifunction Read Menu]",
"(R)-±ÛÀÐ±â      [¼±ÅÃÇÑ º¸µå ±Û ÀÐÀ¾½Ã´Ù]")
("New",     "»õ±ÛÀÐ±â (N)", "Talk",  "Select",   EnumBoards,  $ReadNew,
"(N)-New         [Scan for new messages]",
"(N)-»õ±ÛÀÐ±â    [»õ±Û ÀÐÀ¾½Ã´Ù]")
("Zap",     "¿¹¿Üº¸µå¼³Á¤ (Z)", "Zap",     "Zap",      ZapBoard,  $Zap,
"(Z)-Zap         [Zap boards from (N)ew search]",
"(Z)-Á¦¿Ü        [»õ±ÛÀÐ±â¿¡¼­ Á¦¿ÜÇÒ º¸µå ¼±Á¤]")
("Visit",   "º¸µå¹æ¹® (V)", "Visit",   "Visit",    VisitBoard,  $Visit,
"(V)-Visit       [Mark messages as read]",
"(V)-¹æ¹®        [ÀÐÀº °ÍÀ¸·Î »õ±ÛµéÀ» Ç¥½Ã]")
("Mail",    "ÆíÁö (M)", "$NM",    "Mail",     0,           $Menu "Mail",
"(M)-Mail        [Enter Mail Menu]",
"(M)-ÆíÁö        [ÆíÁö º¸³À½Ã´Ù]")
#("Files",   "È­ÀÏÀü¼Û (F)", "$FM",   "Files",    0,           $Menu "Files",
#"(F)-Files       [Enter File Transfer Menu (Oh! No!!!)]",
#"(F)-È­ÀÏÀü¼Û    [È­ÀÏ Àü¼Û (ÀÌ°Å ÇÏÁö¸¶!!!)]")
("Talk",    "¶°µéÀÚ (T)", "$NM",    "Talk",     0,           $Menu "Talk",
"(T)-Talk        [Enter Talk Menu]",
"(T)-¶°µéÀÚ      [¶°µéÀÚ!!!]")
("Xyz",     "¿¬ÀåÅë (X)", "$NM",     "Xyz",      0,           $Menu "Xyz",
"(X)-Xyz         [Utilities (Change passwd, term type)]",
"(X)-¿¬ÀåÅë      [Àâµ¿»ç´Ï ¿¬ÀåÅë]")
("Admin",   "°ü¸® (A)", "$AM",   "Admin",    AdminMenu,   $Menu "Admin",
"(A)-Admin       [Enter Admin Menu]",
"(A)-°ü¸®        [BBS °ü¸®]")
("Info",    "¹öÁ¯Á¤º¸ (I)", "Info",    "Info",     GetInfoFile, $BoardInfo,
"(I)-Info        [Get Version and Copyright Info]",
"(I)-¹öÁ¯        [¹öÁ¯ Á¤º¸]")
("Welcome", "È¯¿µ·Î°í (W)", "Welcome", "Welcome",  GetWelcome,  $Welcome,
"(W)-Welcome     [Look at the Welcome Screen]",
"(W)-È¯¿µ        [È¯¿µ ·Î°í º¸½Ç·¡¿ä?]")
("Users",   "À¯Àú¸ù¶¥º¸±â(U)", "Talk",    "Users",    AllUsers,    $AllUsers,
"(U)-Users       [List ALL accounts on this BBS]",
"(U)-À¯Àú        [À¯Àú ¸ðÁ¶¸® º¸½Ç·¡¿ä (Áö·çÇØ~~)]")
("Help",    "µµ¿ÍÁà (H)", "Help",    "Help",     0,           $Help,
"(H)-Help        [Get this Help Screen]",
"(H)-µµ¿ÍÁà      [²À ÀÐ¾î!!!]")
("Goodbye", "Áý¿¡°¡ÀÚ (G)", "Goodbye", "Goodbye",  0,           $EndMenu,
"(G)-Goodbye     [Leave This BBS]",
"(G)-ºüÀÌ        [Áý¿¡°¡¼­ °øºÎÁ» ÇÕ½Ã´Ù]")
}

menu "Mail", "ÆíÁö", "Personal Mail Menu", "ÆíÁöÇÔ", "Command: ", "¹» ÇÒ±î: ", "$RNM" {
("Send",    "¹ß¼Û (S)", "Send",    "Exit",     SendMail,    $MailSend,
"(S)-Send        [Send a mail message]",
"(S)-¹ß¼Û        [º¸³»±â]")
("Imail", "³Ý¹ß¼Û (I)", "Imail",    "Exit",   NetMailSend,    $NetMailSend,
"(I)-Imail       [Send Internet mail message]",
"(I)-ÀÎÅÍ³Ý¹ß¼Û  [ÀÎÅÍ³×Æ®¸ÞÀÏ º¸³»±â]")
("GroupSend", "¿ÕÃ¢º¸³»±â (G)", "GroupSend", "Exit", SendMail,    $GroupSend,
"(G)-GroupSend   [Send mail to more than one user]",
"(G)-¿ÕÃ¢¹ß¼Û    [¿ÕÃ¢ º¸³»±â]")
("New",     "»õÆíÁö (N)", "Exit",    "Exit",     OpenMail,    $ReadNewMail,
"(N)-New         [Read new mail messages]",
"(N)-»õÆíÁö      [»õÆíÁö ÀÐ±â]")
("Read",    "ÀÐ±â (R)", "Exit",    "Exit",     OpenMail,    $MailRead,
"(R)-Read        [Enter multipurpose mail read menu]",
"(R)-ÀÐ±â        [ÆíÁö ºê¶ó¿ìÀú]")
("Help",    "µµ¿ÍÁà (H)", "Help",    "Help",     0,           $Help,
"(H)-Help        [Get this help screen]",
"(H)-µµ¿ÍÁà      [²À ÀÐ¾î!!]")
("Exit",    "À§·Î (E)", "Exit",    "Exit",     0,           $EndMenu,
"(E)-Exit        [Exit to main menu]",
"(E)-À§·Î        [ÆíÁö¸Þ´º¼­ ³ª°¡±â]")
("Xit",    "³¡ (X)", "Xit",      "Xit",     0,           $Xit,
"(X)-Quit        [Quit from the BBS]",
"(X)-³¡³»±â      [ºñºñ¿¡½º¿¡¼­ ³ª°¡±â]")
}

#menu "Files", "File Transfer Menu", "Command: ", "$HE" {
#("Select",  "Download", "Exit",    FileBoardNames, $FileSelect,
#"(S)-Select        [Select a File Sub-board]",
#"(S)-Select        [º¸µå °í¸£±â]")
#("List",    "Select",   "Exit",    EnumFileBoards, $FileBoards,
#"(L)-List          [List File sub-boards]",
#"(L)-List          [º¸µå º¸¿©ÁÖ±â]")
#("Protocol", "Download", "Select", SetProtocol, $SelectProtocol,
#"(P)-Protocol      [Select protocol for transfers]",
#"(P)-Protocol      [Àü¼Û ÇÁ·ÎÅäÄÝ °í¸£±â]")
#("Upload",  "Exit",     "Select",  Upload,      $FileUpload,
#"(U)-Upload        [Upload a file]",
#"(U)-Upload        [È­ÀÏ ¾÷·Îµå]")
#("Download", "Exit",    "Select",  Download,    $FileDownload,
#"(D)-Download      [Enter multifunction download menu]",
#"(D)-Download      [È­ÀÏ ´Ù¿î·Îµå ¸Þ´º]")
#("Help",    "Help",     "Help",    0,           $Help,
#"(H)-Help          [Get this help screen]",
#"(H)-Help          [µµ¿ò¸»]")
#("Exit",    "Exit",     "Exit",    0,           $EndMenu,
#"(E)-Exit          [Exit to main menu]",
#"(E)-Exit          [È­ÀÏ Àü¼Û ¸Þ´º¼­ ³ª°¡±â]")
#("Xit",    "³¡ (X)", "Xit",      "Xit",     0,           $Xit,
#"(X)-Quit        [Quit from the BBS]",
#"(X)-³¡³»±â      [ºñºñ¿¡½º¿¡¼­ ³ª°¡±â]")
#}

menu "Xyz", "¿¬ÀåÅë", "Misc. Utilities Menu", "Àâµ¿»ç´Ï", "Command: ", "¹» ÇÒ±î: ", "$HE" {
("Cloak",   "¼û±â (C)", "Exit",     "Exit",    Cloak,       $ToggleCloak,
"(C)-Cloak       [Hide from other users]",
"(C)-¼û±â        [¼û±â]")
("Passwd",  "¾ÏÈ£ (P)", "Exit",     "Passwd",  SetPassword, $SetPasswd,
"(P)-Passwd      [Change your password]",
"(P)-¾ÏÈ£        [¾ÏÈ£¹Ù²Ù±â]")
("Name",    "ÀÌ¸§ (N)", "Exit",     "Name",    SetUsername, $SetUsername,
"(N)-Name        [Change your username]",
"(N)-ÀÌ¸§        [»ç¿ëÀÚ ÀÌ¸§ ¹Ù²Ù±â]")
("Address", "ÆíÁöÁÖ¼Ò (A)", "Exit",     "Address", SetAddress,  $SetAddress,
"(A)-Address     [Set your Internet e-mail address]",
"(A)-ÆíÁöÁÖ¼Ò    [ÀÎÅÍ³Ý ÀüÀÚÆíÁö ÁÖ¼Ò Á¤ÇÏ±â]")
("Lang", "¾ð¾î (L)", "Exit",     "Lang", SetLang,  $SetLang,
"(L)-Lang        [Set your Language]",
"(L)-¾ð¾î        [¾ð¾î ¼±ÅÃ (ÇöÁ¦ ÇÑ±Û/¿µ¾î µÑ»Ó)]")
("Users",   "»ç¿ëÀÚ (U)", "Help",     "Help",    Users,       $OnlineUsers,
"(U)-Users       [Show users currently online]",
"(U)-»ç¿ëÀÚ      [ÇöÁ¦ »ç¿ëÀÚ º¸¿©ÁÖ±â]")
("Terminal", "ÅÍ¹Ì³¯ (T)", "Terminal", "Terminal", SetTerminal, $SetTermtype,
"(T)-Terminal    [Set your terminal type]",
"(T)-ÅÍ¹Ì³¯      [ÇöÁ¦ »ç¿ë ÅÍ¹Ì³¯ ¿¡¹Ä·¹ÀÌ¼Ç Á¤ÀÇ]")
("Info",    "³»Á¤º¸ (I)", "Exit",     "Exit",    GetOwnInfo,  $ShowOwnInfo,
"(I)-Info        [Show your passfile info]",
"(I)-³»Á¤º¸      [ÇöÁ¦ ³» Á¤º¸]")
("Welcome", "È¯¿µ·Î°í (W)", "Exit",     "Exit",    EditWelcome, $EditWelcome,
"(W)-Welcome     [Edit the Welcome Screen]",
"(W)-È¯¿µ·Î°í    [È¯¿µ·Î°í ¹Ù²Ù±â]")
("QueryEdit", "°èÈ¹ (Q)", "Exit",   "Exit",    SetPlan,     $QueryEdit,
"(Q)-QueryEdit   [Edit your plan file]",
"(Q)-°èÈ¹        [³ªÀÇ °èÈ¹]")
("Signature", "¼­¸í (S)", "Exit",   "Exit",    SetSignature, $SignatureEdit,
"(S)-Signature   [Edit your signature file]",
"(S)-¼­¸í¹Ù²Ù±â  [¼­¸í ¹Ù²Ù±â]")
("FileEditor", "ÆíÁý±â (F)", "Exit", "Exit",   SetEditor,   $SelectEditor,
"(F)-FileEditor  [Select Editor]",
"(F)-ÆíÁý±â      [ÆíÁý±â ÁöÁ¤]")
("Help",    "µµ¿ÍÁà (H)", "Help",     "Exit",    0,        $Help,
"(H)-Help        [Get this help screen]",
"(H)-µµ¿ÍÁà      [µµ¿ò¸»]")
("DeleteMe",    "»èÁ¦ (D)", "DeleteMe",     "DeleteMe",    0,             $DeleteMe,
"(D)-DelteId     [Delete your UserID]",
"(D)-»èÁ¦        [¾ÆÀÌµð »èÁ¦]")
("Exit",    "À§·Î (E)", "Help",     "Exit",    0,             $EndMenu,
"(E)-Exit        [Return to Main Menu]",
"(E)-À§·Î        [ÀÌ ¸Þ´º¼­ ³ª°¡±â]")
("Xit",    "³¡ (X)", "Xit",      "Xit",     0,           $Xit,
"(X)-Quit        [Quit from the BBS]",
"(X)-³¡³»±â      [ºñºñ¿¡½º¿¡¼­ ³ª°¡±â]")
("Gnu",     "Gnu (G)",      "Gnu",     GetGNUFile,  $GnuInfo,
"(G)-Gnu         [Gnu General Public License]",
"(G)-Gnu         [±×´©ÀÌÁî ³´ À¯´Ð½º ÆÛºí¸¯ ¶óÀÌ¼¾½º]")
}

menu "Admin", "°ü¸®", "BBS Administration Menu", "ºñºñ¿¡½º °ü¸® ¸Þ´º", "Command: ", "¹» ÇÒ±î: ", "$HE" {
("Add User",     "»õÀ¯Àú (A)", "Add User",     "Exit",      AddAccount,    $AddAccount,
"(A)-Add User     [Add an account]",
"(A)-»õÀ¯Àú       [»õÀ¯Á® ´õÇÏ±â]")
("Delete User",  "Â©·¯ (D)", "Delete",       "Exit",      DeleteAccount, $DeleteAccount,
"(D)-Delete User  [Delete an account]",
"(D)-Â©·¯         [À¯Àú Â¥¸£±â]")
("Info",         "Á¤º¸ (I)", "Info",       "Info",      SetAccountInfo, $SetUserData,
"(I)-Info         [View/change passfile]",
"(I)-Á¤º¸         [»ç¿ëÀÚÀÇ ÆÐ½º¿öµåÁ¤º¸]")
("Permissions",  "ÆÛ¹Ì¼Ç (P)",  "Permissions", "Exit",      SetPermissions, $SetUserPerms,
"(P)-Permissions  [View/change perm]",
"(P)-ÆÛ¹Ì¼Ç       [»ç¿ëÀÚÀÇ ·¹º§ Ã¼Å©/Á¶Á¤]")
("Xempt",        "Á¦¿Ü (X)",  "Xempt",       "Exit",      ExemptUser,    $ToggleExempt,
"(X)-Xempt        [Mark/unmark account to be immune to user clean]",
"(X)-Á¦¿Ü         [À¯ÀúÅ¬¸°¿¡¼­ Á¦¿Ü]")
("New Board",    "»õº¸µå (N)", "New Board", "New", AddBoard, $AddBoard,
"(N)-New Board    [Add a board]",
"(N)-»õº¸µå       [»õº¸µå ¸¸µé±â]")
("Board Delete", "º¸µå»èÁ¦ (B)", "Board Delete", "Board ",    DeleteBoard,   $DeleteBoard,
"(B)-Board Delete [Delete a board]",
"(B)-º¸µå»èÁ¦     [º¸µå ¾ø¾Ö±â]")
("Change Board", "º¸µå¹Ù²Ù±â (C)", "Change", "Change",    SetBoardInfo,  $ChangeBoard,
"(C)-Change Board [Set perm/attr of a board]",
"(C)-º¸µå¹Ù²Ù±â   [º¸µå Á¤º¸ ¹Ù²Ù±â]")
("Managers",     "¸Å´ÏÁ® (M)", "Managers", "Managers",  SetBoardMgrs,  $SetBoardMgrs,
"(M)-Managers     [Set managers for a board]",
"(M)-¸Å´ÏÁ®       [º¸µå ¸Å´ÏÁ® °ü¸®]")
("Help",         "µµ¿ÍÁà (H)", "Help", "Exit", 0, $Help,
"(H)-Help         [Get this help screen]",
"(H)-µµ¿ÍÁà       [µµ¿ò¸»]")
("Exit",         "À§·Î (E)", "Exit", "Exit", 0, $EndMenu,
"(E)-Exit         [Exit to Main Menu]",
"(E)-À§·Î         [À­ ¸Þ´º·Î]")
}

#("Shell",        "Exit",         "Exit",      ShellEscape,   $exec "/bin/sh:TERM=%T",
#"(S)hell         Escape to a UNIX shell")

menu "Talk", "³îÀÚ", "Interactive Talk Menu", "³îÀÚÆÇ", "Command: ", "¹» ÇÒ±î: ", "$U" {
("Users",        "»ç¿ëÀÚ (U)", "Users",          "Exit",        Users,   $OnlineUsers,
"(U)-Users       [Show currently connected users]",
"(U)-»ç¿ëÀÚ      [ÇöÀç »ç¿ëÀÚ]")
("List",         "»ç¿ëÀÚ2 (L)", "List",           "Exit",        Users,   $ShortList,
"(L)-List        [Condensed version of (U)sers]",
"(L)-»ç¿ëÀÚ2     [ÇöÀç »ç¿ëÀÚ (°£·«ÇÏ°Ô)]")
("Monitor",      "¸ð´ÏÅÍ (M)", "Users",          "Exit",        Users,   $Monitor,
"(M)-Monitor     [(L)ist with automatic updates]",
"(M)-¸ð´ÏÅÍ      [ÇöÁ¦»ç¿ëÀÚ ¸ð´ÏÅÍ¸µ]")
("Query",        "µÞÁ¶»ç (Q)", "Query",          "Query",       GetPlan, $Query,
"(Q)-Query       [Read a user's profile]",
"(Q)-µÞÁ¶»ç      [»ç¿ëÀÚ Á¤º¸ º¸±â]")
("Irc",          "¾ÆÀÌ¾Ë¾¾ (I)", "Users",           "Exit",        Irc, $Irc,
"(I)-Irc         [Enter the Irc system]",
"(I)-¾ÆÀÌ¾Ë¾¾    [¸ÁÇÏ´Â Áö¸§±æ - IRC]")
("Chat",         "Àâ´ã (C)", "Chat",           "Chat",        Chat,    $Chat,
"(C)-Chat        [Enter the Chat system - Local]",
"(C)-Àâ´ã        [¿ª½Ã ¸ÁÇÏ´Â ±æ - Local]")
("Talk",         "ÅäÅ© (T)", "Talk",           "Exit",        Page,    $Talk,
"(T)-Talk        [Talk to another user]",
"(T)-ÅäÅ©        [³ª°¡¼­ ÀüÈ­ÇØ¶ó..]")
("Pager",        "È£Ãâ±â (P)", "Users",          "Exit",      SetPager,  $SetPager,
"(P)-Pager       [Set your talk pager status]",
"(P)-È£Ãâ±â      [ÆäÀÌÁ® Á¶Á¤]")
("Override",     "È£Ãâ±â¿É¼Ç (O)", "Users",          "Exit",    SetOverrides, $SetOverrides,
"(O)-Override    [Allow only certain users to page]",
"(O)-¿À¹ö¶óÀÌµå  [³¢¸®³¢¸® ³îÀÚ]")
("Kick",         "ÂÉ±î³» (K)", "Users",          "Exit",        Kick,    $Kick,
"(K)-Kick        [Kick user off of system]",
"(K)-ÂÉ±î³»      [ÂÉ±î³»]")
("Date",         "½Ã°£ (D)", "Date",           "Date",        0,         $ShowDate,
"(D)-Date        [Show local date and time]",
"(D)-½Ã°£        [½Ã°è Á» Â÷°í ´ç°Ü]")
("Help",         "µµ¿ÍÁà (H)", "Help",           "Help",        0,         $Help,
"(H)-Help        [Get this help screen]",
"(H)-µµ¿ÍÁà      [¿©ÅÂ ¸ø ¿Ü¿ü³Ä?]")
("Where", "Á¤º¸1",  "Help",         "Exit",      GetWelcome,   $exec.pause "/home/bbs/bin/pseudo",
"(W)-Where       [Where is Pseudo BBS?]",
"(W)-¾îµð        [»çÀÌºñºñºñ ´Â ¾îµð¿¡?]")
("Z-HanaInfo", "ÇÏ³ª¿¡´Â? (Z)",  "Help",         "Exit",      GetWelcome,   $exec.pause "/home/bbs/bin/hana:TERM=%T",
"(Z)-HanaInfo    [What's going on with HanaBBS?]",
"(Z)-ÇÏ³ªÁ¤º¸    [ÇÏ³ª¿¡´Â ´©°¡ ¸ÓÇÏÁö?]")
("Y-Hana", "ÇÏ³ª·Î (Y)",  "Help",         "Exit",      Routing,   $Routing,
"(Y)-Hana        [To Hana....]",
"(Y)-ÇÏ³ª·Î      [ÇÏ³ª·Î.....]")
("Exit",         "À§·Î (E)", "Exit",           "Exit",        0,         $EndMenu,
"(E)-Exit        [Exit to main menu]",
"(E)-À§·Î        [Ã¥ÀÌ³ª Á» ÀÐ¾î¶ó..]")
("Xit",    "³¡ (X)", "Xit",      "Xit",     0,           $Xit,
"(X)-Quit        [Quit from the BBS]",
"(X)-³¡³»±â      [ºñºñ¿¡½º¿¡¼­ ³ª°¡±â]")
}
ifunction download menu]",
#"(D)-Download      [È­ÀÏ ´Ù¿î·Îµå ¸Þ´º]")
#("Help",    "Help",     "Help",    0,           $Help,
#"(H)-Help          [Get this help screen]",
#"(H)-Help          [µµ¿ò¸»]")
#("Exit",    "Exit",     "Exit",    0,           $EndMenu,
#"(E)-Exit          [Exit to main menu]",
#"(E)-Exit          [È­ÀÏ Àü¼Û ¸Þ´º¼­ ³ª°¡±â]")
#("Xit",   DarkNET-1.08/config/passwds                                                                            644   21270   21270         1141  5736655647  10751                                                                                                                                                                                                                                                                                                                                                                      # This is the bbs passwd file. DO NOT (!) edit it by hand unless you
# know EXACTLY what you're doing! The records in this file MUST be all
# the right length and formatted correctly.
# 
# All data in this file may be manipulated by bbs functions.
#
# The following entry is for the SYSOP account with all privileges and
# password as the initial password. I highly recommend you change it.
# Note that ~bbs/home/SYSOP and ~bbs/home/SYSOP/mail must exist for this
# account to be functional. Admin/(A)dd User and addacct do that for you.
#
SYSOP       :AA6tQYSfGxd/A :000003ff:0000:System Operator          :
                                                                                                                                                                                                                                                                                                                                                                                                                               DarkNET-1.08/config/permstrs                                                                           644   21270   21270         1437  5736655626  11151                                                                                                                                                                                                                                                                                                                                                                      # This file lists the names of the permission bits.
#
# They are referenced in the access file to determine what permissions
# are needed to access each bbs function.
# 
# The following are reserved and should NOT be altered.
# Basic-1 through Basic-4 are given to each account automatically at creation.
# Sysop permission is needed to alter a user's permissions.
#
Basic-1
Basic-2
Basic-3
Basic-4
Sysop
AccountMgr
BoardMgr
SeeCloak
Cloak
WelcomeMgr
Routing
#
# The rest (up to 27 more, or 32 total) are only referenced in the
# access and menu.desc files. You can name them as you please.
# IMPORTANT! Never alter the order of permission names once you start 
# using them. That is, only add to the END of the list and if you want
# to delete a permission name, put something else in its place.
#
                                                                                                                                                                                                                                 DarkNET-1.08/config/protos                                                                             644   21270   21270         1040  5736655626  10606                                                                                                                                                                                                                                                                                                                                                                      # This file lists the protocols available for uploads/downloads.
# You have to tailor this for your own site.
# 
# Record format:
# proto-name:send-command:receive-command
#
# If the receive-command is prefixed by '|', then the destination is
# opened as standard out of the receive-command. For example to do an
# ASCII upload we just "cat > filename". 
#
Kermit:/usr/bin/kermit -si:/usr/bin/kermit -ri:
Xmodem:/usr/bin/sx -be:/usr/bin/rx -bpe:
Ymodem:/usr/bin/sb -be:/usr/bin/rb -bpe:
Zmodem:/usr/bin/sz -be:/usr/bin/rz -bpe:
ASCII:cat:|cat:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                DarkNET-1.08/config/welcome                                                                            644   21270   21270         1036  6044657746  10716                                                                                                                                                                                                                                                                                                                                                                                                                                     |
                                                          ,o __|-.
                                                      _~o/   \/  |
                                                     ' |/        |
                                                      / >        |
      ÃÖ°í¸¦ ÇâÇÏ´Â ±æ¸ñ¿¡¼­...                      '  `        |
                                                                 |
_________________________________________________________________|_____



                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  DarkNET-1.08/config/ad.dark.kr                                                                         644       0       1           62  6044657544  10705                                                                                                                                                                                                                                                                                                                                                                      Today's Ad:          Welcome to DarkNET, K.E.R.I.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              DarkNET-1.08/config/kchathlp.txt                                                                       644   21270   21270         2773  5736655626  11712                                                                                                                                                                                                                                                                                                                                                                      # This is the main Chat client help file, used by the /h command.
# Blank lines do get displayed. Don't use tabs in here.
#
==============================================================================
[ÇÑ±Û¸í·É]          [¿µ¾î]       [¹»ÇÏ´Â°¡?]
==============================================================================
/³ª <±Û>            /me          * <±Û> À» Çàµ¿À¸·Î º¸¿©ÁÝ´Ï´Ù
/Áö                 /clear       * È­¸é Áö¿ó´Ï´Ù.
/³¡ <±Û>            /exit        * Ãª¹æÀ» ³ª°©´Ï´Ù (CTRL-C)
/¹Ù(²ã) [+,-][ls]   /flags       * ¹æÀÇ ¸ðµå Á¶Á¤ (¹æ´ñ¹æ¿ë)
/ÃÊ(´ë) <º°¸í>      /invite      * <º°¸í> À» ¹æÀ¸·Î ÃÊ´ëÇÕ´Ï´Ù (¹æ´ñ¹æ¿ë)
/³¢(¾î) <¹æ>        /join        * »õ¹æ ¶Ç´Â ÀÌ¹Ì ÀÖ´Â ¹æÀ¸·Î µé¾î °©´Ï´Ù
/Â÷ <º°¸í>          /kick        * <º°¸í> À» ¹æ¿¡¼­ ÂÉ±î³À´Ï´Ù (¹æ´ñ¹æ¿ë)
/±ä                 /long        * ÀÚ¼¼ÇÑ »ç¿ëÀÚ ¸®½ºÆ®
/¼Ó <º°¸í> <±Û>     /msg         * <±Û> À» <º°¸í> ¿¡°Ô ¸ô·¡ º¸³À´Ï´Ù
/º°(¸í) <º°¸í>      /nick        * º°¸íÀ» ¹Ù²ß´Ï´Ù
/ÁÖ(ÀÎ) <º°¸í>      /operator    * ¹æ ´ñ¹æÀ» ¸¸µé¾î ÁÝ´Ï´Ù (¹æ´ñ¹æ¿ë)
/´©(±¸) <º°¸í>      /whois       * <º°¸í> ÀÇ µÞÁ¶»ç
/¹æ                 /rooms       * ¸ðµç Ã¤ÆÃ¹æÀ» ³ª¿­ÇÕ´Ï´Ù (ºñ¹Ð¹æ Á¦¿Ü)
/°£                 /users       * °£´ÜÇÑ »ç¿ëÀÚ ¸®½ºÆ®
/¸ð(µÎ)             /who         * ºñ¹Ð¹æ¿Ü¿¡ ¸ðµç ¹æÀÇ À¯Àú¸¦ ³ª¿­ÇØ ÁÝ´Ï´Ù
/»ç(¶÷) <¹æ>        /whoin       * ¹æÀÇ »ç¶÷À» º¸¿©ÁÝ´Ï´Ù
/Á¶(»ç) <¾ÆÀÌµð>    /query       * <¾ÆÀÌµð> ÀÇ µÞÁ¶»ç
/´õ                 /xhelp       * ´õ ÀÚ¼¼ÇÑ µµ¿ò¸»
==============================================================================
     DarkNET-1.08/config/kchatxhlp.txt                                                                      644   21270   21270         1003  5736655626  12063                                                                                                                                                                                                                                                                                                                                                                      # This is the extra Chat client help file, used by the /x command.
# Blank lines do get displayed. Don't use tabs in here.
#

[ÀÔ·Â ¶óÀÎ ÆíÁý]
Ctrl-A     ÁÙ Á¦ÀÏ ¾ÕÀ¸·Î
Ctrl-B     ÇÑ±ÛÀÚ µÚ·Î (Áö¿ìÁö ¾Ê°í)
Ctrl-D     Ä¿¼­°¡ ÀÖ´Â °÷ ±ÛÀÚ »èÁ¦
Ctrl-E     ÁÙ Á¦ÀÏ ³¡À¸·Î
Ctrl-F     ÇÑ±ÛÀÚ ¾ÕÀ¸·Î
Ctrl-H     Ä¿¼­µÚÀÇ ±ÛÀÚ Áö¿ì±â (backspace erase)
Ctrl-U     ÇÑÁÙ ¸ù¶¥ Áö¿ì±â
Ctrl-W     ÇÑ ´Ü¾î Áö¿ì±â
ESC B      ÇÑ´Ü¾î µÚ·Î
ESC F      ÇÑ´Ü¾î ¾ÕÀ¸·Î

[Ã¤ÆÃ¹æ ¸ðµå Á¶Àý]
l          Àá°åÀ½ (ÃÊÃ»¸¸ °¡´É)
s          ºñ¹Ð¹æ
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             DarkNET-1.08/config/modes                                                                              644   21270   21270         1466  5736655626  10403                                                                                                                                                                                                                                                                                                                                                                      #
# From mode 11 up, they are defined locally to be used in the menu.desc
# file as an argument in the "exec" and "exec.pause" menu commands.
#
# Format: <mode-number>:<mode-char>:<mode-string>:<pageable>
#
# The maximum allowed mode number is 31.
# Mode-string may be up to 9 characters. Mode-char is a single character.
# These are what shows up in the (U)sers, (L)ist, and (M)onitor commands.
# Place an 'N' in the <pageable> field to denote that a user in
# this mode cannot be paged under any circumstances. This is a GOOD idea
# for any mode you add!
#
1:c:Connecting:N
2:N:Nothing:
3:M:Mail:
4:R:Reading:
5:P:Posting:
6:U:UL/DL:N
7:C:Chat:
8:m:Monitor:
9:T:Talk:
10:p:Page:
11:I:Irc:
12:F:FtpPosting:N
13:V:Vote:N
14:r:Routing:N
# The following might go with the (A)dmin/(S)hell example in menu.desc.
#11:S:Shell:N
                                                                                                                                                                                                          DarkNET-1.08/config/modes.x                                                                            644   21270   21270         1475  6044660105  10626                                                                                                                                                                                                                                                                                                                                                                      #
# From mode 11 up, they are defined locally to be used in the menu.desc
# file as an argument in the "exec" and "exec.pause" menu commands.
#
# Format: <mode-number>:<mode-char>:<mode-string>:<pageable>
#
# The maximum allowed mode number is 31.
# Mode-string may be up to 9 characters. Mode-char is a single character.
# These are what shows up in the (U)sers, (L)ist, and (M)onitor commands.
# Place an 'N' in the <pageable> field to denote that a user in
# this mode cannot be paged under any circumstances. This is a GOOD idea
# for any mode you add!
#
1:c:¿¬°áÁß:N
2:N:ÈÞ½ÄÁß::
3:M:¿ìÃ¼±¹:
4:R:±ÛÀÐ±â:
5:P:Æ÷½ºÆÃ:
6:U:Àü¼ÛÁß:N
7:C:Ã¤ÆÃÁß:
8:m:¸ð´ÏÅÍ:
9:T:ÅäÅ©Áß:
10:p:ÆäÀÌÂ¡:
11:I:IRCÁß:¾
12:F:FTPÆ÷½ºÆÃÁß:N
13:V:ÅõÇ¥Áß:N
14:r:¿©ÇàÁß:N
# The following might go with the (A)dmin/(S)hell example in menu.desc.
#11:S:Shell:N
                                                                                                                                                                                                   DarkNET-1.08/pico.BBS/                                                                                 755   21270   21270            0  6044661523   7331                                                                                                                                                                                                                                                                                                                                                                      DarkNET-1.08/pico.BBS/ansi.c                                                                           644   21270   21270        10523  5672463051  10537                                                                                                                                                                                                                                                                                                                                                                      #if	!defined(DOS)
static char rcsid[] = "$Id: ansi.c,v 4.5 1994/06/22 20:45:53 dlm Exp $";
#endif
/*
 * Program:	ANSI terminal driver routines
 *
 *
 * Michael Seibel
 * Networks and Distributed Computing
 * Computing and Communications
 * University of Washington
 * Administration Builiding, AG-44
 * Seattle, Washington, 98195, USA
 * Internet: mikes@cac.washington.edu
 *
 * Please address all bugs and comments to "pine-bugs@cac.washington.edu"
 *
 * Copyright 1991-1994  University of Washington
 *
 *  Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee to the University of
 * Washington is hereby granted, provided that the above copyright notice
 * appears in all copies and that both the above copyright notice and this
 * permission notice appear in supporting documentation, and that the name
 * of the University of Washington not be used in advertising or publicity
 * pertaining to distribution of the software without specific, written
 * prior permission.  This software is made available "as is", and
 * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
 * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
 * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
 * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 * Pine and Pico are trademarks of the University of Washington.
 * No commercial use of these trademarks may be made without prior
 * written permission of the University of Washington.
 */
/*
 * The routines in this file provide support for ANSI style terminals
 * over a serial line. The serial I/O services are provided by routines in
 * "termio.c". It compiles into nothing if not an ANSI device.
 */

#define	termdef	1			/* don't define "term" external */

#include        <stdio.h>
#include	"estruct.h"
#include        "edef.h"
#include        "osdep.h"

#if     ANSI_DRIVER

#define	MARGIN	8			/* size of minimim margin and	*/
#define	SCRSIZ	64			/* scroll size for extended lines */
#define BEL     0x07                    /* BEL character.               */
#define ESC     0x1B                    /* ESC character.               */

extern  int     ttopen();               /* Forward references.          */
extern  int     ttgetc();
extern  int     ttputc();
extern  int     ttflush();
extern  int     ttclose();
extern  int     ansimove();
extern  int     ansieeol();
extern  int     ansieeop();
extern  int     ansibeep();
extern  int     ansiopen();
extern	int	ansirev();
/*
 * Standard terminal interface dispatch table. Most of the fields point into
 * "termio" code.
 */
#if defined(VAX) && !defined(__ALPHA)
globaldef
#endif
TERM    term    = {
        NROW-1,
        NCOL,
	MARGIN,
	SCRSIZ,
        ansiopen,
        ttclose,
        ttgetc,
        ttputc,
        ttflush,
        ansimove,
        ansieeol,
        ansieeop,
        ansibeep,
	ansirev
};

ansimove(row, col)
{
        ttputc(ESC);
        ttputc('[');
        ansiparm(row+1);
        ttputc(';');
        ansiparm(col+1);
        ttputc('H');
}

ansieeol()
{
        ttputc(ESC);
        ttputc('[');
        ttputc('K');
}

ansieeop()
{
        ttputc(ESC);
        ttputc('[');
        ttputc('J');
}

ansirev(state)		/* change reverse video state */

int state;	/* TRUE = reverse, FALSE = normal */

{
	static int PrevState = 0;

	if(state != PrevState) {
		PrevState = state ;
		ttputc(ESC);
		ttputc('[');
		ttputc(state ? '7': '0');
		ttputc('m');
	}
}

ansibeep()
{
        ttputc(BEL);
        ttflush();
}

ansiparm(n)
register int    n;
{
        register int    q;

        q = n/10;
        if (q != 0)
                ansiparm(q);
        ttputc((n%10) + '0');
}

#endif

ansiopen()
{
#if     V7
        register char *cp;
        char *getenv();

        if ((cp = getenv("TERM")) == NULL) {
                puts("Shell variable TERM not defined!");
                exit(1);
        }
        if (strcmp(cp, "vt100") != 0) {
                puts("Terminal type not 'vt100'!");
                exit(1);
        }
#endif
	revexist = TRUE;
        ttopen();
}
                                                                                                                                                                             DarkNET-1.08/pico.BBS/attach.c                                                                         644   21270   21270        53163  5672463051  11060                                                                                                                                                                                                                                                                                                                                                                      #if	!defined(lint) && !defined(DOS)
static char rcsid[] = "$Id: attach.c,v 4.18 1994/09/29 19:15:54 mikes Exp $";
#endif
/*
 * Program:	Routines to support attachments in the Pine composer 
 *
 *
 * Michael Seibel
 * Networks and Distributed Computing
 * Computing and Communications
 * University of Washington
 * Administration Builiding, AG-44
 * Seattle, Washington, 98195, USA
 * Internet: mikes@cac.washington.edu
 *
 * Please address all bugs and comments to "pine-bugs@cac.washington.edu"
 *
 * Copyright 1991-1994  University of Washington
 *
 *  Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee to the University of
 * Washington is hereby granted, provided that the above copyright notice
 * appears in all copies and that both the above copyright notice and this
 * permission notice appear in supporting documentation, and that the name
 * of the University of Washington not be used in advertising or publicity
 * pertaining to distribution of the software without specific, written
 * prior permission.  This software is made available "as is", and
 * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
 * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
 * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
 * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 * Pine and Pico are trademarks of the University of Washington.
 * No commercial use of these trademarks may be made without prior
 * written permission of the University of Washington.
 *
 *
 * NOTES:
 *
 *
 */
#include <stdio.h>
#include <ctype.h>
#include <math.h>
#include "osdep.h"
#include "pico.h"
#include "estruct.h"
#include "edef.h"
#include "efunc.h"

#ifdef	ATTACHMENTS


#ifdef	ANSI
    int    ParseAttach(struct hdr_line **,int *,char *,char *,char *,int *);
    PATMT *NewAttach(char *, long, char *);
    void   ZotAttach(struct pico_atmt *);
    int    sinserts(char *, int, char *, int);
#else
    int    ParseAttach();
    PATMT *NewAttach();
    void   ZotAttach();
    int    sinserts();
#endif


/* 
 * max number of attachments
 */
#define	MAXATCH	64


/*
 * AskAttach - ask for attachment fields and build resulting structure
 *             return pointer to that struct if OK, NULL otherwise
 */
AskAttach(fn, sz, cmnt)
char *fn, *sz, *cmnt;
{
    int	    i, status;
    long    l = 0;
    char    bfn[NFILEN];

    i = 2;
    fn[0] = '\0';
    sz[0] = '\0';
    cmnt[0] = '\0';

    while(i){
	if(i == 2){
	    KEYMENU menu_attach[2];

	    menu_attach[0].name  = "^T";
	    menu_attach[0].label = "To Files";
	    menu_attach[1].name = NULL;
	    status = mlreply("File to attach: ", fn, NLINE, QNORML,
			     menu_attach);
			     
	}
	else
	  status = mlreply("Attachment comment: ", cmnt, NLINE, QNORML, NULL);

	switch(status){
	  case HELPCH:
	    if(i == 2)
	      emlwrite("No Attachment file help yet!", NULL);
	    else
	      emlwrite("No Attachment comment help yet!", NULL);

/* remove break and sleep when help text done to force redraw */     
	    sleep(3);
	    break;

	  case (CTRL|'T'):
	    if(i != 2){
		(*term.t_beep)();
		break;
	    }

	    *bfn = '\0';
	    if(*fn == '\0' || !isdir(fn, NULL))
	      strcpy(fn, gethomedir(NULL));

	    if(FileBrowse(fn, bfn, sz, FB_READ) == 1){
		strcat(fn, S_FILESEP);
		strcat(fn, bfn);
		i--;
	    }
	    else
	      *fn = '\0';

	    refresh(FALSE, 1);
	    update();
	    break;

	  case (CTRL|'L'):
	    refresh(FALSE, 1);
	    update();
	    continue;

	  case ABORT:
	    emlwrite("Attach cancelled", NULL);
	    return(0);

	  case TRUE:				/* some comment */
	  case FALSE:				/* No comment */
	    if(i-- == 2){
		fixpath(fn, NLINE);		/* names relative to ~ */
		if((gmode&MDSCUR) && homeless(fn)){
		    emlwrite("\007Restricted mode allows attachments from home directory only", NULL);
		    return(0);
		}

		if((status=fexist(fn, "r", &l)) != FIOSUC){ /* does file exist? */
		    fioperr(status, fn);
		    return(0);
		}
		strcpy(sz, prettysz(l));
	    }
	    else{
		mlerase();
		return(1);			/* mission accomplished! */
	    }

	    break;
	  default:
	    break;
	}
    }
}

extern struct headerentry *headents;

/*
 * SyncAttach - given a pointer to a linked list of attachment structures,
 *              return with that structure sync'd with what's displayed.
 *              delete any attachments in list of structs that's not on 
 *              the display, and add any that aren't in list but on display.
 */
SyncAttach()
{
    int offset = 0,				/* the offset to begin       */
        rv = 0,
        ki = 0,					/* number of known attmnts   */
        bi = 0,					/* build array index         */
        na,					/* old number of attachmnt   */
        status, i, j, n;
    char file[NLINE],				/* buffers to hold it all    */
         size[32],
         comment[1024];
    struct hdr_line *lp;			/* current line in header    */
    struct headerentry *entry;
    PATMT *tp, *knwn[MAXATCH], *bld[MAXATCH];

    for(entry = headents; entry->name != NULL; entry++) {
      if(entry->is_attach)
	break;
    }

    if(Pmaster == NULL)
      return(-1);

    for(i=0;i<MAXATCH;i++)			/* bug - ever pop this? */
	knwn[i] = bld[i] = NULL;		/* zero out table */
    
    tp = Pmaster->attachments;
    while(tp != NULL){				/* fill table of     */
	knwn[ki++] = tp;			/* known attachments */
	tp = tp->next;
    }

    n = 0;

    lp = entry->hd_text;
    while(lp != NULL){
	na = ++n;

	if(status = ParseAttach(&lp, &offset, file, size, comment, &na))
	    rv = (rv < 0) ? rv : status ;	/* remember worst case */

	if(*file == '\0'){
	    if(n != na && na > 0 && na <= ki && (knwn[na-1]->flags&A_FLIT)){
		bld[bi++] = knwn[na-1];
		knwn[na-1] = NULL;
	    }
	    continue;
	}

	if((gmode&MDSCUR) && homeless(file))
	  /* no attachments outsize ~ in secure mode! */
	  continue;

	tp = NULL;
	for(i=0;i < ki; i++){			/* already know about it? */
	    /*
	     * this is kind of gruesome. what we want to do is keep track
	     * of literal attachment entries because they may not be 
	     * actual files we can access or that the user readily 
	     * access
	     */
	    if(knwn[i] && 
	       ((!(knwn[i]->flags&A_FLIT) && !strcmp(file, knwn[i]->filename))
	       || ((knwn[i]->flags&A_FLIT) && i+1 == na))){
		tp = knwn[i];
		knwn[i] = NULL;			/* forget we know about it */

		if(status == -1)		/* ignore garbage! */
		  break;

		if((tp->flags&A_FLIT) && strcmp(file, tp->filename)){
		    rv = 1;
		    if((j=strlen(file)) > strlen(tp->filename)){
			if((tp->filename = (char *)realloc(tp->filename,
					        sizeof(char)*(j+1))) == NULL){
			    emlwrite("\007Can't realloc filename space",NULL);
			    return(-1);
			}
		    }

		    strcpy(tp->filename, file);
		}
		else if(tp->size && strcmp(tp->size, size)){
		    rv = 1;
		    if((j=strlen(size)) > strlen(tp->size)){
			if((tp->size=(char *)realloc(tp->size,
					        sizeof(char)*(j+1))) == NULL){
			    emlwrite("\007Can't realloc space for size", NULL);
			    return(-1);
			}
		    }

		    strcpy(tp->size, size);
		}

		if(strcmp(tp->description, comment)){	/* new comment */
		    rv = 1;
		    if((j=strlen(comment)) > strlen(tp->description)){
			if((tp->description=(char *)realloc(tp->description,
						sizeof(char)*(j+1))) == NULL){
			    emlwrite("\007Can't realloc description", NULL);
			    return(-1);
			}
		    }
		      
		    strcpy(tp->description, comment);
		}
		break;
	    }
	}

	if(tp){
	    bld[bi++] = tp;
	}
	else{
	    if(file[0] != '['){
		if((tp = NewAttach(file, atol(size), comment)) == NULL)
		  return(-1);
		bld[bi++] = tp;
	    }
	    else break;
	}

	if(status < 0)
	  tp->flags |= A_ERR;		/* turn ON error bit */
	else
	  tp->flags &= ~(A_ERR);	/* turn OFF error bit */
    }

    for(i=0; i < bi; i++)		/* link together newly built list */
	bld[i]->next = bld[i+1];

    Pmaster->attachments = bld[0];

    for(i=0; i < ki; i++){		/* kill old/unused references */

	if(knwn[i]){
	    ZotAttach(knwn[i]);
	    free((char *) knwn[i]);
	}
    }

    return(rv);
}




/*
 * ParseAttach - given a header line and an offset into it, return with 
 *		 the three given fields filled in.  Assumes the size of 
 *		 the buffers passed is large enough to hold what's there.
 *		 Always updates header fields that have changed or are 
 *		 fixed.  An error advances offset to next attachment.
 *
 *		returns: 1 if a field changed
 *                       0 nothing changed
 *                      -1 on error
 */
ParseAttach(lp, off, fn, sz, cmnt, no)
struct hdr_line **lp;				/* current header line      */
int  *off;					/* offset into that line    */
char *fn, *sz, *cmnt;				/* places to return fields  */
int  *no;					/* attachment number        */
{
    int  j, status,				/* various return codes     */
         rv = 0,				/* return value             */
         lbln  = 0;				/* label'd attachment	    */
    long l;					/* attachment length        */
    char tmp[1024],
	 c,
        *p,
        *lblsz = NULL,				/* label'd attchmnt's size  */
         number[8];
    register struct hdr_line  *lprev;
    enum {					/* parse levels             */
	LWS,					/* leading white space      */
	NUMB,					/* attachment number        */
	WSN,					/* white space after number */
	TAG,					/* attachments tag (fname)  */
	WST,					/* white space after tag    */
	SIZE,					/* attachments size         */
	SWS,					/* white space after size   */
	COMMENT,				/* attachment comment       */
	TG} level;				/* trailing garbage         */

    *fn = *sz = *cmnt = '\0';			/* initialize return strings */
    p   = tmp;

    level = LWS;				/* start at beginning */
    while(*lp != NULL){

	if((c=(*lp)->text[*off]) == '\0'){	/* end of display line */
	    lprev = *lp;
	    if((*lp = (*lp)->next) != NULL)
	      c = (*lp)->text[*off = 0];	/* reset offset */
	}

	switch(level){
	  case LWS:				/* skip leading white space */
	    if(myisspace(c) || c == '\0'){
		break;
	    }
	    else if(c < '0' || c > '9'){	/* add a number */
		sprintf(number, "%d. ", *no);
		*no = 0;			/* no previous number! */
		sinserts((*lp == NULL) ? &lprev->text[*off]
			               : &(*lp)->text[*off],
			     0, number, j=strlen(number));
		*off += j - 1;
		rv = 1;
		level = TAG;			/* interpret the name */
		break;
	    }
	    level = NUMB;
	  case NUMB:				/* attachment number */
	    if(c == '.'){			/* finished grabbing size */
		/*
		 * replace number if it's not right
		 */
		*p = '\0';
		sprintf(number, "%d", *no);	/* record the current...  */
		*no = atoi(tmp);		/* and the old place in list */
		if(strcmp(number, tmp)){
		    if(p-tmp > *off){		/* where to begin replacemnt */
			j = (p-tmp) - *off;
			sinserts((*lp)->text, *off, "", 0);
			sinserts(&lprev->text[strlen(lprev->text)-j], j, 
				 number, strlen(number));
			*off = 0;
		    }
		    else{
			j = (*off) - (p-tmp);
			sinserts((*lp == NULL) ? &lprev->text[j] 
				               : &(*lp)->text[j], 
				 p-tmp , number, strlen(number));
			*off += strlen(number) - (p-tmp);
		    }
		    rv = 1;
		}

		p = tmp;
		level = WSN;			/* what's next... */
	    }
	    else if(c < '0' || c > '9'){	/* Must be part of tag */
		sprintf(number, "%d. ", *no);
		sinserts((*lp == NULL) ? &lprev->text[(*off) - (p - tmp)]
			               : &(*lp)->text[(*off) - (p - tmp)],
			     0, number, j=strlen(number));
		*off += j;
		*p++ = c;
		level = TAG;			/* interpret the name */
	    }
	    else
	      *p++ = c;

	    break;

	  case WSN:				/* blast whitespace */
	    if(myisspace(c) || c == '\0'){
		break;
	    }
	    else if(c == '['){			/* labeled attachment */
		lbln++;
	    }
	    else if(c == ',' || c == ' '){
		emlwrite("\007Attchmnt: '%c' not allowed in file name", 
			  (void *)(int)c);
		rv = -1;
		level = TG;			/* eat rest of garbage */
		break;
	    }
	    level = TAG;
	  case TAG:				/* get and check filename */
						/* or labeled attachment  */
						/* enclosed in []         */
	    if(c == '\0' || (!lbln && (myisspace(c) || strchr(",(\"", c)))
	       || (lbln && c == ']')){
		if(p != tmp){
		    *p = '\0';			/* got something */

		    strcpy(fn, tmp);		/* store file name */
		    if(!lbln){			/* normal file attachment */
			fixpath(fn, NLINE);
			if((status=fexist(fn, "r", &l)) != FIOSUC){
			    fioperr(status, fn);
			    rv = -1;
			    level = TG;		/* munch rest of garbage */
			    break;
			}


			if((gmode&MDSCUR) && homeless(fn)){
			    emlwrite("\007Restricted mode allows attachments from home directory only", NULL);
			    rv = -1;
			    level = TG;
			    break;
			}

			if(strcmp(fn, tmp)){ 	/* fn changed: display it */
			    if(*off >=  p - tmp){	/* room for it? */
				sinserts((*lp == NULL)? 
					 &lprev->text[(*off)-(p-tmp)] :
					 &(*lp)->text[(*off)-(p-tmp)],
					 p-tmp, fn, j=strlen(fn));
				*off += j - (p - tmp);	/* advance offset */
				rv = 1;
			    }
			    else{
				emlwrite("\007Attchmnt: Problem displaying real file path", NULL);
			    }
			}
		    }
		    else{			/* labelled attachment! */
			/*
			 * should explain about labelled attachments:
			 * these are attachments that came into the composer
			 * with meaningless file names (up to caller of 
			 * composer to decide), for example, attachments
			 * being forwarded from another message.  here, we
			 * just make sure the size stays what was passed
			 * to us.  The user is SOL if they change the label
			 * since, as it is now, after changed, it will
			 * just get dropped from the list of what gets 
			 * passed back to the caller.
			 */
			PATMT *tp;

			if(c != ']'){		/* legit label? */
			    emlwrite("\007Attchmnt: Expected ']' after \"%s\"",
				     fn);
			    rv = -1;
			    level = TG;
			    break;
			}
			strcat(fn, "]");

			/*
			 * This is kind of cheating since otherwise
			 * ParseAttach doesn't know about the attachment
			 * struct.  OK if filename's not found as it will
			 * get taken care of later...
			 */
			tp = Pmaster->attachments; /* caller check Pmaster! */
			j = 0;
			while(tp != NULL){
			    if(++j == *no){
				lblsz = tp->size;
				break;
			    }
			    tp = tp->next;
			}

			if(tp == NULL){
			    emlwrite("\007Attchmnt: Unknown reference: %s",fn);
			    lblsz =  "XXX";
			}
		    }

		    p = tmp;			/* reset p in tmp */
		    level = WST;
		}

		if(!lbln && c == '(')		/* no space 'tween file, size*/
		  level = SIZE;
		else if(c == '\0' || (!lbln && (c == ',' || c == '\"'))){
		    strcpy(sz, (lblsz) ? lblsz : prettysz(l));
		    sprintf(tmp, " (%s) %s", sz, (c == '\"') ? "" : "\"\"");
		    sinserts((*lp == NULL) ? &lprev->text[*off] 
			                   : &(*lp)->text[*off],
			     0, tmp, j = strlen(tmp));
		    *off += j;
		    rv = 1;
		    level = (c == '\"') ? COMMENT : TG;/* cmnt or eat trash */
		}
	    }
	    else if(!lbln && (c == ',' || c == ' ' || c == '[' || c == ']')){
		emlwrite("\007Attchmnt: '%c' not allowed in file name",
			  (void *)(int)c);
		rv = -1;			/* bad char in file name */
		level = TG;			/* gobble garbage */
	    }
	    else
	      *p++ = c;				/* add char to name */

	    break;

	  case WST:				/* skip white space */
	    if(!myisspace(c)){
		/*
		 * whole attachment, comment or done! 
		 */
		if(c == ',' || c == '\0' || c == '\"'){
		    strcpy(sz, (lblsz) ? lblsz : prettysz(l));
		    sprintf(tmp, " (%s) %s", sz, 
				           (c == '\"') ? "" : "\"\"");
		    sinserts((*lp == NULL) ? &lprev->text[*off]
				           : &(*lp)->text[*off],
			     0, tmp, j = strlen(tmp));
		    *off += j;
		    rv = 1;
		    level = (c == '\"') ? COMMENT : TG;
		    lbln = 0;			/* reset flag */
		}
		else if(c == '('){		/* get the size */
		    level = SIZE;
		}
		else{
		    emlwrite("\007Attchmnt: Expected '(' or '\"' after %s",fn);
		    rv = -1;			/* bag it all */
		    level = TG;
		}
	    }
	    break;

	  case SIZE:				/* check size */
	    if(c == ')'){			/* finished grabbing size */
		*p = '\0';
		/*
		 * replace sizes if they don't match!
		 */
		strcpy(sz, tmp);
		if(strcmp(sz, (lblsz) ? lblsz : prettysz(l))){
		    strcpy(sz, (lblsz) ? lblsz : prettysz(l));
		    if(p-tmp > *off){		/* where to begin replacemnt */
			j = (p-tmp) - *off;
			sinserts((*lp)->text, *off, "", 0);
			sinserts(&lprev->text[strlen(lprev->text)-j], j, 
				 sz, strlen(sz));
			*off = 0;
		    }
		    else{
			j = (*off) - (p-tmp);
			sinserts((*lp == NULL) ? &lprev->text[j] 
				               : &(*lp)->text[j], 
				 p-tmp , sz, strlen(sz));
			*off += strlen(sz) - (p-tmp);
		    }
		    rv = 1;
		}

		p = tmp;
		level = SWS;			/* what's next... */
	    }
	    else if(c == '\0' || c == ','){
		*p = '\0';
		emlwrite("\007Attchmnt: Size field missing ')': \"%s\"", tmp);
		rv = -1;
		level = TG;
	    }
	    else
	      *p++ = c;

	    break;

	  case SWS:				/* skip white space */
	    if(!myisspace(c)){
		if(c == ','){			/* no description */
		    level = TG;			/* munch rest of garbage */
		    lbln = 0;			/* reset flag */
		}
		else if(c != '\"' && c != '\0'){
		    emlwrite("\007Attchmnt: Malformed comment, quotes required", NULL);
		    rv = -1;
		    level = TG;
		}
		else
		  level = COMMENT;
	    }
	    break;

	  case COMMENT:				/* slurp up comment */
	    if(c == '\"' || c == '\0'){		/* got comment */
		*p = '\0';			/* cap it off */
		p = tmp;			/* reset p */
		strcpy(cmnt,tmp);		/* copy the comment  */
		if(c == '\0'){
		    emlwrite("\007Attchmnt: Closing quote required at end of comment", NULL);
		    rv = -1;
		}
		level = TG;			/* prepare for next one */
		lbln = 0;			/* reset flag */
	    }
	    else
	      *p++ = c;

	    break;

	  case TG:				/* get comma or final EOL */
	    if(!myisspace(c)){
		if(c != ',' && c != '\0'){
		    if(rv != -1)
		      emlwrite("\007Attchmnt: Comma must separate attachments", NULL);
		    rv = -1;
		}
	    }
	    break;

	  default:				/* something's very wrong */
	    emlwrite("\007Attchmnt: Weirdness in ParseAttach", NULL);
	    return(-1);				/* just give up */
	}

	if(c == '\0')				/* we're done */
	  break;

	(*off)++;

	/*
	 * not in comment or label name? done. 
	 */
	if(c == ',' && (level != COMMENT && !lbln))
	  break;				/* put offset past ',' */
    }

    return(rv);
}



/*
 * NewAttach - given a filename (assumed to accessible) and comment, creat
 */
PATMT *NewAttach(f, l, c)
char *f;
long l;
char *c;
{
    PATMT  *tp;

    if((tp=(PATMT *)malloc(sizeof(PATMT))) == NULL){
	emlwrite("No memory to add attachment", NULL);
	return(NULL);
    }
    else{
	tp->filename = tp->description = NULL;
	tp->size = tp->id = NULL;
	tp->next = NULL;
    }

    /* file and size malloc */
    if((tp->filename = (char *)malloc(strlen(f)+1)) == NULL){
	emlwrite("Can't malloc name for attachment", NULL);
	free((char *) tp);
	return(NULL);
    }
    strcpy(tp->filename, f);

    if(l > -1){
	tp->size = (char *)malloc(sizeof(char)*(strlen(prettysz(l))+1));
	if(tp->size == NULL){
	    emlwrite("Can't malloc size for attachment", NULL);
	    free((char *) tp->filename);
	    free((char *) tp);
	    return(NULL);
	}
	else
	  strcpy(tp->size, prettysz(l));
    }

    /* description malloc */
    if((tp->description = (char *)malloc(strlen(c)+1)) == NULL){
	emlwrite("Can't malloc description for attachment", NULL);
	free((char *) tp->size);
	free((char *) tp->filename);
	free((char *) tp);
	return(NULL);
    }
    strcpy(tp->description, c);

    return(tp);
}



/*
 * AttachError - Sniff list of attachments, returning TRUE if there's
 *               any sign of trouble...
 */
int
AttachError()
{
    PATMT *ap;

    if(!Pmaster)
      return(0);

    ap = Pmaster->attachments;
    while(ap){
	if((ap->flags) & A_ERR)
	  return(1);

	ap = ap->next;
    }

    return(FALSE);
}



void ZotAttach(p)
PATMT *p;
{
    if(!p)
      return;
    if(p->description)
      free((char *)p->description);
    if(p->filename)
      free((char *)p->filename);
    if(p->size)
      free((char *)p->size);
    if(p->id)
      free((char *)p->id);
    p->next = NULL;
}
#endif	/* ATTACHMENTS */


/*
 * intag - return TRUE if i is in a column that makes up an
 *         attachment line number
 */
intag(s, i)
char *s;
int   i;
{
    char *p = s;
    int n = 0;

    while(*p != '\0' && (p-s) < 5){		/* is there a tag? it */
	if(n && *p == '.')			/* can't be more than 4 */
	  return(i <= p-s);				/* chars long! */

	if(*p < '0' || *p > '9')
	  break;
	else
	  n = (n * 10) + (*p - '0');

	p++;
    }

    return(FALSE);
}


/*
 * prettysz - return pointer to string containing nice
 */
char *prettysz(l)
long l;
{
    static char b[32];

    if(l < 1000)
      sprintf(b, "%d  B", l);			/* xxx B */
    else if(l < 10000)
      sprintf(b, "%1.1f KB", (float)l/1000);    /* x.x KB */
    else if(l < 1000000)
      sprintf(b, "%d KB", l/1000);		/* xxx KB */
    else if(l < 10000000)
      sprintf(b, "%1.1f MB", (float)l/1000000); /* x.x MB */
    else
      sprintf(b, "%d MB", l/1000000);		/* xxx MB */
    return(b);
}


/*
 * sinserts - s insert into another string
 */
sinserts(ds, dl, ss, sl)
char *ds, *ss;					/* dest. and source strings */
int  dl, sl;					/* their lengths */
{
    char *dp, *edp;				/* pointers into dest. */
    int  j;					/* jump difference */

    if(sl >= dl){				/* source bigger than dest. */
	dp = ds + dl;				/* shift dest. to make room */
	if((edp = strchr(dp, '\0')) != NULL){
	    j = sl - dl;

	    for( ;edp >= dp; edp--)
	      edp[j] = *edp;

	    while(sl--)
	       *ds++ = *ss++;
	}
	else
	  emlwrite("\007No end of line???", NULL);	/* can this happen? */
    }
    else{					/* dest is longer, shrink it */
	j = dl - sl;				/* difference in lengths */

	while(sl--)				/* copy ss onto ds */
	  *ds++ = *ss++;

	if(strlen(ds) > j){			/* shuffle the rest left */
	    do
	      *ds = ds[j];
	    while(*ds++ != '\0');
	}
	else
	  *ds = '\0';
    }
}
/
			    emlwrite("\007Attchmnt: Expected ']' after \"%s\"",
				     fn);
			    rv = -1;
			    level = TG;
			    break;
			}
			strcat(fn, "]");

			/*
			 * This is kind of cheating since otherwise
			 * ParseAttach doesn't know about the attachment
			 * struct.  OK if filename's not found as it will
			 * get taken care of later...
			 */
			tp = Pmaster->attachments; /* caller check PmaDarkNET-1.08/pico.BBS/basic.c                                                                          644   21270   21270        40317  5742634031  10666                                                                                                                                                                                                                                                                                                                                                                      #if	!defined(lint) && !defined(DOS)
static char rcsid[] = "$Id: basic.c,v 4.13 1994/07/07 01:25:41 mikes Exp $";
#endif
/*
 * Program:	Cursor manipulation functions
 *
 *
 * Michael Seibel
 * Networks and Distributed Computing
 * Computing and Communications
 * University of Washington
 * Administration Builiding, AG-44
 * Seattle, Washington, 98195, USA
 * Internet: mikes@cac.washington.edu
 *
 * Please address all bugs and comments to "pine-bugs@cac.washington.edu"
 *
 * Copyright 1991-1994  University of Washington
 *
 *  Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee to the University of
 * Washington is hereby granted, provided that the above copyright notice
 * appears in all copies and that both the above copyright notice and this
 * permission notice appear in supporting documentation, and that the name
 * of the University of Washington not be used in advertising or publicity
 * pertaining to distribution of the software without specific, written
 * prior permission.  This software is made available "as is", and
 * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
 * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
 * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
 * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 * Pine and Pico are trademarks of the University of Washington.
 * No commercial use of these trademarks may be made without prior
 * written permission of the University of Washington.
 *
 */
/*
 * The routines in this file move the cursor around on the screen. They
 * compute a new value for the cursor, then adjust ".". The display code
 * always updates the cursor location, so only moves between lines, or
 * functions that adjust the top line in the window and invalidate the
 * framing, are hard.
 */
#include        <stdio.h>
#include	"estruct.h"
#include        "edef.h"
#include        "pico.h"
#include        "efunc.h"


#ifdef	ANSI
    int getgoal(struct LINE *);
#else
    int getgoal();
#endif


/*
 * Move the cursor to the
 * beginning of the current line.
 * Trivial.
 */
gotobol(f, n)
int f, n;
{
    curwp->w_doto  = 0;
    return (TRUE);
}

/*
 * Move the cursor backwards by "n" characters. If "n" is less than zero call
 * "forwchar" to actually do the move. Otherwise compute the new cursor
 * location. Error if you try and move out of the buffer. Set the flag if the
 * line pointer for dot changes.
 */
backchar(f, n)
int             f;
register int    n;
{
    register LINE   *lp;

    if (n < 0)
      return (forwchar(f, -n));

    while (n--) {
	if (curwp->w_doto == 0) {
	    if ((lp=lback(curwp->w_dotp)) == curbp->b_linep){
		if(Pmaster)
		    /*
		     * go up into editing the mail header if on 
		     * the top line and the user hits the left arrow!!!
		     *
		     * if the editor returns anything except -1, the 
		     * user requested something special, so let 
		     * pico know...
		     */
		  return((HeaderEditor(2, 1) == -2) ? forwpage(0, 1) : FALSE);
		else
		  return (FALSE);
	    }

	    curwp->w_dotp  = lp;
	    curwp->w_doto  = llength(lp);
	    curwp->w_flag |= WFMOVE;
	} else {
	  curwp->w_doto--;
	  if (curwp->w_doto > 0) {
	    if (isHan(curwp->w_dotp->l_text, curwp->w_doto) == 2)
	      curwp->w_doto--;
	  }
	}
    }

    return (TRUE);
}


/*
 * Move the cursor to the end of the current line. Trivial. No errors.
 */
gotoeol(f, n)
int f, n;
{
    curwp->w_doto  = llength(curwp->w_dotp);
    return (TRUE);
}


/*
 * Move the cursor forwwards by "n" characters. If "n" is less than zero call
 * "backchar" to actually do the move. Otherwise compute the new cursor
 * location, and move ".". Error if you try and move off the end of the
 * buffer. Set the flag if the line pointer for dot changes.
 */
forwchar(f, n)
int             f;
register int    n;
{
    if (n < 0)
      return (backchar(f, -n));

    while (n--) {
	if (curwp->w_doto == llength(curwp->w_dotp)) {
	    if (curwp->w_dotp == curbp->b_linep)
	      return (FALSE);

	    curwp->w_dotp  = lforw(curwp->w_dotp);
	    curwp->w_doto  = 0;
	    curwp->w_flag |= WFMOVE;
	} else {
	  if (curwp->w_doto+1 < llength(curwp->w_dotp) &&
	      isHan(curwp->w_dotp->l_text, curwp->w_doto) == 1) {
	    curwp->w_doto += 2;
	  } else {
	    curwp->w_doto++;
	  }
	}
    }
    
    return (TRUE);
}


/*
 * move to a particular line.
 * argument (n) must be a positive integer for
 * this to actually do anything
 */
gotoline(f, n)
int f, n;
{
    if (n < 1)		/* if a bogus argument...then leave */
      return(FALSE);

    /* first, we go to the start of the buffer */
    curwp->w_dotp  = lforw(curbp->b_linep);
    curwp->w_doto  = 0;
    return(forwline(f, n-1));
}


/*
 * Goto the beginning of the buffer. Massive adjustment of dot. This is
 * considered to be hard motion; it really isn't if the original value of dot
 * is the same as the new value of dot. Normally bound to "M-<".
 */
gotobob(f, n)
int f, n;
{
    curwp->w_dotp  = lforw(curbp->b_linep);
    curwp->w_doto  = 0;
    curwp->w_flag |= WFHARD;
    return (TRUE);
}


/*
 * Move to the end of the buffer. Dot is always put at the end of the file
 * (ZJ). The standard screen code does most of the hard parts of update.
 * Bound to "M->".
 */
gotoeob(f, n)
int f, n;
{
    curwp->w_dotp  = curbp->b_linep;
    curwp->w_doto  = 0;
    curwp->w_flag |= WFHARD;
    return (TRUE);
}


/*
 * Move forward by full lines. If the number of lines to move is less than
 * zero, call the backward line function to actually do it. The last command
 * controls how the goal column is set. Bound to "C-N". No errors are
 * possible.
 */
forwline(f, n)
int f, n;
{
    register LINE   *dlp;

    if (n < 0)
      return (backline(f, -n));

    if ((lastflag&CFCPCN) == 0)             /* Reset goal if last   */
      curgoal = getccol(FALSE);       /* not C-P or C-N       */

    thisflag |= CFCPCN;
    dlp = curwp->w_dotp;
    while (n-- && dlp!=curbp->b_linep)
      dlp = lforw(dlp);

    curwp->w_dotp  = dlp;
    curwp->w_doto  = getgoal(dlp);
    curwp->w_flag |= WFMOVE;
    return (TRUE);
}


/*
 * This function is like "forwline", but goes backwards. The scheme is exactly
 * the same. Check for arguments that are less than zero and call your
 * alternate. Figure out the new line and call "movedot" to perform the
 * motion. No errors are possible. Bound to "C-P".
 */
backline(f, n)
int f, n;
{
    register LINE   *dlp;
    register int    status = 0;

    if (n < 0)
      return (forwline(f, -n));

    if(Pmaster){
	/*
	 * go up into editing the mail header if on the top line
	 * and the user hits the up arrow!!!
	 */
	if (lback(curwp->w_dotp) == curbp->b_linep)
	  /*
	   * if the editor returns anything except -1 then the user
	   * has requested something special, so let pico know...
	   */
	  status = HeaderEditor(1, 1);
    }

    if ((lastflag&CFCPCN) == 0)             /* Reset goal if the    */
      curgoal = getccol(FALSE);       /* last isn't C-P, C-N  */

    thisflag |= CFCPCN;
    dlp = curwp->w_dotp;
    while (n-- && lback(dlp)!=curbp->b_linep)
      dlp = lback(dlp);

    curwp->w_dotp  = dlp;
    curwp->w_doto  = getgoal(dlp);
    curwp->w_flag |= WFMOVE;
    return (TRUE);
}


/*
 * go back to the begining of the current paragraph
 * here we look for a <NL><NL> or <NL><TAB> or <NL><SPACE>
 * combination to delimit the begining of a paragraph	
 */
gotobop(f, n)
int f, n;	/* default Flag & Numeric argument */
{
    if (n < 0)	/* the other way...*/
      return(gotoeop(f, -n));

    while (n-- > 0) {	/* for each one asked for */

	/* first scan back until we are in a word */
	while(!inword())
	  if(lback(curwp->w_dotp) == curbp->b_linep 
	     && curwp->w_doto == 0)
	    /* top line and nowhere else to go */
	    return(FALSE);
	  else if(backchar(FALSE, 1) == FALSE)
	    break;

	curwp->w_doto = 0;	/* and go to the B-O-Line */

	/* and scan back until we hit a <NL><NL> or <NL><TAB>
	   or a <NL><SPACE>					*/
	while (lback(curwp->w_dotp) != curbp->b_linep)
	  if (llength(curwp->w_dotp) != 0 &&
	      lgetc(curwp->w_dotp, curwp->w_doto).c != TAB &&
	      lgetc(curwp->w_dotp, curwp->w_doto).c != ' ')
	    curwp->w_dotp = lback(curwp->w_dotp);
	  else
	    break;

	/* and then forward until we are in a word */
	while(!inword())
	  if(forwchar(FALSE,1) == FALSE)
	    break;
    }

    curwp->w_flag |= WFMOVE;	/* force screen update */
}


/* 
 * go forword to the end of the current paragraph
 * here we look for a <NL><NL> or <NL><TAB> or <NL><SPACE>
 * combination to delimit the begining of a paragraph
 */
gotoeop(f, n)
int f, n;	/* default Flag & Numeric argument */

{
    register int suc;	/* success of last backchar */

    if (n < 0)	/* the other way...*/
      return(gotobop(f, -n));

    while (n-- > 0) {	/* for each one asked for */
	
	/* first scan forward until we are in a word */
	if(curwp->w_dotp != curbp->b_linep){
	    curwp->w_doto = 0;		/* go to the B-O-Line */
	    curwp->w_dotp = lforw(curwp->w_dotp);
	}

	/* and scan forword until we hit a <NL><NL> or <NL><TAB>
	   or a <NL><SPACE>					*/
	while (curwp->w_dotp != curbp->b_linep) {
	    if (llength(curwp->w_dotp) != 0 &&
		lgetc(curwp->w_dotp, curwp->w_doto).c != TAB &&
		lgetc(curwp->w_dotp, curwp->w_doto).c != ' ')
	      curwp->w_dotp = lforw(curwp->w_dotp);
	    else
	      break;
	}
	
	/* and then backward until we are in a word */
	suc = TRUE;
	while (suc && !inword()) {
	    if(lback(curwp->w_dotp) == curbp->b_linep 
	       && curwp->w_doto == 0)
	      break;
	    suc = backchar(FALSE, 1);
	}
	curwp->w_doto = llength(curwp->w_dotp);	/* and to the EOL */
    }

    curwp->w_flag |= WFMOVE;	/* force screen update */
    return(TRUE);
}

/*
 * This routine, given a pointer to a LINE, and the current cursor goal
 * column, return the best choice for the offset. The offset is returned.
 * Used by "C-N" and "C-P".
 */
getgoal(dlp)
register LINE   *dlp;
{
    register int    c;
    register int    col;
    register int    newcol;
    register int    dbo;

    col = 0;
    dbo = 0;
    while (dbo != llength(dlp)) {
	c = lgetc(dlp, dbo).c;
	newcol = col;
	if (c == '\t')
	  newcol |= 0x07;
	else if (c<0x20 || c==0x7F)
	  ++newcol;

	++newcol;
	if (newcol > curgoal)
	  break;

	col = newcol;
	++dbo;
    }

    if (dbo < llength(dlp) && isHan(dlp, dbo) == 2)
      ++dbo;
    return (dbo);
}

/*
 * Scroll forward by a specified number of lines, or by a full page if no
 * argument. Bound to "C-V". The "2" in the arithmetic on the window size is
 * the overlap; this value is the default overlap value in ITS EMACS. Because
 * this zaps the top line in the display window, we have to do a hard update.
 */
forwpage(f, n)
int             f;
register int    n;
{
    register LINE   *lp;
    register int    nl;

    if (f == FALSE) {
	n = curwp->w_ntrows - 2;        /* Default scroll.      */
	if (n <= 0)                     /* Forget the overlap   */
	  n = 1;                  /* if tiny window.      */
    } else if (n < 0)
      return (backpage(f, -n));
#if     CVMVAS
    else                                    /* Convert from pages   */
      n *= curwp->w_ntrows;           /* to lines.            */
#endif
    nl = n;
    lp = curwp->w_linep;
    while (n-- && lp!=curbp->b_linep)
      lp = lforw(lp);

    curwp->w_dotp  = lp;
    curwp->w_doto  = 0;
    curwp->w_flag |= WFHARD;
    if(lp == curbp->b_linep)
      return(TRUE);
    else
      curwp->w_linep = lp;

    /*
     * if the header is open, close it ...
     */
    if(Pmaster && ComposerTopLine != COMPOSER_TOP_LINE){
	n -= ComposerTopLine - COMPOSER_TOP_LINE;
	ToggleHeader(0);
    }

    /*
     * scroll down from the top the same number of lines we've moved 
     * forward
     */
    if(optimize)
      scrollup(curwp, -1, nl-n-1);

    return (TRUE);
}


/*
 * This command is like "forwpage", but it goes backwards. The "2", like
 * above, is the overlap between the two windows. The value is from the ITS
 * EMACS manual. Bound to "M-V". We do a hard update for exactly the same
 * reason.
 */
backpage(f, n)
int             f;
register int    n;
{
    register LINE   *lp;
    register int    nl;
    int             status = 0;

    if (f == FALSE) {
	n = curwp->w_ntrows - 2;        /* Default scroll.      */
	if (n <= 0)                     /* Don't blow up if the */
	  n = 1;                  /* window is tiny.      */
    } else if (n < 0)
      return (forwpage(f, -n));
#if     CVMVAS
    else                                    /* Convert from pages   */
      n *= curwp->w_ntrows;           /* to lines.            */
#endif
    if(Pmaster){
	/*
	 * go up into editing the mail header if on the top line
	 * and the user hits the up arrow!!!
	 */
	if (lback(curwp->w_dotp) == curbp->b_linep){
	    /*
	     * if the editor returns anything except -1 then the user
	     * has requested something special, so let pico know...
	     */
	    status = HeaderEditor(1, 1);
	}
    }

    nl = n;
    lp = curwp->w_linep;
    while (n-- && lback(lp)!=curbp->b_linep)
      lp = lback(lp);

    curwp->w_linep = lp;
    curwp->w_dotp  = lp;
    curwp->w_doto  = 0;
    curwp->w_flag |= WFHARD;

	/*
	 * scroll down from the top the same number of lines we've moved 
	 * forward
	 *
	 * This isn't too cool, but it has to be this way so we can 
	 * gracefully scroll in the message header
	 */
    if(Pmaster){
	if((lback(lp)==curbp->b_linep) && (ComposerTopLine==COMPOSER_TOP_LINE))
	  n -= entry_line(1000, TRUE); /* never more than 1000 headers */
	if(nl-n-1 < curwp->w_ntrows)
	  if(optimize)
	    scrolldown(curwp, -1, nl-n-1);
    }
    else
      if(optimize)
	scrolldown(curwp, -1, nl-n-1);

    if(Pmaster){
	/*
	 * if we're at the top of the page, and the header is closed, 
	 * open it ...
	 */
	if((lback(lp) == curbp->b_linep) 
	   && (ComposerTopLine == COMPOSER_TOP_LINE)){
	    ToggleHeader(1);
	    movecursor(ComposerTopLine, 0);
	}
    }

    return (TRUE);
}


/*
 * Set the mark in the current window to the value of "." in the window. No
 * errors are possible. Bound to "M-.".  If told to set an already set mark
 * unset it.
 */
setmark(f, n)
int f, n;
{
    if(!curwp->w_markp){
        curwp->w_markp = curwp->w_dotp;
        curwp->w_marko = curwp->w_doto;
	emlwrite("Mark Set", NULL);
    }
    else{
	/* clear inverse chars between here and dot */
	markregion(0);
	curwp->w_markp = NULL;
	emlwrite("Mark UNset", NULL);
    }

#ifdef	_WINDOWS
    mswin_allowcopycut(curwp->w_markp ? kremove : NULL);
#endif
    return (TRUE);
}


/*
 * Swap the values of "." and "mark" in the current window. This is pretty
 * easy, bacause all of the hard work gets done by the standard routine
 * that moves the mark about. The only possible error is "no mark". Bound to
 * "C-X C-X".
 */
swapmark(f, n)
int f, n;
{
    register LINE   *odotp;
    register int    odoto;

    if (curwp->w_markp == NULL) {
	if(Pmaster == NULL)
	  emlwrite("No mark in this window", NULL);
	return (FALSE);
    }

    odotp = curwp->w_dotp;
    odoto = curwp->w_doto;
    curwp->w_dotp  = curwp->w_markp;
    curwp->w_doto  = curwp->w_marko;
    curwp->w_markp = odotp;
    curwp->w_marko = odoto;
    curwp->w_flag |= WFMOVE;
    return (TRUE);
}


/*
 * Set the mark in the current window to the value of "." in the window. No
 * errors are possible. Bound to "M-.".  If told to set an already set mark
 * unset it.
 */
setimark(f, n)
int f, n;
{
    curwp->w_imarkp = curwp->w_dotp;
    curwp->w_imarko = curwp->w_doto;
    return(TRUE);
}


/*
 * Swap the values of "." and "mark" in the current window. This is pretty
 * easy, bacause all of the hard work gets done by the standard routine
 * that moves the mark about. The only possible error is "no mark". Bound to
 * "C-X C-X".
 */
swapimark(f, n)
int f, n;
{
    register LINE   *odotp;
    register int    odoto;

    if (curwp->w_imarkp == NULL) {
	if(Pmaster == NULL)
	  emlwrite("Programmer botch! No mark in this window", NULL);
	return (FALSE);
    }

    odotp = curwp->w_dotp;
    odoto = curwp->w_doto;
    curwp->w_dotp  = curwp->w_imarkp;
    curwp->w_doto  = curwp->w_imarko;
    curwp->w_imarkp = odotp;
    curwp->w_imarko = odoto;
    curwp->w_flag |= WFMOVE;
    return (TRUE);
}
  if (llength(curwp->w_dotp) != 0 &&
	      lgetc(curwp->w_dotp, curwp->w_doto).c != TAB &&
	      lgetc(curwp->w_dotp, curwp->w_doto).c != ' ')
	    curwp->w_dotp = lback(curwp->w_dotp);
	  else
	    break;

	/* and then forward until we are in a word */
	while(!inword())
	  if(forwchar(FALSE,1) == FALSDarkNET-1.08/pico.BBS/bind.c                                                                           644   21270   21270        25405  5672473034  10530                                                                                                                                                                                                                                                                                                                                                                      #if	!defined(lint) && !defined(DOS)
static char rcsid[] = "$Id: bind.c,v 4.4 1994/03/17 00:56:12 mikes Exp $";
#endif
/*
 * Program:	Key binding routines
 *
 *
 * Michael Seibel
 * Networks and Distributed Computing
 * Computing and Communications
 * University of Washington
 * Administration Builiding, AG-44
 * Seattle, Washington, 98195, USA
 * Internet: mikes@cac.washington.edu
 *
 * Please address all bugs and comments to "pine-bugs@cac.washington.edu"
 *
 * Copyright 1991-1994  University of Washington
 *
 *  Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee to the University of
 * Washington is hereby granted, provided that the above copyright notice
 * appears in all copies and that both the above copyright notice and this
 * permission notice appear in supporting documentation, and that the name
 * of the University of Washington not be used in advertising or publicity
 * pertaining to distribution of the software without specific, written
 * prior permission.  This software is made available "as is", and
 * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
 * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
 * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
 * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 * Pine and Pico are trademarks of the University of Washington.
 * No commercial use of these trademarks may be made without prior
 * written permission of the University of Washington.
 *
 */
/*	This file is for functions having to do with key bindings,
	descriptions, help commands, and command line execution.

	written 11-feb-86 by Daniel Lawrence
								*/

#include	<stdio.h>
#include	"estruct.h"
#include	"edef.h"
#include	"pico.h"

#ifdef	ANSI
    int arraylen(char **);
#else
    int arraylen();
#endif

/* 
 * help - help function for pico (UW pared down version of uemacs).
 *	  this function will intentionally garbage with helpful 
 *	  tips and then wait for a ' ' to be hit to then update the 
 *        screen.
 */


static char *helptext[] = {
    "\tPico Help Text",
    " ",
    "\tPico is designed to be a simple, easy-to-use text editor with a",
    "\tlayout very similar to the pine mailer.  The status line at the",
    "\ttop of the display shows pico's version, the current file being",
    "\tedited and whether or not there are outstanding modifications",
    "\tthat have not been saved.  The third line from the bottom is used",
    "\tto report informational messages and for additional command input.",
    "\tThe bottom two lines list the available editing commands.",
    " ",
    "\tEach character typed is automatically inserted into the buffer",
    "\tat the current cursor position.  Editing commands and cursor",
    "\tmovement (besides arrow keys) are given to pico by typing",
    "\tspecial control-key sequences.  A caret, '^', is used to denote",
    "~\tthe control key, sometimes marked \"CTRL\", so the ~C~T~R~L~-~q key",
    "~\tcombination is written as ~^~Q.",
    " ",
    "\tThe following functions are available in pico (where applicable,",
    "\tcorresponding function key commands are in parentheses).",
    " ",
    "~\t~^~G (~F~1)   Display this help text.",
    " ",
    "~\t~^~F        move Forward a character.",
    "~\t~^~B        move Backward a character.",
    "~\t~^~P        move to the Previous line.",
    "~\t~^~N        move to the Next line.",
    "~\t~^~A        move to the beginning of the current line.",
    "~\t~^~E        move to the End of the current line.",
    "~\t~^~V (~F~8)   move forward a page of text.",
    "~\t~^~Y (~F~7)   move backward a page of text.",
    " ",
    "~\t~^~W (~F~6)   Search for (where is) text, neglecting case.",
    "~\t~^~L        Refresh the display.",
    " ",
    "~\t~^~D        Delete the character at the cursor position.",
    "~\t~^~^        Mark cursor position as beginning of selected text.",
    "\t\t  Note: Setting mark when already set unselects text.",
    "~\t~^~K (~F~9)   Cut selected text (displayed in inverse characters).",
    "\t\t  Note: The selected text's boundary on the cursor side",
    "\t\t        ends at the left edge of the cursor.  So, with ",
    "\t\t        selected text to the left of the cursor, the ",
    "\t\t        character under the cursor is not selected.",
    "~\t~^~U (~F~1~0)  Uncut (paste) last cut text inserting it at the",
    "\t\t  current cursor position.",
    "~\t~^~I        Insert a tab at the current cursor position.",
    " ",
    "~\t~^~J (~F~4)   Format (justify) the current paragraph.",
    "\t\t  Note: paragraphs delimited by blank lines or indentation.",
    "~\t~^~T (~F~1~2)  To invoke the spelling checker",
    "~\t~^~C (~F~1~1)  Report current cursor position",
    " ",
    "~\t~^~R (~F~5)   Insert an external file at the current cursor position.",
    "~\t~^~O (~F~3)   Output the current buffer to a file, saving it.",
    "~\t~^~X (~F~2)   Exit pico, saving buffer.",
    "    ",
    "\tPine and Pico are trademarks of the University of Washington.",
    "\tNo commercial use of these trademarks may be made without prior",
    "\twritten permission of the University of Washington.",
    "    ",
    "    End of Help.",
    " ",
    NULL
};


/*
 * arraylen - return the number of bytes in an array of char
 */
arraylen(array)
char **array;
{
    register int i=0;

    while(array[i++] != NULL) ;
    return(i);
}


/*
 * whelp - display help text for the composer and pico
 */
whelp(f, n)
{
    if(Pmaster){
	(*Pmaster->helper)(Pmaster->composer_help, "Help on the Pine Composer", 1);
	curwp->w_flag |= WFMODE;
    }
    else
      pico_help(helptext);

        sgarbf = TRUE;
}

static KEYMENU eng_menu_scroll[] = {
    {NULL, NULL},		{NULL, NULL},	{NULL, NULL},
    {NULL, NULL},		{NULL, NULL},	{NULL, NULL},
    {"^X", "Exit Help"},	{NULL, NULL},	{NULL, NULL},
    {NULL, NULL},		{NULL, NULL},	{NULL, NULL}
};

static KEYMENU kr_menu_scroll[] = {
    {NULL, NULL},		{NULL, NULL},	{NULL, NULL},
    {NULL, NULL},		{NULL, NULL},	{NULL, NULL},
    {"^X", "µµ¿ò¸» ³¡"},	{NULL, NULL},	{NULL, NULL},
    {NULL, NULL},		{NULL, NULL},	{NULL, NULL}
};

static KEYMENU *menu_scroll = eng_menu_scroll;

#define	PREV_KEY	3
#define	NEXT_KEY	9


#define	OVERLAP	2		/* displayed page overlap */

bind_init()
{
	extern int lang;

	if (lang)
		menu_scroll = kr_menu_scroll;
	else
		menu_scroll = eng_menu_scroll;
}

/*
 * scrollw - takes beginning row and ending row to diplay an array
 *           of text lines.  returns either 0 if scrolling terminated
 *           normally or the value of a ctrl character typed to end it.
 *
 * updates - 
 *     01/11/89 - added stripe call if 1st char is tilde - '~'
 *
 */
wscrollw(begrow, endrow, textp, textlen)
int	begrow, endrow;
char	*textp[];
int	textlen;
{
    register int	loffset = 0; 
    register int	prevoffset = -1; 
    register int	dlines;
    register int	i;
    register int	cont;
    register int	done = 0;
    register char	*buf;
    int	 c;
     
    dlines = endrow - begrow - 1;
    while(!done) {
        /*
         * diplay a page loop ...
         */
	if(prevoffset != loffset){
       	    for(i = 0; i < dlines; i++){
                movecursor(i + begrow, 0);
                peeol();
                if((loffset+i) < textlen){
		    buf = &(textp[loffset+i][0]);
		    if(*buf == '~'){
			buf++;
			wstripe(begrow+i, 0, buf, '~');
		    }
		    else{
			pputs(buf, 0);
		    }
                }
            }
	    /*
	     * put up the options prompt
	     */
            movecursor(begrow + dlines, 0);
            cont = (loffset+dlines < textlen);
            if(cont){                               /* continue ? */
		extern int lang;
		menu_scroll[NEXT_KEY].name  = "^V";
		if (lang)
		  menu_scroll[NEXT_KEY].label = "´ÙÀ½Àå";
		else
		  menu_scroll[NEXT_KEY].label = "Next Pg";
	    }
	    else
	      menu_scroll[NEXT_KEY].name = NULL;

	    if(loffset){
		extern int lang;
		menu_scroll[PREV_KEY].name  = "^Y";
		if (lang)
		  menu_scroll[PREV_KEY].label = "ÀÌÀüÀå";
		else
		  menu_scroll[PREV_KEY].label = "Prev Pg";
	    }
	    else
	      menu_scroll[PREV_KEY].name = NULL;

	    wkeyhelp(menu_scroll);
	}

	(*term.t_flush)();

        c = GetKey();

	prevoffset = loffset;
	switch(c){
	    case  (CTRL|'X') :		/* quit */
 	    case  F2  :
		done = 1;
		break;
	    case  (CTRL|'Y') :		/* prev page */
	    case  F7  :			/* prev page */
		if((loffset-dlines-OVERLAP) > 0){
               	    loffset -= (dlines-OVERLAP);
		}
	        else{
		    if(loffset != 0){
			prevoffset = -1;
		    }
		    else{
		    	(*term.t_beep)();
		    }
		    loffset = 0;
	        }
		break;
	    case  (CTRL|'V') :			/* next page */
 	    case  F8  :
		if(cont){
               	   loffset += (dlines-OVERLAP);
		}
		else{
		   (*term.t_beep)();
		}
		break;
	    case  '\016' :		/* prev-line */
	    case  (CTRL|'N') :
	      if(cont)
		loffset++;
	      else
		(*term.t_beep)();
	      break;
	    case  '\020' :		/* prev-line */
	    case  (CTRL|'P') :
	      if(loffset > 0)
		loffset--;
	      else
		(*term.t_beep)();
	      break;
	    case  '\014' :		/* refresh */
	    case  (CTRL|'L') :		/* refresh */
	        modeline(curwp);
		update();
		prevoffset = -1;
		break;
	    case  NODATA :
	        break;
	    default :
		emlwrite("Unknown Command.");
		(*term.t_beep)();
		break;
	}
    }
    return(TRUE);
}


/*
 * normal - given a char and list of function key to command key mappings, 
 *          return, depending on gmode, the right command.  The list is
 *          an array of (Fkey, command-key) pairs.  sc is the index in the
 *          array that means to ignore fkey vs. command key mapping
 *
 *          rules:  1. if c not in table (either fkey or command), let it thru
 *                  2. if c matches, but in other mode, punt it
 */
normal(c, list, sc)
int c, sc;
int list[][2];
{
    register int i;

    for(i=0; i < 12; i++){
	if(c == list[i][(FUNC&c) ? 0 : 1]){	/* in table? */
	    if(i == sc)				/* SPECIAL CASE! */
	      return(list[i][1]);

	    if(list[i][1] == NODATA)		/* no mapping ! */
	      return(c);

	    if(((FUNC&c) == FUNC) ^ ((gmode&MDFKEY) == MDFKEY))
	      return(BADESC);			/* keystroke not allowed! */
	    else
	      return(list[i][1]);		/* never return func keys */
	}
    }

    return(c);
}


/*
 * rebind - replace the first function with the second
 */
rebindfunc(a, b)
int (*a)(), (*b)();
{
    KEYTAB *kp;

    kp = (Pmaster) ? &keytab[0] : &pkeytab[0];

    while(kp->k_fp != NULL){		/* go thru whole list, and */
	if(kp->k_fp == a)
	  kp->k_fp = b;			/* replace all occurances */
	kp++;
    }
}
m the bottom is used",
    "\tto report informational messages and for additional command input.",
    "\tThe bottom two lines list the available editing commands.",
    " ",
    "\tEach character typed is automatically inserted into the buffer",
    DarkNET-1.08/pico.BBS/browse.c                                                                         644   21270   21270       110012  5672463051  11120                                                                                                                                                                                                                                                                                                                                                                      #if	!defined(lint) && !defined(DOS)
static char rcsid[] = "$Id: browse.c,v 4.21 1994/09/27 16:19:37 mikes Exp $";
#endif
/*
 * Program:	Routines to support file browser in pico and Pine composer
 *
 *
 * Michael Seibel
 * Networks and Distributed Computing
 * Computing and Communications
 * University of Washington
 * Administration Builiding, AG-44
 * Seattle, Washington, 98195, USA
 * Internet: mikes@cac.washington.edu
 *
 * Please address all bugs and comments to "pine-bugs@cac.washington.edu"
 *
 * Copyright 1991-1994  University of Washington
 *
 *  Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee to the University of
 * Washington is hereby granted, provided that the above copyright notice
 * appears in all copies and that both the above copyright notice and this
 * permission notice appear in supporting documentation, and that the name
 * of the University of Washington not be used in advertising or publicity
 * pertaining to distribution of the software without specific, written
 * prior permission.  This software is made available "as is", and
 * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
 * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
 * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
 * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 * Pine and Pico are trademarks of the University of Washington.
 * No commercial use of these trademarks may be made without prior
 * written permission of the University of Washington.
 *
 *
 * NOTES:
 *
 *   Misc. thoughts (mss, 5 Apr 92)
 * 
 *      This is supposed to be just a general purpose browser, equally
 *	callable from either pico or the pine composer.  Someday, it could
 * 	even be used to "wrap" the unix file business for really novice 
 *      users.  The stubs are here for renaming, copying, creating directories,
 *      deleting, undeleting (thought is delete just moves files to 
 *      ~/.pico.deleted directory or something and undelete offers the 
 *      files in there for undeletion: kind of like the mac trashcan).
 *
 *   Nice side effects
 *
 *      Since the full path name is always maintained and referencing ".." 
 *      stats the path stripped of its trailing name, the unpleasantness of 
 *      symbolic links is hidden.  
 *
 *   Fleshed out the file managements stuff (mss, 24 June 92)
 *
 *
 */
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#include "osdep.h"
#include "pico.h"
#include "estruct.h"
#include "edef.h"
#include "efunc.h"

#if	defined(bsd)
extern int errno;
#endif

/*
 * directory cell structure
 */
struct fcell {
    char *fname;				/* file name 	       */
    unsigned mode;				/* file's mode	       */
    char size[16];				/* file's size in s    */
    struct fcell *next;
    struct fcell *prev;
};


/*
 * master browser structure
 */
static struct bmaster {
    struct fcell *head;				/* first cell in list  */
    struct fcell *top;				/* cell in top left    */
    struct fcell *current;			/* currently selected  */
    int    longest;				/* longest file name   */
    int	   fpl;					/* file names per line */
    int    cpf;					/* chars / file / line */
    char   dname[NLINE];			/* this dir's name     */
    char   *names;				/* malloc'd name array */
} *gmp;						/* global master ptr   */

#ifdef	ANSI
    struct bmaster *getfcells(char *);
    int    PaintCell(int, int, int, struct fcell *, int);
    int    PaintBrowser(struct bmaster *, int);
    int    BrowserKeys(void);
    int    layoutcells(struct bmaster *);
    int    PlaceCell(struct bmaster *, struct fcell *, int *, int *);
    int    zotfcells(struct fcell *);
    int    zotmaster(struct bmaster **);
    struct fcell *FindCell(struct bmaster *, char *);
    int    sisin(char *, char *);
    int    BrowserAnchor(char *);
#else
    struct bmaster *getfcells();
    int    PaintCell();
    int    PaintBrowser();
    int    BrowserKeys();
    int    layoutcells();
    int    PlaceCell();
    int    zotfcells();
    int    zotmaster();
    struct fcell *FindCell();
    int    sisin();
    int    BrowserAnchor();
#endif


static	KEYMENU menu_browse[] = {
    {"?", "Get Help"},	{NULL, NULL},		{"R", "Rename"},
    {"-", "Back Pg"},	{"D", "Del File"},	{"M","Make Copy"},
    {"S", "[Select]"},	{"G", "Goto Dir"},	{"W", "Where is"},
    {"Spc", "Fwd Pg"},	{NULL, NULL},		{NULL, NULL}
};
#define	QUIT_KEY	1


/*
 * function key mappings...
 */
static int  bfmappings[12][2] = { { F1,  '?'},	/* function key */
				  { F2,  's'},	/* mappings... */
			          { F3,  'e'},
  			          { F4,  'g'},
			          { F5,  'r'},
 			          { F6,  'w'},
			          { F7,  '-'},
			          { F8,  ' '},
			          { F9,  'd'},
			          { F10, NODATA },
			          { F11, 'm'},
			          { F12, NODATA } };


/*
 * Browser help for pico (pine composer help handed to us by pine)
 */
static char *BrowseHelpText[] = {
"Help for Browse Command",
"  ",
"\tPico's file browser is used to select a file from the",
"\tfile system for inclusion in the edited text.",
"  ",
"~\tBoth directories and files are displayed.  Press ~S",
"~\tor ~R~e~t~u~r~n to select a file or directory.  When a file",
"\tis selected during the \"Read File\" command, it is",
"\tinserted into edited text.  Answering \"yes\" to the",
"\tverification question after a directory is selected causes",
"\tthe contents of that directory to be displayed for selection.",
"  ",
"\tThe file named \"..\" is special, and means the \"parent\"",
"\tof the directory being displayed.  Select this directory",
"\tto move upward in the directory tree.",
"  ",
"End of Browser Help.",
"  ",
NULL
};





/*
 * FileBrowse - display contents of given directory dir
 *
 *	    intput:  
 *		     dir points to initial dir to browse.
 *		     fn  initial file name. 
 *		     flags
 *
 *         returns:
 *                   dir points to currently selected directory (without
 *			trailing file system delimiter)
 *                   fn  points to currently selected file
 *                   sz  points to size of file if ptr passed was non-NULL
 *
 *                   1 if a file's been selected
 *                   0 if no files seleted
 *                  -1 if there where problems
 */
FileBrowse(dir, fn, sz, flags)
char *dir, *fn, *sz;			/* dir, name and optional size */
int   flags;
{
    int status, i, j, c;
    int row, col;
    char *p, child[NLINE], tmp[NLINE];
    struct bmaster *mp, *getfcells();
    struct fcell *tp;

    child[0] = '\0';

    if((gmode&MDSCUR) && homeless(dir)){
	emlwrite("\007Can't read %s in restricted mode", dir);
	sleep(2);
	return(0);
    }

    emlwrite("Building file list...", NULL);

    /* build contents of cell structures */
    if((gmp = getfcells(dir)) == NULL)
      return(-1);

    /* paint screen */
    PaintBrowser(gmp, 0);

    while(1){						/* the big loop */
	movecursor(term.t_nrow-2, 0);

	(*term.t_flush)();

	c = GetKey();

	if(Pmaster){
	    if(c == NODATA || time_to_check()){		/* new mail ? */
		if((*Pmaster->newmail)(&j, 0, c == NODATA ? 0 : 2) >= 0){
		    mlerase();
		    (*Pmaster->showmsg)(c);
		    mpresf = 1;
		}

		if(j || mpresf){
		    (*term.t_move)(term.t_nrow-2, 0);
		    (*Pmaster->clearcur)();
		}

		if(c == NODATA)			/* GetKey timed out */
		  continue;
	    }
	}
	else{
	    if(timeout && (c == NODATA || time_to_check()))
	      if(pico_new_mail())
		emlwrite("You may possibly have new mail.", NULL);
	    
	    if(c == NODATA)
	      continue;
	}

	if(mpresf){				/* blast old messages */
	    if(mpresf++ > MESSDELAY){		/* every few keystrokes */
		mlerase();
	    }
        }

	switch(normal(c, bfmappings, 2)){	/* process commands */

	  case K_PAD_RIGHT:			/* move right */
	  case (CTRL|'@'):
	  case (CTRL|'F'):			/* forward  */
	    if(gmp->current->next == NULL){
		(*term.t_beep)();
		break;
	    }

	    PlaceCell(gmp, gmp->current, &row, &col);
	    PaintCell(row, col, gmp->cpf, gmp->current, 0);
	    gmp->current = gmp->current->next;
	    if(PlaceCell(gmp, gmp->current, &row, &col)){
		PaintBrowser(gmp, 1);
	    }
	    else
	      PaintCell(row, col, gmp->cpf, gmp->current, 1);
	    break;

	  case K_PAD_LEFT:				/* move left */
	  case (CTRL|'B'):				/* back */
	    if(gmp->current->prev == NULL){
		(*term.t_beep)();
		break;
	    }

	    PlaceCell(gmp, gmp->current, &row, &col);
	    PaintCell(row, col, gmp->cpf, gmp->current, 0);
	    gmp->current = gmp->current->prev;
	    if(PlaceCell(gmp, gmp->current, &row, &col)){
		PaintBrowser(gmp, 1);
	    }
	    else
	      PaintCell(row, col, gmp->cpf, gmp->current, 1);
	    break;

	  case (CTRL|'A'):				/* beginning of line */
	    tp = gmp->current;
	    i = col;
	    while(i > 0){
		i -= gmp->cpf;
		if(tp->prev != NULL)
		  tp = tp->prev;
	    }
	    PlaceCell(gmp, gmp->current, &row, &col);
	    PaintCell(row, col, gmp->cpf, gmp->current, 0);
	    gmp->current = tp;
	    if(PlaceCell(gmp, tp, &row, &col)){
		PaintBrowser(gmp, 1);
	    }
	    else
	      PaintCell(row, col, gmp->cpf, gmp->current, 1);
	    break;

	  case (CTRL|'E'):				/* end of line */
	    tp = gmp->current;
	    i = col + gmp->cpf;
	    while(i+gmp->cpf <= gmp->cpf * gmp->fpl){
		i += gmp->cpf;
		if(tp->next != NULL)
		  tp = tp->next;
	    }

	    PlaceCell(gmp, gmp->current, &row, &col);
	    PaintCell(row, col, gmp->cpf, gmp->current, 0);
	    gmp->current = tp;
	    if(PlaceCell(gmp, tp, &row, &col)){
		PaintBrowser(gmp, 1);
	    }
	    else
	      PaintCell(row, col, gmp->cpf, gmp->current, 1);
	    break;

	  case (CTRL|'V'):				/* page forward */
	  case ' ':
	  case K_PAD_NEXTPAGE :
	  case K_PAD_END :
	    tp = gmp->top;
	    i = term.t_nrow - 4;

	    while(i-- && tp->next != NULL){
		j = 0;
		while(++j <= gmp->fpl  && tp->next != NULL)
		  tp = tp->next;
	    }

	    if(tp == NULL)
	      continue;

	    PlaceCell(gmp, gmp->current, &row, &col);
	    PaintCell(row, col, gmp->cpf, gmp->current, 0);
	    gmp->current = tp;
	    if(PlaceCell(gmp, tp, &row, &col)){
		PaintBrowser(gmp, 1);
	    }
	    else
	      PaintCell(row, col, gmp->cpf, gmp->current, 1);
	    break;

	  case '-' :
	  case (CTRL|'Y'):				/* page backward */
	  case K_PAD_PREVPAGE :
	  case K_PAD_HOME :
	    tp = gmp->top;
	    i = term.t_nrow - 6;
	    while(i-- && tp != NULL){
		j = gmp->fpl;
		while(j-- && tp != NULL)
		  tp = tp->prev;
	    }

	    if(tp || (gmp->current != gmp->top)){	/* clear old hilite */
		PlaceCell(gmp, gmp->current, &row, &col);
		PaintCell(row, col, gmp->cpf, gmp->current, 0);
	    }

	    if(tp)					/* new page ! */
		gmp->current = tp;
	    else if(gmp->current != gmp->top)		/* goto top of page */
		gmp->current = gmp->top;
	    else					/* do nothing */
	      continue;

	    if(PlaceCell(gmp, gmp->current, &row, &col)){
		PaintBrowser(gmp, 1);
	    }
	    else
	      PaintCell(row, col, gmp->cpf, gmp->current, 1);

	    break;

	  case K_PAD_DOWN :
	  case (CTRL|'N'):				/* next */
	    tp = gmp->current;
	    i = gmp->fpl;
	    while(i--){
		if(tp->next == NULL){
		    (*term.t_beep)();
		    break;
		}
		else
		  tp = tp->next;
	    }
	    if(i != -1)					/* can't go down */
	      break;

	    PlaceCell(gmp, gmp->current, &row, &col);
	    PaintCell(row, col, gmp->cpf, gmp->current, 0);
	    gmp->current = tp;
	    if(PlaceCell(gmp, tp, &row, &col)){
		PaintBrowser(gmp, 1);
	    }
	    else
	      PaintCell(row, col, gmp->cpf, gmp->current, 1);
	    break;

	  case K_PAD_UP :
	  case (CTRL|'P'):				/* previous */
	    tp = gmp->current;
	    i = gmp->fpl;
	    while(i-- && tp)
	      tp = tp->prev;

	    if(tp == NULL)
	      break;

	    PlaceCell(gmp, gmp->current, &row, &col);
	    PaintCell(row, col, gmp->cpf, gmp->current, 0);
	    gmp->current = tp;
	    if(PlaceCell(gmp, tp, &row, &col)){
		PaintBrowser(gmp, 1);
	    }
	    else
	      PaintCell(row, col, gmp->cpf, gmp->current, 1);
	    break;

	  case 'e':					/* user exits */
	  case 'E':
	    zotmaster(&gmp);
	    return(0);

	  case 'x':			            /* user exits wrong */
	  case 'X':
	    if(!(gmode&MDBRONLY)){
		emlwrite("\007Unknown command '%c'", (void *)c);
		break;
	    }

	    zotmaster(&gmp);
	    return(0);

	  case 'd':					/* delete */
	  case 'D':
	    if(gmp->current->mode){
/* BUG: if dir is empty it should be deleted */
		emlwrite("\007Can't delete a directory", NULL);
		break;
	    }

	    if(gmode&MDSCUR){				/* not allowed! */
		emlwrite("Delete not allowed in restricted mode",NULL);
		break;
	    }

	    sprintf(child, "%s%c%s", gmp->dname, C_FILESEP, 
		    gmp->current->fname);

	    i = 0;
	    while(i++ < 2){		/* verify twice!! */
		if(i == 1){
		    if(fexist(child, "w", (long *)NULL) != FIOSUC)
		      strcpy(tmp, "File is write protected! OVERRIDE");
		    else
		      sprintf(tmp, "Delete file \"%.*s\"", NLINE - 20, child);
		}
		else
		  strcpy(tmp, "File CANNOT be UNdeleted!  Really delete");

		if((status = mlyesno(tmp, FALSE)) != TRUE){
		    emlwrite((status ==  ABORT)
			       ? "Delete Cancelled"
			       : "File Not Deleted",
			     NULL);
		    break;
		}
	    }

	    if(status == TRUE){
		if(unlink(child) < 0){
		    emlwrite("Delete Failed: %s", errstr(errno));
		}
		else{			/* fix up pointers and redraw */
		    tp = gmp->current;
		    if(tp->next){
			gmp->current = tp->next;
			if(tp->next->prev = tp->prev)
			  tp->prev->next = tp->next;
		    }
		    else if(tp->prev) {
			gmp->current = tp->prev;
			if(tp->prev->next = tp->next)
			  tp->next->prev = tp->prev;
		    }

		    tp->fname = NULL;
		    tp->next = tp->prev = NULL;
		    if(tp != gmp->current)
		      free((char *) tp);

		    if((tp = FindCell(gmp, gmp->current->fname)) != NULL){
			gmp->current = tp;
			PlaceCell(gmp, gmp->current, &row, &col);
		    }
			    
		    PaintBrowser(gmp, 1);
		    mlerase();
		}
	    }

	    BrowserKeys();
	    break;

	  case '?':					/* HELP! */
	    if(Pmaster)
	      (*Pmaster->helper)(Pmaster->browse_help,
				 "Help for Browsing", 1);
	    else
	      pico_help(BrowseHelpText, "Help for Browsing", 1);
	    /* fall thru to repaint everything */

	  case (CTRL|'L'):
	    PaintBrowser(gmp, 0);
	    break;

	  case 'g':				/* jump to a directory */
	  case 'G':
	    i = 0;
	    child[0] = '\0';

	    while(!i){

		status = mlreply("Directory to go to: ", child, NLINE, QNORML,
				 NULL);

		switch(status){
		  case HELPCH:
		    emlwrite("\007No help yet!", NULL);
/* remove break and sleep after help text is installed */
		    sleep(3);
		    break;
		  case (CTRL|'L'):
		    PaintBrowser(gmp, 0);
		    break;
		  case ABORT:
		    emlwrite("Goto cancelled", NULL);
		    i++;
		    break;
		  case FALSE:
		  case TRUE:
		    i++;

		    if(*child == '\0')
		      strcpy(child, gethomedir(NULL));

		    if(!compresspath(gmp->dname, child, NLINE)){
			emlwrite("Invalid Directory: %s", child);
			break;
		    }

		    if((gmode&MDSCUR) && homeless(child)){
			emlwrite("Restricted mode browsing limited to home directory",NULL);
			break;
		    }

		    if(isdir(child, (long *) NULL)){
			if((mp = getfcells(child)) == NULL){
			    /* getfcells should explain what happened */
			    i++;
			    break;
			}

			zotmaster(&gmp);
			gmp = mp;
			PaintBrowser(gmp, 0);
		    }
		    else
		      emlwrite("\007Not a directory: \"%s\"", child);

		    break;
		  default:
		    break;
		}
	    }
	    BrowserKeys();
	    break;

	  case 'm':					/* copy */
	  case 'M':
	    if(gmp->current->mode){
		emlwrite("\007Can't copy a directory", NULL);
		break;
	    }

	    if(gmode&MDSCUR){				/* not allowed! */
		emlwrite("Copy not allowed in restricted mode",NULL);
		break;
	    }

	    i = 0;
	    child[0] = '\0';

	    while(!i){

		switch(status=mlreply("Name of new copy: ", child, NLINE,
				      QFFILE, NULL)){
		  case HELPCH:
		    emlwrite("\007No help yet!", NULL);
/* remove break and sleep after help text is installed */
		    sleep(3);
		    break;
		  case (CTRL|'L'):
		    PaintBrowser(gmp, 0);
		    break;
		  case ABORT:
		    emlwrite("Make Copy Cancelled", NULL);
		    i++;
		    break;
		  case FALSE:
		    i++;
		    mlerase();
		    break;
		  case TRUE:
		    i++;

		    if(child[0] == '\0'){
			emlwrite("No destination, file not copied", NULL);
			break;
		    }

		    if(!strcmp(gmp->current->fname, child)){
			emlwrite("\007Can't copy file on to itself!", NULL);
			break;
		    }

		    strcpy(tmp, child); 		/* add full path! */
		    sprintf(child, "%s%c%s", gmp->dname, C_FILESEP, tmp);

		    if((status = fexist(child, "w", (long *)NULL)) == FIOSUC){
			sprintf(tmp,"File \"%.*s\" exists! OVERWRITE",
				NLINE - 20, child);
			if((status = mlyesno(tmp, 0)) != TRUE){
			    emlwrite((status == ABORT)
				      ? "Make copy cancelled" 
				      : "File Not Renamed",
				     NULL);
			    break;
			}
		    }
		    else if(status != FIOFNF){
			fioperr(status, child);
			break;
		    }

		    sprintf(tmp, "%s%c%s", gmp->dname, C_FILESEP, 
			    gmp->current->fname);

		    if(copy(tmp, child) < 0){
			/* copy()  will report any error messages */
			break;
		    }
		    else{			/* highlight new file */
			emlwrite("File copied to %s", child);

			if((p = strrchr(child, C_FILESEP)) == NULL){
			    emlwrite("Problems refiguring browser", NULL);
			    break;
			}

			*p = '\0';
			strcpy(tmp, (p == child) ? S_FILESEP: child);

			/*
			 * new file in same dir? if so, refigure files
			 * and redraw...
			 */
			if(!strcmp(tmp, gmp->dname)){ 
			    strcpy(child, gmp->current->fname);
			    if((mp = getfcells(gmp->dname)) == NULL)
			      /* getfcells should explain what happened */
			      break;

			    zotmaster(&gmp);
			    gmp = mp;
			    if((tp = FindCell(gmp, child)) != NULL){
				gmp->current = tp;
				PlaceCell(gmp, gmp->current, &row, &col);
			    }

			    PaintBrowser(gmp, 1);
			}
		    }
		    break;
		  default:
		    break;
		}
	    }
	    BrowserKeys();
	    break;

	  case 'r':					/* rename */
	  case 'R':
	    i = 0;
	    child[0] = '\0';

	    if(!strcmp(gmp->current->fname, "..")){
		emlwrite("\007Can't rename \"..\"", NULL);
		break;
	    }

	    if(gmode&MDSCUR){				/* not allowed! */
		emlwrite("Rename not allowed in restricted mode",NULL);
		break;
	    }

	    while(!i){

		switch(status=mlreply("Rename file to: ", child, NLINE, QFFILE,
				      NULL)){
		  case HELPCH:
		    emlwrite("\007No help yet!", NULL);
/* remove break and sleep after help text is installed */
		    sleep(3);
		    break;
		  case (CTRL|'L'):
		    PaintBrowser(gmp, 0);
		    break;
		  case ABORT:
		    emlwrite("Rename cancelled", NULL);
		    i++;
		    break;
		  case FALSE:
		  case TRUE:
		    i++;

		    if(child[0] == '\0' || status == FALSE){
			mlerase();
			break;
		    }

		    strcpy(tmp, child);
		    sprintf(child, "%s%c%s", gmp->dname, C_FILESEP, tmp);

		    status = fexist(child, "w", (long *)NULL);
		    if(status == FIOSUC || status == FIOFNF){
			if(status == FIOSUC){
			    sprintf(tmp,"File \"%.*s\" exists! OVERWRITE",
				    NLINE - 20, child);

			    if((status = mlyesno(tmp, FALSE)) != TRUE){
				emlwrite((status ==  ABORT)
					  ? "Rename cancelled"
					  : "Not Renamed",
					 NULL);
				break;
			    }
			}

			sprintf(tmp, "%s%c%s", gmp->dname, C_FILESEP, 
				gmp->current->fname);

			if(rename(tmp, child) < 0){
			    emlwrite("Rename Failed: %s", errstr(errno));
			}
			else{
			    if((p = strrchr(child, C_FILESEP)) == NULL){
				emlwrite("Problems refiguring browser", NULL);
				break;
			    }
			    
			    *p = '\0';
			    strcpy(tmp, (p == child) ? S_FILESEP: child);

			    if((mp = getfcells(tmp)) == NULL)
			      /* getfcells should explain what happened */
			      break;

			    zotmaster(&gmp);
			    gmp = mp;

			    if((tp = FindCell(gmp, ++p)) != NULL){
				gmp->current = tp;
				PlaceCell(gmp, gmp->current, &row, &col);
			    }

			    PaintBrowser(gmp, 1);
			    mlerase();
			}
		    }
		    else{
			fioperr(status, child);
		    }
		    break;
		  default:
		    break;
		}
	    }
	    BrowserKeys();
	    break;

	  case 's':					/* user's selected */
	  case 'S':
	  case (CTRL|'M'):

	    if(gmp->current->mode){
		*child = '\0';

		while(1){
		    i = mlyesno("A directory is selected, enter it", 1);
		    if(i == TRUE){
			strcpy(tmp, gmp->dname);
			p = gmp->current->fname;
			if(p[0] == '.' && p[1] == '.' && p[2] == '\0'){

			    if((p=strrchr(tmp, C_FILESEP)) != NULL){
				*p = '\0';

				if((gmode&MDSCUR) && homeless(tmp)){
				    emlwrite("\007Can't visit parent in restricted mode", NULL);
				    break;
				}

				strcpy(child, &p[1]);
				if(p == tmp
#ifdef	DOS
				   || (tmp[1] == ':' && tmp[2] == '\0')
#endif
				         ){	/* is it root? */
				    if(*child)
#ifdef	DOS
				      strcat(tmp, S_FILESEP);
#else
				      strcpy(tmp, S_FILESEP);
#endif
				    else{
					emlwrite("\007Can't move up a directory", NULL);
					break;
				    }
				}
			    }
			}
			else{
			    if(tmp[1] != '\0')		/* were in root? */
			      strcat(tmp, S_FILESEP);
			    strcat(tmp, gmp->current->fname);
			}

			if((mp = getfcells(tmp)) == NULL)
			  /* getfcells should explain what happened */
			  break;

			zotmaster(&gmp);
			gmp = mp;

			if(*child){
			    if((tp = FindCell(gmp, child)) != NULL){
				gmp->current = tp;
				PlaceCell(gmp, gmp->current, &row, &col);
			    }
			    else
			      emlwrite("\007Problem finding dir \"%s\"",child);
			}

			PaintBrowser(gmp, 0);
			break;
		    }
		    else if(i == FALSE){
			mlerase();
			break;
		    }
		    else if(i == ABORT){
			emlwrite("Select cancelled", NULL);
			break;
		    }
		    else if(i == (CTRL|'L')){
			PaintBrowser(gmp, 0);
		    }
		    else
		      (*term.t_beep)();
		}
	    }
	    else{				/* just return */
		strcpy(dir, gmp->dname);
		strcpy(fn, gmp->current->fname);
		if(sz != NULL)			/* size uninteresting */
		  strcpy(sz, gmp->current->size);

#ifndef	_WINDOWS
		if(gmode&MDBRONLY){
		    i = 0;
		    sprintf(child, "%s%c%s", gmp->dname, C_FILESEP, fn);
			/* stat file for executable bit */
		    if(fexist(child, "x", NULL) == FIOSUC){
			while(!i){
			    switch(mlyesno("Program selected, run it", 1)){
			      case TRUE:
				strcpy(child, fn);
				while(!i){
				    status = mlreply("Command line : ",
						     child, NLINE, QNORML,
						     NULL);
				    switch(status){
				      case HELPCH:
					emlwrite("\007No help yet!", NULL);
/* remove break and sleep after help text is installed */
					sleep(3);
					break;
				      case (CTRL|'L'):
					PaintBrowser(gmp, 0);
					break;
				      case ABORT:
					emlwrite("Command cancelled", NULL);
					i++;
					break;
				      case FALSE:
				      case TRUE:
					i++;

					if(child[0]=='\0' || status==FALSE){
					    mlerase();
					    break;
					}

					vttidy();
					system(child);
					ttopen();

					/* recompute browser */
					/* redraw browser */
					PaintBrowser(gmp, 0);
					break;
					default:
					break;
				    }
				}

				break;
			      case FALSE:
				i += 2;
				mlerase();
				break;
			      case ABORT:
				i++;
				emlwrite("Command cancelled", NULL);
				break;
			      case (CTRL|'L'):
				PaintBrowser(gmp, 0);
				break;
			      default:
				(*term.t_beep)();
				break;
			    }
			}
		    }

		    if(i == 2)		/* do something else to executable? */
		      i = 0;

		    while(!i){
			*child = '\0';
			status = mlreply("Program to use on file : ",
				       child, NLINE, QNORML, NULL);
			switch(status){
			  case HELPCH:
			    emlwrite("\007No help yet!", NULL);
/* remove break and sleep after help text is installed */
			    sleep(3);
			    break;
			  case (CTRL|'L'):
			    PaintBrowser(gmp, 0);
			    break;
			  case ABORT:
			    emlwrite("Command cancelled", NULL);
			    i++;
			    break;
			  case FALSE:
			  case TRUE:
			    i++;

			    if(child[0] == '\0' || status == FALSE){
				mlerase();
				break;
			    }

			    strcat(child, " ");
			    strcat(child, gmp->dname);
			    strcat(child, S_FILESEP);
			    strcat(child, fn);

			    vttidy();
			    system(child);
			    ttopen();

			    /* recompute browser */
			    /* redraw browser */
			    PaintBrowser(gmp, 0);
			    break;
			  default:
			    break;
			}
		    }

		    BrowserKeys();
		}
		else{
		    zotmaster(&gmp);
		    return(1);
		}
#else
		/* xxx Can't execute files under windoes, do this... */
		zotmaster (&gmp);
		return (1);
#endif
	    }
	    break;

	  case 'w':				/* Where is */
	  case 'W':
	    i = 0;

	    while(!i){

		switch(readpattern("File name to find")){
		  case HELPCH:
		    emlwrite("\007No help yet!", NULL);
/* remove break and sleep after help text is installed */
		    sleep(3);
		    break;
		  case (CTRL|'L'):
		    PaintBrowser(gmp, 0);
		    break;
		  case ABORT:
		    emlwrite("Whereis cancelled", NULL);
		    i++;
		    break;
		  case FALSE:
		    mlerase();
		    i++;
		    break;
		  case TRUE:
		    if((tp = FindCell(gmp, pat)) != NULL){
			PlaceCell(gmp, gmp->current, &row, &col);
			PaintCell(row, col, gmp->cpf, gmp->current, 0);
			gmp->current = tp;

			if(PlaceCell(gmp, tp, &row, &col)){ /* top changed */
			    PaintBrowser(gmp, 1);
			}
			else
			  PaintCell(row, col, gmp->cpf, gmp->current, 1);
			mlerase();
		    }
		    else
		      emlwrite("\"%s\" not found", pat);

		    i++;
		    break;
		  default:
		    break;
		}
	    }
	    mlerase();
	    BrowserKeys();
	    break;

	  case (CTRL|'Z'):
	    if(gmode&MDSSPD){
		bktoshell();
		PaintBrowser(gmp,0);
		break;
	    }					/* fall thru with error! */

	  default:				/* what? */
	    if(c < 0xff)
	      emlwrite("\007Unknown command: '%c'", (void *) c);
	    else if(c & CTRL)
	      emlwrite("\007Unknown command: ^%c", (void *)(c&0xff));
	    else
	      emlwrite("\007Unknown command", NULL);
	  case NODATA:				/* no op */
	    break;
	}
    }
}



/*
 * getfcells - make a master browser struct and fill it in
 *             return NULL if there's a problem.
 */
struct bmaster *getfcells(dname)
char *dname;
{
    int  i, 					/* various return codes */
         nentries = 0;				/* number of dir ents */
    long l;
    char *np,					/* names of files in dir */
         *dcp,					/* to add file to path */
         **filtnames;				/* array filtered names */
    struct fcell *ncp,				/* new cell pointer */
                 *tcp;				/* trailing cell ptr */
    struct bmaster *mp;

    if((mp=(struct bmaster *)malloc(sizeof(struct bmaster))) == NULL){
	emlwrite("\007Can't malloc space for master filename cell", NULL);
	return(NULL);
    }

    if(dname[0] == '.' && dname[1] == '\0'){		/* remember this dir */
	if(!getcwd(mp->dname, 256))
	  mp->dname[0] = '\0';
    }
    else if(dname[0] == '.' && dname[1] == '.' && dname[2] == '\0'){
	if(!getcwd(mp->dname, 256))
	  mp->dname[0] = '\0';
	else{
	    if((np = (char *)strrchr(mp->dname, C_FILESEP)) != NULL)
	      if(np != mp->dname)
		*np = '\0';
	}
    }
    else
      strcpy(mp->dname, dname);

    mp->head = mp->top = NULL;
    mp->cpf = mp->fpl = 0;
    mp->longest = 5;				/* .. must be labeled! */

    if((mp->names = getfnames(mp->dname, &nentries)) == NULL){
	free((char *) mp);
	return(NULL);
    }

    /*
     * this is the fun part.  build an array of pointers to the fnames we're
     * interested in (i.e., do any filtering), then pass that off to be
     * sorted before building list of cells...
     *
     * right now default filtering on ".*" except "..", but this could
     * easily be made a user option later on...
     */
    if((filtnames=(char **)malloc((nentries+1) * sizeof(char *))) == NULL){
	emlwrite("\007Can't malloc space for name array", NULL);
	zotmaster(&mp);
	return(NULL);
    }

    i = 0;					/* index of filt'd array */
    np = mp->names;
    while(nentries--){
	if(*np == '.'){					/* filter .* */
	    if(np[1] == '\0' || (np[1] != '.' && np[2] != '\0')){
		np += strlen(np) + 1;
		continue;
	    }
	}

	filtnames[i++] = np;

	if((l = strlen(np)) > mp->longest)	/* cast l ? */
	  mp->longest = l;			/* remember longest */
	np += l + 1;				/* advance name pointer */

    }
    nentries = i;				/* new # of entries */

    /* 
     * sort files case independently
     */
    qsort((QSType *)filtnames, (size_t)nentries, sizeof(char *), sstrcasecmp);

    /* 
     * this is so we use absolute path names for stats.
     * remember: be careful using dname as directory name, and fix mp->dname
     * when we're done
     */
    dcp = (char *)strchr(mp->dname, '\0');
    if(dcp == mp->dname || dcp[-1] != C_FILESEP){
	dcp[0] = C_FILESEP;
	dcp[1] = '\0';
    }
    else
      dcp--;

    i = 0;
    while(nentries--){				/* stat filtered files */
	/* get a new cell */
	if((ncp=(struct fcell *)malloc(sizeof(struct fcell))) == NULL){
	    emlwrite("\007Can't malloc cells for browser!", NULL);
	    zotfcells(mp->head);		/* clean up cells */
	    free((char *) filtnames);
	    free((char *) mp);
	    return(NULL);			/* bummer. */
	}
	ncp->next = ncp->prev = NULL;
	ncp->mode = 0;

	if(mp->head == NULL){			/* tie it onto the list */
	    mp->head = mp->top = mp->current = ncp;
	}
	else{
	    tcp->next = ncp;
	    ncp->prev = tcp;
	}
	tcp = ncp;

	/* fill in the new cell */
	ncp->fname = filtnames[i++];

	strcpy(&dcp[1], ncp->fname);		/* use abolute path! */

	if(ncp->fname[0] == '.' && ncp->fname[1] == '.' && ncp->fname[2] == '\0'){
	    ncp->mode = 1;				/* parent is special */
	    strcpy(ncp->size, "(parent dir)");
	}
	else if(isdir(mp->dname, &l)){
	    ncp->mode = 1;
	    strcpy(ncp->size, "(dir)");
	}
	else
	  strcpy(ncp->size,  prettysz(l));
    }

    *dcp = '\0';				/* remember to cap dname */
    free((char *) filtnames);			/* 'n blast filt'd array*/

    layoutcells(mp);

    return(mp);
}



/*
 * PaintCell - print the given cell at the given location on the display
 *             the format of a printed cell is:
 *
 *                       "<fname>       <size>  "
 */
PaintCell(x, y, l, cell, inverted)
struct fcell *cell;
int    x, y, l, inverted;
{
    char *p;					/* temp str pointer */
    int   i = 0,				/* current display count */
          j, sl, fl;				/* lengths */

    if(cell == NULL)
	return(-1);

    fl = strlen(cell->fname);
    sl = strlen(cell->size);

    movecursor(x, y);
    if(inverted)
      (*term.t_rev)(1);
    
    /* room for fname? */
    p = (fl+2 > l) ? &cell->fname[fl-(l-2)] : cell->fname;
    while(*p != '\0'){				/* write file name */
	pputc(*p++, 0);
	i++;
    }

    if(sl+3 <= l-i){				/* room for size? */
	j = (l-i)-(sl+2);			/* put space between */
	i += j;
	while(j--)				/* file name and size */
	  pputc(' ', 0);

	p = cell->size;
	while(*p != '\0'){			/* write file size */
	    pputc(*p++, 0);
	    i++;
	}
    }

    if(inverted)
      (*term.t_rev)(0);

    while(i++ < l)				/* pad ending */
      pputc(' ', 0);

    return(1);
}



/*
 * PaintBrowse - with the current data, display the browser.  if level == 0 
 *               paint the whole thing, if level == 1 just paint the cells
 *               themselves
 */
PaintBrowser(mp, level)
struct bmaster *mp;
int level;
{
    int i, cl;
    struct fcell *tp;

    if(!level){
	cl = (Pmaster) ? term.t_nrow : term.t_nrow - 1;
	for(i = 0; i <= cl; i++){		/* clear screen */
	    movecursor(i, 0);
	    peeol();
	}

	BrowserAnchor(mp->dname);
    }

    i = 0;
    tp = mp->top;
    cl = COMPOSER_TOP_LINE;			/* current display line */
    while(tp){

	PaintCell(cl, mp->cpf * i, mp->cpf, tp, tp == mp->current);

	if(++i >= mp->fpl){
	    i = 0;
	    if(++cl > term.t_nrow-3)
	      break;
	}

	tp = tp->next;
    }

    if(level){
	while(cl <= term.t_nrow - 3){
	    if(!i)
	      movecursor(cl, 0);
	    peeol();
	    movecursor(++cl, 0);
	}
    }
    else{
	BrowserKeys();
    }

    return(1);
}


/*
 * BrowserKeys - just paints the keyhelp at the bottom of the display
 */
BrowserKeys()
{
    menu_browse[QUIT_KEY].name  = (gmode&MDBRONLY) ? "X" : "E";
    menu_browse[QUIT_KEY].label = (gmode&MDBRONLY) ? "Exit" : "Exit Brwsr";
    wkeyhelp(menu_browse);
}


/*
 * layoutcells - figure out max length of cell and how many cells can 
 *               go on a line of the display
 */
layoutcells(mp)
struct bmaster *mp;
{
    int i = 1;

    mp->cpf = mp->longest + 12;			/* max chars / file */

    while(i*mp->cpf < term.t_ncol)		/* no force... */
      i++;					/* like brute force! */

    mp->fpl = i - 1;				/* files per line */
}


/*
 * PlaceCell - given a browser master, return row and col of the display that
 *             it should go.  
 *
 *             return 1 if mp->top has changed, x,y relative to new page
 *             return 0 if otherwise (same page)
 *             return -1 on error
 */
PlaceCell(mp, cp, x, y)
struct bmaster *mp;
struct fcell *cp;
int    *x, *y;
{
    int cl = COMPOSER_TOP_LINE;			/* current line */
    int ci = 0;					/* current index on line */
    int rv = 0;
    int secondtry = 0;
    struct fcell *tp;

    /* will cp fit on screen? */
    tp = mp->top;
    while(1){
	if(tp == cp){				/* bingo! */
	    *x = cl;
	    *y = ci * mp->cpf;
	    break;
	}

	if((tp = tp->next) == NULL){		/* above top? */
	    if(secondtry++){
		emlwrite("\007Internal error: can't find fname cell", NULL);
		return(-1);
	    }
	    else{
		tp = mp->top = mp->head;	/* try from the top! */
		cl = COMPOSER_TOP_LINE;
		ci = 0;
		rv = 1;
		continue;			/* start over! */
	    }
	}

	if(++ci >= mp->fpl){			/* next line? */
	    ci = 0;
	    if(++cl > term.t_nrow-3){		/* next page? */
		ci = mp->fpl;			/* tp is at bottom right */
		while(ci--)			/* find new top */
		  tp = tp->prev;
		mp->top = tp;
		ci = 0;
		cl = COMPOSER_TOP_LINE;		/* keep checking */
		rv = 1;
	    }
	}

    }

    /* not on display! */
    return(rv);
	
}


/*
 * zotfcells - clean up malloc'd cells of file names
 */
zotfcells(hp)
struct fcell *hp;
{
    struct fcell *tp;

    while(hp){
	tp = hp;
	hp = hp->next;
	tp->next = NULL;
	free((char *) tp);
    }
}


/*
 * zotmaster - blast the browser master struct
 */
zotmaster(mp)
struct bmaster **mp;
{
    zotfcells((*mp)->head);			/* free cells       */
    free((char *)(*mp)->names);			/* free file names  */
    free((char *)*mp);				/* free master      */
    *mp = NULL;					/* make double sure */
}


/*
 * FindCell - starting from the current cell find the first occurance of 
 *            the given string wrapping around if necessary
 */
struct fcell *FindCell(mp, string)
struct bmaster *mp;
char   *string;
{
    struct fcell *tp, *fp;

    if(*string == '\0')
      return(NULL);

    fp = NULL;
    tp = mp->current->next;
    
    while(tp && !fp){
	if(sisin(tp->fname, string))
	  fp = tp;
	else
	  tp = tp->next;
    }

    tp = mp->head;
    while(tp != mp->current && !fp){
	if(sisin(tp->fname, string))
	  fp = tp;
	else
	  tp = tp->next;
    }

    return(fp);
}


/*
 * sisin - case insensitive substring matching function
 */
sisin(s1, s2)
char *s1, *s2;
{
    register int j;

    while(*s1){
	j = 0;
	while(toupper(s1[j]) == toupper(s2[j]))
	  if(s2[++j] == '\0')			/* bingo! */
	    return(1);

	s1++;
    }
    return(0);
} 


/*
 * BrowserAnchor - draw the browser's anchor line.
 */
BrowserAnchor(dir)
char *dir;
{
    register char *p;
    register int  i, j, l;
    char          buf[NLINE];

    movecursor(0, 0);
    (*term.t_rev)(1);

    i = 0;
    l = strlen(dir);
    j = (term.t_ncol-(l+16))/2;

    if(Pmaster)
      sprintf(buf, "   PINE %s", Pmaster->pine_version);
    else
      sprintf(buf,"   UW PICO(tm) %s", (gmode&MDBRONLY) ? "BROWSER" : version);

    p = buf;
    while(*p){
	pputc(*p++, 0);
	i++;
    }

    if(l > term.t_ncol - i - 21){		/* fit dir name on line */
	p = dir;
	while((p = strchr(p, C_FILESEP)) != NULL)
	  if((l - (p - dir)) <= term.t_ncol - i - 21)
	    break;
	  else
	    p++;

	if(*p == '\0')				/* no suitable length! */
	  p = &dir[l-(term.t_ncol-i-19)];

	sprintf(buf, "%s Dir ...%s", (gmode&MDBRONLY) ? "" : " BROWSER  ", p);
    }
    else 
      sprintf(buf,"%s  Dir: %s", (gmode&MDBRONLY) ? "" : " BROWSER  ", dir);

    if(i < j)					/* keep it centered */
      j = j - i;				/* as long as we can */
    else
      j = ((term.t_ncol-i)-(strlen(p)+15))/2;

    while(j-- && i++)
      pputc(' ', 0);

    p = buf;
    while(i++ < term.t_ncol && *p)		/* show directory */
      pputc(*p++, 0);

    while(i++ < term.t_ncol)
      pputc(' ', 0);

    (*term.t_rev)(0);
}


/*
 * ResizeBrowser - handle a resize event
 */
ResizeBrowser()
{
    if(gmp){
	layoutcells(gmp);
	PaintBrowser(gmp, 0);
	return(1);
    }
    else
      return(0);
}
mber: be careful using dname as directory name, and fix mp->dname
     * when we're done
     */
    dcp = (char *)strchr(mp->dname, '\0');
    if(dcp == mp->dname || dcp[-1] != C_FILESEP){
	dcp[0] = C_FILESEP;
	dcp[1] = '\0';
    }
    else
      dcp--;

    i = 0;
    while(nentries--){				/* stat filtered files */
	/* get a new cell */
	if((ncp=(struct fcell *)malloc(sizeof(struct fcell))) == NULL){
	    emlwrite("\007Can't malloc cells for browser!", NULL);
	    zotfcells(mp->head);		/* clean DarkNET-1.08/pico.BBS/buffer.c                                                                         644   21270   21270        25010  5672463051  11053                                                                                                                                                                                                                                                                                                                                                                      #if	!defined(lint) && !defined(DOS)
static char rcsid[] = "$Id: buffer.c,v 4.7 1994/08/16 15:51:39 mikes Exp $";
#endif
/*
 * Program:	Buffer management routines
 *
 *
 * Michael Seibel
 * Networks and Distributed Computing
 * Computing and Communications
 * University of Washington
 * Administration Builiding, AG-44
 * Seattle, Washington, 98195, USA
 * Internet: mikes@cac.washington.edu
 *
 * Please address all bugs and comments to "pine-bugs@cac.washington.edu"
 *
 * Copyright 1991-1994  University of Washington
 *
 *  Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee to the University of
 * Washington is hereby granted, provided that the above copyright notice
 * appears in all copies and that both the above copyright notice and this
 * permission notice appear in supporting documentation, and that the name
 * of the University of Washington not be used in advertising or publicity
 * pertaining to distribution of the software without specific, written
 * prior permission.  This software is made available "as is", and
 * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
 * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
 * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
 * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 * Pine and Pico are trademarks of the University of Washington.
 * No commercial use of these trademarks may be made without prior
 * written permission of the University of Washington.
 *
 */
/*
 * Buffer management.
 * Some of the functions are internal,
 * and some are actually attached to user
 * keys. Like everyone else, they set hints
 * for the display system.
 */
#include        <stdio.h>
#include	"osdep.h"
#include	"estruct.h"
#include        "pico.h"
#include        "edef.h"

#ifdef	ANSI
int sgetline(char **, int *, char *, int);
#else
int sgetline();
#endif


/*
 * Look through the list of
 * buffers. Return TRUE if there
 * are any changed buffers. Buffers
 * that hold magic internal stuff are
 * not considered; who cares if the
 * list of buffer names is hacked.
 * Return FALSE if no buffers
 * have been changed.
 */
anycb()
{
        register BUFFER *bp;

        bp = bheadp;
        while (bp != NULL) {
                if ((bp->b_flag&BFTEMP)==0 && (bp->b_flag&BFCHG)!=0)
                        return (TRUE);
                bp = bp->b_bufp;
        }
        return (FALSE);
}

/*
 * Find a buffer, by name. Return a pointer
 * to the BUFFER structure associated with it. If
 * the named buffer is found, but is a TEMP buffer (like
 * the buffer list) conplain. If the buffer is not found
 * and the "cflag" is TRUE, create it. The "bflag" is
 * the settings for the flags in in buffer.
 */
BUFFER  *
bfind(bname, cflag, bflag)
register char   *bname;
{
        register BUFFER *bp;
	register BUFFER *sb;	/* buffer to insert after */
        register LINE   *lp;

        bp = bheadp;
        while (bp != NULL) {
                if (strcmp(bname, bp->b_bname) == 0) {
                        if ((bp->b_flag&BFTEMP) != 0) {
                                mlwrite("Cannot select builtin buffer");
                                return (NULL);
                        }
                        return (bp);
                }
                bp = bp->b_bufp;
        }
        if (cflag != FALSE) {
                if ((bp=(BUFFER *)malloc(sizeof(BUFFER))) == NULL)
                        return (NULL);
                if ((lp=lalloc(0)) == NULL) {
                        free((char *) bp);
                        return (NULL);
                }
		/* find the place in the list to insert this buffer */
		if (bheadp == NULL || strcmp(bheadp->b_bname, bname) > 0) {
			/* insert at the begining */
	                bp->b_bufp = bheadp;
        	        bheadp = bp;
        	} else {
			sb = bheadp;
			while (sb->b_bufp != NULL) {
				if (strcmp(sb->b_bufp->b_bname, bname) > 0)
					break;
				sb = sb->b_bufp;
			}

			/* and insert it */
       			bp->b_bufp = sb->b_bufp;
        		sb->b_bufp = bp;
       		}

		/* and set up the other buffer fields */
		bp->b_active = TRUE;
                bp->b_dotp  = lp;
                bp->b_doto  = 0;
                bp->b_markp = NULL;
                bp->b_marko = 0;
                bp->b_flag  = bflag;
		bp->b_mode  = gmode;
                bp->b_nwnd  = 0;
                bp->b_linep = lp;
                strcpy(bp->b_fname, "");
                strcpy(bp->b_bname, bname);
                lp->l_fp = lp;
                lp->l_bp = lp;
        }
        return (bp);
}

/*
 * This routine blows away all of the text
 * in a buffer. If the buffer is marked as changed
 * then we ask if it is ok to blow it away; this is
 * to save the user the grief of losing text. The
 * window chain is nearly always wrong if this gets
 * called; the caller must arrange for the updates
 * that are required. Return TRUE if everything
 * looks good.
 */
bclear(bp)
register BUFFER *bp;
{
        register LINE   *lp;
        register int    s = FALSE;

	if(Pmaster){
	    if ((bp->b_flag&BFTEMP) == 0 	/* Not scratch buffer.  */
		&& (bp->b_flag&BFCHG) != 0){	/* Something changed    */
		emlwrite("buffer lines not freed.");
		return (s);
	    }
	}
	else{
	    if ((bp->b_flag&BFTEMP) == 0	/* Not scratch buffer.  */
		&& (bp->b_flag&BFCHG) != 0	/* Something changed    */
		&& (s=mlyesno("Discard changes", -1)) != TRUE){
		return (s);
	    }
	}

        bp->b_flag  &= ~BFCHG;                  /* Not changed          */
        while ((lp=lforw(bp->b_linep)) != bp->b_linep)
                lfree(lp);
        bp->b_dotp  = bp->b_linep;              /* Fix "."              */
        bp->b_doto  = 0;
        bp->b_markp = NULL;                     /* Invalidate "mark"    */
        bp->b_marko = 0;
        return (TRUE);
}


/*
 * packbuf - will pack up the main buffer in the buffer provided 
 *           to be returned to the program that called pico.
 *	     if need be, allocate memory for the new message. 
 *           will also free the memory associated with the editor
 *           buffer, by calling zotedit.
 */
packbuf(buf, blen, lcrlf)
char	**buf;
int	*blen;
int	lcrlf;				/* EOLs are local or CRLF */
{
    register int    s;
    register int    i = 0;
    register LINE   *lp;
    register int    retval = 0;
    register char   *bufp;
    register char   *eobuf;
 
    if(anycb() != FALSE){

        lp = lforw(curbp->b_linep);
        do{					/* how many chars? */
            i += llength(lp);
	    /*
	     * add extra for new lines to be inserted later
	     */
	    i += 2;
	    lp = lforw(lp);
        }
        while(lp != curbp->b_linep);

        if(i > *blen){				/* new buffer ? */
            /*
             * don't forget to add one for the null terminator!!!
             */
	    if((bufp = (char *)malloc((i+1)*sizeof(char))) == NULL){
                    zotedit();			/* bag it! */
		    return(COMP_FAILED);
	    }
            free(*buf);
	    *buf = bufp;
	    *blen = i;
        }
        else{
            bufp = *buf;
        }
    
        eobuf = bufp + *blen;
        lp = lforw(curbp->b_linep);             /* First line.          */
        do {
	    for (i = 0; i < llength(lp); i++){	/* copy into buffer */
	        if((bufp+1) < eobuf){
		    *bufp++ = (lp->l_text[i].c & 0xFF);
	        }
	        else{
		    /*
		     * the idea is to malloc enough space for the new
		     * buffer...
		     */
		    *bufp = '\0';
                    zotedit();
		    return(BUF_CHANGED|COMP_FAILED);
	        }
	    }
	    if(lcrlf){
		*bufp++ = '\n';			/* EOLs use local convention */
	    }
	    else{
		*bufp++ = 0x0D;			/* EOLs use net standard */
		*bufp++ = 0x0A;
	    }
            lp = lforw(lp);
        }
        while (lp != curbp->b_linep);
	if(lcrlf)
	  *--bufp = '\0';
	else
	  *bufp = '\0';
        retval = BUF_CHANGED;
    }

    zotedit();
    return(retval);
}


/*
 * readbuf - reads in a buffer.
 */
readbuf(buf)
char	**buf;
{
        register LINE   *lp1;
        register LINE   *lp2;
        register BUFFER *bp;
        register WINDOW *wp;
        register int    i;
        register int    s;
        char   *sptr;          /* pointer into buffer string */
        int		nbytes;
        char            line[NLINE];
	CELL            ac;
 
	bp = curbp;
        bp->b_flag &= ~(BFTEMP|BFCHG);
	sptr = *buf;
	ac.a  = 0;

        while((s=sgetline(&sptr,&nbytes,line,NLINE)) == FIOSUC || s == FIOLNG){

                if ((lp1=lalloc(nbytes)) == NULL) {
                        s = FIOERR;             /* Keep message on the  */
                        break;                  /* display.             */
                }
                lp2 = lback(curbp->b_linep);
                lp2->l_fp = lp1;
                lp1->l_fp = curbp->b_linep;
                lp1->l_bp = lp2;
                curbp->b_linep->l_bp = lp1;
                for (i=0; i<nbytes; ++i){
		    ac.c = line[i];
		    lputc(lp1, i, ac);
		}
        }

        for (wp=wheadp; wp!=NULL; wp=wp->w_wndp) {
                if (wp->w_bufp == curbp) {
                        wheadp->w_linep = lforw(curbp->b_linep);
                        wheadp->w_dotp  = lback(curbp->b_linep);
                        wheadp->w_doto  = 0;
                        wheadp->w_markp = NULL;
                        wheadp->w_marko = 0;
                        wheadp->w_flag |= WFHARD;
                }
        }

	strcpy(bp->b_bname, "main");
	strcpy(bp->b_fname, "");

	bp->b_dotp = bp->b_linep;
	bp->b_doto = 0;
}


/*
 * sgetline - copy characters from ibuf to obuf, ending at the first 
 *            newline.  return with ibuf pointing to first char after
 *            newline.
 */
sgetline(ibuf, nchars, obuf, blen)
char	**ibuf;
int	*nchars;
char	*obuf;
int	blen;
{
    register char 	*len;
    register char 	*cbuf = *ibuf;
    register char 	*bufp = obuf;
    register int 	retval = FIOSUC;
#define CR '\015'
#define LF '\012'

    *nchars = 0;
    if(*cbuf == '\0'){
	retval = FIOEOF;
    }
    else{
	len = obuf + blen;
	while (*cbuf != CR && *cbuf != LF && *cbuf != '\0'){
	    if(bufp < len){
		*bufp++ = *cbuf++;
		(*nchars)++;
	    }
	    else{
		*bufp = '\0';
		retval = FIOLNG;
		break;
	    }
	}
    }
    *bufp = '\0';			/* end retured line */
    *ibuf = (*cbuf == CR) ? ++cbuf : cbuf;
    *ibuf = (*cbuf == LF) ? ++cbuf : cbuf;
    return(retval);
}
*bp;

        bp = bheadp;
        while (bp != NULL) {
                if ((bp->b_flag&BFTEMP)==0 && (bp->b_flag&BFCHG)!=0)
                        return (TRUE);
                bp = bp->b_bufp;
        }
        return (FALSE);
}

/*
 * Find a buffer, by name. Return a pointer
 * to the BUFFER structure associated with it. If
 * the named buffer is found, but is a TEMP buffer (like
 * the buffer list) conplain. If the buffer is not found
 * and the "cflag" is TRUE, create it. The "bflag" is
 * thDarkNET-1.08/pico.BBS/composer.c                                                                       644   21270   21270       200124  5672463657  11466                                                                                                                                                                                                                                                                                                                                                                      #if	!defined(lint) && !defined(DOS)
static char rcsid[] = "$Id: composer.c,v 4.45 1994/09/29 22:29:00 mikes Exp $";
#endif
/*
 * Program:	Pine composer routines
 *
 *
 * Michael Seibel
 * Networks and Distributed Computing
 * Computing and Communications
 * University of Washington
 * Administration Builiding, AG-44
 * Seattle, Washington, 98195, USA
 * Internet: mikes@cac.washington.edu
 *
 * Please address all bugs and comments to "pine-bugs@cac.washington.edu"
 *
 * Copyright 1991-1994  University of Washington
 *
 *  Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee to the University of
 * Washington is hereby granted, provided that the above copyright notice
 * appears in all copies and that both the above copyright notice and this
 * permission notice appear in supporting documentation, and that the name
 * of the University of Washington not be used in advertising or publicity
 * pertaining to distribution of the software without specific, written
 * prior permission.  This software is made available "as is", and
 * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
 * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
 * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
 * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 * Pine and Pico are trademarks of the University of Washington.
 * No commercial use of these trademarks may be made without prior
 * written permission of the University of Washington.
 *
 *
 * NOTES:
 *
 *  - composer.c is the composer for the PINE mail system
 *
 *  - tabled 01/19/90
 *
 *  Notes: These routines aren't incorporated yet, because the composer as
 *         a whole still needs development.  These are ideas that should
 *         be implemented in later releases of PINE.  See the notes in 
 *         pico.c concerning what needs to be done ....
 *
 *  - untabled 01/30/90
 *
 *  Notes: Installed header line editing, with wrapping and unwrapping, 
 *         context sensitive help, and other mail header editing features.
 *
 *  - finalish code cleanup 07/15/91
 * 
 *  Notes: Killed/yanked header lines use emacs kill buffer.
 *         Arbitrarily large headers are handled gracefully.
 *         All formatting handled by FormatLines.
 *
 *  - Work done to optimize display painting 06/26/92
 *         Not as clean as it should be, needs more thought 
 *
 */
#include <stdio.h>
#include <ctype.h>
#include "osdep.h"
#include "pico.h"
#include "estruct.h"
#include "edef.h"
#include "efunc.h"


#ifdef	ANSI
    int InitEntryText(char *, struct headerentry *);
    int HeaderOffset(int);
    int HeaderFocus(int, int);
    int LineEdit(int);
    int header_downline(int);
    int header_upline(int);
    int FormatLines(struct hdr_line *, char *, int, int, int);
    char *strqchr(char *, int, int *);
    int PaintBody(int);
    int ComposerHelp(int);
    int NewTop(void);
    void display_delimiter(int);
    int InvertPrompt(int, int);
    int partial_entries(void);
    int physical_line(struct hdr_line *);
    int strend(char *, int);
    int KillHeaderLine(struct hdr_line *, int);
    int SaveHeaderLines(void);
    char *break_point(char *, int, int, int *);
    int hldelete(struct hdr_line *);
    int is_blank(int, int, int);
    int zotentry(struct hdr_line *);
    void zotcomma(char *);
    struct hdr_line *first_hline(int *);
    struct hdr_line *next_hline(int *, struct hdr_line *);
    struct hdr_line *prev_hline(int *, struct hdr_line *);
#else
    int InitEntryText();
    int HeaderOffset();
    int HeaderFocus();
    int LineEdit();
    int header_downline();
    int header_upline();
    int FormatLines();
    char *strqchr();
    int PaintBody();
    int ComposerHelp();
    int NewTop();
    void display_delimiter();
    int InvertPrompt();
    int partial_entries();
    int physical_line();
    int strend();
    int KillHeaderLine();
    int SaveHeaderLines();
    char *break_point();
    int hldelete();
    int is_blank();
    int zotentry();
    void zotcomma();
    struct hdr_line *first_hline();
    struct hdr_line *next_hline();
    struct hdr_line *prev_hline();
#endif


/*
 * definition header field array, structures defined in pico.h
 */
struct headerentry *headents;


/*
 * structure that keeps track of the range of header lines that are
 * to be displayed and other fun stuff about the header
 */
struct on_display ods;				/* global on_display struct */


/*
 * useful macros
 */
#define	HALLOC()	(struct hdr_line *)malloc(sizeof(struct hdr_line))
#define	LINELEN()	(term.t_ncol - headents[ods.cur_e].prlen)
#define	BOTTOM()	(term.t_nrow - 2)
#define	FULL_SCR()	(term.t_nrow-5)
#define	HALF_SCR()	(FULL_SCR()/2)


/*
 * useful declarations
 */
static int     last_key;			/* last keystroke  */


static KEYMENU menu_header[] = {
    {"^G", "Get Help"},		{"^X", "Send"}, 	{"^R", "Rich Hdr"},
    {"^Y", "PrvPg/Top"},	{"^K", "Cut Line"},	{"^O", "Postpone"},
    {"^C", "Cancel"},		{"^D", "Del Char"},	{"^J", "Attach"},
    {"^V", "NxtPg/End"},	{"^U", "UnDel Line"},	{NULL, NULL}
};
#define	TO_KEY		11


/*
 * function key mappings for header editor
 */
static int ckm[12][2] = {
    { F1,  (CTRL|'G')},
    { F2,  (CTRL|'C')},
    { F3,  (CTRL|'X')},
    { F4,  (CTRL|'D')},
    { F5,  (CTRL|'R')},
    { F6,  (CTRL|'J')},
    { F7,  0 },
    { F8,  0 },
    { F9,  (CTRL|'K')},
    { F10, (CTRL|'U')},
    { F11, (CTRL|'O')},
    { F12, (CTRL|'T')}
};


/*
 * InitMailHeader - initialize header array, and set beginning editor row 
 *                  range.  The header entry structure should look just like 
 *                  what is written on the screen, the vector 
 *                  (entry, line, offset) will describe the current cursor 
 *                  position in the header.
 */
InitMailHeader(mp)
PICO  *mp;
{
    char *addrbuf;
    struct headerentry *he;

    /*
     * initialize some of on_display structure, others below...
     */
    ods.p_off  = 0;
    ods.p_line = COMPOSER_TOP_LINE;
    ods.top_l = ods.cur_l = NULL;

    headents = mp->headents;
    /*--- initialize the fields in the headerent structure ----*/
    for(he = headents; he->name != NULL; he++){
	he->hd_text    = NULL;
	he->display_it = he->display_it ? he->display_it : !he->rich_header;
        if(he->is_attach) {
            /*--- A lot of work to do since attachments are special ---*/
            he->maxlen = 0;
	    if(mp->attachments != NULL){
		char   buf[NLINE];
                int    x = 0;
                PATMT *ap = mp->attachments;
 
                addrbuf = (char *)malloc((size_t)1024);
                addrbuf[0] = '\0';
                buf[0] = '\0';
                while(ap){
                 if(ap->filename){
                     sprintf(buf, "%d. %s %s%s%s\"%s\"%s",
                             ++x,
                             ap->filename,
                             ap->size ? "(" : "",
                             ap->size ? ap->size : "",
                             ap->size ? ") " : "",
                             ap->description ? ap->description : "", 
                             ap->next ? "," : "");
                     strcat(addrbuf, buf);
                 }
                 ap = ap->next;
                }
                InitEntryText(addrbuf, he);
                free((char *)addrbuf);
            } else {
                InitEntryText("", he);
            }
            he->realaddr = NULL;
        } else {
            addrbuf = *(he->realaddr);
            InitEntryText(addrbuf, he);
	}
    }

    /*
     * finish initialization and then figure out display layout...
     */
    ods.top_l = ods.cur_l = first_hline(&ods.cur_e);
    ods.top_e = ods.cur_e;
    UpdateHeader();
}



/*
 * InitEntryText - Add the given header text into the header entry 
 *		   line structure.
 */
InitEntryText(address, e)
char	*address;
struct headerentry *e;
{
    struct  hdr_line	*curline;
    register  int	longest;

    /*
     * get first chunk of memory, and tie it to structure...
     */
    if((curline = HALLOC()) == NULL){
        emlwrite("Unable to make room for full Header.", NULL);
        return(FALSE);
    }
    longest = term.t_ncol - e->prlen - 1;
    curline->text[0] = '\0';
    curline->next = NULL;
    curline->prev = NULL;
    e->hd_text = curline;		/* tie it into the list */

    if(FormatLines(curline, address, longest, e->break_on_comma, 0) == -1)
      return(FALSE);
    else
      return(TRUE);
}



/*
 *  ResizeHeader - Handle resizing display when SIGWINCH received.
 *
 *	notes:
 *		works OK, but needs thorough testing
 *		  
 */
ResizeHeader()
{
    register struct headerentry *i;
    register int offset;

    offset = (ComposerEditing) ? HeaderOffset(ods.cur_e) : 0;

    for(i=headents; i->name; i++){		/* format each entry */
	if(FormatLines(i->hd_text, "", (term.t_ncol - i->prlen),
		       i->break_on_comma, 0) == -1){
	    return(-1);
	}
    }

    if(ComposerEditing)				/* restart at the top */
      HeaderFocus(ods.cur_e, offset);		/* fix cur_l and p_off */
    else {
      for(i = headents; i->name != NULL; i++);  /* Find last line */
      i--;
      HeaderFocus(i - headents, -1);		/* put focus on last line */
    }

    if(ComposerTopLine != COMPOSER_TOP_LINE)
      UpdateHeader();

    PaintBody(0);

    if(ComposerEditing)
      movecursor(ods.p_line, ods.p_off+headents[ods.cur_e].prlen);

    (*term.t_flush)();
    return(TRUE);
}



/*
 * HeaderOffset - return the character offset into the given header
 */
HeaderOffset(h)
int	h;
{
    register struct hdr_line *l;
    int	     i = 0;

    l = headents[h].hd_text;

    while(l != ods.cur_l){
	i += strlen(l->text);
	l = l->next;
    }
    return(i+ods.p_off);
}



/*
 * HeaderFocus - put the dot at the given offset into the given header
 */
HeaderFocus(h, offset)
int	h, offset;
{
    register struct hdr_line *l;
    register int    i;
    int	     last = 0;

    if(offset == -1)				/* focus on last line */
      last = 1;

    l = headents[h].hd_text;
    while(1){
	if(last && l->next == NULL){
	    break;
	}
	else{
	    if((i=strlen(l->text)) >= offset)
	      break;
	    else
	      offset -= i;
	}
	if((l = l->next) == NULL)
	  return(FALSE);
    }

    ods.cur_l = l;
    ods.p_len = strlen(l->text);
    ods.p_off = (last) ? 0 : offset;

    return(TRUE);
}



/*
 * HeaderEditor() - edit the mail header field by field, trapping 
 *                  important key sequences, hand the hard work off
 *                  to LineEdit().  
 *	returns:
 *              -2    if we drop out bottom *and* want to page forward
 *		-1    if we drop out the bottom 
 *		FALSE if editing is cancelled
 *		TRUE  if editing is finished
 */
HeaderEditor(f, n)
int f, n;
{
    register  int	i;
    register  int	ch;
    register  int	status;			/* return status of something*/
    register  char	*bufp;
    struct headerentry *h;
    int                 cur_e, count, retval = -1;
    char               *errmss;

    ComposerEditing = TRUE;
    display_delimiter(0);			/* provide feedback */

    /* 
     * Decide where to begin editing.  if f == TRUE begin editing
     * at the bottom.  this case results from the cursor backing
     * into the editor from the bottom.  otherwise, the user explicitly
     * requested editing the header, and we begin at the top.
     * 
     * further, if f == 1, we moved into the header by hitting the up arrow
     * in the message text, else if f == 2, we moved into the header by
     * moving past the left edge of the top line in the message.  so, make 
     * the end of the last line of the last entry the current cursor position
     * lastly, if f == 3, we moved into the header by hitting backpage() on
     * the top line of the message, so scroll a page back.  
     */
    if(f){
	if(f == 2){				/* 2 leaves cursor at end  */
	    struct hdr_line *l = ods.cur_l;
	    int              e = ods.cur_e;

	    /*--- make sure on last field ---*/
	    while(l = next_hline(&e, l))
	      if(headents[ods.cur_e].display_it){
		  ods.cur_l = l;
		  ods.cur_e = e;
	      }

	    ods.p_off = 1000;			/* and make sure at EOL    */
	}
	else{
	    /*
	     * note: assumes that ods.cur_e and ods.cur_l haven't changed
	     *       since we left...
	     */

	    /* fix postition */
	    if(curwp->w_doto < headents[ods.cur_e].prlen)
	      ods.p_off = 0;
	    else if(curwp->w_doto < ods.p_off + headents[ods.cur_e].prlen)
	      ods.p_off = curwp->w_doto - headents[ods.cur_e].prlen;
	    else
	      ods.p_off = 1000;

	    /* and scroll back if needed */
	    if(f == 3)
	      for(i = 0; header_upline(0) && i <= FULL_SCR(); i++)
		;
	}

	ods.p_line = ComposerTopLine - 2;
    }
    else{		/* use offset 0 of first line of first entry */
	ods.p_line = COMPOSER_TOP_LINE;
	ods.cur_e = ods.top_e;
        ods.cur_l = ods.top_l;
        ods.p_off = 0;
    }

    InvertPrompt(ods.cur_e, TRUE);		/* highlight header field */
    sgarbk = 1;

    do{
	if(sgarbk){
	    ShowPrompt();			/* display correct options */
	    sgarbk = 0;
	}

	ch = LineEdit(TRUE);			/* work on the current line */

        switch (ch){
	  case (CTRL|'R') :			/* Toggle header display */
            /*---- Are there any headers to expand above us? ---*/
            for(h = headents; h != &headents[ods.cur_e]; h++)
              if(h->rich_header)
                break;
            if(h->rich_header)
	      InvertPrompt(ods.cur_e, FALSE);	/* Yes, don't leave inverted */

	    if(partial_entries()){
                /*--- Just turned off all rich headers --*/
		if(headents[ods.cur_e].rich_header){
                    /*-- current header got turned off too --*/
                    /* Check below */
                    for(cur_e =ods.cur_e; headents[cur_e].name!=NULL; cur_e++)
                      if(!headents[cur_e].rich_header)
                        break;
                    if(headents[cur_e].name == NULL) {
                        /* didn't find one, check above */
                        for(cur_e =ods.cur_e; headents[cur_e].name!=NULL;
                            cur_e--)
                          if(!headents[cur_e].rich_header)
                            break;

                    }
		    ods.p_off = 0;
		    ods.cur_e = cur_e;
		    ods.cur_l = headents[ods.cur_e].hd_text;
		}
	    }

	    ods.p_line = 0;			/* force update */
	    UpdateHeader();
	    PaintHeader(COMPOSER_TOP_LINE, FALSE);
	    PaintBody(1);
	    break;

	  case (CTRL|'C') :			/* bag whole thing ?*/
	    if(abort_composer(1, 0) == TRUE)
	      return(FALSE);

	    break;

	  case (CTRL|'X') :			/* Done. Send it. */
	    i = 0;
#ifdef	ATTACHMENTS
	    if(headents[ods.cur_e].is_attach){
		/* verify the attachments, and pretty things up in case
		 * we come back to the composer due to error...
		 */
		if((i = SyncAttach()) != 0){
		    sleep(2);		/* give time for error to absorb */
		    FormatLines(headents[ods.cur_e].hd_text, "",
				term.t_ncol - headents[ods.cur_e].prlen,
				headents[ods.cur_e].break_on_comma, 0);
		}
	    }
	    else
#endif
	    if(headents[ods.cur_e].builder)	/* verify text? */
	      i = call_builder(&headents[ods.cur_e]) > 0;

	    if(wquit(1,0) == TRUE)
	      return(TRUE);

	    if(i){
		/*
		 * need to be careful here because pointers might be messed up.
		 * also, could do a better job of finding the right place to
		 * put the dot back (i.e., the addr/list that was expanded).
		 */
		ods.cur_l = headents[ods.cur_e].hd_text; /* attach cur_l */
		ods.p_off = 0;
		ods.p_line = 0;			/* force realignment */
		UpdateHeader();
		PaintHeader(COMPOSER_TOP_LINE, FALSE);
		PaintBody(1);
	    }
	    break;
	  case (CTRL|'Z') :			/* Suspend compose */
	    if(gmode&MDSSPD){			/* is it allowed? */
		bktoshell();
		PaintBody(0);
	    }
	    else{
		(*term.t_beep)();
		emlwrite("Unknown Command: ^Z", NULL);
	    }
	    break;

	  case (CTRL|'O') :			/* Suspend message */
	    if(headents[ods.cur_e].is_attach){
		if(SyncAttach() < 0){
		    if(mlyesno("Problem with attachments. Postpone anyway?",
			       FALSE) != TRUE){
			if(FormatLines(headents[ods.cur_e].hd_text, "",
				       term.t_ncol - headents[ods.cur_e].prlen,
				       headents[ods.cur_e].break_on_comma,
				       0) == -1)
			  emlwrite("\007Format lines failed!", NULL);
			UpdateHeader();
			PaintHeader(COMPOSER_TOP_LINE, FALSE);
			PaintBody(1);
			continue;
		    }
		}
	    }
	    else if(headents[ods.cur_e].builder)
	      call_builder(&headents[ods.cur_e]);

	    suspend_composer(1, 0);
	    return(TRUE);

#ifdef	ATTACHMENTS
	  case (CTRL|'J') :			/* handle attachments */
	    { char fn[NLINE], sz[32], cmt[NLINE];

	      if(AskAttach(fn, sz, cmt)){
		  int	 a_e;
		  struct hdr_line *lp;

                  /*--- Find headerentry that is attachments (only first) --*/
                  for(a_e = 0; headents[a_e].name != NULL; a_e++ )
                    if(headents[a_e].is_attach){
			/* make sure field stays displayed */
			headents[a_e].rich_header = 0;
			headents[a_e].display_it = 1;
			break;
		    }

		  /* append new attachment line */
		  for(lp = headents[a_e].hd_text; lp->next; lp=lp->next)
		    ;

		  /* build new attachment line */
		  if(lp->text[0]){		/* adding a line? */
		      strcat(lp->text, ",");	/* append delimiter */
		      if(lp->next = HALLOC()){	/* allocate new line */
			  lp->next->prev = lp;
			  lp->next->next = NULL;
			  lp = lp->next;
		      }
		      else{
			  emlwrite(
				 "\007Can't allocate line for new attachment!",
				 NULL);
			  break;
		      }
		  }

		  sprintf(lp->text, "%s (%s) \"%.*s\"", fn, sz, 80, cmt);

		  /* validate the new attachment, and reformat if needed */
		  if(status = SyncAttach()){
		      if(status < 0)
			emlwrite("\007Problem attaching: %s", fn);

		      if(FormatLines(headents[a_e].hd_text, "",
				     term.t_ncol - headents[a_e].prlen,
				     headents[a_e].break_on_comma, 0) == -1){
			  emlwrite("\007Format lines failed!", NULL);
			  break;
		      }
		  }

		  UpdateHeader();
		  PaintHeader(COMPOSER_TOP_LINE, status != 0);
		  PaintBody(1);
	      }

	      sgarbk = 1;			/* clean up prompt */
	    }
	    break;
#endif

	  case (CTRL|'I') :			/* tab */
	    ods.p_off = 0;			/* fall through... */

	  case (CTRL|'N') :
	  case K_PAD_DOWN :
	    header_downline(1);
	    break;

	  case (CTRL|'P') :
	  case K_PAD_UP :
	    header_upline(1);
	    break;

	  case (CTRL|'V') :			/* down a page */
	    cur_e = ods.cur_e;
	    if(!next_hline(&cur_e, ods.cur_l)){
		header_downline(1); 		/* cause us to return */
		retval = -2;
	    }
	    else
	      for(i = 0; i <= FULL_SCR() && header_downline(0); i++)
		;

	    break;

	  case (CTRL|'Y') :			/* up a page */
	    for(i = 0; header_upline(0) && i <= FULL_SCR(); i++)
	      if(i < 0)
		break;

	    break;

#ifdef DELETED
	  case (CTRL|'T') :			/* Call field selector */
            if(headents[ods.cur_e].is_attach) {
                /*--- selector for attachments ----*/
		char dir[NLINE], fn[NLINE], sz[NLINE];

		strcpy(dir, gmode&MDCURDIR ? "." : gethomedir(NULL));
		fn[0] = '\0';
		if(FileBrowse(dir, fn, sz, FB_READ) == 1){ /* got a new file */
		    char buf[NLINE];
		    sprintf(buf, "%s%c%s (%s) \"\"%s", dir, C_FILESEP, fn, sz, 
			    (!headents[ods.cur_e].hd_text->text[0]) ? "":",");
		    if(FormatLines(headents[ods.cur_e].hd_text, buf,
				   term.t_ncol - headents[ods.cur_e].prlen,
				   headents[ods.cur_e].break_on_comma,0)==-1){
			emlwrite("\007Format lines failed!", NULL);
		    }

		    UpdateHeader();
		}				/* else, nothing of interest */
            } else if (headents[ods.cur_e].selector != NULL) {
                /*---- General selector for non-attachments -----*/
                errmss = NULL;
                bufp = (*(headents[ods.cur_e].selector))(&errmss);
                if(bufp != NULL) {
                    if(headents[ods.cur_e].break_on_comma) {
                        /*--- Must be an address ---*/
                        if(ods.cur_l->text[0] != '\0'){
			    for(i = ++ods.p_len; i; i--)
			      ods.cur_l->text[i] = ods.cur_l->text[i-1];

			    ods.cur_l->text[0] = ',';
			}

                        if(FormatLines(ods.cur_l, bufp,
				      (term.t_ncol-headents[ods.cur_e].prlen), 
                                      headents[ods.cur_e].break_on_comma,
				      0) == -1){
                            emlwrite("Problem adding address to header !",
                                     NULL);
                            (*term.t_beep)();
                            break;
                        }

    		        UpdateHeader();
			free(bufp);
                    } else {
                        strcpy(headents[ods.cur_e].hd_text->text, bufp);
                    }
    	            PaintBody(0); /* Repaint entire screen */
		} else {
    	            PaintBody(0); /* Repaint entire screen,then error msg */
                    if(errmss != NULL) {
                        (*term.t_beep)();
	                emlwrite(errmss, NULL);
                    }
                }
	    } else {
                /*----- No selector -----*/
		(*term.t_beep)();
		continue;
	    }
	    PaintBody(0);
	    continue;
#endif /* DELETED */

	  case (CTRL|'G'):			/* HELP */
	    ComposerHelp(ods.cur_e);		/* fall through... */

	  case (CTRL|'L'):			/* redraw requested */
	    PaintBody(0);
	    break;

	  default :				/* huh? */
	    if(ch&CTRL)
	      emlwrite("\007Unknown command: ^%c", (void *)(ch&0xff));
	    else
	  case BADESC:
	      emlwrite("\007Unknown command", NULL);

	  case NODATA:
	    break;
	}
    }
    while (ods.p_line < ComposerTopLine);

    display_delimiter(1);
    curwp->w_flag |= WFMODE;
    movecursor(currow, curcol);
    ComposerEditing = FALSE;
    return(retval);
}


/*
 *
 */
int
header_downline(beyond)
     int beyond;
{
    struct hdr_line *new_l;
    int    new_e, status, fullpaint, len;

    /* calculate the next line: physical *and* logical */
    status    = 0;
    new_e     = ods.cur_e;
    if((new_l = next_hline(&new_e, ods.cur_l)) == NULL && !beyond)
      return(0);

    fullpaint = ++ods.p_line >= BOTTOM();	/* force full redraw?       */

    /* expand what needs expanding */
    if(new_e != ods.cur_e || !new_l){		/* new (or last) field !    */
	if(new_l)
	  InvertPrompt(ods.cur_e, FALSE);	/* turn off current entry   */

	if(headents[ods.cur_e].is_attach) {	/* varify data ?	    */
	    if(status = SyncAttach()){		/* fixup if 1 or -1	    */
		headents[ods.cur_e].rich_header = 0;
		if(FormatLines(headents[ods.cur_e].hd_text, "",
			       term.t_ncol-headents[new_e].prlen,
			       headents[ods.cur_e].break_on_comma, 0) == -1)
		  emlwrite("\007Format lines failed!", NULL);
	    }
	} else if(headents[ods.cur_e].builder) { /* expand addresses	    */
	    if(status = (call_builder(&headents[ods.cur_e]) > 0)){
		struct hdr_line *l;		/* fixup ods.cur_l */
		ods.p_line = 0;			/* force top line recalc */
		for(l = headents[ods.cur_e].hd_text; l; l = l->next)
		  ods.cur_l = l;

		NewTop();			/* get new top_l */
	    }
	}

	if(new_l){				/* if one below, turn it on */
	    InvertPrompt(new_e, TRUE);
	    sgarbk = 1;				/* paint keymenu too	    */
	}
    }

    if(new_l){					/* fixup new pointers	    */
	ods.cur_l = (ods.cur_e != new_e) ? headents[new_e].hd_text : new_l;
	ods.cur_e = new_e;
	if(ods.p_off > (len = strlen(ods.cur_l->text)))
	  ods.p_off = len;
    }

    if(!new_l || status || fullpaint){		/* handle big screen paint  */
	UpdateHeader();
	PaintHeader(COMPOSER_TOP_LINE, FALSE);
	PaintBody(1);

	if(!new_l){				/* make sure we're done     */
	    ods.p_line = ComposerTopLine;
	    InvertPrompt(ods.cur_e, FALSE);	/* turn off current entry   */
	}
    }

    return(new_l ? 1 : 0);
}


/*
 *
 */
int
header_upline(gripe)
    int gripe;
{
    struct hdr_line *new_l;
    int    new_e, status, fullpaint, len;

    /* calculate the next line: physical *and* logical */
    status    = 0;
    fullpaint = ods.p_line-- == COMPOSER_TOP_LINE;
    new_e     = ods.cur_e;
    if(!(new_l = prev_hline(&new_e, ods.cur_l))){	/* all the way up! */
	ods.p_line = COMPOSER_TOP_LINE;
	if(gripe)
	  emlwrite("Can't move beyond top of header", NULL);

	return(0);
    }

    if(new_e != ods.cur_e){			/* new field ! */
	InvertPrompt(ods.cur_e, FALSE);
	if(headents[ods.cur_e].is_attach){
	    if(status = SyncAttach()){		/* non-zero ? reformat field */
		headents[ods.cur_e].rich_header = 0;
		if(FormatLines(headents[ods.cur_e].hd_text, "",
			       term.t_ncol - headents[ods.cur_e].prlen,
			       headents[ods.cur_e].break_on_comma,0) == -1)
		  emlwrite("\007Format lines failed!", NULL);
	    }
	}
	else if(headents[ods.cur_e].builder){
	    status = call_builder(&headents[ods.cur_e]) > 0;
	}

	InvertPrompt(new_e, TRUE);
	sgarbk = 1;
    }

    ods.cur_e = new_e;				/* update pointers */
    ods.cur_l = new_l;
    if(ods.p_off > (len = strlen(ods.cur_l->text)))
      ods.p_off = len;

    if(status || fullpaint){
	UpdateHeader();
	PaintHeader(COMPOSER_TOP_LINE, FALSE);
	PaintBody(1);
    }

    return(1);
}



/*
 * LineEdit - the idea is to manage 7 bit ascii character only input.
 *            Always use insert mode and handle line wrapping
 *
 *	returns:
 *		Any characters typed in that aren't printable 
 *		(i.e. commands)
 *
 *	notes: 
 *		Assume we are guaranteed that there is sufficiently 
 *		more buffer space in a line than screen width (just one 
 *		less thing to worry about).  If you want to change this,
 *		then pputc will have to be taught to check the line buffer
 *		length, and HALLOC() will probably have to become a func.
 */
LineEdit(allowedit)
int	allowedit;
{
    register struct	hdr_line   *lp;		/* temporary line pointer    */
    register int	i;
    register int	ch = 0;
    register int	status;			/* various func's return val */
    register char	*tbufp;			/* temporary buffer pointers */
	     int	j;
	     int	skipmove = 0;
             char	*strng;

    strng   = ods.cur_l->text;			/* initialize offsets */
    ods.p_len = strlen(strng);
    if(ods.p_off < 0)				/* offset within range? */
      ods.p_off = 0;
    else if(ods.p_off > ods.p_len)
      ods.p_off = ods.p_len;
    else if(ods.p_off > LINELEN())		/* shouldn't happen, but */
        ods.p_off = LINELEN();			/* you never know...     */

    while(1){					/* edit the line... */

	if(skipmove)
	  skipmove = 0;
	else
	  movecursor(ods.p_line, ods.p_off+headents[ods.cur_e].prlen);

	last_key = ch;

	(*term.t_flush)();			/* get everything out */

        ch = GetKey();

	if(ch == NODATA || time_to_check()){	/* new mail ? */
	    if((*Pmaster->newmail)(&j, 0, ch == NODATA ? 0 : 2) >= 0){
		mlerase();
		(*Pmaster->showmsg)(ch);
		mpresf = 1;
	    }

	    if(j || mpresf){
		(*term.t_move)(ods.p_line,ods.p_off+headents[ods.cur_e].prlen);
		(Pmaster->clearcur)();
	    }

	    if(ch == NODATA)			/* GetKey timed out */
	      continue;
	}

        if(mpresf){				/* blast old messages */
	    if(mpresf++ > NMMESSDELAY){		/* every few keystrokes */
		mlerase();
		movecursor(ods.p_line, ods.p_off+headents[ods.cur_e].prlen);
	    }
        }


        if((ishangul(ch)) || (ch > 0x1f && ch < 0x7f)){		/* char input */
            /*
             * if we are allowing editing, insert the new char
             * end up leaving tbufp pointing to newly
             * inserted character in string, and offset to the
             * index of the character after the inserted ch ...
             */
            if(allowedit){
		if(headents[ods.cur_e].only_file_chars && !fallowc((char)ch)){
		    /* no garbage in filenames */
		    emlwrite("\007Can't have a '%c' in folder name",(void *)ch);
		    continue;
		}
		else if(headents[ods.cur_e].is_attach && intag(strng,ods.p_off)){
		    emlwrite("\007Can't edit attachment number!", NULL);
		    continue;
		}

		if(headents[ods.cur_e].single_space){
		    if(ch == ' ' 
		       && (strng[ods.p_off]==' ' || strng[ods.p_off-1]==' '))
		      continue;
		}

		/*
		 * go ahead and add the character...
		 */
		tbufp = &strng[++ods.p_len];	/* find the end */
		do{
		    *tbufp = tbufp[-1];
		} while(--tbufp > &strng[ods.p_off]);	/* shift right */
		strng[ods.p_off++] = ch;	/* add char to str */

		/* make this entry sticky */
		headents[ods.cur_e].sticky = 1;

		/*
		 * then find out where things fit...
		 */
		if(ods.p_len < LINELEN()){
		    CELL c;

		    c.a = 0;
		    c.c = ch;
		    if(pinsert(c)){		/* add char to str */
			skipmove++;		/* must'a been optimal */
			continue; 		/* on to the next! */
		    }
		}
		else{
                    if((status = FormatLines(ods.cur_l, "", LINELEN(), 
    			        headents[ods.cur_e].break_on_comma,0)) == -1){
                        (*term.t_beep)();
                        continue;
                    }
                    else{
			/*
			 * during the format, the dot may have moved
			 * down to the next line...
			 */
			if(ods.p_off >= strlen(strng)){
			    ods.p_line++;
			    ods.p_off -= strlen(strng);
			    ods.cur_l = ods.cur_l->next;
			    strng = ods.cur_l->text;
			}
			ods.p_len = strlen(strng);
		    }
		    UpdateHeader();
		    PaintHeader(COMPOSER_TOP_LINE, FALSE);
		    PaintBody(1);
                    continue;
		}
            }
            else{  
                (*term.t_beep)();
                continue;
            } 
        }
        else {					/* interpret ch as a command */
            switch (ch = normal(ch, ckm, 2)) {
	      case (CTRL|'@') :		/* word skip */
		while(strng[ods.p_off] && !myisspace(strng[ods.p_off]))
		  ods.p_off++;		/* skip any text we're in */

		while(strng[ods.p_off] && myisspace(strng[ods.p_off]))
		  ods.p_off++;		/* skip any whitespace after it */

		if(strng[ods.p_off] == '\0'){
		    ods.p_off = 0;	/* end of line, let caller handle it */
		    return(K_PAD_DOWN);
		}

		continue;

	      case (CTRL|'K') :			/* kill line cursor's on */
		lp = ods.cur_l;
		ods.p_off = 0;

		if(ods.cur_l->next != NULL && ods.cur_l->prev != NULL)
		  ods.cur_l = next_hline(&ods.cur_e, ods.cur_l);
		else if(ods.cur_l->prev != NULL)
		  ods.cur_l = prev_hline(&ods.cur_e, ods.cur_l);

		if(KillHeaderLine(lp, (last_key == (CTRL|'K')))){
		    if(optimize && 
		       !(ods.cur_l->prev==NULL && ods.cur_l->next==NULL))
		      scrollup(wheadp, ods.p_line, 1);

		    if(ods.cur_l->next == NULL)
		      zotcomma(ods.cur_l->text);
		    
		    i = (ods.p_line == COMPOSER_TOP_LINE);
		    UpdateHeader();
		    PaintHeader(i ? COMPOSER_TOP_LINE: ods.p_line, FALSE);
		    PaintBody(1);
		}
		strng = ods.cur_l->text;
		ods.p_len = strlen(strng);
		headents[ods.cur_e].sticky = 1;
		continue;

	      case (CTRL|'U') :			/* un-delete deleted lines */
		if(SaveHeaderLines()){
		    UpdateHeader();
		    PaintHeader(COMPOSER_TOP_LINE, FALSE);
		    PaintBody(1);

		    ods.p_off = 0;		/* dot hasn't moved! */
		    strng = ods.cur_l->text;
		    ods.p_len = strlen(strng);
		    headents[ods.cur_e].sticky = 1;
		}
		else
		  emlwrite("Problem Unkilling text", NULL);
		continue;

	      case (CTRL|'F') :
	      case K_PAD_RIGHT:			/* move character right */
		if(ods.p_off < ods.p_len){
		    pputc(pscr(ods.p_line, 
			       (ods.p_off++)+headents[ods.cur_e].prlen)->c,0);
		    skipmove++;
		    continue;
		}
		ods.p_off = 0;
		return(K_PAD_DOWN);

	      case (CTRL|'B') :
	      case K_PAD_LEFT	:		/* move character left */
		if(ods.p_off > 0){
		    ods.p_off--;
		    continue;
		}
		if(ods.p_line != COMPOSER_TOP_LINE)
		  ods.p_off = 1000;		/* put cursor at end of line */
		return(K_PAD_UP);

	      case (CTRL|'M') :			/* goto next field */
		ods.p_off = 0;
		return(K_PAD_DOWN);

	      case K_PAD_HOME :
	      case (CTRL|'A') :			/* goto beginning of line */
		ods.p_off = 0;
		continue;

	      case K_PAD_END  :
	      case (CTRL|'E') :			/* goto end of line */
		ods.p_off = ods.p_len;
		continue;

	      case (CTRL|'D')   :		/* blast this char */
	      case K_PAD_DELETE :
		if(!allowedit){
		    (*term.t_beep)();
		    continue;
		}
		else if(ods.p_off >= strlen(strng))
		  continue;

		if(headents[ods.cur_e].is_attach && intag(strng, ods.p_off)){
		    emlwrite("\007Can't edit attachment number!", NULL);
		    continue;
		}

		headents[ods.cur_e].sticky = 1;
		pputc(strng[ods.p_off++], 0); 	/* drop through and rubout */

	      case 0x7f       :			/* blast previous char */
	      case (CTRL|'H') :
		if(!allowedit){
		    (*term.t_beep)();
		    continue;
		}

		if(headents[ods.cur_e].is_attach && intag(strng, ods.p_off-1)){
		    emlwrite("\007Can't edit attachment number!", NULL);
		    continue;
		}

		if(ods.p_off > 0){		/* just shift left one char */
		    ods.p_len--;
		    tbufp = &strng[--ods.p_off];
		    while(*tbufp++ != '\0')
		      tbufp[-1] = *tbufp;
		    tbufp = &strng[ods.p_off];
		    if(pdel())			/* physical screen delete */
		      skipmove++;		/* must'a been optimal */
		}
		else{				/* may have work to do */
		    if(ods.cur_l->prev == NULL){  
			(*term.t_beep)();	/* no erase into next field */
			continue;
		    }

		    ods.p_line--;
		    ods.cur_l = ods.cur_l->prev;
		    strng = ods.cur_l->text;
		    if((i=strlen(strng)) > 0){
			strng[i-1] = '\0';	/* erase the character */
			ods.p_off = i-1;
		    }
		    else
		      ods.p_off = 0;
		    
		    tbufp = &strng[ods.p_off];
		}

		if((status = FormatLines(ods.cur_l, "", LINELEN(), 
				   headents[ods.cur_e].break_on_comma,0))==-1){
		    (*term.t_beep)();
		    continue;
		}
		else{
		    /*
		     * beware, the dot may have moved...
		     */
		    while((ods.p_len=strlen(strng)) < ods.p_off){
			ods.p_line++;
			ods.p_off -= strlen(strng);
			ods.cur_l = ods.cur_l->next;
			strng = ods.cur_l->text;
			ods.p_len = strlen(strng);
			tbufp = &strng[ods.p_off];
			status = TRUE;
		    }
		    UpdateHeader();
		    PaintHeader(COMPOSER_TOP_LINE, FALSE);
		    if(status == TRUE)
		      PaintBody(1);
		}

		movecursor(ods.p_line, ods.p_off+headents[ods.cur_e].prlen);

		headents[ods.cur_e].sticky = 1;

		if(skipmove)
		  continue;

		break;

              default   :
		return(ch);
            }
        }

	while (*tbufp != '\0')		/* synchronizing loop */
	  pputc(*tbufp++, 0);

	if(ods.p_len < LINELEN())
	  peeol();

    }
}



/*
 * FormatLines - Place the given text at the front of the given line->text
 *               making sure to properly format the line, then check
 *               all lines below for proper format.
 *
 *	notes:
 *		Not much optimization at all.  Right now, it recursively
 *		fixes all remaining lines in the entry.  Some speed might
 *		gained if this was built to iteratively scan the lines.
 *
 *	returns:
 *		-1 on error
 *		FALSE if only this line is changed
 *		TRUE  if text below the first line is changed
 */
FormatLines(h, instr, maxlen, break_on_comma, quoted)
struct  hdr_line  *h;				/* where to begin formatting */
char	*instr;					/* input string */
int	maxlen;					/* max chars on a line */
int	break_on_comma;				/* break lines on commas */
int	quoted;					/* this line inside quotes */
{
    int		retval = FALSE;
    register	int	i, l;
    char	*ostr;				/* pointer to output string */
    register	char	*breakp;		/* pointer to line break */
    register	char	*bp, *tp;		/* temporary pointers */
    char	*buf;				/* string to add later */
    struct hdr_line	*nlp, *lp;

    ostr = h->text;
    nlp = h->next;
    l = strlen(instr) + strlen(ostr);
    if((buf = (char *)malloc(l+10)) == NULL)
      return(-1);

    if(l >= maxlen){				/* break then fixup below */
	if(strlen(instr) < maxlen){		/* room for more */

	    if(break_on_comma && (bp = (char *)strqchr(instr, ',', &quoted))){
		bp += (bp[1] == ' ') ? 2 : 1;
		for(tp = bp; *tp && *tp == ' '; tp++)
		  ;

		strcpy(buf, tp);
		strcat(buf, ostr);
		for(i = 0; &instr[i] < bp; i++)
		  ostr[i] = instr[i];
		ostr[i] = '\0';
		retval = TRUE;
	    }
	    else{
		breakp = break_point(ostr, maxlen-strlen(instr),
				     break_on_comma ? ',' : ' ',
				     break_on_comma ? &quoted : NULL);

		if(breakp == ostr){	/* no good breakpoint */
		    if(break_on_comma && *breakp == ','){
			breakp = ostr + 1;
			retval = TRUE;
		    }
		    else if(strchr(instr,(break_on_comma && !quoted)?',':' ')){
			strcpy(buf, ostr);
			strcpy(ostr, instr);
		    }
		    else{		/* instr's broken as we can get it */
			breakp = &ostr[maxlen-strlen(instr)-1];
			retval = TRUE;
		    }
		}
		else
		  retval = TRUE;
	    
		if(retval){
		    strcpy(buf, breakp);	/* save broken line  */
		    if(breakp == ostr){
			strcpy(ostr, instr);	/* simple if no break */
		    }
		    else{
			*breakp = '\0';		/* more work to break it */
			i = strlen(instr);
			/*
			 * shift ostr i chars
			 */
			for(bp=breakp; bp >= ostr && i; bp--)
			  *(bp+i) = *bp;
			for(tp=ostr, bp=instr; *bp != '\0'; tp++, bp++)
			  *tp = *bp;		/* then add instr */
		    }
		}
	    }
	}
	else{					/* instr > maxlen ! */
	    if(break_on_comma){
		breakp = (!(bp = strqchr(instr, ',', &quoted))
			  || bp - instr >= maxlen)
			   ? &instr[maxlen]
			   : bp + ((bp[1] == ' ') ? 2 : 1);
	    }
	    else{
		breakp = break_point(instr, maxlen, ' ', NULL);

		if(breakp == instr)		/* no good break point */
		  breakp = &instr[maxlen - 1];
	    }
	    
	    strcpy(buf, breakp);		/* save broken line */
	    strcat(buf, ostr);			/* add line that was there */
	    for(tp=ostr,bp=instr; bp < breakp; tp++, bp++)
	      *tp = *bp;

	    *tp = '\0';
	}

	if(nlp == NULL){			/* no place to add below? */
	    if((lp = HALLOC()) == NULL){
		emlwrite("Can't allocate any more lines for header!", NULL);
		free(buf);
		return(-1);
	    }

	    if(optimize && (i = physical_line(h)) != -1)
	      scrolldown(wheadp, i - 1, 1);

	    h->next = lp;			/* fix up links */
	    lp->prev = h;
	    lp->next = NULL;
	    lp->text[0] = '\0';
	    nlp = lp;
	    retval = TRUE;
	}
	else
	    retval = FALSE;
    }
    else{					/* combined length < max */
	if(*instr){
	    strcpy(buf, instr);			/* insert instr before ostr */
	    strcat(buf, ostr);
	    strcpy(ostr, buf);
	}

	*buf = '\0';
	breakp = NULL;

	if(break_on_comma && (breakp = strqchr(ostr, ',', &quoted))){
	    breakp += (breakp[1] == ' ') ? 2 : 1;
	    strcpy(buf, breakp);
	    *breakp = '\0';

	    if(strlen(buf) && !nlp){
		if((lp = HALLOC()) == NULL){
		    emlwrite("Can't allocate any more lines for header!",NULL);
		    free(buf);
		    return(-1);
		}

		if(optimize && (i = physical_line(h)) != -1)
		  scrolldown(wheadp, i - 1, 1);

		h->next = lp;		/* fix up links */
		lp->prev = h;
		lp->next = NULL;
		lp->text[0] = '\0';
		nlp = lp;
		retval = TRUE;
	    }
	}

	if(nlp){
	    if(!strlen(buf) && !breakp){
		if(strlen(ostr) + strlen(nlp->text) >= maxlen){
		    breakp = break_point(nlp->text, maxlen-strlen(ostr), 
					 break_on_comma ? ',' : ' ',
					 break_on_comma ? &quoted : NULL);
		    
		    if(breakp == nlp->text){	/* commas this line? */
			for(tp=ostr; *tp  && *tp != ' '; tp++)
			  ;

			if(!*tp){		/* no commas, get next best */
			    breakp += maxlen - strlen(ostr) - 1;
			    retval = TRUE;
			}
			else
			  retval = FALSE;
		    }
		    else
		      retval = TRUE;

		    if(retval){			/* only if something to do */
			for(tp = &ostr[strlen(ostr)],bp=nlp->text; bp<breakp; 
			tp++, bp++)
			  *tp = *bp;		/* add breakp to this line */
			*tp = '\0';
			for(tp=nlp->text, bp=breakp; *bp != '\0'; tp++, bp++)
			  *tp = *bp;		/* shift next line to left */
			*tp = '\0';
		    }
		}
		else{
		    strcat(ostr, nlp->text);

		    if(optimize && (i = physical_line(nlp)) != -1)
		      scrollup(wheadp, i, 1);

		    hldelete(nlp);

		    if(!(nlp = h->next)){
			free(buf);
			return(TRUE);		/* can't go further */
		    }
		    else
		      retval = TRUE;		/* more work to do? */
		}
	    }
	}
	else{
	    free(buf);
	    return(FALSE);
	}

    }

    i = FormatLines(nlp, buf, maxlen, break_on_comma, quoted);
    free(buf);
    switch(i){
      case -1:					/* bubble up worst case */
	return(-1);
      case FALSE:
	if(retval == FALSE)
	  return(FALSE);
      default:
	return(TRUE);
    }
}



/*
 * PaintHeader - do the work of displaying the header from the given 
 *               physical screen line the end of the header.
 *
 *       17 July 91 - fixed reshow to deal with arbitrarily large headers.
 */
void
PaintHeader(line, clear)
    int	line;					/* physical line on screen   */
    int	clear;					/* clear before painting */
{
    register struct hdr_line	*lp;
    register char	*bufp;
    register int	curline;
    register int	curoffset;
    char     buf[NLINE];
    int      e;

    if(clear)
      pclear(COMPOSER_TOP_LINE, ComposerTopLine);

    curline   = COMPOSER_TOP_LINE;
    curoffset = 0;

    for(lp = ods.top_l, e = ods.top_e; ; curline++){
	if((curline == line) || ((lp = next_hline(&e, lp)) == NULL))
	  break;
    }

    while(headents[e].name != NULL){			/* begin to redraw */
	while(lp != NULL){
	    buf[0] = '\0';
            if((!lp->prev || curline == COMPOSER_TOP_LINE) && !curoffset){
	        if(InvertPrompt(e, (e == ods.cur_e && ComposerEditing)) == -1
		   && !is_blank(curline, 0, headents[e].prlen))
		   sprintf(buf, "          ");
	    }
	    else if(!is_blank(curline, 0, headents[e].prlen))
	      sprintf(buf, "          ");

	    if(*(bufp = buf) != '\0'){		/* need to paint? */
		movecursor(curline, 0);		/* paint the line... */
		while(*bufp != '\0')
		  pputc(*bufp++, 0);
	    }

	    bufp = &(lp->text[curoffset]);	/* skip chars already there */
	    curoffset += headents[e].prlen;
	    while(*bufp == pscr(curline, curoffset)->c && *bufp != '\0'){
		bufp++;
		if(++curoffset >= term.t_ncol)
		  break;
	    }

	    if(*bufp != '\0'){			/* need to move? */
		movecursor(curline, curoffset);
		while(*bufp != '\0'){		/* display what's not there */
		    pputc(*bufp++, 0);
		    curoffset++;
		}
	    }

	    if(curoffset < term.t_ncol 
	       && !is_blank(curline, curoffset, term.t_ncol - curoffset)){
		movecursor(curline, curoffset);
		peeol();
	    }
	    curline++;

            curoffset = 0;
	    if(curline >= BOTTOM())
	      break;

	    lp = lp->next;
        }

	if(curline >= BOTTOM())
	  return;				/* don't paint delimiter */

	while(headents[++e].name != NULL)
	  if(headents[e].display_it){
	      lp = headents[e].hd_text;
	      break;
	  }
    }

    display_delimiter(ComposerEditing ? 0 : 1);
}




/*
 * PaintBody() - generic call to handle repainting everything BUT the 
 *		 header
 *
 *	notes:
 *		The header redrawing in a level 0 body paint gets done
 *		in update()
 */
PaintBody(level)
int	level;
{
    curwp->w_flag |= WFHARD;			/* make sure framing's right */
    if(level == 0)				/* specify what to update */
        sgarbf = TRUE;

    update();					/* display message body */

    if(level == 0 && ComposerEditing){
	mlerase();				/* clear the error line */
	ShowPrompt();
    }
}



/*
 * ArrangeHeader - set up display parm such that header is reasonably 
 *                 displayed
 */
ArrangeHeader()
{
    int      e;
    register struct hdr_line *l;

    ods.p_line = ods.p_off = 0;
    e = ods.top_e = 0;
    l = ods.top_l = headents[e].hd_text;
    while(headents[e+1].name || (l && l->next))
      if(l = next_hline(&e, l)){
	  ods.cur_l = l;
	  ods.cur_e = e;
      }

    UpdateHeader();
}


/*
 * ComposerHelp() - display mail help in a context sensitive way
 *                  based on the level passed ...
 */
ComposerHelp(level)
int	level;
{
    char buf[80];

    curwp->w_flag |= WFMODE;
    sgarbf = TRUE;

    if(level < 0 || !headents[level].name){
	(*term.t_beep)();
	emlwrite("Sorry, I can't help you with that.", NULL);
	sleep(2);
	return(FALSE);
    }

    sprintf(buf, "Help for Composer %.40s Field", headents[level].name);
    (*Pmaster->helper)(headents[level].help, buf, 1);
}



/*
 * ToggleHeader() - set or unset pico values to the full screen size
 *                  painting header if need be.
 */
ToggleHeader(show)
int show;
{
    /*
     * check to see if we need to display the header... 
     */
    if(show){
	UpdateHeader();				/* figure bounds  */
	PaintHeader(COMPOSER_TOP_LINE, FALSE);	/* draw it */
    }
    else{
        /*
         * set bounds for no header display
         */
        curwp->w_toprow = ComposerTopLine = COMPOSER_TOP_LINE;
        curwp->w_ntrows = BOTTOM() - ComposerTopLine;
    }
    return(TRUE);
}



/*
 * HeaderLen() - return the length in lines of the exposed portion of the
 *               header
 */
HeaderLen()
{
    register struct hdr_line *lp;
    int      e;
    int      i;
    
    i = 1;
    lp = ods.top_l;
    e  = ods.top_e;
    while(lp != NULL){
	lp = next_hline(&e, lp);
	i++;
    }
    return(i);
}



/*
 * first_hline() - return a pointer to the first displayable header line
 * 
 *	returns:
 *		1) pointer to first displayable line in header and header
 *                 entry, via side effect, that the first line is a part of
 *              2) NULL if no next line, leaving entry at LASTHDR
 */
struct hdr_line *
first_hline(entry)
    int *entry;
{
    /* init *entry so we're sure to start from the top */
    for(*entry = 0; headents[*entry].name; (*entry)++)
      if(headents[*entry].display_it)
	return(headents[*entry].hd_text);

    *entry = 0;
    return(NULL);		/* this shouldn't happen */
}



/*
 * next_hline() - return a pointer to the next line structure
 * 
 *	returns:
 *		1) pointer to next displayable line in header and header
 *                 entry, via side effect, that the next line is a part of
 *              2) NULL if no next line, leaving entry at LASTHDR
 */
struct hdr_line *
next_hline(entry, line)
    int *entry;
    struct hdr_line *line;
{
    if(line == NULL)
      return(NULL);

    if(line->next == NULL){
	while(headents[++(*entry)].name != NULL){
	    if(headents[*entry].display_it)
	      return(headents[*entry].hd_text);
	}
	--(*entry);
	return(NULL);
    }
    else
      return(line->next);
}



/*
 * prev_hline() - return a pointer to the next line structure back
 * 
 *	returns:
 *              1) pointer to previous displayable line in header and 
 *                 the header entry that the next line is a part of 
 *                 via side effect
 *              2) NULL if we can't go back further
 */
struct hdr_line *
prev_hline(entry, line)
    int *entry;
    struct hdr_line *line;
{
    if(line == NULL)
      return(NULL);

    if(line->prev == NULL){
	while(--(*entry) >= 0){
	    if(headents[*entry].display_it){
		line = headents[*entry].hd_text;
		while(line->next != NULL)
		  line = line->next;
		return(line);
	    }
	}
	++(*entry);
	return(NULL);
    }
    else
      return(line->prev);
}



/*
 * UpdateHeader() - determines the best range of lines to be displayed 
 *                  using the global ods value for the current line and the
 *		    top line, also sets ComposerTopLine and pico limits
 *                    
 *      notes:
 *	        This is pretty ugly because it has to keep the current line
 *		on the screen in a reasonable location no matter what.
 *		There are also a couple of rules to follow:
 *                 1) follow paging conventions of pico (ie, half page 
 *		      scroll)
 *                 2) if more than one page, always display last half when 
 *                    pline is toward the end of the header
 * 
 *      returns:
 *             TRUE  if anything changed (side effects: new p_line, top_l
 *		     top_e, and pico parms)
 *             FALSE if nothing changed 
 *             
 */
UpdateHeader()
{
    register struct	hdr_line	*lp;
    int	     i, le;
    int      ret = FALSE;
    int      old_top = ComposerTopLine;
    int      old_p = ods.p_line;

    if(ods.p_line < COMPOSER_TOP_LINE || ods.p_line >= BOTTOM()){
	NewTop();				/* get new top_l */
	ret = TRUE;
    }
    else{					/* make sure p_line's OK */
	i = COMPOSER_TOP_LINE;
	lp = ods.top_l;
	le = ods.top_e;
	while(lp != ods.cur_l){
	    /*
	     * this checks to make sure cur_l is below top_l and that
	     * cur_l is on the screen...
	     */
	    if((lp = next_hline(&le, lp)) == NULL || ++i >= BOTTOM()){
		NewTop();
		ret = TRUE;
		break;
	    }
	}
    }

    ods.p_line = COMPOSER_TOP_LINE;		/* find  p_line... */
    lp = ods.top_l;
    le = ods.top_e;
    while(lp && lp != ods.cur_l){
	lp = next_hline(&le, lp);
	ods.p_line++;
    }

    if(!ret)
      ret = !(ods.p_line == old_p);

    ComposerTopLine = ods.p_line;		/* figure top composer line */
    while(lp && ComposerTopLine <= BOTTOM()){
	lp = next_hline(&le, lp);
	ComposerTopLine += (lp) ? 1 : 2;	/* allow for delim at end   */
    }

    if(!ret)
      ret = !(ComposerTopLine == old_top);

    if(wheadp->w_toprow != ComposerTopLine){	/* update pico params... */
        wheadp->w_toprow = ComposerTopLine;
        wheadp->w_ntrows = ((i = BOTTOM() - ComposerTopLine) > 0) ? i : 0;
	ret = TRUE;
    }
    return(ret);
}



/*
 * NewTop() - calculate a new top_l based on the cur_l
 *
 *	returns:
 *		with ods.top_l and top_e pointing at a reasonable line
 *		entry
 */
NewTop()
{
    register struct hdr_line *lp;
    register int i;
    int      e;

    lp = ods.cur_l;
    e  = ods.cur_e;
    i  = HALF_SCR();

    while(lp != NULL && i--){
	ods.top_l = lp;
	ods.top_e = e;
	lp = prev_hline(&e, lp);
    }
}



/*
 * display_delimiter() - just paint the header/message body delimiter with
 *                       inverse value specified by state.
 */
void
display_delimiter(state)
int	state;
{
    register char    *bufp;
    static   short   ps   = 0;			/* previous state */

    if(ComposerTopLine - 1 >= BOTTOM())		/* silently forget it */
      return;

    bufp = "----- Message Text -----";

    if(state == ps){				/* optimize ? */
	for(ps = 0; bufp[ps] && pscr(ComposerTopLine-1,ps)->c == bufp[ps];ps++)
	  ;

	if(bufp[ps] == '\0'){
	    ps = state;
	    return;				/* already displayed! */
	}
    }

    ps = state;

    movecursor(ComposerTopLine - 1, 0);
    if(state)
      (*term.t_rev)(1);

    while(*bufp != '\0')
      pputc(*bufp++, 0);

    if(state)
      (*term.t_rev)(0);

    peeol();
}



/*
 * InvertPrompt() - invert the prompt associated with header entry to state
 *                  state (true if invert, false otherwise).
 *	returns:
 *		non-zero if nothing done
 *		0 if prompt inverted successfully
 *
 *	notes:
 *		come to think of it, this func and the one above could
 *		easily be combined
 */
InvertPrompt(entry, state)
int	entry, state;
{
    register char   *bufp;
    register int    i;
    static   short  ps = 0; 			/* prev state of entry e */

    bufp = headents[entry].prompt;		/* fresh prompt paint */
    if((i = entry_line(entry, FALSE)) == -1)
      return(-1);				/* silently forget it */

    if((ps&(1<<entry)) == (state ? 1<<entry : 0)){	/* optimize ? */
	int j;

	for(j = 0; bufp[j] && pscr(i, j)->c == bufp[j]; j++)
	  ;

	if(bufp[j] == '\0'){
	    if(state)
	      ps |= 1<<entry;
	    else
	      ps &= ~(1<<entry);
	    return(0);				/* already displayed! */
	}
    }

    if(state)
      ps |= 1<<entry;
    else
      ps &= ~(1<<entry);

    movecursor(i, 0);
    if(state)
      (*term.t_rev)(1);

    while(*bufp && *(bufp + 1))
      pputc(*bufp++, 1);			/* putc upto last char */

    if(state)
      (*term.t_rev)(0);

    pputc(*bufp, 0);				/* last char not inverted */
    return(TRUE);
}




/*
 * partial_entries() - toggle display of the bcc and fcc fields.
 *
 *	returns:
 *		TRUE if there are partial entries on the display
 *		FALSE otherwise.
 */
partial_entries()
{
    register struct headerentry *h;
    int                          is_on;
  
    /*---- find out status of first rich header ---*/
    for(h = headents; !h->rich_header && h->name != NULL; h++)
      ;

    is_on = h->display_it;
    for(h = headents; h->name != NULL; h++) 
      if(h->rich_header) 
        h->display_it = ! is_on;

    return(is_on);
}



/*
 * entry_line() - return the physical line on the screen associated
 *                with the given header entry field.  Note: the field
 *                may span lines, so if the last char is set, return
 *                the appropriate value.
 *
 *	returns:
 *             1) physical line number of entry
 *             2) -1 if entry currently not on display
 */
entry_line(entry, lastchar)
int	entry, lastchar;
{
    register int    p_line = COMPOSER_TOP_LINE;
    int    i;
    register struct hdr_line    *line;

    for(line=ods.top_l, i=ods.top_e; headents[i].name && i <= entry; p_line++){
	if(p_line >= BOTTOM())
	  break;
	if(i == entry){
	    if(lastchar){
		if(line->next == NULL)
		  return(p_line);
	    }
	    else if(line->prev == NULL)
	      return(p_line);
	    else
	      return(-1);
	}
	line = next_hline(&i, line);
    }
    return(-1);
}



/*
 * physical_line() - return the physical line on the screen associated
 *                   with the given header line pointer.
 *
 *	returns:
 *             1) physical line number of entry
 *             2) -1 if entry currently not on display
 */
physical_line(l)
struct hdr_line *l;
{
    register int    p_line = COMPOSER_TOP_LINE;
    register struct hdr_line    *lp;
    int    i;

    for(lp=ods.top_l, i=ods.top_e; headents[i].name && lp != NULL; p_line++){
	if(p_line >= BOTTOM())
	  break;

	if(lp == l)
	  return(p_line);

	lp = next_hline(&i, lp);
    }
    return(-1);
}



/*
 * call_builder() - resolve any nicknames in the address book associated
 *                  with the given entry...
 *
 *    NOTES:
 * 
 *      BEWARE: this function can cause cur_l and top_l to get lost so BE 
 *              CAREFUL before and after you call this function!!!
 * 
 *      There could to be something here to resolve cur_l and top_l
 *      reasonably into the new linked list for this entry.  
 *
 *      The reason this would mostly work without it is resolve_niks gets
 *      called for the most part in between fields.  Since we're moving
 *      to the beginning or end (i.e. the next/prev pointer in the old 
 *      freed cur_l is NULL) of the next entry, we get a new cur_l
 *      pointing at a good line.  Then since top_l is based on cur_l in
 *      NewTop() we have pretty much lucked out.
 * 
 *      Where we could get burned is in a canceled exit (ctrl|x).  Here
 *      nicknames get resolved into addresses, which invalidates cur_l
 *      and top_l.  Since we don't actually leave, we could begin editing
 *      again with bad pointers.  This would usually results in a nice 
 *      core dump.
 *
 *	RETURNS:
 *              TRUE if any names where resolved, otherwise
 *              FALSE if not, or
 *		-1 on error
 */
call_builder(entry)
struct headerentry *entry;
{
    register    int     retval = FALSE;
    register	int	i;
    register    struct  hdr_line  *line = entry->hd_text;
    char	*sbuf;
    char	*errmsg, *s = NULL, *fcc = NULL;

    if(!entry->builder)
      return(0);

    line = entry->hd_text;
    i = 0;
    while(line != NULL){
	i += term.t_ncol;
        line = line->next;
    }
    if((sbuf=(char *)malloc((unsigned) i)) == NULL){
	emlwrite("Can't malloc space to expand address", NULL);
	return(-1);
    }
    
    *sbuf = '\0';
    /*
     * cat the whole entry into one string...
     */
    line = entry->hd_text;
    while(line != NULL){
	i = strlen(line->text);
	/*
	 * to keep pine address builder happy, addresses should be separated
	 * by ", ".  Add this space if needed, otherwise...
	 *
	 * if this line is NOT a continuation of the previous line, add
	 * white space for pine's address builder if its not already there...
	 *
	 * also if it's not a continuation (i.e., there's already and addr on 
	 * the line), and there's another line below, treat the new line as
	 * an implied comma
	 */
        if(line->text[i-1] == ',')
	  strcat(line->text, " ");		/* help address builder */
	else if(line->next != NULL && !strend(line->text, ',')){
	    if(strqchr(line->text, ',', NULL))
	      strcat(line->text, ", ");		/* implied comma */
	}
	else if(line->prev != NULL && line->next != NULL){
	    if(strchr(line->prev->text, ' ') != NULL 
	       && line->text[i-1] != ' ')
	      strcat(line->text, " ");
	}
	strcat(sbuf, line->text);
        line = line->next;
    }

    errmsg = NULL;
    retval = (*entry->builder)(sbuf, &s, &errmsg,
			       entry->affected_entry ? &fcc : NULL);
    if(errmsg){
	if(*errmsg){
	    char err[500];

	    sprintf(err, "%s field: %s", entry->name, errmsg);
	    (*term.t_beep)();
	    emlwrite(err, NULL);
	}
	else
	    mlerase();

	free(errmsg);
    }

    if(retval != -1){
	if(strcmp(sbuf, s)){
	    line = entry->hd_text;
	    InitEntryText(s, entry);		/* arrange new one */
	    zotentry(line); 			/* blast old list o'entries */
	}

	if(fcc && !entry->affected_entry->sticky){
	    line = entry->affected_entry->hd_text;
	    if(strcmp(line->text, fcc)){ /* make sure they see it if changed */
		entry->affected_entry->display_it = 1;
		InitEntryText(fcc, entry->affected_entry);
		zotentry(line);			/* blast old list o'entries */
	    }
	}

        retval = TRUE;
    }

    if(s)
	free(s);
    if(fcc)
	free(fcc);
    free(sbuf);
    return(retval);
}


/*
 * strend - neglecting white space, returns TRUE if c is at the
 *          end of the given line.  otherwise FALSE.
 */
strend(s, ch)
char *s;
int   ch;
{
    register char *b;
    register char  c;

    c = (char)ch;

    if(s == NULL)
      return(FALSE);

    if(*s == '\0')
      return(FALSE);

    b = &s[strlen(s)];
    while(myisspace(*--b)){
	if(b == s)
	  return(FALSE);
    }

    return(*b == c);
}


/*
 * strqchr - returns pointer to first non-quote-enclosed occurance of c in 
 *           the given string.  otherwise NULL.
 */
char *
strqchr(s, ch, q)
    char *s;
    int   ch;
    int  *q;
{
    int	 quoted = (q) ? *q : 0;

    for(; s && *s; s++){
	if(*s == '"'){
	    quoted = !quoted;
	    if(q)
	      *q = quoted;
	}

	if(!quoted && *s == ch)
	  return(s);
    }

    return(NULL);
}


/*
 * KillHeaderLine() - kill a line in the header
 *
 *	notes:
 *		This is pretty simple.  Just using the emacs kill buffer
 *		and its accompanying functions to cut the text from lines.
 *
 *	returns:
 *		TRUE if hldelete worked
 *		FALSE otherwise
 */
KillHeaderLine(l, append)
struct	hdr_line    *l;
int     append;
{
    register char	*c;

    if(!append)
	kdelete();

    c = l->text;
    while(*c != '\0')				/* splat out the line */
      kinsert(*c++);

    kinsert('\n');				/* helpful to yank in body */

    return(hldelete(l));			/* blast it  */
}



/*
 * SaveHeaderLines() - insert the saved lines in the list before the 
 *                     current line in the header
 *
 *	notes:
 *		Once again, just using emacs' kill buffer and its 
 *              functions.
 *
 *	returns:
 *		TRUE if something good happend
 *		FALSE otherwise
 */
SaveHeaderLines()
{
    extern   unsigned	kused;			/* length of kill buffer */
    char     *buf;				/* malloc'd copy of buffer */
    register char       *bp;			/* pointer to above buffer */
    register unsigned	i;			/* index */
    
    if(kused){
	if((bp = buf = (char *)malloc(kused+5)) == NULL){
	    emlwrite("Can't malloc space for saved text", NULL);
	    return(FALSE);
	}
    }
    else
      return(FALSE);

    for(i=0; i < kused; i++)
      if(kremove(i) != '\n')			/* filter out newlines */
	*bp++ = kremove(i);
    *bp = '\0';

    while(--bp >= buf)				/* kill trailing white space */
      if(*bp != ' '){
	  if(ods.cur_l->text[0] != '\0'){
	      if(*bp == '>'){			/* inserting an address */
		  *++bp = ',';			/* so add separator */
		  *++bp = '\0';
	      }
	  }
	  else{					/* nothing in field yet */
	      if(*bp == ','){			/* so blast any extra */
		  *bp = '\0';			/* separators */
	      }
	  }
	  break;
      }

    if(FormatLines(ods.cur_l, buf, LINELEN(),
		   headents[ods.cur_e].break_on_comma, 0) == -1)
      i = FALSE;
    else
      i = TRUE;

    free(buf);
    return(i);
}




/*
 * break_point - Break the given line s at the most reasonable character c
 *               within l max characters.
 *
 *	returns:
 *		Pointer to the best break point in s, or
 *		Pointer to the beginning of s if no break point found
 */
char *
break_point(s, l, ch, q)
    char *s;
    int   l, ch, *q;
{
    register char *b = s + l;
    int            quoted = (q) ? *q : 0;

    while(b != s){
	if(ch == ',' && *b == '"')		/* don't break on quoted ',' */
	  quoted = !quoted;			/* toggle quoted state */

	if(*b == ch){
	    if(ch == ' '){
		if(b + 1 < s + l){
		    b++;			/* leave the ' ' */
		    break;
		}
	    }
	    else{
		/*
		 * if break char isn't a space, leave a space after
		 * the break char.
		 */
		if(!(b+1 >= s+l || (b[1] == ' ' && b+2 == s+l))){
		    b += (b[1] == ' ') ? 2 : 1;
		    break;
		}
	    }
	}
	b--;
    }

    if(q)
      *q = quoted;

    return((quoted) ? s : b);
}




/*
 * hldelete() - remove the header line pointed to by l from the linked list
 *              of lines.
 *
 *	notes:
 *		the case of first line in field is kind of bogus.  since
 *              the array of headers has a pointer to the first line, and 
 *		i don't want to worry about this too much, i just copied 
 *		the line below and removed it rather than the first one
 *		from the list.
 *
 *	returns:
 *		TRUE if it worked 
 *		FALSE otherwise
 */
hldelete(l)
struct hdr_line  *l;
{
    register struct hdr_line *lp;

    if(l == NULL)
      return(FALSE);

    if(l->next == NULL && l->prev == NULL){	/* only one line in field */
	l->text[0] = '\0';
	return(TRUE);				/* no free only line in list */
    }
    else if(l->next == NULL){			/* last line in field */
	l->prev->next = NULL;
    }
    else if(l->prev == NULL){			/* first line in field */
	strcpy(l->text, l->next->text);
	lp = l->next;
	if((l->next = lp->next) != NULL)
	  l->next->prev = l;
	l = lp;
    }
    else{					/* some where in field */
	l->prev->next = l->next;
	l->next->prev = l->prev;
    }

    l->next = NULL;
    l->prev = NULL;
    free((char *)l);
    return(TRUE);
}



/*
 * is_blank - returns true if the next n chars from coordinates row, col
 *           on display are spaces
 */
is_blank(row, col, n)
int row, col, n;
{
    n += col;
    for( ;col < n; col++){
	if(pscr(row, col)->c != ' ')
	  return(0);
    }
    return(1);
}


/*
 * ShowPrompt - display key help corresponding to the current header entry
 */
ShowPrompt()
{
    int new_e = ods.cur_e;

    if(headents[ods.cur_e].key_label) {
	menu_header[TO_KEY].name  = "^T";
	menu_header[TO_KEY].label = headents[ods.cur_e].key_label;
    }
    else
      menu_header[TO_KEY].name  = NULL;

    wkeyhelp(menu_header);
}


/*
 * packheader - packup all of the header fields for return to caller. 
 *              NOTE: all of the header info passed in, including address
 *                    of the pointer to each string is contained in the
 *                    header entry array "headents".
 */
packheader()
{
    register int	i = 0;		/* array index */
    register int	count;		/* count of chars in a field */
    register int	retval = TRUE;	/* count of chars in a field */
    register char	*bufp;		/* */
    register struct	hdr_line *line;

    while(headents[i].name != NULL){
#ifdef	ATTACHMENTS
	/*
	 * attachments are special case, already in struct we pass back
	 */
	if(headents[i].is_attach){
	    i++;
	    continue;
	}
#endif

        /*
         * count chars to see if we need a new malloc'd space for our
         * array.
         */
        line = headents[i].hd_text;
        count = 0;
        while(line != NULL){
            /*
             * add one for possible concatination of a ' ' character ...
             */
            count += (strlen(line->text) + 1);
            line = line->next;
        }
        line = headents[i].hd_text;
        if(count < headents[i].maxlen){		
            *headents[i].realaddr[0] = '\0';
        }
        else{
            /*
             * don't forget to include space for the null terminator!!!!
             */
            if((bufp = (char *)malloc((count+1) * sizeof(char))) != NULL){
                *bufp = '\0';

                free(*headents[i].realaddr);
                *headents[i].realaddr = bufp;
            }
            else{
                emlwrite("Can't make room to pack header field.", NULL);
                retval = FALSE;
            }
        }

        if(retval != FALSE){
	    while(line != NULL){
                strcat(*headents[i].realaddr, line->text);
		if(line->text[strlen(line->text)-1] == ',')
		  strcat(*headents[i].realaddr, " ");
                line = line->next;
            }
        }

        i++;
    }
    return(retval);    
}



/*
 * zotheader - free all malloc'd lines associated with the header structs
 */
zotheader()
{
    register struct headerentry *i;
  
    for(i=headents; i->name != NULL; i++){
	zotentry(i->hd_text);
      }
}


/*
 * zotentry - free malloc'd space associated with the given linked list
 */
zotentry(l)
register struct hdr_line *l;
{
    register struct hdr_line *ld, *lf = l;

    while((ld = lf) != NULL){
	lf = ld->next;
	ld->next = ld->prev = NULL;
	free((char *) ld);
    }
}



/*
 * zotcomma - blast any trailing commas and white space from the end 
 *	      of the given line
 */
void
zotcomma(s)
char *s;
{
    register char *p;

    p = &s[strlen(s)];
    while(--p >= s){
	if(*p != ' '){
	    if(*p == ',')
	      *p = '\0';
	    return;
	}
    }
}
       end of the given line.  otherwise FALSE.
 */
strend(s, ch)
char *s;
int   ch;
{
    register char *b;
    register char  c;

    c = (char)ch;

    if(s == NULL)
      return(FALSE);

    if(*s == '\0')
      return(FALSE);

    b = &s[strlen(s)];
    while(myisspace(*--b)){
	if(b == s)
	  return(FALSE);
    }

    return(*b == c);
}


/*
 * strqchr - returns pointer to first non-quote-enclosed occurance of c in 
 *  DarkNET-1.08/pico.BBS/display.c                                                                        644   21270   21270       144570  5742637404  11307                                                                                                                                                                                                                                                                                                                                                                      #if	!defined(lint) && !defined(DOS)
static char rcsid[] = "$Id: display.c,v 4.27 1994/10/10 21:56:33 mikes Exp $";
#endif
/*
 * Program:	Display functions
 *
 *
 * Michael Seibel
 * Networks and Distributed Computing
 * Computing and Communications
 * University of Washington
 * Administration Builiding, AG-44
 * Seattle, Washington, 98195, USA
 * Internet: mikes@cac.washington.edu
 *
 * Please address all bugs and comments to "pine-bugs@cac.washington.edu"
 *
 * Copyright 1991-1994  University of Washington
 *
 *  Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee to the University of
 * Washington is hereby granted, provided that the above copyright notice
 * appears in all copies and that both the above copyright notice and this
 * permission notice appear in supporting documentation, and that the name
 * of the University of Washington not be used in advertising or publicity
 * pertaining to distribution of the software without specific, written
 * prior permission.  This software is made available "as is", and
 * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
 * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
 * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
 * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 * Pine and Pico are trademarks of the University of Washington.
 * No commercial use of these trademarks may be made without prior
 * written permission of the University of Washington.
 *
 */
/*
 * The functions in this file handle redisplay. There are two halves, the
 * ones that update the virtual display screen, and the ones that make the
 * physical display screen the same as the virtual display screen. These
 * functions use hints that are left in the windows by the commands.
 *
 */

#include        <stdio.h>
#include	"osdep.h"
#include        "pico.h"
#include	"estruct.h"
#include        "edef.h"
#include        "efunc.h"


#ifdef	ANSI
    int vtmove(int, int);
    int vtputc(CELL);
    int vtpute(CELL);
    int vteeol(void);
    int updateline(int, CELL *, CELL *, short *);
    int updext(void);
    int mlputi(int, int);
    int mlputli(long, int);
    int showCompTitle(void);
    int nlforw(void);
    int dumbroot(int, int);
    int dumblroot(long, int);
#else
    int vtmove();
    int vtputc();
    int vtpute();
    int vteeol();
    int updateline();
    int updext();
    int mlputi();
    int mlputli();
    int showCompTitle();
    int nlforw();
    int dumbroot();
    int dumblroot();
#endif


/*
 * Standard pico keymenus...
 */

static KEYMENU eng_menu_pico[] = {
    {"^G", "Get Help"},
    {"^Y", "Prev Pg"},	{"^K", "Cut Text"},	{"^C", "Cur Pos"},
    {"^X", "Exit"},		{"^J", "Justify"},	{"^W", "Where is"},
#ifdef	SPELLER
    {"^V", "Next Pg"},	{"^U", NULL},	{"^T", "To Spell"}
#else
    {"^V", "Next Pg"},	{"^U", NULL},	{"^D", "Del Char"}
#endif
    , {"",""}, {"", ""}
};

static KEYMENU kr_menu_pico[] = {
    {"^G", "µµ¿ò¸»"},
    {"^Y", "Àü ÆäÀÌÁö"}, {"^K", "Â©¶ó"},	{"^C", "ÇöÀç À§Ä¡"},
    {"^X", "³¡"},		{"^J", "ÁÙ¸ÂÃÄ"},	{"^W", "¾îµð¿¡"},
#ifdef	SPELLER
    {"^V", "´ÙÀ½Àå"},	{"^U", NULL},	{"^T", "¸ÂÃã¹ý"}
#else
    {"^V", "´ÙÀ½Àå"},	{"^U", NULL},	{"^D", "ÇÑ±ÛÀÚ »èÁ¦"}
#endif
    , {"",""}, {"", ""}
};

static KEYMENU *menu_pico = eng_menu_pico;
#define UNCUT_KEY	8


static KEYMENU menu_compose[] = {
    {"^G", "Get Help"},	{"^X", "Send"}, 	{"^R", "Read File"},
    {"^Y", "Prev Pg"},	{"^K", "Cut Text"},	{"^O", "Postpone"},
    {"^C", "Cancel"},	{"^J", "Justify"},	{NULL, NULL},
#ifdef	SPELLER
    {"^V", "Next Pg"},	{"^U", NULL},		{"^T", "To Spell"}
#else
    {"^V", "Next Pg"},	{"^U", NULL},		{"^D", "Del Char"}
#endif
    , NULL
};

#define	WHERE_KEY	8


#define WFDEBUG 0                       /* Window flag debug. */

typedef struct  VIDEO {
        short   v_flag;                 /* Flags */
        CELL    v_text[1];              /* Screen data. */
}       VIDEO;

#define VFCHG   0x0001                  /* Changed flag			*/
#define	VFEXT	0x0002			/* extended (beyond column 80)	*/
#define	VFREV	0x0004			/* reverse video status		*/
#define	VFREQ	0x0008			/* reverse video request	*/

int     vtrow   = 0;                    /* Row location of SW cursor */
int     vtcol   = 0;                    /* Column location of SW cursor */
int     ttrow   = HUGE;                 /* Row location of HW cursor */
int     ttcol   = HUGE;                 /* Column location of HW cursor */
int	lbound	= 0;			/* leftmost column of current line
					   being displayed */

VIDEO   **vscreen;                      /* Virtual screen. */
VIDEO   **pscreen;                      /* Physical screen. */


menu_init()
{
	extern int lang;

	if (lang)
		menu_pico = kr_menu_pico;
	else
		menu_pico = eng_menu_pico;
}

/*
 * Initialize the data structures used by the display code. The edge vectors
 * used to access the screens are set up. The operating system's terminal I/O
 * channel is set up. All the other things get initialized at compile time.
 * The original window has "WFCHG" set, so that it will get completely
 * redrawn on the first call to "update".
 */
vtinit()
{
    register int i;
    register VIDEO *vp;

    (*term.t_open)();

    (*term.t_rev)(FALSE);
    vscreen = (VIDEO **) malloc((term.t_nrow+1)*sizeof(VIDEO *));
    if (vscreen == NULL){
	emlwrite("Allocating memory for virtual display failed.", NULL);
        return(FALSE);
    }


    pscreen = (VIDEO **) malloc((term.t_nrow+1)*sizeof(VIDEO *));
    if (pscreen == NULL){
	free((void *)vscreen);
	emlwrite("Allocating memory for physical display failed.", NULL);
        return(FALSE);
    }


    for (i = 0; i <= term.t_nrow; ++i) {
        vp = (VIDEO *) malloc(sizeof(VIDEO)+(term.t_ncol*sizeof(CELL)));

        if (vp == NULL){
	    free((void *)vscreen);
	    free((void *)pscreen);
	    emlwrite("Allocating memory for virtual display lines failed.",
		     NULL);
            return(FALSE);
	}

	vp->v_flag = 0;
        vscreen[i] = vp;
        vp = (VIDEO *) malloc(sizeof(VIDEO)+(term.t_ncol*sizeof(CELL)));

        if (vp == NULL){
            free((void *)vscreen[i]);
	    while(--i >= 0){
		free((void *)vscreen[i]);
		free((void *)pscreen[i]);
	    }

	    free((void *)vscreen);
	    free((void *)pscreen);
	    emlwrite("Allocating memory for physical display lines failed.",
		     NULL);
            return(FALSE);
	}

	vp->v_flag = 0;
        pscreen[i] = vp;
    }

    return(TRUE);
}


/*
 * Clean up the virtual terminal system, in anticipation for a return to the
 * operating system. Move down to the last line and clear it out (the next
 * system prompt will be written in the line). Shut down the channel to the
 * terminal.
 */
vttidy()
{
    movecursor(term.t_nrow-1, 0);
    peeol();
    movecursor(term.t_nrow, 0);
    peeol();
    (*term.t_close)();
}


/*
 * Set the virtual cursor to the specified row and column on the virtual
 * screen. There is no checking for nonsense values; this might be a good
 * idea during the early stages.
 */
vtmove(row, col)
int row, col;
{
    vtrow = row;
    vtcol = col;
}


/*
 * Write a character to the virtual screen. The virtual row and column are
 * updated. If the line is too long put a "$" in the last column. This routine
 * only puts printing characters into the virtual terminal buffers. Only
 * column overflow is checked.
 */
vtputc(c)
CELL c;
{
    register VIDEO      *vp;
    CELL     ac;

    vp = vscreen[vtrow];
    ac.c = ' ';
    ac.a = c.a;

    if (vtcol >= term.t_ncol) {
        vtcol = (vtcol + 0x07) & ~0x07;
	ac.c = '$';
        vp->v_text[term.t_ncol - 1] = ac;
    }
    else if (c.c == '\t') {
        do {
            vtputc(ac);
	}
        while ((vtcol&0x07) != 0);
    }
    else if (c.c < 0x20 || c.c == 0x7F) {
	ac.c = '^';
        vtputc(ac);
	ac.c = (c.c ^ 0x40);
        vtputc(ac);
    }
    else
      vp->v_text[vtcol++] = c;
}


/* put a character to the virtual screen in an extended line. If we are
 * not yet on left edge, don't print it yet. check for overflow on
 * the right margin.
 */
vtpute(c)
CELL c;
{
    register VIDEO      *vp;
    CELL                 ac;

    vp = vscreen[vtrow];
    ac.c = ' ';
    ac.a = c.a;

    if (vtcol >= term.t_ncol) {
        vtcol = (vtcol + 0x07) & ~0x07;
	ac.c = '$';
        vp->v_text[term.t_ncol - 1] = ac;
    }
    else if (c.c == '\t'){
        do {
            vtpute(ac);
        }
        while (((vtcol + lbound)&0x07) != 0 && vtcol < term.t_ncol);
    }
    else if (c.c < 0x20 || c.c == 0x7F) {
	ac.c = '^';
        vtpute(ac);
	ac.c = (c.c ^ 0x40);
        vtpute(ac);
    }
    else {
	if (vtcol >= 0)
	  vp->v_text[vtcol] = c;
	++vtcol;
    }
}


/*
 * Erase from the end of the software cursor to the end of the line on which
 * the software cursor is located.
 */
vteeol()
{
    register VIDEO      *vp;
    CELL     c;

    c.c = ' ';
    c.a = 0;
    vp = vscreen[vtrow];
    while (vtcol < term.t_ncol)
      vp->v_text[vtcol++] = c;
}


/*
 * Make sure that the display is right. This is a three part process. First,
 * scan through all of the windows looking for dirty ones. Check the framing,
 * and refresh the screen. Second, make sure that "currow" and "curcol" are
 * correct for the current window. Third, make the virtual and physical
 * screens the same.
 */
update()
{
    register LINE   *lp;
    register WINDOW *wp;
    register VIDEO  *vp1;
    register VIDEO  *vp2;
    register int     i;
    register int     j;
    register int     scroll = 0;
    CELL	     c;

#if	TYPEAH
    if (typahead())
	return(TRUE);
#endif

#ifdef _WINDOWS
    /* This tells our MS Windows module to not bother updating the
     * cursor position while a massive screen update is in progress.
     */
    mswin_beginupdate ();
#endif

/*
 * BUG: setting and unsetting whole region at a time is dumb.  fix this.
 */
    if(curwp->w_markp){
	unmarkbuffer();
	markregion(1);
    }

    wp = wheadp;

    while (wp != NULL){
        /* Look at any window with update flags set on. */

        if (wp->w_flag != 0){
            /* If not force reframe, check the framing. */

            if ((wp->w_flag & WFFORCE) == 0){
                lp = wp->w_linep;

                for (i = 0; i < wp->w_ntrows; ++i){
                    if (lp == wp->w_dotp)
		      goto out;

                    if (lp == wp->w_bufp->b_linep)
		      break;

                    lp = lforw(lp);
		}
	    }

            /* Not acceptable, better compute a new value for the line at the
             * top of the window. Then set the "WFHARD" flag to force full
             * redraw.
             */
            i = wp->w_force;

            if (i > 0){
                --i;

                if (i >= wp->w_ntrows)
                  i = wp->w_ntrows-1;
	    }
            else if (i < 0){
                i += wp->w_ntrows;

                if (i < 0)
		  i = 0;
	    }
            else if(optimize){
		/* 
		 * find dotp, if its been moved just above or below the 
		 * window, use scrollxxx() to facilitate quick redisplay...
		 */
		lp = lforw(wp->w_dotp);
		if(lp != wp->w_dotp){
		    if(lp == wp->w_linep && lp != wp->w_bufp->b_linep){
			scroll = 1;
		    }
		    else {
			lp = wp->w_linep;
			for(j=0;j < wp->w_ntrows; ++j){
			    if(lp != wp->w_bufp->b_linep)
			      lp = lforw(lp);
			    else
			      break;
			}
			if(lp == wp->w_dotp && j == wp->w_ntrows)
			  scroll = 2;
		    }
		}
		j = i = wp->w_ntrows/2;
	    }
	    else
	      i = wp->w_ntrows/2;

            lp = wp->w_dotp;

            while (i != 0 && lback(lp) != wp->w_bufp->b_linep){
                --i;
                lp = lback(lp);
	    }

	    /*
	     * this is supposed to speed things up by using tcap sequences
	     * to efficiently scroll the terminal screen.  the thinking here
	     * is that its much faster to update pscreen[] than to actually
	     * write the stuff to the screen...
	     */
	    if(optimize){
		switch(scroll){
		  case 1:			/* scroll text down */
		    j = j-i+1;			/* add one for dot line */
			/* 
			 * do we scroll down the header as well?  Well, only 
			 * if we're not editing the header, we've backed up 
			 * to the top, and the composer is not being 
			 * displayed...
			 */
		    if(Pmaster && !ComposerEditing 
		       && (lback(lp) == wp->w_bufp->b_linep)
		       && (ComposerTopLine == COMPOSER_TOP_LINE))
		      j += entry_line(1000, TRUE); /* Never > 1000 headers */

		    scrolldown(wp, -1, j);
		    break;
		  case 2:			/* scroll text up */
		    j = wp->w_ntrows - (j-i);	/* we chose new top line! */
		    if(Pmaster && j){
			/* 
			 * do we scroll down the header as well?  Well, only 
			 * if we're not editing the header, we've backed up 
			 * to the top, and the composer is not being 
			 * displayed...
			 */
			if(!ComposerEditing 
			   && (ComposerTopLine != COMPOSER_TOP_LINE))
			  scrollup(wp, COMPOSER_TOP_LINE, 
				   j+entry_line(1000, TRUE));
			else
			  scrollup(wp, -1, j);
		    }
		    else
		      scrollup(wp, -1, j);
		    break;
		    default :
		      break;
		}
	    }

            wp->w_linep = lp;
            wp->w_flag |= WFHARD;       /* Force full. */
out:
	    /*
	     * if the line at the top of the page is the top line
	     * in the body, show the header...
	     */
	    if(Pmaster && !ComposerEditing){
		if(lback(wp->w_linep) == wp->w_bufp->b_linep){
		    if(ComposerTopLine == COMPOSER_TOP_LINE){
			i = term.t_nrow - 4 - HeaderLen();
			if(i > 0 && nlforw() >= i) {	/* room for header ? */
			    if((i = nlforw()/2) == 0 && term.t_nrow&1)
			      i = 1;
			    while(wp->w_linep != wp->w_bufp->b_linep && i--)
			      wp->w_linep = lforw(wp->w_linep);
			    
			}
			else
			  ToggleHeader(1);
		    }
		}
		else{
		    if(ComposerTopLine != COMPOSER_TOP_LINE)
		      ToggleHeader(0);		/* hide it ! */
		}
	    }

            /* Try to use reduced update. Mode line update has its own special
             * flag. The fast update is used if the only thing to do is within
             * the line editing.
             */
            lp = wp->w_linep;
            i = wp->w_toprow;

            if ((wp->w_flag & ~WFMODE) == WFEDIT){
                while (lp != wp->w_dotp){
                    ++i;
                    lp = lforw(lp);
		}

                vscreen[i]->v_flag |= VFCHG;
                vtmove(i, 0);

                for (j = 0; j < llength(lp); ++j)
                    vtputc(lgetc(lp, j));

                vteeol();
	    }
	    else if ((wp->w_flag & (WFEDIT | WFHARD)) != 0){
                while (i < wp->w_toprow+wp->w_ntrows){
                    vscreen[i]->v_flag |= VFCHG;
                    vtmove(i, 0);

		    /* if line has been changed */
                    if (lp != wp->w_bufp->b_linep){
                        for (j = 0; j < llength(lp); ++j)
                            vtputc(lgetc(lp, j));

                        lp = lforw(lp);
		    }

                    vteeol();
                    ++i;
		}
	    }
#if ~WFDEBUG
            if ((wp->w_flag&WFMODE) != 0)
                modeline(wp);

            wp->w_flag  = 0;
            wp->w_force = 0;
#endif
	}
#if WFDEBUG
        modeline(wp);
        wp->w_flag =  0;
        wp->w_force = 0;
#endif

	/* and onward to the next window */
        wp = wp->w_wndp;
    }

    /* Always recompute the row and column number of the hardware cursor. This
     * is the only update for simple moves.
     */
    lp = curwp->w_linep;
    currow = curwp->w_toprow;

    while (lp != curwp->w_dotp){
        ++currow;
        lp = lforw(lp);
    }

    curcol = 0;
    i = 0;

    while (i < curwp->w_doto){
	c = lgetc(lp, i++);

        if (c.c == '\t')
            curcol |= 0x07;
        else if (c.c < 0x20 || c.c == 0x7F)
            ++curcol;

        ++curcol;
    }

    if (curcol >= term.t_ncol - 1) { 		/* extended line. */
	/* flag we are extended and changed */
	vscreen[currow]->v_flag |= VFEXT | VFCHG;
	updext();				/* and output extended line */
    } else
      lbound = 0;				/* not extended line */

    /* make sure no lines need to be de-extended because the cursor is
     * no longer on them 
     */

    wp = wheadp;

    while (wp != NULL) {
	lp = wp->w_linep;
	i = wp->w_toprow;

	while (i < wp->w_toprow + wp->w_ntrows) {
	    if (vscreen[i]->v_flag & VFEXT) {
		/* always flag extended lines as changed */
		vscreen[i]->v_flag |= VFCHG;
		if ((wp != curwp) || (lp != wp->w_dotp) ||
		    (curcol < term.t_ncol - 1)) {
		    vtmove(i, 0);
		    for (j = 0; j < llength(lp); ++j)
		      vtputc(lgetc(lp, j));
		    vteeol();

		    /* this line no longer is extended */
		    vscreen[i]->v_flag &= ~VFEXT;
		}
	    }
	    lp = lforw(lp);
	    ++i;
	}
	/* and onward to the next window */
        wp = wp->w_wndp;
    }

    /* Special hacking if the screen is garbage. Clear the hardware screen,
     * and update your copy to agree with it. Set all the virtual screen
     * change bits, to force a full update.
     */

    if (sgarbf != FALSE){
	if(Pmaster){
	    showCompTitle();

	    if(ComposerTopLine != COMPOSER_TOP_LINE){
		UpdateHeader();			/* arrange things */
		PaintHeader(COMPOSER_TOP_LINE, TRUE);
	    }

	    /*
	     * since we're using only a portion of the screen and only 
	     * one buffer, only clear enough screen for the current window
	     * which is to say the *only* window.
	     */
	    for(i=wheadp->w_toprow;i<=term.t_nrow; i++){
		movecursor(i, 0);
		peeol();
		vscreen[i]->v_flag |= VFCHG;
	    }
	    movecursor(wheadp->w_toprow, 0);
	}
	else{
	    for (i = 0; i < term.t_nrow - 2; ++i){
		vscreen[i]->v_flag |= VFCHG;
		vp1 = pscreen[i];
		c.c = ' ';
		c.a = 0;
		for (j = 0; j < term.t_ncol; ++j)
		  vp1->v_text[j] = c;
	    }

	    movecursor(0, 0);	               /* Erase the screen. */
	    (*term.t_eeop)();

	}

        sgarbf = FALSE;				/* Erase-page clears */
        mpresf = FALSE;				/* the message area. */

	if(Pmaster)
	  modeline(curwp);
	else
	  sgarbk = TRUE;			/* fix the keyhelp as well...*/
    }

    /* Make sure that the physical and virtual displays agree. Unlike before,
     * the "updateline" code is only called with a line that has been updated
     * for sure.
     */
    if(Pmaster){
	i = curwp->w_toprow;
	c.c = term.t_nrow-2;
    }
    else{
	i = 0;
	c.c = term.t_nrow;
    }

    for (; i < (int)c.c; ++i){

        vp1 = vscreen[i];

	/* for each line that needs to be updated, or that needs its
	   reverse video status changed, call the line updater	*/
	j = vp1->v_flag;
        if (j & VFCHG){

#if	TYPEAH
	    if (typahead()){
#ifdef _WINDOWS
		mswin_endupdate ();
#endif
	        return(TRUE);
	    }
#endif
            vp2 = pscreen[i];

            updateline(i, &vp1->v_text[0], &vp2->v_text[0], &vp1->v_flag);

	}
    }

    if(Pmaster == NULL){

	if(sgarbk != FALSE){
	    extern int lang;

	    movecursor(term.t_nrow-1, 0);
	    peeol();
	    movecursor(term.t_nrow, 0);
	    peeol();
	    if(lastflag&CFFILL){
		if (lang) {
		  menu_pico[UNCUT_KEY].label = "¹°·¯";
		  emlwrite("ÁÙ¸ÂÃá°Å Ãë¼Ò ÇÒ¼ö ÀÖ¾î¿ä!", NULL);
		} else {
		  menu_pico[UNCUT_KEY].label = "UnJustify";
		  emlwrite("Can now UnJustify!", NULL);
		}
		mpresf = HUGE;	/* remove this after next keystroke! */
	    }
	    else
	    {
	      if (lang)
		menu_pico[UNCUT_KEY].label = "¹°·¯";
	      else
		menu_pico[UNCUT_KEY].label = "UnCut Text";
	    }

	    wkeyhelp(menu_pico);
	    sgarbk = FALSE;
        }
    }

    /* Finally, update the hardware cursor and flush out buffers. */

    if (isHan(curwp->w_dotp->l_text, curcol-lbound) == 2)
      curcol++;
    movecursor(currow, curcol - lbound);
#ifdef _WINDOWS
    mswin_endupdate ();
#endif
    (*term.t_flush)();
}

/* updext - update the extended line which the cursor is currently
 *	    on at a column greater than the terminal width. The line
 *	    will be scrolled right or left to let the user see where
 *	    the cursor is
 */
updext()
{
    register int rcursor;		/* real cursor location */
    register LINE *lp;			/* pointer to current line */
    register int j;			/* index into line */

    /* calculate what column the real cursor will end up in */
    rcursor = ((curcol - term.t_ncol) % term.t_scrsiz) + term.t_margin;
    lbound = curcol - rcursor + 1;

    /* scan through the line outputing characters to the virtual screen
     * once we reach the left edge
     */
    vtmove(currow, -lbound);		/* start scanning offscreen */
    lp = curwp->w_dotp;			/* line to output */
    for (j=0; j<llength(lp); ++j)	/* until the end-of-line */
      vtpute(lgetc(lp, j));

    /* truncate the virtual line */
    vteeol();

    /* and put a '$' in column 1 */
    vscreen[currow]->v_text[0].c = '$';
    vscreen[currow]->v_text[0].a = 0;
}


/*
 * Update a single line. This does not know how to use insert or delete
 * character sequences; we are using VT52 functionality. Update the physical
 * row and column variables. It does try an exploit erase to end of line. The
 * RAINBOW version of this routine uses fast video.
 */
updateline(row, vline, pline, flags)
int  row;
CELL vline[];				/* what we want it to end up as */
CELL pline[];				/* what it looks like now       */
short *flags;				/* and how we want it that way  */
{
    register CELL *cp1;
    register CELL *cp2;
    register CELL *cp3;
    register CELL *cp4;
    register CELL *cp5;
    register CELL *cp6;
    register CELL *cp7;
    register int  display = TRUE;
    register int nbflag;		/* non-blanks to the right flag? */


    /* set up pointers to virtual and physical lines */
    cp1 = &vline[0];
    cp2 = &pline[0];
    cp3 = &vline[term.t_ncol];

    /* advance past any common chars at the left */
    while (cp1 != cp3 && cp1[0].c == cp2[0].c && cp1[0].a == cp2[0].a) {
	++cp1;
	++cp2;
    }

/* This can still happen, even though we only call this routine on changed
 * lines. A hard update is always done when a line splits, a massive
 * change is done, or a buffer is displayed twice. This optimizes out most
 * of the excess updating. A lot of computes are used, but these tend to
 * be hard operations that do a lot of update, so I don't really care.
 */
    /* if both lines are the same, no update needs to be done */
    if (cp1 == cp3){
	*flags &= ~VFCHG;			/* mark it clean */
	return(TRUE);
    }

    /* find out if there is a match on the right */
    nbflag = FALSE;
    cp3 = &vline[term.t_ncol];
    cp4 = &pline[term.t_ncol];

    while (cp3[-1].c == cp4[-1].c && cp3[-1].a == cp4[-1].a) {
	--cp3;
	--cp4;
	if (cp3[0].c != ' ' || cp3[0].a != 0)/* Note if any nonblank */
	  nbflag = TRUE;		/* in right match. */
    }

    cp5 = cp3;

    if (nbflag == FALSE && eolexist == TRUE) {	/* Erase to EOL ? */
	while (cp5 != cp1 && cp5[-1].c == ' ' && cp5[-1].a == 0)
	  --cp5;

	if (cp3-cp5 <= 3)		/* Use only if erase is */
	  cp5 = cp3;			/* fewer characters. */
    }

    movecursor(row, cp1-&vline[0]);		/* Go to start of line. */

    if (!nbflag) {				/* use insert or del char? */
	cp6 = cp3;
	cp7 = cp4;

	if(inschar&&(cp7!=cp2 && cp6[0].c==cp7[-1].c && cp6[0].a==cp7[-1].a)){
	    while (cp7 != cp2 && cp6[0].c==cp7[-1].c && cp6[0].a==cp7[-1].a){
		--cp7;
		--cp6;
	    }

	    if (cp7==cp2 && cp4-cp2 > 3){
		o_insert((char)cp1->c);     /* insert the char */
		display = FALSE;        /* only do it once!! */
	    }
	}
	else if(delchar && cp3 != cp1 && cp7[0].c == cp6[-1].c
		&& cp7[0].a == cp6[-1].a){
	    while (cp6 != cp1 && cp7[0].c==cp6[-1].c && cp7[0].a==cp6[-1].a){
		--cp7;
		--cp6;
	    }

	    if (cp6==cp1 && cp5-cp6 > 3){
		o_delete();		/* insert the char */
		display = FALSE;        /* only do it once!! */
	    }
	}
    }

    while (cp1 != cp5) {		/* Ordinary. */
	if(display){
	    (*term.t_rev)(cp1->a);	/* set inverse for this char */
	    (*term.t_putchar)(cp1->c);
	}

	++ttcol;
	*cp2++ = *cp1++;
    }

    (*term.t_rev)(0);			/* turn off inverse anyway! */

    if (cp5 != cp3) {			/* Erase. */
	if(display)
	  peeol();
	while (cp1 != cp3)
	  *cp2++ = *cp1++;
    }
    *flags &= ~VFCHG;			/* flag this line is changed */
}


/*
 * Redisplay the mode line for the window pointed to by the "wp". This is the
 * only routine that has any idea of how the modeline is formatted. You can
 * change the modeline format by hacking at this routine. Called by "update"
 * any time there is a dirty window.
 */
modeline(wp)
WINDOW *wp;
{
    if(Pmaster){
        if(ComposerEditing)
	  ShowPrompt();
	else{
	    menu_compose[WHERE_KEY].name  = (Pmaster->alt_ed) ? "^_" : "^W";
	    menu_compose[WHERE_KEY].label = (Pmaster->alt_ed) ? "Alt Edit" 
							      : "Where is";
	    menu_compose[UNCUT_KEY].label = (thisflag&CFFILL) ? "UnFill"
							      : "UnCut Text";
	    wkeyhelp(menu_compose);
	}
    }
    else{
	register char *cp;
	register int n;		/* cursor position count */
	register BUFFER *bp;
	register i;		/* loop index */
	register lchar;		/* character to draw line in buffer with */
	char     tline[NLINE];	/* buffer for part of mode line */
	CELL     c;

	n = 0;
	c.a = 1;
#if	defined(MSDOS) || defined(LINUX)
	vtmove(1, 0);
	vteeol();
#endif
	vscreen[n]->v_flag |= VFCHG; /* Redraw next time. */
	vtmove(n, 0);		/* Seek to right line. */

#if	REVSTA
	if (revexist)
	  lchar = ' ';
	else
#endif
	  lchar = '-';

	c.c = lchar;
	vtputc(c);
	bp = wp->w_bufp;

	n = 1;

	sprintf((cp=tline), "  UW PICO(tm) %s  ", version);	/* VERSION */
	
	while ((c.c = *cp++) != 0) {
	    vtputc(c);
	    ++n;
	}

	if (bp->b_fname[0] != 0){            /* File name. */
	    sprintf(tline," File: ");
	    cp = &bp->b_fname[0];

	    if(strlen(cp) > (term.t_ncol-n-22)){   /* room for full path ? */
		strcat(tline,".../");
		while(strlen(cp) >= (term.t_ncol-n-22)){
		    if(strchr(cp,'/') == NULL)
		      cp = (char *)strchr(&bp->b_fname[0],'\0')-term.t_ncol-n-22;
		    else
		      cp = (char *)strchr(cp,'/') + 1;
		}
	    }

	    strcat(tline,cp);

	    c.c = ' ';
	    for(i=((term.t_ncol-n-12-strlen(tline))/2); i > 0; n++, i--)
	      vtputc(c);

	    cp = &tline[0];

	    while ((c.c = *cp++) != 0){
		vtputc(c);
		++n;
            }

        }
        else{
	    extern int lang;

	    if (lang)
	      cp = " »õ±Û ";
	    else
	      cp = " New Buffer ";
	    c.c = lchar;
            for(i=(term.t_ncol-strlen(cp))/2; n < i; n++)
	      vtputc(c);
	    while ((c.c = *cp++) != 0) {
		vtputc(c);
		++n;
            }
	}

#if WFDEBUG
	vtputc(lchar);
	vtputc((wp->w_flag&WFMODE)!=0  ? 'M' : lchar);
	vtputc((wp->w_flag&WFHARD)!=0  ? 'H' : lchar);
	vtputc((wp->w_flag&WFEDIT)!=0  ? 'E' : lchar);
	vtputc((wp->w_flag&WFMOVE)!=0  ? 'V' : lchar);
	vtputc((wp->w_flag&WFFORCE)!=0 ? 'F' : lchar);
	n += 6;
#endif

	if ((bp->b_flag&BFCHG) != 0)                /* "MOD" if changed. */
	  cp = "Modified  ";
	else
	  cp = "          ";

	c.c = lchar;
	while (n < (term.t_ncol - strlen(cp))){	    /* Pad to full width. */
	    vtputc(c);
	    ++n;
        }

	while ((c.c = *cp++) != 0){
	    vtputc(c);
	    ++n;
	}
    }
}



/*
 * Send a command to the terminal to move the hardware cursor to row "row"
 * and column "col". The row and column arguments are origin 0. Optimize out
 * random calls. Update "ttrow" and "ttcol".
 */
movecursor(row, col)
int row, col;
{
    if (row!=ttrow || col!=ttcol) {
        ttrow = row;
        ttcol = col;
        (*term.t_move)(row, col);
    }
}


/*
 * Erase the message line. This is a special routine because the message line
 * is not considered to be part of the virtual screen. It always works
 * immediately; the terminal buffer is flushed via a call to the flusher.
 */
mlerase()
{
    movecursor(term.t_nrow - 2, 0);
    (*term.t_rev)(0);
    if (eolexist == TRUE)
      peeol();
    else
      while(++ttcol < term.t_ncol)		/* track's ttcol */
	(*term.t_putchar)(' ');

    (*term.t_flush)();
    mpresf = FALSE;
}


/*
 * Ask a yes or no question in the message line. Return either TRUE, FALSE, or
 * ABORT. The ABORT status is returned if the user bumps out of the question
 * with a ^G. if d >= 0, d is the default answer returned. Otherwise there
 * is no default.
 */
mlyesno(prompt, dflt)
char  *prompt;
int   dflt;
{
    int     rv;
    char    buf[NLINE];
    KEYMENU menu_yesno[12];
    extern int lang;

    for(rv = 0; rv < 12; rv++)
      menu_yesno[rv].name = NULL;

    menu_yesno[1].name  = "Y";
    menu_yesno[1].label = (dflt == TRUE) ? "[Yes]" : "Yes";
    menu_yesno[6].name  = "^C";
    if (lang)
      menu_yesno[6].label = "Ãë¼Ò";
    else
      menu_yesno[6].label = "Cancel";
    menu_yesno[7].name  = "N";
    menu_yesno[7].label = (dflt == FALSE) ? "[No]" : "No";
    wkeyhelp(menu_yesno);		/* paint generic menu */
    sgarbk = TRUE;			/* mark menu dirty */
    if(Pmaster)
      curwp->w_flag |= WFMODE;

    sprintf(buf, "%s ? ", prompt);
    mlwrite(buf, NULL);
    (*term.t_rev)(1);
    rv = -1;
    while(1){
	switch(GetKey()){
	  case (CTRL|'M') :		/* default */
	    if(dflt >= 0){
		pputs((dflt) ? "Yes" : "No", 1);
		rv = dflt;
	    }
	    else
	      (*term.t_beep)();

	    break;

	  case (CTRL|'C') :		/* Bail out! */
	  case F2         :
	    pputs("ABORT", 1);
	    rv = ABORT;
	    break;

	  case 'y' :
	  case 'Y' :
	  case F3  :
	    pputs("Yes", 1);
	    rv = TRUE;
	    break;

	  case 'n' :
	  case 'N' :
	  case F4  :
	    pputs("No", 1);
	    rv = FALSE;
	    break;

	  default:
	    (*term.t_beep)();
	  case NODATA :
	    break;
	}

	(*term.t_flush)();
	if(rv != -1){
	    (*term.t_rev)(0);
	    return(rv);
	}
    }
}



/*
 * Write a prompt into the message line, then read back a response. Keep
 * track of the physical position of the cursor. If we are in a keyboard
 * macro throw the prompt away, and return the remembered response. This
 * lets macros run at full speed. The reply is always terminated by a carriage
 * return. Handle erase, kill, and abort keys.
 */
mlreply(prompt, buf, nbuf, flg, extras)
char    *prompt, *buf;
int      nbuf, flg;
KEYMENU *extras;
{
    return(mlreplyd(prompt, buf, nbuf, flg|QDEFLT, extras));
}


/*
 * function key mappings
 */
static int rfkm[12][2] = {
    { F1,  (CTRL|'G')},
    { F2,  (CTRL|'C')},
    { F3,  0 },
    { F4,  0 },
    { F5,  0 },
    { F6,  0 },
    { F7,  0 },
    { F8,  0 },
    { F9,  0 },
    { F10, 0 },
    { F11, 0 },
    { F12, 0 }
};


/*
 * mlreplyd - write the prompt to the message line along with an default
 *	      answer already typed in.  Carraige return accepts the
 *	      default.  answer returned in buf which also holds the initial
 *            default, nbuf is it's length, def set means use default value,
 *            and ff means for-file which checks that all chars are allowed
 *            in file names.
 */
mlreplyd(prompt, buf, nbuf, flg, extras)
char    *prompt;
char    *buf;
int      nbuf, flg;
KEYMENU *extras;
{
    register int    c;				/* current char       */
    register char   *b;				/* pointer in buf     */
    register int    i, j;
    register int    maxl;
    register int    plen;
    int      changed = FALSE;
    KEYMENU  menu_mlreply[12];
    extern int lang;

    menu_mlreply[0].name = "^G";
    if (lang)
      menu_mlreply[0].label = "Get Help";
    else
      menu_mlreply[0].label = "µµ¿ò¸»";
    for(j = 0, i = 1; i < 6; i++){	/* insert odd extras */
	menu_mlreply[i].name = NULL;
	rfkm[2*i][1] = 0;
	if(extras){
	    for(; extras[j].name && j != 2*(i-1); j++)
	      ;

	    if(extras[j].name){
		rfkm[2*i][1] = (extras[j].name[0] == '^')
				 ? (CTRL | extras[j].name[1])
				 : extras[j].name[1];
		menu_mlreply[i].name  = extras[j].name;
		menu_mlreply[i].label = extras[j].label;
	    }
	}
    }

    menu_mlreply[6].name = "^C";
    if (lang)
      menu_mlreply[6].label = "Ãë¼Ò";
    else
      menu_mlreply[6].label = "Cancel";
    for(j = 0, i = 7; i < 12; i++){	/* insert even extras */
	menu_mlreply[i].name = NULL;
	rfkm[2*(i-6)+1][1] = 0;
	if(extras){
	    for(; extras[j].name && j != (2*(i-6)) - 1; j++)
	      ;

	    if(extras[j].name){
		rfkm[2*(i-6)+1][1] = (extras[j].name[0] == '^')
				       ? (CTRL | extras[j].name[1])
				       : extras[j].name[0];
		menu_mlreply[i].name  = extras[j].name;
		menu_mlreply[i].label = extras[j].label;
	    }
	}
    }

    mlwrite(prompt, NULL);		/* paint prompt */
    plen = strlen(prompt);
    if(!(flg&QDEFLT))
      *buf = '\0';

    (*term.t_rev)(1);

    maxl = (nbuf < term.t_ncol - plen - 1) ? nbuf : term.t_ncol - plen - 1;

    pputs(buf, 1);
    b = &buf[strlen(buf)];
    
    (*term.t_rev)(0);
    wkeyhelp(menu_mlreply);		/* paint generic menu */
    sgarbk = 1;				/* mark menu dirty */
    (*term.t_rev)(1);

    for (;;) {
	movecursor(term.t_nrow - 2, plen + b - buf);
	(*term.t_flush)();


	while((c = GetKey()) == NODATA)
	  ;

	switch(normal(c, rfkm, 2)){
	  case (CTRL|'A') :			/* CTRL-A beginning     */
	    b = buf;
	    continue;

	  case (CTRL|'B') :			/* CTRL-B back a char   */
	    if(ttcol > plen)
		b--;
	    continue;

	  case (CTRL|'C') :			/* CTRL-C abort		*/
	    pputs("^C", 1);
	    ctrlg(FALSE, 0);
	    (*term.t_rev)(0);
	    (*term.t_flush)();
	    return(ABORT);

	  case (CTRL|'E') :			/* CTRL-E end of line   */
	    b = &buf[strlen(buf)];
	    continue;

	  case (CTRL|'F') :			/* CTRL-F forward a char*/
	    if(*b != '\0')
		b++;
	    continue;

	  case (CTRL|'G') :			/* CTRL-G help		*/
	    pputs("HELP", 1);
	    (*term.t_rev)(0);
	    (*term.t_flush)();
	    return(HELPCH);

	  case (CTRL|'H') :			/* CTRL-H backspace	*/
	  case 0x7f :				/*        rubout	*/
	    if (b <= buf)
	      break;
	    b--;
	    ttcol--;				/* cheating!  no pputc */
	    (*term.t_putchar)('\b');

	  case (CTRL|'D') :			/* CTRL-D delete char   */
	    changed=TRUE;
	    i = 0;
	    do					/* blat out left char   */
	      b[i] = b[i+1];
	    while(b[i++] != '\0');
	    break;

	  case (CTRL|'L') :			/* CTRL-L redraw	*/
	    (*term.t_rev)(0);
	    return(CTRL|'L');

	  case (CTRL|'T') :			/* CTRL-T special	*/
	    (*term.t_rev)(0);
	    return(CTRL|'T');

	  case (CTRL|'V') :			/* CTRL-V special	*/
	    if(flg & QPAGE){
		(*term.t_rev)(0);
		return(CTRL|'V');
	    }
	    else
	      (*term.t_beep)();

	    break;

	  case (CTRL|'Y') :			/* CTRL-Y special	*/
	    if(flg & QPAGE){
		(*term.t_rev)(0);
		return(CTRL|'Y');
	    }
	    else
	      (*term.t_beep)();

	    break;

	  case (CTRL|'K') :			/* CTRL-K kill line	*/
	    changed=TRUE;
	    buf[0] = '\0';
	    b = buf;
	    movecursor(ttrow, plen);
	    break;

	  case K_PAD_LEFT:
	    if(ttcol > plen)
	      b--;
	    continue;

	  case K_PAD_RIGHT:
	    if(*b != '\0')
	      b++;
	    continue;

	  case F3 :				/* abort */
	    pputs("ABORT", 1);
	    ctrlg(FALSE, 0);
	    (*term.t_rev)(0);
	    (*term.t_flush)();
	    return(ABORT);

	  case F1 :				/* sort of same thing */
	    (*term.t_rev)(0);
	    (*term.t_flush)();
	    return(HELPCH);

	  case (CTRL|'M') :			/*        newline       */
	    (*term.t_rev)(0);
	    (*term.t_flush)();
	    return(changed);

	  default : 
	    if(strlen(buf) >= maxl){		/* contain the text      */
		(*term.t_beep)();
		continue;
	    }
	    changed=TRUE;

	    if(c&(~0xff)){			/* bag ctrl/special chars */
		(*term.t_beep)();
	    }
	    else{
		i = strlen(b);
		if(flg&QFFILE){
		    if(!fallowc(c)){ 		/* c OK in filename? */
			(*term.t_beep)();
			continue;
		    }
		}
		do				/* blat out left char   */
		  b[i+1] = b[i];
		while(i-- >= 0);
		*b++ = c;
		pputc(c, 0);
	    }
	}

	pputs(b, 1);				/* show default */
	i = term.t_ncol-1;
	while(pscreen[ttrow]->v_text[i].c == ' ' 
	      && pscreen[ttrow]->v_text[i].a == 0)
	  i--;

	while(ttcol <= i)
	  pputc(' ', 0);
    }
}


/*
 * emlwrite() - write the message string to the error half of the screen
 *              center justified.  much like mlwrite (which is still used
 *              to paint the line for prompts and such), except it center
 *              the text.
 */
void
emlwrite(message, arg) 
char	*message;
void	*arg;
{
    register char *bufp = message;
    register char *ap;
    register long l;

    mlerase();

    if((l = strlen(message)) == 0)		/* nothing to write, bag it */
      return;

    /*
     * next, figure out where the to move the cursor so the message 
     * comes out centered
     */
    if((ap=(char *)strchr(message, '%')) != NULL){
	l -= 2;
	switch(ap[1]){
	  case '%':
	  case 'c':
	    l += 1;
	    break;
	  case 'd':
	    l += (long)dumbroot((int)arg, 10);
	    break;
	  case 'D':
	    l += (long)dumblroot((long)arg, 10);
	    break;
	  case 'o':
	    l += (long)dumbroot((int)arg, 8);
	    break;
	  case 'x':
	    l += (long)dumbroot((int)arg, 16);
	    break;
	  case 's':
            l += strlen((char *)arg);
	    break;
	}
    }

    if(l-4 <= term.t_ncol)			/* this wouldn't be good */
      movecursor(term.t_nrow-2, (term.t_ncol - (int)l - 4)/2);
    else
      movecursor(term.t_nrow-2, 0);

    (*term.t_rev)(1);
    pputs("[ ", 1);
    while (*bufp != '\0' && ttcol < term.t_ncol-2){
	if(*bufp == '\007')
	  (*term.t_beep)();
	else if(*bufp == '%'){
	    switch(*++bufp){
	      case 'c':
		pputc((char)(int)arg, 0);
		break;
	      case 'd':
		mlputi((int)arg, 10);
		break;
	      case 'D':
		mlputli((long)arg, 10);
		break;
	      case 'o':
		mlputi((int)arg, 16);
		break;
	      case 'x':
		mlputi((int)arg, 8);
		break;
	      case 's':
		pputs((char *)arg, 0);
		break;
	      case '%':
	      default:
		pputc(*bufp, 0);
		break;
	    }
	}
	else
	  pputc(*bufp, 0);
	bufp++;
    }

    pputs(" ]", 1);
    (*term.t_rev)(0);
    (*term.t_flush)();
    mpresf = TRUE;
}


/*
 * Write a message into the message line. Keep track of the physical cursor
 * position. A small class of printf like format items is handled. Assumes the
 * stack grows down; this assumption is made by the "++" in the argument scan
 * loop. Set the "message line" flag TRUE.
 */
mlwrite(fmt, arg)
char *fmt;
void *arg;
{
    register int c;
    register char *ap;

    /*
     * the idea is to only highlight if there is something to show
     */
    mlerase();

    ttcol = 0;
    (*term.t_rev)(1);
    ap = (char *) &arg;
    while ((c = *fmt++) != 0) {
        if (c != '%') {
            (*term.t_putchar)(c);
            ++ttcol;
	}
        else {
            c = *fmt++;
            switch (c) {
	      case 'd':
		mlputi(*(int *)ap, 10);
		ap += sizeof(int);
		break;

	      case 'o':
		mlputi(*(int *)ap,  8);
		ap += sizeof(int);
		break;

	      case 'x':
		mlputi(*(int *)ap, 16);
		ap += sizeof(int);
		break;

	      case 'D':
		mlputli(*(long *)ap, 10);
		ap += sizeof(long);
		break;

	      case 's':
		pputs(*(char **)ap, 1);
		ap += sizeof(char *);
		break;

              default:
		(*term.t_putchar)(c);
		++ttcol;
	    }
	}
    }

    c = ttcol;
    while(ttcol < term.t_ncol)
      pputc(' ', 0);

    movecursor(term.t_nrow - 2, c);
    (*term.t_rev)(0);
    (*term.t_flush)();
    mpresf = TRUE;
}


/*
 * Write out an integer, in the specified radix. Update the physical cursor
 * position. This will not handle any negative numbers; maybe it should.
 */
mlputi(i, r)
int i, r;
{
    register int q;
    static char hexdigits[] = "0123456789ABCDEF";

    if (i < 0){
        i = -i;
	pputc('-', 1);
    }

    q = i/r;

    if (q != 0)
      mlputi(q, r);

    pputc(hexdigits[i%r], 1);
}


/*
 * do the same except as a long integer.
 */
mlputli(l, r)
long l;
int  r;
{
    register long q;

    if (l < 0){
        l = -l;
        pputc('-', 1);
    }

    q = l/r;

    if (q != 0)
      mlputli(q, r);

    pputc((int)(l%r)+'0', 1);
}


/*
 * scrolldown - use stuff to efficiently move blocks of text on the
 *              display, and update the pscreen array to reflect those
 *              moves...
 *
 *        wp is the window to move in
 *        r  is the row at which to begin scrolling
 *        n  is the number of lines to scrol
 */
scrolldown(wp, r, n)
WINDOW *wp;
int     r, n;
{
#ifdef	TERMCAP
    register int i;
    register int l;
    register VIDEO *vp1;
    register VIDEO *vp2;

    if(!n)
      return;

    if(r < 0){
	r = wp->w_toprow;
	l = wp->w_ntrows;
    }
    else{
	if(r > wp->w_toprow)
	    vscreen[r-1]->v_flag |= VFCHG;
	l = wp->w_toprow+wp->w_ntrows-r;
    }

    o_scrolldown(r, n);

    for(i=l-n-1; i >=  0; i--){
	vp1 = pscreen[r+i]; 
	vp2 = pscreen[r+i+n];
	bcopy(vp1, vp2, term.t_ncol * sizeof(CELL));
    }
    pprints(r+n-1, r);
    ttrow = HUGE;
    ttcol = HUGE;
#endif /* TERMCAP */
}


/*
 * scrollup - use tcap stuff to efficiently move blocks of text on the
 *            display, and update the pscreen array to reflect those
 *            moves...
 */
scrollup(wp, r, n)
WINDOW *wp;
int     r, n;
{
#ifdef	TERMCAP
    register int i;
    register VIDEO *vp1;
    register VIDEO *vp2;

    if(!n)
      return;

    if(r < 0)
      r = wp->w_toprow;

    o_scrollup(r, n);

    i = 0;
    while(1){
	if(Pmaster){
	    if(!(r+i+n < wp->w_toprow+wp->w_ntrows))
	      break;
	}
	else{
	    if(!((i < wp->w_ntrows-n)&&(r+i+n < wp->w_toprow+wp->w_ntrows)))
	      break;
	}
	vp1 = pscreen[r+i+n]; 
	vp2 = pscreen[r+i];
	bcopy(vp1, vp2, term.t_ncol * sizeof(CELL));
	i++;
    }
    pprints(wp->w_toprow+wp->w_ntrows-n, wp->w_toprow+wp->w_ntrows-1);
    ttrow = HUGE;
    ttcol = HUGE;
#endif /* TERMCAP */
}


/*
 * print spaces in the physical screen starting from row abs(n) working in
 * either the positive or negative direction (depending on sign of n).
 */
pprints(x, y)
int x, y;
{
    register int i;
    register int j;

    if(x < y){
	for(i = x;i <= y; ++i){
	    for(j = 0; j < term.t_ncol; j++){
		pscreen[i]->v_text[j].c = ' ';
		pscreen[i]->v_text[j].a = 0;
	    }
        }
    }
    else{
	for(i = x;i >= y; --i){
	    for(j = 0; j < term.t_ncol; j++){
		pscreen[i]->v_text[j].c = ' ';
		pscreen[i]->v_text[j].a = 0;
	    }
        }
    }
    ttrow = y;
    ttcol = 0;
}



/*
 * doton - return the physical line number that the dot is on in the
 *         current window, and by side effect the number of lines remaining
 */
doton(r, chs)
int       *r;
unsigned  *chs;
{
    register int  i = 0;
    register LINE *lp = curwp->w_linep;
    int      l = -1;

    *chs = 0;
    while(i++ < curwp->w_ntrows){
	if(lp == curwp->w_dotp)
	  l = i-1;
	lp = lforw(lp);
	if(lp == curwp->w_bufp->b_linep){
	    i++;
	    break;
	}
	if(l >= 0)
	  (*chs) += llength(lp);
    }
    *r = i-l-2;
    return(l+curwp->w_toprow);
}



/*
 * resize_pico - given new window dimensions, allocate new resources
 */
resize_pico(row, col)
int  row, col;
{
    int old_nrow, old_ncol;
    register int i;
    register VIDEO *vp;

    old_nrow = term.t_nrow;
    old_ncol = term.t_ncol;

    term.t_nrow = row;
    term.t_ncol = col;

    if (old_ncol == term.t_ncol && old_nrow == term.t_nrow)
      return(TRUE);

    curwp->w_toprow = 2;
    curwp->w_ntrows = term.t_nrow-4; 	      /* "-4" for mode line and keys */

    if(Pmaster)
      fillcol = (term.t_ncol > 80) ? 77 : term.t_ncol - 6;
    else
      fillcol = term.t_ncol - 6;	       /* we control the fill column */

    /* 
     * free unused screen space ...
     */
    for(i=term.t_nrow+1; i <= old_nrow; ++i){
	free((char *) vscreen[i]);
	free((char *) pscreen[i]);
    }

    /* 
     * realloc new space for screen ...
     */
    if((vscreen=(VIDEO **)realloc(vscreen,(term.t_nrow+1)*sizeof(VIDEO *))) == NULL){
	if(Pmaster)
	  return(-1);
	else
	  exit(1);
    }

    if((pscreen=(VIDEO **)realloc(pscreen,(term.t_nrow+1)*sizeof(VIDEO *))) == NULL){
	if(Pmaster)
	  return(-1);
	else
	  exit(1);
    }

    for (i = 0; i <= term.t_nrow; ++i) {
	if(i <= old_nrow)
	  vp = (VIDEO *) realloc(vscreen[i], sizeof(VIDEO)+(term.t_ncol*sizeof(CELL)));
	else
	  vp = (VIDEO *) malloc(sizeof(VIDEO)+(term.t_ncol*sizeof(CELL)));

	if (vp == NULL)
	  exit(1);
	vp->v_flag = VFCHG;
	vscreen[i] = vp;
	if(old_ncol < term.t_ncol){  /* don't let any garbage in */
	    vtrow = i;
	    vtcol = (i < old_nrow) ? old_ncol : 0;
	    vteeol();
	}

	if(i <= old_nrow)
	  vp = (VIDEO *) realloc(pscreen[i], sizeof(VIDEO)+(term.t_ncol*sizeof(CELL)));
	else
	  vp = (VIDEO *) malloc(sizeof(VIDEO)+(term.t_ncol*sizeof(CELL)));

	if (vp == NULL)
	  exit(1);

	vp->v_flag = VFCHG;
	pscreen[i] = vp;
    }

    if(!ResizeBrowser()){
	if(Pmaster){
	    ResizeHeader();
	}
	else{
	    lchange(WFHARD);                   /* set update flags... */
	    curwp->w_flag |= WFMODE;           /* and modeline so we  */
	    refresh(0, 1);                     /* redraw the whole enchilada. */
	    update();                          /* do it */
	}
    }

    return(TRUE);
}


/*
 * showCompTitle - display the anchor line passed in from pine
 */
showCompTitle()
{
    if(Pmaster){
	register char *bufp;
	extern   char *pico_anchor;

	if((bufp = pico_anchor) == NULL)
	  return(1);

	movecursor(COMPOSER_TITLE_LINE, 0);
	(*term.t_rev)(1);   
	while (ttcol < term.t_ncol)
	  if(*bufp != '\0')
	    pputc(*bufp++, 1);
          else
	    pputc(' ', 1);

	(*term.t_rev)(0);
	movecursor(COMPOSER_TITLE_LINE + 1, 0);
	peeol();
    }
}



/*
 * zotdisplay - blast malloc'd space created for display maps
 */
zotdisplay()
{
    register int i;

    for (i = 0; i <= term.t_nrow; ++i){		/* free screens */
	free((char *) vscreen[i]);
	free((char *) pscreen[i]);
    }

    free((char *) vscreen);
    free((char *) pscreen);
}



/*
 * nlforw() - returns the number of lines from the top to the dot
 */
nlforw()
{
    register int  i = 0;
    register LINE *lp = curwp->w_linep;
    
    while(lp != curwp->w_dotp){
	lp = lforw(lp);
	i++;
    }
    return(i);
}



/*
 * pputc - output the given char, keep track of it on the physical screen
 *	   array, and keep track of the cursor
 */
pputc(c, a)
int   c;				/* char to write */
int   a;				/* and its attribute */
{
    if((ttcol >= 0 && ttcol < term.t_ncol) 
       && (ttrow >= 0 && ttrow <= term.t_nrow)){
/*	(*term.t_rev)(a);*/
	(*term.t_putchar)(c);			/* write it */
/*	(*term.t_rev)(!a);*/
	pscreen[ttrow]->v_text[ttcol].c = c;	/* keep track of it */
	pscreen[ttrow]->v_text[ttcol++].a = a;	/* keep track of it */
    }
}


/*
 * pputs - print a string and keep track of the cursor
 */
pputs(s, a)
register char *s;			/* string to write */
register int   a;			/* and its attribute */
{
    while (*s != '\0')
      pputc(*s++, a);
}


/*
 * peeol - physical screen array erase to end of the line.  remember to
 *	   track the cursor.
 */
peeol()
{
    register int r = ttrow;
    register int c = ttcol;
    CELL         cl;

    cl.c = ' ';
    cl.a = 0;
    (*term.t_eeol)();
    while(c < term.t_ncol && c >= 0 && r <= term.t_nrow && r >= 0)
      pscreen[r]->v_text[c++] = cl;
}


/*
 * pscr - return the character cell on the physical screen map on the 
 *        given line, l, and offset, o.
 */
CELL *
pscr(l, o)
int l, o;
{
    if((l >= 0 && l <= term.t_nrow) && (o >= 0 && o < term.t_ncol))
      return(&(pscreen[l]->v_text[o]));
    else
      return(NULL);
}


/*
 * pclear() - clear the physical screen from row x through row y
 */
pclear(x, y)
register int x;
register int y;
{
    register int i;

    for(i=x; i < y; i++){
	movecursor(i, 0);
	peeol();
    }
}


/*
 * dumbroot - just get close 
 */
dumbroot(x, b)
int x, b;
{
    if(x < b)
      return(1);
    else
      return(dumbroot(x/b, b) + 1);
}


/*
 * dumblroot - just get close 
 */
dumblroot(x, b)
long x;
int  b;
{
    if(x < b)
      return(1);
    else
      return(dumblroot(x/b, b) + 1);
}


/*
 * pinsertc - use optimized insert, fixing physical screen map.
 *            returns true if char written, false otherwise
 */
pinsert(c)
CELL c;
{
    register int   i;
    register CELL *p;

    if(o_insert((char)c.c)){		/* if we've got it, use it! */
	p = pscreen[ttrow]->v_text;	/* then clean up physical screen */
	for(i = term.t_ncol-1; i > ttcol; i--)
	  p[i] = p[i-1];		/* shift right */
	p[ttcol++] = c;			/* insert new char */
	
	return(1);
    }

    return(0);
}


/*
 * pdel - use optimized delete to rub out the current char and
 *        fix the physical screen array.
 *        returns true if optimized the delete, false otherwise
 */
pdel()
{
    register int   i;
    register CELL *c;

    if(delchar){			/* if we've got it, use it! */
	(*term.t_putchar)('\b'); 	/* move left a char */
	--ttcol;
	o_delete();			/* and delete it */

	c = pscreen[ttrow]->v_text;	/* then clean up physical screen */
	for(i=ttcol; i < term.t_ncol; i++)
	  c[i] = c[i+1];
	c[i].c = ' ';
	c[i].a = 0;
	
	return(1);
    }

    return(0);
}



/*
 * wstripe - write out the given string at the given location, and reverse
 *           video on flagged characters.  Does the same thing as pine's
 *           stripe.
 */
void
wstripe(line, column, pmt, key)
int	line, column;
char	*pmt;
int      key;
{
    register char *buf;
    register int  i = 0;
    register int  j = 0;
    register int  l;

    l = strlen(pmt);
    while(1){
	if(i >= term.t_ncol || j >= l)
	  return;				/* equal strings */

	if(pmt[j] == key)
	  j++;

	if(pscr(line, i)->c != pmt[j]){
	    if(j >= 1 && pmt[j-1] == key)
	      j--;
	    break;
	}

	j++;
	i++;
    }

    movecursor(line, column+i);
    buf = &pmt[j];
    do{
	if(*buf == key){
	    buf++;
	    (*term.t_rev)(1);
	    pputc(*buf, 1);
	    (*term.t_rev)(0);
	}
	else{
	    pputc(*buf, 0);
	}
    }    
    while(*++buf != '\0');
    peeol();
    (*term.t_flush)();
}



/*
 *  wkeyhelp - paint list of possible commands on the bottom
 *             of the display (yet another pine clone)
 *  NOTE: function key mode is handled here since all the labels
 *        are the same...
 */
wkeyhelp(keymenu)
KEYMENU *keymenu;
{
    char *obufp, *p, fkey[4], linebuf[NLINE];
    int   row, slot, tspace, nspace[6], index, n;

    /*
     * Calculate amount of space for the names column by column...
     */
    for(index = 0; index < 6; index++)
      if(!(gmode&MDFKEY)){
	  nspace[index] = (keymenu[index].name)
			    ? strlen(keymenu[index].name) : 0;
	  if(keymenu[index+6].name 
	     && (n = strlen(keymenu[index+6].name)) > nspace[index])
	    nspace[index] = n;

	  nspace[index]++;
      }
      else
	nspace[index] = (index < 4) ? 3 : 4;

    tspace = term.t_ncol/6;		/* total space for each item */
    index  = 0;
    for(row = 0; row <= 1; row++){
	linebuf[0] = '\0';
	obufp = &linebuf[0];
	for(slot = 0; slot < 6; slot++){
	    if(keymenu[index].name && keymenu[index].label){
#if	defined(DOS) && defined(MOUSE)
		register_key(index,
			     (gmode&MDFKEY) ? F1 + (2 * slot) + row:
			       (keymenu[index].name[0] == '^')
				 ? (CTRL | keymenu[index].name[1])
				 : keymenu[index].name[0],
			     keymenu[index].label,
			     term.t_nrow - 1 + row,
			     (slot * tspace) + nspace[slot],
			     strlen(keymenu[index].label));
#endif
		if(gmode&MDFKEY){
		    p = fkey;
		    sprintf(fkey, "F%d", (2 * slot) + row + 1);
		}
		else
		  p = keymenu[index].name;

		n = nspace[slot];
		while(p && *p && n--){
		    *obufp++ = '~';	/* insert "invert" token */
		    *obufp++ = *p++;
		}

		while(n-- > 0)
		  *obufp++ = ' ';

		p = keymenu[index].label;
		n = tspace - nspace[slot];
		while(p && *p && n-- > 0)
		  *obufp++ = *p++;

		while(n-- > 0)
		  *obufp++ = ' ';
	    }
	    else{
		n = tspace;
		while(n--)
		  *obufp++ = ' ';

#if	defined(DOS) && defined(MOUSE)
		register_key(index, NODATA, NULL, 0, 0, 0);
#endif
	    }

	    *obufp = '\0';
	    index++;
	}

	wstripe(term.t_nrow - 1 + row, 0, linebuf, '~');
    }
}
   * realloc new space for screen ...
     */
    if((vscreen=(VIDEO **)realloc(vscreen,(term.t_nrow+1)*sizeof(VIDEO *))) == NULL){
	if(DarkNET-1.08/pico.BBS/ebind.h                                                                          644   21270   21270        12256  5672467637  10716                                                                                                                                                                                                                                                                                                                                                                      /*
 * $Id: ebind.h,v 4.5 1994/06/15 22:17:43 mikes Exp $
 *
 * Program:	Default key bindings
 *
 *
 * Michael Seibel
 * Networks and Distributed Computing
 * Computing and Communications
 * University of Washington
 * Administration Builiding, AG-44
 * Seattle, Washington, 98195, USA
 * Internet: mikes@cac.washington.edu
 *
 * Please address all bugs and comments to "pine-bugs@cac.washington.edu"
 *
 * Copyright 1991-1994  University of Washington
 *
 *  Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee to the University of
 * Washington is hereby granted, provided that the above copyright notice
 * appears in all copies and that both the above copyright notice and this
 * permission notice appear in supporting documentation, and that the name
 * of the University of Washington not be used in advertising or publicity
 * pertaining to distribution of the software without specific, written
 * prior permission.  This software is made available "as is", and
 * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
 * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
 * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
 * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 * Pine and Pico are trademarks of the University of Washington.
 * No commercial use of these trademarks may be made without prior
 * written permission of the University of Washington.
 *
 *
 * NOTES:
 *
 *	This files describes the key bindings for pico and the pine 
 *      composer.  The binds are static, (i.e., no way for the user
 *      to change them) so as to keep pico/composer as simple to use
 *      as possible.  This, of course, means the number of functions is
 *      greatly reduced, but, then again, this is seen as very desirable.
 *
 *      There are very limited number of flat ctrl-key bindings left, and 
 *      most of them are slated for yet-to-be implemented functions, like
 *      invoking an alternate editor in the composer and necessary funcs
 *      for imlementing attachment handling.  We really want to avoid 
 *      going to multiple keystroke functions. -mss
 *
 */

/*	EBIND:		Initial default key to function bindings for
			MicroEMACS 3.2

			written by Dave G. Conroy
			modified by Steve Wilhite, George Jones
			greatly modified by Daniel Lawrence
*/

#ifndef	EBIND_H
#define	EBIND_H


/*
 * Command table.
 * This table  is *roughly* in ASCII order, left to right across the
 * characters of the command. This expains the funny location of the
 * control-X commands.
 */
KEYTAB  keytab[NBINDS] = {
	{K_PAD_UP,		backline},
	{K_PAD_DOWN,		forwline},
	{K_PAD_RIGHT,		forwchar},
	{K_PAD_LEFT,		backchar},
	{K_PAD_PREVPAGE,	backpage},
	{K_PAD_NEXTPAGE,	forwpage},
	{K_PAD_HOME,		gotobol},
	{K_PAD_END,		gotoeol},
	{K_PAD_DELETE,		forwdel},
	{CTRL|'A',		gotobol},
	{CTRL|'B',		backchar},
	{CTRL|'C',		abort_composer},
	{CTRL|'D',		forwdel},
	{CTRL|'E',		gotoeol},
	{CTRL|'F',		forwchar},
	{CTRL|'G',		whelp},
	{CTRL|'H',		backdel},
	{CTRL|'I',		tab},
	{CTRL|'J',		fillpara},
	{CTRL|'K',		killregion},
	{CTRL|'L',		refresh},
	{CTRL|'M',		newline},
	{CTRL|'N',		forwline},
#ifdef DELETED
	{CTRL|'O',		suspend_composer},
#endif
	{CTRL|'P',		backline},
#ifdef DELETED
	{CTRL|'R',		insfile},
#endif
#ifdef	SPELLER
	{CTRL|'T',		spell},
#endif	/* SPELLER */
	{CTRL|'U',		yank},
	{CTRL|'V',		forwpage},
	{CTRL|'W',		forwsearch},
	{CTRL|'X',		wquit},
	{CTRL|'Y',		backpage},
#ifdef	JOB_CONTROL
	{CTRL|'Z',		bktoshell},
#endif
	{CTRL|'@',		forwword},
	{CTRL|'^',		setmark},
#ifdef DELETED
	{CTRL|'_',		alt_editor},
#endif
	{0x7F,			backdel},
	{0,			NULL}
};


/*
 * Command table.
 * This table  is *roughly* in ASCII order, left to right across the
 * characters of the command. This expains the funny location of the
 * control-X commands.
 */
KEYTAB  pkeytab[NBINDS] = {
	{K_PAD_UP,		backline},
	{K_PAD_DOWN,		forwline},
	{K_PAD_RIGHT,		forwchar},
	{K_PAD_LEFT,		backchar},
	{K_PAD_PREVPAGE,	backpage},
	{K_PAD_NEXTPAGE,	forwpage},
	{K_PAD_HOME,		gotobol},
	{K_PAD_END,		gotoeol},
	{K_PAD_DELETE,		forwdel},
	{CTRL|'A',		gotobol},
	{CTRL|'B',		backchar},
	{CTRL|'C',		showcpos},
	{CTRL|'D',		forwdel},
	{CTRL|'E',		gotoeol},
	{CTRL|'F',		forwchar},
	{CTRL|'G',		whelp},
	{CTRL|'H',		backdel},
	{CTRL|'I',		tab},
	{CTRL|'J',		fillpara},
#ifdef	ONLYWHILETESTING
	{CTRL|'K',		killtext},
#else
	{CTRL|'K',		killregion},
#endif
	{CTRL|'L',		refresh},
	{CTRL|'M',		newline},
	{CTRL|'N',		forwline},
#ifdef DELETED
	{CTRL|'O',		filewrite},
#endif
	{CTRL|'P',		backline},
#ifdef DELETED
	{CTRL|'R',		insfile},
#endif
#ifdef	SPELLER
	{CTRL|'T',		spell},
#endif	/* SPELLER */
	{CTRL|'U',		yank},
	{CTRL|'V',		forwpage},
	{CTRL|'W',		forwsearch},
	{CTRL|'X',		wquit},
	{CTRL|'Y',		backpage},
#ifdef	JOB_CONTROL
	{CTRL|'Z',		bktoshell},
#endif
	{CTRL|'@',		forwword},
	{CTRL|'^',		setmark},
	{0x7F,			backdel},
	{0,			NULL}
};

#endif	/* EBIND_H */
                                                                                                                                                                                                                                                                                                                                                  DarkNET-1.08/pico.BBS/edef.h                                                                           644   21270   21270        14724  5672463052  10525                                                                                                                                                                                                                                                                                                                                                                      /*
 * $Id: edef.h,v 4.7 1994/08/03 03:04:27 mikes Exp $
 *
 * Program:	Global definitions and initializations
 *
 *
 * Michael Seibel
 * Networks and Distributed Computing
 * Computing and Communications
 * University of Washington
 * Administration Builiding, AG-44
 * Seattle, Washington, 98195, USA
 * Internet: mikes@cac.washington.edu
 *
 * Please address all bugs and comments to "pine-bugs@cac.washington.edu"
 *
 * Copyright 1991-1994  University of Washington
 *
 *  Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee to the University of
 * Washington is hereby granted, provided that the above copyright notice
 * appears in all copies and that both the above copyright notice and this
 * permission notice appear in supporting documentation, and that the name
 * of the University of Washington not be used in advertising or publicity
 * pertaining to distribution of the software without specific, written
 * prior permission.  This software is made available "as is", and
 * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
 * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
 * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
 * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 * Pine and Pico are trademarks of the University of Washington.
 * No commercial use of these trademarks may be made without prior
 * written permission of the University of Washington.
 *
 */
/*	EDEF:		Global variable definitions for
			MicroEMACS 3.2

			written by Dave G. Conroy
			modified by Steve Wilhite, George Jones
			greatly modified by Daniel Lawrence
*/

#ifndef	EDEF_H
#define	EDEF_H

#ifdef	maindef

/* for MAIN.C */

/* initialized global definitions */

int     fillcol = 72;                   /* Current fill column          */
char    pat[NPAT];                      /* Search pattern		*/
int	eolexist = TRUE;		/* does clear to EOL exist	*/
int	optimize = FALSE;		/* optimize flag(cf line speed)	*/
int	scrollexist = TRUE;		/* does insert line exist	*/
int	inschar = TRUE;			/* does insert character exist	*/
int	delchar = TRUE;			/* does delete character exist	*/
int     sgarbk = TRUE;                  /* TRUE if keyhelp garbaged     */
int     mline_open = FALSE;             /* TRUE if message line is open */
int	ComposerTopLine = 2;		/* TRUE if message line is open */
int	ComposerEditing = FALSE;	/* TRUE if message line is open */
int	revexist = FALSE;		/* does reverse video exist?	*/
char	modecode[] = "WCSEVO";		/* letters to represent modes	*/
int	gmode = MDWRAP;			/* global editor mode		*/
int     sgarbf  = TRUE;                 /* TRUE if screen is garbage	*/
int     mpresf  = FALSE;                /* TRUE if message in last line */
int	clexec	= FALSE;		/* command line execution flag	*/

/* uninitialized global definitions */
int     currow;                 /* Cursor row                   */
int     curcol;                 /* Cursor column                */
int     thisflag;               /* Flags, this command          */
int     lastflag;               /* Flags, last command          */
int     curgoal;                /* Goal for C-P, C-N            */
WINDOW  *curwp;                 /* Current window               */
BUFFER  *curbp;                 /* Current buffer               */
WINDOW  *wheadp;                /* Head of list of windows      */
BUFFER  *bheadp;                /* Head of list of buffers      */
BUFFER  *blistp;                /* Buffer for C-X C-B           */

BUFFER  *bfind();               /* Lookup a buffer by name      */
WINDOW  *wpopup();              /* Pop up window creation       */
LINE    *lalloc();              /* Allocate a line              */

#else

/* for all the other .C files */

/* initialized global external declarations */

extern  int     fillcol;                /* Fill column                  */
extern  char    pat[];                  /* Search pattern               */
extern	int	eolexist;		/* does clear to EOL exist?	*/
extern	int	optimize;		/* optimize flag(cf line speed)	*/
extern	int	scrollexist;		/* does insert line exist	*/
extern	int	inschar;		/* does insert character exist	*/
extern	int	delchar;		/* does delete character exist	*/
extern  int     sgarbk;
extern  int     mline_open;             /* Message line is open         */
extern	int	ComposerTopLine;	/* TRUE if message line is open */
extern	int	ComposerEditing;	/* TRUE if message line is open */
extern	int	timeout;		/* how long we wait in GetKey	*/
extern	int	revexist;		/* does reverse video exist?	*/
extern	char	modecode[];		/* letters to represent modes	*/
extern	KEYTAB	keytab[];		/* key bind to functions table	*/
extern	KEYTAB	pkeytab[];		/* pico's function table	*/
extern	int	gmode;			/* global editor mode		*/
extern  int     sgarbf;                 /* State of screen unknown      */
extern  int     mpresf;                 /* Stuff in message line        */
extern	int	clexec;			/* command line execution flag	*/

/* initialized global external declarations */
extern  int     currow;                 /* Cursor row                   */
extern  int     curcol;                 /* Cursor column                */
extern  int     thisflag;               /* Flags, this command          */
extern  int     lastflag;               /* Flags, last command          */
extern  int     curgoal;                /* Goal for C-P, C-N            */
extern  WINDOW  *curwp;                 /* Current window               */
extern  BUFFER  *curbp;                 /* Current buffer               */
extern  WINDOW  *wheadp;                /* Head of list of windows      */
extern  BUFFER  *bheadp;                /* Head of list of buffers      */
extern  BUFFER  *blistp;                /* Buffer for C-X C-B           */

extern  BUFFER  *bfind();               /* Lookup a buffer by name      */
extern  WINDOW  *wpopup();              /* Pop up window creation       */
extern  LINE    *lalloc();              /* Allocate a line              */

#endif

/* terminal table defined only in TERM.C */

#ifndef	termdef
#if defined(VMS) && !defined(__ALPHA)
globalref
#else
extern
#endif
       TERM    term;                   /* Terminal information.        */
#endif

#endif	/* EDEF_H */
rbage	*/
int     mpresf  = FALSE;           DarkNET-1.08/pico.BBS/efunc.h                                                                          644   21270   21270        27241  5672463052  10720                                                                                                                                                                                                                                                                                                                                                                      /*
 * $Id: efunc.h,v 4.12 1994/09/27 16:04:00 mikes Exp $
 *
 * Program:	Pine's composer and pico's function declarations
 *
 *
 * Michael Seibel
 * Networks and Distributed Computing
 * Computing and Communications
 * University of Washington
 * Administration Builiding, AG-44
 * Seattle, Washington, 98195, USA
 * Internet: mikes@cac.washington.edu
 *
 * Please address all bugs and comments to "pine-bugs@cac.washington.edu"
 *
 * Copyright 1991-1994  University of Washington
 *
 *  Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee to the University of
 * Washington is hereby granted, provided that the above copyright notice
 * appears in all copies and that both the above copyright notice and this
 * permission notice appear in supporting documentation, and that the name
 * of the University of Washington not be used in advertising or publicity
 * pertaining to distribution of the software without specific, written
 * prior permission.  This software is made available "as is", and
 * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
 * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
 * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
 * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 * Pine and Pico are trademarks of the University of Washington.
 * No commercial use of these trademarks may be made without prior
 * written permission of the University of Washington.
 *
 */
/*	EFUNC.H:	MicroEMACS function declarations and names

		This file list all the C code functions used by MicroEMACS
	and the names to use to bind keys to them. To add functions,
	declare it here in both the extern function list and the name
	binding table.

	Update History:

	Daniel Lawrence
*/

#ifndef	EFUNC_H
#define	EFUNC_H


/*	External function declarations		*/
#ifdef	ANSI
/* attach.c */
extern	int AskAttach(char *, char *, char *);
extern	int SyncAttach(void);
extern	int intag(char *, int);
extern	char *prettysz(long);
extern  int AttachError(void);

/* basic.c */
extern	int gotobol(int, int);
extern	int backchar(int, int);
extern	int gotoeol(int, int);
extern	int forwchar(int, int);
extern	int gotoline(int, int);
extern	int gotobob(int, int);
extern	int gotoeob(int, int);
extern	int forwline(int, int);
extern	int backline(int, int);
extern	int gotobop(int, int);
extern	int gotoeop(int, int);
extern	int forwpage(int, int);
extern	int backpage(int, int);
extern	int setmark(int, int);
extern	int swapmark(int, int);
extern	int setimark(int, int);
extern	int swapimark(int, int);

/* bind.c */
extern	int whelp(int, int);
extern	int wscrollw(int, int, char **,int);
extern	int normal(int, int (*)[2],int);
extern	int rebindfunc(int (*a)(int, int),int (*)(int, int));

/* browse.c */
extern	int FileBrowse(char *, char *, char *, int);
extern	int ResizeBrowser(void);

/* buffer.c */
extern	int anycb(void);
extern	struct BUFFER *bfind(char *, int, int);
extern	int bclear(struct BUFFER *);
extern	int packbuf(char **, int *, int);
extern	int readbuf(char **);

/* composer.c */
extern	int InitMailHeader(struct pico_struct *);
extern	int ResizeHeader(void);
extern	int HeaderEditor(int, int);
extern	void PaintHeader(int, int);
extern	int ArrangeHeader(void);
extern	int ToggleHeader(int);
extern	int HeaderLen(void);
extern	int UpdateHeader(void);
extern	int entry_line(int, int);
extern	int call_builder(struct headerentry *);
extern	int ShowPrompt(void);
extern	int packheader(void);
extern	int zotheader(void);

/* display.c */
extern	int vtinit(void);
extern	int vttidy(void);
extern	int update(void);
extern	int modeline(struct WINDOW *);
extern	int movecursor(int, int);
extern	int mlerase(void);
extern	int mlyesno(char *, int);
extern	int mlreply(char *, char *, int, int, KEYMENU *);
extern	int mlreplyd(char *, char *, int, int, KEYMENU *);
extern	void emlwrite(char *, void *);
extern	int mlwrite(char *, void *);
extern	int scrolldown(struct WINDOW *, int, int);
extern	int scrollup(struct WINDOW *, int, int);
extern	int pprints(int, int);
extern	int doton(int *, unsigned int *);
extern	int resize_pico(int, int);
extern	int zotdisplay(void);
extern	int pputc(int, int);
extern	int pputs(char *, int);
extern	int peeol(void);
extern	CELL *pscr(int, int);
extern	int pclear(int, int);
extern	int pinsert(CELL);
extern	int pdel(void);
extern	void wstripe(int, int, char *, int);
extern	int wkeyhelp(KEYMENU *);

/* file.c */
extern	int fileread(int, int);
extern	int insfile(int, int);
extern	int readin(char *, int);
extern	int filewrite(int, int);
extern	int filesave(int, int);
extern	int writeout(char *);
extern	char *writetmp(int, int);
extern	int filename(int, int);

/* fileio.c */
extern	int ffropen(char *);
extern	int ffputline(CELL *, int);
extern	int ffgetline(char *, int);

/* line.c */
extern	struct LINE *lalloc(int);
extern	int lfree(struct LINE *);
extern	int lchange(int);
extern	int linsert(int, int);
extern	int geninsert(LINE **, short *, LINE *, int, int, int);
extern	int lnewline(void);
extern	int ldelete(int, int);
extern	int kdelete(void);
extern	int kinsert(int);
extern	int kremove(int);

/* osdep.c */
extern	int ttopen(void);
extern	int ttclose(void);
extern	int ttisslow(void);
extern	int ttputc(int);
extern	int ttflush(void);
extern	int ttgetc(void);
extern	int ttgetwinsz(void);
extern	int GetKey(void);
extern	int alt_editor(int, int);
#ifdef	JOB_CONTROL
extern	int bktoshell(void);
#endif
extern	int fallowc(int);
extern	int fexist(char *, char *, long *);
extern	int isdir(char *, long *);
extern	char *gethomedir(int *);
extern	int homeless(char *);
extern	char *errstr(int);
extern	char *getfnames(char *, int *);
extern	void fioperr(int, char *);
extern	int fixpath(char *, int);
extern	int compresspath(char *, char *, int);
extern	void tmpname(char *);
extern	void makename(char *, char *);
extern	int copy(char *, char *);
extern	int ffwopen(char *);
extern	int ffclose(void);
extern	FILE *P_open(char *);
extern	int P_close(FILE *);
extern	int worthit(int *);
extern	int o_insert(char);
extern	int o_delete(void);
extern	int pico_new_mail(void);
extern	int time_to_check(void);
extern	int sstrcasecmp(const void *, const void *);
#ifdef	DOS
extern	int register_mfunc(unsigned long (*)(int,int,int),int,int,int,int);
extern	void clear_mfunc(void);
extern	unsigned long pico_mouse(int, int, int);
#endif

/* pico.c */
extern	int pico(struct pico_struct *);
extern	int edinit(char *);
extern	int execute(int, int, int);
extern	int quickexit(int, int);
extern	int abort_composer(int, int);
extern	int suspend_composer(int, int);
extern	int wquit(int, int);
extern	int ctrlg(int, int);
extern	int rdonly(void);
extern	int pico_help(char **, char *, int);
extern	int zotedit(void);

/* random.c */
extern	int setfillcol(int, int);
extern	int showcpos(int, int);
extern	int tab(int, int);
extern	int newline(int, int);
extern	int forwdel(int, int);
extern	int backdel(int, int);
extern	int killtext(int, int);
extern	int yank(int, int);

/* region.c */
extern	int killregion(int, int);
extern	int markregion(int);

/* search.c */
extern	int forwsearch(int, int);
extern	int readpattern(char *);
extern	int forscan(int *, char *, int);

/* spell.c */
#ifdef	SPELLER
extern	int spell(int, int);
#endif

/* window.c */
extern	int refresh(int, int);

/* word.c */
extern	int wrapword(void);
extern	int backword(int, int);
extern	int forwword(int, int);
extern	int fillpara(int, int);
extern	int inword(void);

#else
/* attach.c */
extern	int AskAttach();
extern	int SyncAttach();
extern	int intag();
extern	char *prettysz();
extern  int AttachError();

/* basic.c */
extern	int gotobol();
extern	int backchar();
extern	int gotoeol();
extern	int forwchar();
extern	int gotoline();
extern	int gotobob();
extern	int gotoeob();
extern	int forwline();
extern	int backline();
extern	int gotobop();
extern	int gotoeop();
extern	int forwpage();
extern	int backpage();
extern	int setmark();
extern	int swapmark();
extern	int setimark();
extern	int swapimark();

/* bind.c */
extern	int whelp();
extern	int wscrollw();
extern	int normal();
extern	int rebindfunc();

/* browse.c */
extern	int FileBrowse();
extern	int ResizeBrowser();

/* buffer.c */
extern	int anycb();
extern	struct BUFFER *bfind();
extern	int bclear();
extern	int packbuf();
extern	int readbuf();

/* composer.c */
extern	int InitMailHeader();
extern	int ResizeHeader();
extern	int HeaderEditor();
extern	void PaintHeader();
extern	int ArrangeHeader();
extern	int ToggleHeader();
extern	int HeaderLen();
extern	int UpdateHeader();
extern	int entry_line();
extern	int call_builder();
extern	int ShowPrompt();
extern	int packheader();
extern	int zotheader();

/* display.c */
extern	int vtinit();
extern	int vttidy();
extern	int update();
extern	int modeline();
extern	int movecursor();
extern	int mlerase();
extern	int mlyesno();
extern	int mlreply();
extern	int mlreplyd();
extern	void emlwrite();
extern	int mlwrite();
extern	int scrolldown();
extern	int scrollup();
extern	int pprints();
extern	int doton();
extern	int resize_pico();
extern	int zotdisplay();
extern	int pputc();
extern	int pputs();
extern	int peeol();
extern	CELL *pscr();
extern	int pclear();
extern	int pinsert();
extern	int pdel();
extern	void wstripe();
extern	int wkeyhelp();

/* file.c */
extern	int fileread();
extern	int insfile();
extern	int readin();
extern	int filewrite();
extern	int filesave();
extern	int writeout();
extern	char *writetmp();
extern	int filename();

/* fileio.c */
extern	int ffropen();
extern	int ffputline();
extern	int ffgetline();

/* line.c */
extern	struct LINE *lalloc();
extern	int lfree();
extern	int lchange();
extern	int linsert();
extern	int geninsert();
extern	int lnewline();
extern	int ldelete();
extern	int kdelete();
extern	int kinsert();
extern	int kremove();

/* osdep.c */
extern	int ttopen();
extern	int ttclose();
extern	int ttisslow();
extern	int ttputc();
extern	int ttflush();
extern	int ttgetc();
extern	int ttgetwinsz();
extern	int GetKey();
extern	int alt_editor();
#ifdef	JOB_CONTROL
extern	int bktoshell();
#endif
extern	int fallowc();
extern	int fexist();
extern	int isdir();
extern	char *gethomedir();
extern	int homeless();
extern	char *errstr();
extern	char *getfnames();
extern	void fioperr();
extern	int fixpath();
extern	int compresspath();
extern	void tmpname();
extern	void makename();
extern	int copy();
extern	int ffwopen();
extern	int ffclose();
extern	FILE *P_open();
extern	int P_close();
extern	int worthit();
extern	int o_insert();
extern	int o_delete();
extern	int pico_new_mail();
extern	int time_to_check();
extern	int sstrcasecmp();
#ifdef	DOS
extern	int register_mfunc();
extern	void clear_mfunc();
extern	unsigned long pico_mouse();
#endif

/* pico.c */
extern	int pico();
extern	int edinit();
extern	int execute();
extern	int quickexit();
extern	int abort_composer();
extern	int suspend_composer();
extern	int wquit();
extern	int ctrlg();
extern	int rdonly();
extern	int pico_help();
extern	int zotedit();

/* random.c */
extern	int setfillcol();
extern	int showcpos();
extern	int tab();
extern	int newline();
extern	int forwdel();
extern	int backdel();
extern	int killtext();
extern	int yank();

/* region.c */
extern	int killregion();
extern	int markregion();

/* search.c */
extern	int forwsearch();
extern	int readpattern();
extern	int forscan();

/* spell.c */
#ifdef	SPELLER
extern	int spell();
#endif

/* window.c */
extern	int refresh();

/* word.c */
extern	int wrapword();
extern	int backword();
extern	int forwword();
extern	int fillpara();
extern	int inword();

#endif	/* ANSI */
#endif	/* EFUNC_H */
                                                                                                                                                                                                                                                                                                                                                               DarkNET-1.08/pico.BBS/estruct.h                                                                        644   21270   21270        30545  5672463052  11312                                                                                                                                                                                                                                                                                                                                                                      /*
 * $Id: estruct.h,v 4.8 1994/08/03 03:04:39 mikes Exp $
 *
 * Program:	Struct and preprocessor definitions
 *
 *
 * Michael Seibel
 * Networks and Distributed Computing
 * Computing and Communications
 * University of Washington
 * Administration Builiding, AG-44
 * Seattle, Washington, 98195, USA
 * Internet: mikes@cac.washington.edu
 *
 * Please address all bugs and comments to "pine-bugs@cac.washington.edu"
 *
 * Copyright 1991-1994  University of Washington
 *
 *  Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee to the University of
 * Washington is hereby granted, provided that the above copyright notice
 * appears in all copies and that both the above copyright notice and this
 * permission notice appear in supporting documentation, and that the name
 * of the University of Washington not be used in advertising or publicity
 * pertaining to distribution of the software without specific, written
 * prior permission.  This software is made available "as is", and
 * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
 * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
 * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
 * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 * Pine and Pico are trademarks of the University of Washington.
 * No commercial use of these trademarks may be made without prior
 * written permission of the University of Washington.
 *
 */
/*	ESTRUCT:	Structure and preprocesser defined for
			MicroEMACS 3.6

			written by Dave G. Conroy
			modified by Steve Wilhite, George Jones
			greatly modified by Daniel Lawrence
*/

#ifndef	ESTRUCT_H
#define	ESTRUCT_H

/*	Configuration options	*/

#define CVMVAS  1	/* arguments to page forward/back in pages	*/
#define	NFWORD	1	/* forward word jumps to begining of word	*/
#define	TYPEAH	0	/* type ahead causes update to be skipped	*/
#define	REVSTA	1	/* Status line appears in reverse video		*/


/*	internal constants	*/

#define	NBINDS	50			/* max # of bound keys		*/
#define NFILEN  80                      /* # of bytes, file name        */
#define NBUFN   16                      /* # of bytes, buffer name      */
#define NLINE   256                     /* # of bytes, line             */
#define	NSTRING	256			/* # of bytes, string buffers	*/
#define NPAT    80                      /* # of bytes, pattern          */
#undef	HUGE
#define HUGE    1000                    /* Huge number                  */
#define	NLOCKS	100			/* max # of file locks active	*/

#define AGRAVE  0x60                    /* M- prefix,   Grave (LK201)   */
#define METACH  0x1B                    /* M- prefix,   Control-[, ESC  */
#define CTMECH  0x1C                    /* C-M- prefix, Control-\       */
#define EXITCH  0x1D                    /* Exit level,  Control-]       */
#define CTRLCH  0x1E                    /* C- prefix,   Control-^       */
#define HELPCH  0x1F                    /* Help key,    Control-_       */

#undef  CTRL
#define CTRL    0x0100                  /* Control flag, or'ed in       */
#define META    0x0200                  /* Meta flag, or'ed in          */
#define CTLX    0x0400                  /* ^X flag, or'ed in            */
#define	SPEC	0x0800			/* special key (arrow's, etc)	*/
#define	FUNC	0x1000			/* special key (function keys)	*/
#if	MSDOS
#define	SHFT	0x2000			/* shifted (for function keys)	*/
#define	ALTD	0x4000			/* ALT key...			*/
#endif

#define	QNORML	0x0000			/* Flag meaning no flag ;)	*/
#define	QFFILE	0x0001			/* Flag buffer for file neme	*/
#define	QDEFLT	0x0002			/* Flag to use default answer	*/
#define	QPAGE	0x0004			/* Flag to allow ^V and ^Y	*/

#undef	FALSE
#define FALSE   0                       /* False, no, bad, etc.         */
#undef	TRUE
#define TRUE    1                       /* True, yes, good, etc.        */
#define ABORT   2                       /* Death, ^G, abort, etc.       */

#define FIOSUC  0                       /* File I/O, success.           */
#define FIOFNF  1                       /* File I/O, file not found.    */
#define FIOEOF  2                       /* File I/O, end of file.       */
#define FIOERR  3                       /* File I/O, error.             */
#define	FIOLNG	4			/*line longer than allowed len	*/
#define	FIODIR	5			/* File is a directory		*/
#define	FIONWT	6			/* File lacks write permission	*/
#define	FIONRD	7			/* File lacks read permission	*/
#define	FIONEX	8			/* File lacks exec permission	*/


#define CFCPCN  0x0001                  /* Last command was C-P, C-N    */
#define CFKILL  0x0002                  /* Last command was a kill      */
#define CFFILL  0x0004                  /* Last command was a kill      */

#define	BELL	0x07			/* a bell character		*/
#define	TAB	0x09			/* a tab character		*/


/*
 * There is a window structure allocated for every active display window. The
 * windows are kept in a big list, in top to bottom screen order, with the
 * listhead at "wheadp". Each window contains its own values of dot and mark.
 * The flag field contains some bits that are set by commands to guide
 * redisplay; although this is a bit of a compromise in terms of decoupling,
 * the full blown redisplay is just too expensive to run for every input
 * character.
 */
typedef struct  WINDOW {
        struct  WINDOW *w_wndp;         /* Next window                  */
        struct  BUFFER *w_bufp;         /* Buffer displayed in window   */
        struct  LINE *w_linep;          /* Top line in the window       */
        struct  LINE *w_dotp;           /* Line containing "."          */
        short   w_doto;                 /* Byte offset for "."          */
        struct  LINE *w_markp;          /* Line containing "mark"       */
        short   w_marko;                /* Byte offset for "mark"       */
        struct  LINE *w_imarkp;         /* INTERNAL Line with "mark"    */
        short   w_imarko;               /* INTERNAL "mark" byte offset  */
        char    w_toprow;               /* Origin 0 top row of window   */
        char    w_ntrows;               /* # of rows of text in window  */
        char    w_force;                /* If NZ, forcing row.          */
        char    w_flag;                 /* Flags.                       */
}       WINDOW;

#define WFFORCE 0x01                    /* Window needs forced reframe  */
#define WFMOVE  0x02                    /* Movement from line to line   */
#define WFEDIT  0x04                    /* Editing within a line        */
#define WFHARD  0x08                    /* Better to a full display     */
#define WFMODE  0x10                    /* Update mode line.            */

/*
 * Text is kept in buffers. A buffer header, described below, exists for every
 * buffer in the system. The buffers are kept in a big list, so that commands
 * that search for a buffer by name can find the buffer header. There is a
 * safe store for the dot and mark in the header, but this is only valid if
 * the buffer is not being displayed (that is, if "b_nwnd" is 0). The text for
 * the buffer is kept in a circularly linked list of lines, with a pointer to
 * the header line in "b_linep".
 * 	Buffers may be "Inactive" which means the files accosiated with them
 * have not been read in yet. These get read in at "use buffer" time.
 */
typedef struct  BUFFER {
        struct  BUFFER *b_bufp;         /* Link to next BUFFER          */
        struct  LINE *b_dotp;           /* Link to "." LINE structure   */
        short   b_doto;                 /* Offset of "." in above LINE  */
        struct  LINE *b_markp;          /* The same as the above two,   */
        short   b_marko;                /* but for the "mark"           */
        struct  LINE *b_linep;          /* Link to the header LINE      */
	char	b_active;		/* window activated flag	*/
        char    b_nwnd;                 /* Count of windows on buffer   */
        char    b_flag;                 /* Flags                        */
	char	b_mode;			/* editor mode of this buffer	*/
        char    b_fname[NFILEN];        /* File name                    */
        char    b_bname[NBUFN];         /* Buffer name                  */
}       BUFFER;

#if TERMCAP || TERMINFO
struct  KBSTREE {
	char	value;
        int     func;              /* Routine to handle it         */
	struct	KBSTREE *down; 
	struct	KBSTREE	*left;
};
#endif

#define BFTEMP  0x01                    /* Internal temporary buffer    */
#define BFCHG   0x02                    /* Changed since last write     */


/*
 * The starting position of a region, and the size of the region in
 * characters, is kept in a region structure.  Used by the region commands.
 */
typedef struct  {
        struct  LINE *r_linep;          /* Origin LINE address.         */
        short   r_offset;               /* Origin LINE offset.          */
        long    r_size;                 /* Length in characters.        */
}       REGION;


/*
 * character and attribute pair.  The basic building block
 * of the editor.  The bitfields may have to be changed to a char
 * and short if there are problems...
 */
typedef	struct CELL {
	unsigned int c : 8;		/* Character value in cell      */
	unsigned int a : 8;		/* Its attributes               */
} CELL;


/*
 * All text is kept in circularly linked lists of "LINE" structures. These
 * begin at the header line (which is the blank line beyond the end of the
 * buffer). This line is pointed to by the "BUFFER". Each line contains a the
 * number of bytes in the line (the "used" size), the size of the text array,
 * and the text. The end of line is not stored as a byte; it's implied. Future
 * additions will include update hints, and a list of marks into the line.
 */
typedef struct  LINE {
        struct  LINE *l_fp;             /* Link to the next line        */
        struct  LINE *l_bp;             /* Link to the previous line    */
        short   l_size;                 /* Allocated size               */
        short   l_used;                 /* Used size                    */
        CELL    l_text[1];              /* A bunch of characters.       */
}       LINE;

#define lforw(lp)       ((lp)->l_fp)
#define lback(lp)       ((lp)->l_bp)
#define lgetc(lp, n)    ((lp)->l_text[(n)])
#define lputc(lp, n, c) ((lp)->l_text[(n)]=(c))
#define llength(lp)     ((lp)->l_used)

/*
 * The editor communicates with the display using a high level interface. A
 * "TERM" structure holds useful variables, and indirect pointers to routines
 * that do useful operations. The low level get and put routines are here too.
 * This lets a terminal, in addition to having non standard commands, have
 * funny get and put character code too. The calls might get changed to
 * "termp->t_field" style in the future, to make it possible to run more than
 * one terminal type.
 */
typedef struct  {
        short   t_nrow;                 /* Number of rows.              */
        short   t_ncol;                 /* Number of columns.           */
	short	t_margin;		/* min margin for extended lines*/
	short	t_scrsiz;		/* size of scroll region "	*/
        int     (*t_open)();            /* Open terminal at the start.  */
        int     (*t_close)();           /* Close terminal at end.       */
        int     (*t_getchar)();         /* Get character from keyboard. */
        int     (*t_putchar)();         /* Put character to display.    */
        int     (*t_flush)();           /* Flush output buffers.        */
        int     (*t_move)();            /* Move the cursor, origin 0.   */
        int     (*t_eeol)();            /* Erase to end of line.        */
        int     (*t_eeop)();            /* Erase to end of page.        */
        int     (*t_beep)();            /* Beep.                        */
	int	(*t_rev)();		/* set reverse video state	*/
}       TERM;

/*	structure for the table of initial key bindings		*/

typedef struct  {
        short   k_code;                 /* Key code                     */
        int     (*k_fp)();              /* Routine to handle it         */
}       KEYTAB;

/*      sturcture used for key menu painting         */

typedef struct {
	char	*name;			/* key to display  		*/
	char	*label;			/* function name key envokes	*/
}	KEYMENU;


#endif	/* ESTRUCT_H */
EOF  2                       /* File I/O, end of file.       */
#define FIOERR  3                       /* File I/O, error.             */
#define	FIOLNG	4DarkNET-1.08/pico.BBS/file.c                                                                           644   21270   21270        45471  5672464714  10545                                                                                                                                                                                                                                                                                                                                                                      #if	!defined(lint) && !defined(DOS)
static char rcsid[] = "$Id: file.c,v 4.14 1994/10/11 23:46:51 mikes Exp $";
#endif
/*
 * Program:	High level file input and output routines
 *
 *
 * Michael Seibel
 * Networks and Distributed Computing
 * Computing and Communications
 * University of Washington
 * Administration Builiding, AG-44
 * Seattle, Washington, 98195, USA
 * Internet: mikes@cac.washington.edu
 *
 * Please address all bugs and comments to "pine-bugs@cac.washington.edu"
 *
 * Copyright 1991-1994  University of Washington
 *
 *  Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee to the University of
 * Washington is hereby granted, provided that the above copyright notice
 * appears in all copies and that both the above copyright notice and this
 * permission notice appear in supporting documentation, and that the name
 * of the University of Washington not be used in advertising or publicity
 * pertaining to distribution of the software without specific, written
 * prior permission.  This software is made available "as is", and
 * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
 * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
 * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
 * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 * Pine and Pico are trademarks of the University of Washington.
 * No commercial use of these trademarks may be made without prior
 * written permission of the University of Washington.
 *
 */
/*
 * The routines in this file
 * handle the reading and writing of
 * disk files. All of details about the
 * reading and writing of the disk are
 * in "fileio.c".
 */
#include        <stdio.h>
#include	"osdep.h"
#include        "pico.h"
#include	"estruct.h"
#include        "edef.h"
#include        "efunc.h"


#ifdef	ANSI
    int ifile(char *);
#else
    int ifile();
#endif


/*
 * Read a file into the current
 * buffer. This is really easy; all you do it
 * find the name of the file, and call the standard
 * "read a file into the current buffer" code.
 * Bound to "C-X C-R".
 */
fileread(f, n)
int f, n;
{
        register int    s;
        char fname[NFILEN];

        if ((s=mlreply("Read file: ", fname, NFILEN, QNORML, NULL)) != TRUE)
                return(s);

	if(gmode&MDSCUR){
	    emlwrite("File reading disabled in secure mode",NULL);
	    return(0);
	}

	if (strlen(fname) == 0) {
	  emlwrite("No file name entered",NULL);
	  return(0);
	}

        return(readin(fname, TRUE));
}




static char *inshelptext[] = {
  "Insert File Help Text",
  " ",
  "\tType in a file name to have it inserted into your editing",
  "\tbuffer between the line that the cursor is currently on",
  "\tand the line directly below it.  You may abort this by ",
  "~\ttyping the ~F~3 (~^~C) key after exiting help.",
  " ",
  "End of Insert File Help",
  " ",
  NULL
};

static char *writehelp[] = {
  "Write File Help Text",
  " ",
  "\tType in a file name to have it written out, thus saving",
  "\tyour buffer, to a file.  You can abort this by typing ",
  "~\tthe ~F~3 (~^~C) key after exiting help.",
  " ",
  "End of Write File Help",
  " ",
  " ",
  NULL
};


/*
 * Insert a file into the current
 * buffer. This is really easy; all you do it
 * find the name of the file, and call the standard
 * "insert a file into the current buffer" code.
 * Bound to "C-X C-I".
 */
insfile(f, n)
int f, n;
{
        register int    s;
        char fname[NFILEN], dir[NFILEN];
        int	retval, bye = 0;
        char	*prompt;
	char     pbuf[40];
        register int	availen;
	KEYMENU menu_ins[2];

	prompt = pbuf;
	strcat(strcat(strcpy(prompt, "Insert file from "),
				    gmode&MDCURDIR ? "current" : "home"),
				    " directory: ");
        availen = term.t_ncol - strlen(prompt);

	if (curbp->b_mode&MDVIEW)	/* don't allow this command if	*/
		return(rdonly());	/* we are in read only mode	*/

        fname[0] = '\0';
	menu_ins[0].name  = "^T";
	menu_ins[0].label = "To Files";
	menu_ins[1].name  = NULL;
        while(!bye){
	    s = mlreplyd(prompt, fname, NFILEN, QDEFLT, menu_ins);
            if (s != TRUE){
		switch(s){
#ifdef DELETED
		  case (CTRL|'T'):
		    if(*fname && isdir(fname, NULL))
		      strcpy(dir, fname);
		    else
		      strcpy(dir, gmode&MDCURDIR ? "." : gethomedir(NULL));

		    fname[0] = '\0';
		    if((s = FileBrowse(dir, fname, NULL, FB_READ)) == 1){
			if(gmode&MDSCUR){
			    emlwrite("Can't insert file in restricted mode",
				     NULL);
			    sleep(2);
			}
			else{
			    strcat(dir, S_FILESEP);
			    strcat(dir, fname);
			    retval = ifile(dir);
			}
			bye++;
		    }
		    else
		      fname[0] = '\0';

		    refresh(FALSE, 1);
		    if(s != 1){
			update(); 		/* redraw on return */
			continue;
		    }
		    break;
#endif /* DELETED */
		  case HELPCH:
		    if(Pmaster){
			(*Pmaster->helper)(Pmaster->ins_help,
					   "Help for Insert File", 1);
		    }
		    else
		      pico_help(inshelptext, "Help for Insert File", 1);
		  case (CTRL|'L'):
		    refresh(FALSE, 1);
		    update();
		    continue;
		  default:
                    retval = s;
		    bye++;
		}
            }
            else{
		bye++;
		if(gmode&MDSCUR){
		    emlwrite("Can't insert file in restricted mode",NULL);
		}
		else{
		    fixpath(fname, NFILEN);
		    retval = ifile(fname);
		}
            }
        }
        curwp->w_flag |= WFMODE|WFHARD;

        return(retval);
}


/*
 * Read file "fname" into the current
 * buffer, blowing away any text found there. Called
 * by both the read and find commands. Return the final
 * status of the read. Also called by the mainline,
 * to read in a file specified on the command line as
 * an argument.
 */
readin(fname, lockfl)
char    fname[];	/* name of file to read */
int	lockfl;		/* check for file locks? */
{
        register LINE   *lp1;
        register LINE   *lp2;
        register int    i;
        register WINDOW *wp;
        register BUFFER *bp;
        register int    s;
        register int    nbytes;
        register int    nline;
	register char	*sptr;		/* pointer into filename string */
	int		lflag;		/* any lines longer than allowed? */
        char            line[NLINE];
	CELL            ac;

        bp = curbp;                             /* Cheap.               */
	ac.a = 0;
        if ((s=bclear(bp)) != TRUE)             /* Might be old.        */
                return (s);
        bp->b_flag &= ~(BFTEMP|BFCHG);
	/* removed 'C' mode detection */
        strcpy(bp->b_fname, fname);
        if ((s=ffropen(fname)) == FIOERR)       /* Hard file open.      */
                goto out;
        if (s == FIOFNF) {                      /* File not found.      */
                emlwrite("New file", NULL);
                goto out;
        }
        emlwrite("Reading file", NULL);
        nline = 0;
	lflag = FALSE;
        while ((s=ffgetline(line, NLINE)) == FIOSUC || s == FIOLNG) {
		if (s == FIOLNG)
			lflag = TRUE;
                nbytes = strlen(line);
                if ((lp1=lalloc(nbytes)) == NULL) {
                        s = FIOERR;             /* Keep message on the  */
                        break;                  /* display.             */
                }
                lp2 = lback(curbp->b_linep);
                lp2->l_fp = lp1;
                lp1->l_fp = curbp->b_linep;
                lp1->l_bp = lp2;
                curbp->b_linep->l_bp = lp1;
                for (i=0; i<nbytes; ++i){
		    ac.c = line[i];
		    lputc(lp1, i, ac);
		}
                ++nline;
        }
        ffclose();                              /* Ignore errors.       */
        if (s == FIOEOF) {                      /* Don't zap message!   */
                sprintf(line,"Read %d line%s", nline, (nline > 1) ? "s" : "");
                emlwrite(line, NULL);
        }
	if (lflag){
		sprintf(line,"Read %d line%s, Long lines wrapped",
			nline, (nline > 1) ? "s" : "");
                emlwrite(line, NULL);
        }
out:
        for (wp=wheadp; wp!=NULL; wp=wp->w_wndp) {
                if (wp->w_bufp == curbp) {
                        wp->w_linep = lforw(curbp->b_linep);
                        wp->w_dotp  = lforw(curbp->b_linep);
                        wp->w_doto  = 0;
                        wp->w_imarkp = NULL;
                        wp->w_imarko = 0;

			if(Pmaster)
			  wp->w_flag |= WFHARD;
			else
			  wp->w_flag |= WFMODE|WFHARD;
                }
        }
        if (s == FIOERR || s == FIOFNF)		/* False if error.      */
                return(FALSE);
        return (TRUE);
}


/*
 * Ask for a file name, and write the
 * contents of the current buffer to that file.
 * Update the remembered file name and clear the
 * buffer changed flag. This handling of file names
 * is different from the earlier versions, and
 * is more compatable with Gosling EMACS than
 * with ITS EMACS. Bound to "C-X C-W".
 */
filewrite(f, n)
int f, n;
{
        register WINDOW *wp;
        register int    s;
        char            fname[NFILEN];
	char		shows[128], *bufp;
	long		l;		/* length returned from fexist() */
	KEYMENU		menu_write[2];

	if(curbp->b_fname[0] != 0)
	  strcpy(fname, curbp->b_fname);
	else
	  fname[0] = '\0';

	menu_write[0].name  = "^T";
	menu_write[0].label = "To Files";
	menu_write[1].name  = NULL;
	for(;;){
#ifdef DELETED
	    s = mlreplyd("File Name to write : ", fname, NFILEN,
			 QDEFLT|QFFILE, menu_write);

	    fixpath(fname, NFILEN);		/*  fixup ~ in file name  */
#endif

	    switch(s){
	      case FALSE:
		if(strlen(fname) == 0)		/* no file name to write to */
		  return(s);
	      case TRUE:
		break;
#ifdef DELETED
	      case (CTRL|'T'):
		/* If we have a file name, break up into path and file name.*/
		*shows = 0;
		if(*fname) {
		    if (isdir (fname, NULL)) {
			/* fname is a directory. */
			strcpy (shows, fname);
			*fname = '\0';
		    }
		    else {
			/* Find right most seperator. */
			bufp = strrchr (fname, C_FILESEP);
			if (bufp != NULL) {
			    /* Copy directory part to 'shows', and file
			     * name part to front of 'fname'. */
			    *bufp = '\0';
			    strcpy (shows, fname);
			    memcpy (fname, bufp+1, strlen (bufp+1) + 1);
			}
		    }
		}

		/* If we did not end up with a valid directory, use home. */
		if (!isdir (shows, NULL))
		  strcpy(shows, gethomedir(NULL));

		s = FileBrowse(shows, fname, NULL, FB_SAVE);
		strcat(shows, S_FILESEP);
		strcat(shows, fname);
		strcpy(fname, shows);

		refresh(FALSE, 1);
		update();
		if(s == 1)
		  break;
		else
		  continue;
#endif /* DELETED */
	      case HELPCH:
		pico_help(writehelp, "", 1);
	      case (CTRL|'L'):
		refresh(FALSE, 1);
		update();
		continue;
	      default:
		return(s);
		break;
	    }

	    if(strcmp(fname, curbp->b_fname) == 0)
		break;

	    if((s=fexist(fname, "w", &l)) == FIOSUC){ /* exists.  overwrite? */

		sprintf(shows, "File \"%s\" exists, OVERWRITE", fname);
		if((s=mlyesno(shows, FALSE)) != TRUE){
		    if((bufp = strrchr(fname,C_FILESEP)) == NULL)
		      fname[0] = '\0';
		    else
		      *++bufp = '\0';
		}
		else
		  break;
	    }
	    else if(s == FIOFNF){
		break;				/* go write it */
	    }
	    else{				/* some error, can't write */
		fioperr(s, fname);
		return(ABORT);
	    }
	}
	emlwrite("Writing...", NULL);

        if ((s=writeout(fname)) != -1) {
	        if(!(gmode&MDTOOL)){
		    strcpy(curbp->b_fname, fname);
		    curbp->b_flag &= ~BFCHG;

		    wp = wheadp;                    /* Update mode lines.   */
		    while (wp != NULL) {
                        if (wp->w_bufp == curbp)
			    if((Pmaster && s == TRUE) || Pmaster == NULL)
                                wp->w_flag |= WFMODE;
                        wp = wp->w_wndp;
		    }
		}

		if(s > 1)
		  emlwrite("Wrote %d lines", (void *)s);
		else
		  emlwrite("Wrote 1 line", NULL);
        }
        return ((s == -1) ? FALSE : TRUE);
}



/*
 * Save the contents of the current
 * buffer in its associatd file. No nothing
 * if nothing has changed (this may be a bug, not a
 * feature). Error if there is no remembered file
 * name for the buffer. Bound to "C-X C-S". May
 * get called by "C-Z".
 */
filesave(f, n)
int f, n;
{
        register WINDOW *wp;
        register int    s;

	if (curbp->b_mode&MDVIEW)	/* don't allow this command if	*/
		return(rdonly());	/* we are in read only mode	*/
        if ((curbp->b_flag&BFCHG) == 0)         /* Return, no changes.  */
                return (TRUE);
        if (curbp->b_fname[0] == 0) {           /* Must have a name.    */
                emlwrite("No file name", NULL);
		sleep(2);
                return (FALSE);
        }

	emlwrite("Writing...", NULL);
        if ((s=writeout(curbp->b_fname)) != -1) {
                curbp->b_flag &= ~BFCHG;
                wp = wheadp;                    /* Update mode lines.   */
                while (wp != NULL) {
                        if (wp->w_bufp == curbp)
			  if(Pmaster == NULL)
                                wp->w_flag |= WFMODE;
                        wp = wp->w_wndp;
                }
		if(s > 1){
		    emlwrite("Wrote %d lines", (void *)s);
		}
		else
		  emlwrite("Wrote 1 line", NULL);
        }
        return (s);
}

/*
 * This function performs the details of file
 * writing. Uses the file management routines in the
 * "fileio.c" package. The number of lines written is
 * displayed. Sadly, it looks inside a LINE; provide
 * a macro for this. Most of the grief is error
 * checking of some sort.
 *
 * CHANGES: 1 Aug 91: returns number of lines written or -1 on error, MSS
 */
writeout(fn)
char    *fn;
{
        register int    s;
        register LINE   *lp;
        register int    nline;
	char     line[80];

        if ((s=ffwopen(fn)) != FIOSUC)          /* Open writes message. */
                return (-1);

        lp = lforw(curbp->b_linep);             /* First line.          */
        nline = 0;                              /* Number of lines.     */
        while (lp != curbp->b_linep) {
                if ((s=ffputline(&lp->l_text[0], llength(lp))) != FIOSUC)
                        break;
                ++nline;
                lp = lforw(lp);
        }
        if (s == FIOSUC) {                      /* No write error.      */
                s = ffclose();
        } else                                  /* Ignore close error   */
                ffclose();                      /* if a write error.    */
        if (s != FIOSUC)                        /* Some sort of error.  */
                return (-1);
        return (nline);
}


/*
 * writetmp - write a temporary file for message text, mindful of 
 *	      access restrictions and included text.  If n is true, include
 *	      lines that indicated included message text, otw forget them
 */
char *writetmp(f, n)
int f, n;
{
        static   char	fn[NFILEN];
        register int    s;
        register LINE   *lp;
        register int    nline;

	tmpname(fn);
	
        if ((s=ffwopen(fn)) != FIOSUC)          /* Open writes message. */
                return(NULL);

#ifndef _WINDOWS	/* For some reason, in windows changing the mode */
			/* _always_ causes the file close to fail. */
	chmod(fn, MODE_READONLY);		/* fix access rights */
#endif

        lp = lforw(curbp->b_linep);             /* First line.          */
        nline = 0;                              /* Number of lines.     */
        while (lp != curbp->b_linep) {
	    if(n || (!n && lp->l_text[0].c != '>'))
                if ((s=ffputline(&lp->l_text[0], llength(lp))) != FIOSUC)
                        break;
                ++nline;
                lp = lforw(lp);
        }
        if (s == FIOSUC) {                      /* No write error.      */
                s = ffclose();
        } else                                  /* Ignore close error   */
                ffclose();                      /* if a write error.    */
        if (s != FIOSUC){                       /* Some sort of error.  */
	        unlink(fn);
                return(NULL);
	}
        return(fn);
}


/*
 * Insert file "fname" into the current
 * buffer, Called by insert file command. Return the final
 * status of the read.
 */
ifile(fname)
char    fname[];
{
        register LINE   *lp0;
        register LINE   *lp1;
        register LINE   *lp2;
        register int    i;
        register BUFFER *bp;
        register int    s;
        register int    nbytes;
        register int    nline;
	int		lflag;		/* any lines longer than allowed? */
        char            line[NLINE];
        char     dbuf[128];
        register char    *dbufp;
	CELL            ac;

        bp = curbp;                             /* Cheap.               */
        bp->b_flag |= BFCHG;			/* we have changed	*/
	bp->b_flag &= ~BFTEMP;			/* and are not temporary*/
	ac.a = 0;
        if ((s=ffropen(fname)) == FIOERR)       /* Hard file open.      */
                goto out;
        if (s == FIOFNF) {                      /* File not found.      */
		emlwrite("No such file: %s",fname);
		return(FALSE);
        }
        emlwrite("Inserting %s.", fname);

	/* back up a line and save the mark here */
	curwp->w_dotp = lback(curwp->w_dotp);
	curwp->w_doto = 0;
	curwp->w_imarkp = curwp->w_dotp;
	curwp->w_imarko = 0;

        nline = 0;
	lflag = FALSE;
        while ((s=ffgetline(line, NLINE)) == FIOSUC || s == FIOLNG) {
		if (s == FIOLNG)
			lflag = TRUE;
                nbytes = strlen(line);
                if ((lp1=lalloc(nbytes)) == NULL) {
                        s = FIOERR;             /* Keep message on the  */
                        break;                  /* display.             */
                }
		lp0 = curwp->w_dotp;	/* line previous to insert */
		lp2 = lp0->l_fp;	/* line after insert */

		/* re-link new line between lp0 and lp2 */
		lp2->l_bp = lp1;
		lp0->l_fp = lp1;
		lp1->l_bp = lp0;
		lp1->l_fp = lp2;

		/* and advance and write out the current line */
		curwp->w_dotp = lp1;
                for (i=0; i<nbytes; ++i){
		    ac.c = line[i];
		    lputc(lp1, i, ac);
		}
                ++nline;
        }
        ffclose();                              /* Ignore errors.       */
	curwp->w_imarkp = lforw(curwp->w_imarkp);
        if (s == FIOEOF) {                      /* Don't zap message!   */
	        sprintf(dbuf,"Inserted %d line%s",nline,(nline>1) ? "s" : "");
		emlwrite(dbuf, NULL);
        }
	if (lflag) {
		sprintf(dbuf,"Inserted %d line%s, Long lines wrapped.",
			nline, (nline>1) ? "s" : "");
		emlwrite(dbuf, NULL);
        }
out:
	/* advance to the next line and mark the window for changes */
	curwp->w_flag |= WFHARD;

	/* copy window parameters back to the buffer structure */
	curbp->b_dotp = curwp->w_dotp;
	curbp->b_doto = curwp->w_doto;
	curbp->b_markp = curwp->w_imarkp;
	curbp->b_marko = curwp->w_imarko;

        if (s == FIOERR)                        /* False if error.      */
                return (FALSE);
        return (TRUE);
}
reak;
	    }

	    if(strcmp(fname, curbp->b_fname) == 0)
		break;

	    if((s=fexist(fname, "w", &l)) == FIOSUC){ /* exists.  overwrite? */

		sprintf(shows, "File \"%s\" exists, OVERWRITE", fname);DarkNET-1.08/pico.BBS/fileio.c                                                                         644   21270   21270        10076  5672463052  11060                                                                                                                                                                                                                                                                                                                                                                      #if	!defined(lint) && !defined(DOS)
static char rcsid[] = "$Id: fileio.c,v 4.5 1994/02/25 18:36:33 hubert Exp $";
#endif
/*
 * Program:	ASCII file reading routines
 *
 *
 * Michael Seibel
 * Networks and Distributed Computing
 * Computing and Communications
 * University of Washington
 * Administration Builiding, AG-44
 * Seattle, Washington, 98195, USA
 * Internet: mikes@cac.washington.edu
 *
 * Please address all bugs and comments to "pine-bugs@cac.washington.edu"
 *
 * Copyright 1991-1994  University of Washington
 *
 *  Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee to the University of
 * Washington is hereby granted, provided that the above copyright notice
 * appears in all copies and that both the above copyright notice and this
 * permission notice appear in supporting documentation, and that the name
 * of the University of Washington not be used in advertising or publicity
 * pertaining to distribution of the software without specific, written
 * prior permission.  This software is made available "as is", and
 * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
 * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
 * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
 * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 * Pine and Pico are trademarks of the University of Washington.
 * No commercial use of these trademarks may be made without prior
 * written permission of the University of Washington.
 *
 */
/*
 * The routines in this file read and write ASCII files from the disk. All of
 * the knowledge about files are here. A better message writing scheme should
 * be used.
 */
#include        <stdio.h>
#include	"estruct.h"
#include        "edef.h"


FILE    *ffp;                           /* File pointer, all functions. */

/*
 * Open a file for reading.
 */
ffropen(fn)
  char    *fn;
{
    if ((ffp=fopen(fn, "r")) == NULL)
      return (FIOFNF);

    return (FIOSUC);
}


/*
 * Write a line to the already opened file. The "buf" points to the buffer,
 * and the "nbuf" is its length, less the free newline. Return the status.
 * Check only at the newline.
 */
ffputline(buf, nbuf)
    CELL  buf[];
{
    register int    i;

    for (i = 0; i < nbuf; ++i)
       fputc(buf[i].c&0xFF, ffp);

    fputc('\n', ffp);

    if (ferror(ffp)) {
        emlwrite("Write I/O error");
        return (FIOERR);
    }

    return (FIOSUC);
}



/*
 * Read a line from a file, and store the bytes in the supplied buffer. The
 * "nbuf" is the length of the buffer. Complain about long lines and lines
 * at the end of the file that don't have a newline present. Check for I/O
 * errors too. Return status.
 */
ffgetline(buf, nbuf)
  register char   buf[];
{
    register int    c;
    register int    i;

    i = 0;

    while ((c = fgetc(ffp)) != EOF && c != '\n') {
	/*
	 * Don't blat the CR should the newline be CRLF and we're
	 * running on a unix system.  NOTE: this takes care of itself
	 * under DOS since the non-binary open turns newlines into '\n'.
	 */
	if(c == '\r'){
	    if((c = fgetc(ffp)) == EOF || c == '\n')
	      break;

	    if (i < nbuf-2)		/* Bare CR. Insert it and go on... */
	      buf[i++] = '\r';		/* else, we're up a creek */
	}

        if (i >= nbuf-2) {
	    buf[nbuf - 2] = c;	/* store last char read */
	    buf[nbuf - 1] = 0;	/* and terminate it */
            emlwrite("File has long line");
            return (FIOLNG);
        }
        buf[i++] = c;
    }

    if (c == EOF) {
        if (ferror(ffp)) {
            emlwrite("File read error");
            return (FIOERR);
        }

        if (i != 0)
	  emlwrite("File doesn't end with newline.  Adding one.", NULL);
	else
	  return (FIOEOF);
    }

    buf[i] = 0;
    return (FIOSUC);
}
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  DarkNET-1.08/pico.BBS/ibmpc.c                                                                          644   21270   21270        22171  5672463052  10702                                                                                                                                                                                                                                                                                                                                                                      /*
 *
 * $Id: ibmpc.c,v 4.8 1994/03/17 00:58:33 mikes Exp $
 *
 * Program:	IBM PC specific routine
 *
 *
 * Michael Seibel
 * Networks and Distributed Computing
 * Computing and Communications
 * University of Washington
 * Administration Builiding, AG-44
 * Seattle, Washington, 98195, USA
 * Internet: mikes@cac.washington.edu
 *
 * Please address all bugs and comments to "pine-bugs@cac.washington.edu"
 *
 * Copyright 1991-1994  University of Washington
 *
 *  Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee to the University of
 * Washington is hereby granted, provided that the above copyright notice
 * appears in all copies and that both the above copyright notice and this
 * permission notice appear in supporting documentation, and that the name
 * of the University of Washington not be used in advertising or publicity
 * pertaining to distribution of the software without specific, written
 * prior permission.  This software is made available "as is", and
 * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
 * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
 * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
 * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 * Pine and Pico are trademarks of the University of Washington.
 * No commercial use of these trademarks may be made without prior
 * written permission of the University of Washington.
 *
 */

/*
 * The routines in this file provide support for the IBM-PC and other
 * compatible terminals. It goes directly to the graphics RAM to do
 * screen output. It compiles into nothing if not an IBM-PC driver
 */

#include        <stdio.h>
#include	<conio.h>
#include	<time.h>
#include	"osdep.h"
#if     IBMPC
#define	termdef	1			/* don't define "term" external */
#include	"pico.h"
#include	"estruct.h"
#include        "efunc.h"
#include        "edef.h"

#ifdef	ANSI
    int  ibmmove(int, int);
    int  ibmeeol(void);
    int  ibmputc(int);
    int  ibmoutc(char);
    int  ibmeeop(void);
    int  ibmrev(int);
    void beep(unsigned int, unsigned int);
    int  cutebeep(void);
    int  ibmbeep(void);
    int  ibmopen(void);
    int  ibmclose(void);
#else
    int  ibmmove();
    int  ibmeeol();
    int  ibmputc();
    int  ibmoutc();
    int  ibmeeop();
    int  ibmrev();
    void beep();
    int  cutebeep();
    int  ibmbeep();
    int  ibmopen();
    int  ibmclose();
#endif


#define NROW    25              /* Screen size.                 */
#define NCOL    80              /* Edit if you want to.         */
#define	MARGIN	8		/* size of minimim margin and	*/
#define	SCRSIZ	64		/* scroll size for extended lines */
#define	NPAUSE	200		/* # times thru update to pause */
#define BEL     0x07            /* BEL character.               */
#define ESC     0x1B            /* ESC character.               */
#define	SPACE	32		/* space character		*/




#define	 SET_COLOR(fore,back)	((((back) & 0xf) << 4) | ((fore) & 0xf))

int	 nfcolor = 7;		/* current forground color */
int	 nbcolor = 1;		/* current background color */
int	 rfcolor = 0;		/* reverse forground color */
int	 rbcolor = 3;		/* reverse background color */
unsigned cattr;			/* current combined attribute */

static unsigned display_mode;	/*  */

/*
 * Standard terminal interface dispatch table. Most of the fields point into
 * "termio" code.
 */
TERM    term    = {
        NROW-1,
        NCOL,
	MARGIN,
	SCRSIZ,
        ibmopen,
        ibmclose,
        ttgetc,
	ibmputc,
        ttflush,
        ibmmove,
        ibmeeol,
        ibmeeop,
        ibmbeep,
	ibmrev
};


extern union REGS rg;


static char *colist[] = {
	"black",
	"blue",
	"green",
	"cyan",
	"red",
	"magenta",
	"yellow",
	"white",
        "BLACK",
        "BLUE",
        "GREEN",
        "CYAN",
        "RED",
        "MAGENTA",
        "YELLOW",
        "WHITE" };

/*
 * pico_setcolor - given the color name, return the color's value
 */
int
setcolor(s)
char *s;
{
    int i;

    for (i=0; i<16; i++)
      if (!strcmp(colist[i],s))
	return(i);

    return(7);
}


/*
 * pico_XXcolor() - each function sets a particular attribute
 */
pico_nfcolor(s)
char *s;
{
    nfcolor = setcolor(s);
}

pico_nbcolor(s)
char *s;
{
    nbcolor = setcolor(s);
}

pico_rfcolor(s)
char *s;
{
    rfcolor = setcolor(s);
}

pico_rbcolor(s)
char *s;
{
    rbcolor = setcolor(s);
}



/*
 * ibmmove - Use BIOS video services, function 2h to set cursor postion
 */
ibmmove(row, col)
int row, col;
{
    rg.h.ah = 2;		/* set cursor position function code */
    rg.h.bh = 0;		/* set screen page number */
    rg.h.dl = col;
    rg.h.dh = row;
    int86(BIOS_VIDEO, &rg, &rg);
}


/*
 * ibmeeol - erase to the end of the line
 */
ibmeeol()
{
    int col, row, page;

    /* find the current cursor position */
    rg.h.ah = 3;		/* read cursor position function code */
    int86(BIOS_VIDEO, &rg, &rg);
    page = rg.h.bh;
    col = rg.h.dl;		/* record current column */
    row = rg.h.dh;		/* and row */

    rg.h.ah = 0x09;		/* write char to screen with new attrs */
    rg.h.al = ' ';
    rg.h.bl = cattr;
    rg.h.bh = page;
    rg.x.cx = NCOL-col;
    int86(BIOS_VIDEO, &rg, &rg);
}


/*
 * ibmputc - put a character at the current position in the
 *	     current colors
 */
ibmputc(ch)
int ch;
{
    int col, row, page;

    rg.h.ah = 0x03;			/* first, get current position */
    int86(BIOS_VIDEO, &rg, &rg);
    page = rg.h.bh;
    row = rg.h.dh;
    col = rg.h.dl;
    
    if(ch == '\b'){
	if(col > 0)		/* advance the cursor */
	  ibmmove(row, --col);
    }
    else{
	rg.h.ah = 0x09;		/* write char to screen with new attrs */
	rg.h.al = ch;
	rg.h.bl = cattr;		/* inverting if needed */
	rg.h.bh = page;
	rg.x.cx = 1;		/* only once */
	int86(BIOS_VIDEO, &rg, &rg);

	if(col < 80)		/* advance the cursor */
	  ibmmove(row, ++col);
    }
}


/* 
 * ibmoutc - output a single character with the right attributes, but
 *           don't advance the cursor
 */
ibmoutc(c)
char c;
{
    rg.h.ah = 0x09;		/* write char to screen with new attrs */
    rg.h.al = c;
    rg.h.bl = cattr;	/* inverting if needed */
    rg.h.bh = 0;
    rg.x.cx = 1;		/* only once */
    int86(BIOS_VIDEO, &rg, &rg);
}


/*
 * ibmeeop - clear from cursor to end of page
 */
ibmeeop()
{
    rg.h.ah = 6;		/* scroll page up function code */
    rg.h.al = 0;		/* # lines to scroll (clear it) */
    rg.x.cx = 0;		/* upper left corner of scroll */
    rg.x.dx = (term.t_nrow << 8) | (term.t_ncol - 1);
    rg.h.bh = cattr;
    int86(BIOS_VIDEO, &rg, &rg);

    ibmmove(0, 0);
}


/*
 * ibmrev - change reverse video state
 */
ibmrev(state)
int state;
{
    cattr = (state) ? SET_COLOR(rfcolor, rbcolor)
		    : SET_COLOR(nfcolor, nbcolor);
}


/*
 * getrevstate - return the current reverse state
 */
getrevstate()
{
    return(cattr == SET_COLOR(rfcolor, rbcolor));
}


/* 
 * beep - make the speaker sing!
 */
void
beep(freq, dur)
unsigned freq, dur;
{
    unsigned oport;

    if(!freq)
	return;

    freq = (unsigned)(1193180 / freq);
    /* set up the timer */
    outp(0x43, 0xb6);			/* set timer channel 2 registers */
    outp(0x42, (0xff&freq));		/* low order byte of count */
    outp(0x42, (freq>>8));		/* hi order byte of count */

    /* make the sound */
    oport = inp(0x61);
    outp(0x61, oport | 0x03);
    ssleep((clock_t)((dur < 75) ? 75 : dur));
    outp(0x61, oport);
}


/*
 * cutebeep - make the speeker sing the way we want!
 */
cutebeep()
{
    beep(575, 50);
    ssleep((clock_t)25);
    beep(485, 90);
}


/*
 * ibmbeep - system beep...
 */
ibmbeep()
{
    cutebeep();
}


/*
 * enter_text_mode - get current video mode, saving to be restored 
 *                   later, then explicitly set 80 col text mode.
 *
 *     NOTE: this gets kind of weird.  Both pine and pico call this
 *           during initialization.  To make sure it's only invoked once
 *           it only responds if passed NULL which pico only does if not
 *           called from in pine, and pine does all the time.  make sense?
 *           thought not.
 */
void
enter_text_mode(p)
PICO *p;
{
    static int i = 0;

    if(!p && !i++){
	rg.h.ah = 0x0f;			/* save old mode */
	int86(BIOS_VIDEO, &rg, &rg);
	display_mode = rg.h.al;

	rg.h.ah = 0;			/* then set text mode */
	rg.h.al = 2;
	int86(BIOS_VIDEO, &rg, &rg);		/* video services */
    }
}


/*
 * exit_text_mode - leave text mode by restoring saved original 
 *                  video mode.
 */
void
exit_text_mode(p)
PICO *p;
{
    static int i = 0;

    if(!p && !i++){			/* called many, invoke once! */
	rg.h.ah = 0;			/* just restore old mode */
	rg.h.al = display_mode;
	int86(BIOS_VIDEO, &rg, &rg);
    }
}


/*
 * ibmopen - setup text mode and setup key labels...
 */
ibmopen()
{

    enter_text_mode(Pmaster);

    cattr    = SET_COLOR(nfcolor, nbcolor);
    revexist = TRUE;
    inschar  = delchar = 0;

    ttopen();
}


ibmclose()
{
#if	COLOR
    ibmfcol(7);
    ibmbcol(0);
#endif

    exit_text_mode(Pmaster);

    ttclose();
}
#endif
                                                                                                                                                                                                                                                                                                                                                                                                       DarkNET-1.08/pico.BBS/line.c                                                                           644   21270   21270        41337  5742635443  10547                                                                                                                                                                                                                                                                                                                                                                      #if	!defined(lint) && !defined(DOS)
static char rcsid[] = "$Id: line.c,v 4.6 1994/07/07 01:26:22 mikes Exp $";
#endif
/*
 * Program:	Line management routines
 *
 *
 * Michael Seibel
 * Networks and Distributed Computing
 * Computing and Communications
 * University of Washington
 * Administration Builiding, AG-44
 * Seattle, Washington, 98195, USA
 * Internet: mikes@cac.washington.edu
 *
 * Please address all bugs and comments to "pine-bugs@cac.washington.edu"
 *
 * Copyright 1991-1994  University of Washington
 *
 *  Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee to the University of
 * Washington is hereby granted, provided that the above copyright notice
 * appears in all copies and that both the above copyright notice and this
 * permission notice appear in supporting documentation, and that the name
 * of the University of Washington not be used in advertising or publicity
 * pertaining to distribution of the software without specific, written
 * prior permission.  This software is made available "as is", and
 * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
 * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
 * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
 * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 * Pine and Pico are trademarks of the University of Washington.
 * No commercial use of these trademarks may be made without prior
 * written permission of the University of Washington.
 *
 */
/*
 * The functions in this file are a general set of line management utilities.
 * They are the only routines that touch the text. They also touch the buffer
 * and window structures, to make sure that the necessary updating gets done.
 * There are routines in this file that handle the kill buffer too. It isn't
 * here for any good reason.
 *
 * Note that this code only updates the dot and mark values in the window list.
 * Since all the code acts on the current window, the buffer that we are
 * editing must be being displayed, which means that "b_nwnd" is non zero,
 * which means that the dot and mark values in the buffer headers are nonsense.
 */

#include        <stdio.h>
#include	"estruct.h"
#include	"pico.h"
#include        "edef.h"
#include        "efunc.h"


#ifdef	ANSI
    int insspace(int, int);
    int ldelnewline(void);
#else
    int insspace();
    int ldelnewline();
#endif


#define NBLOCK	16                      /* Line block chunk size        */
#define KBLOCK  1024                    /* Kill buffer block size       */

char    *kbufp  = NULL;                 /* Kill buffer data             */
unsigned kused   = 0;                   /* # of bytes used in KB        */
unsigned ksize   = 0;                   /* # of bytes allocated in KB   */

/*
 * This routine allocates a block of memory large enough to hold a LINE
 * containing "used" characters. The block is always rounded up a bit. Return
 * a pointer to the new block, or NULL if there isn't any memory left. Print a
 * message in the message line if no space.
 */
LINE    *
lalloc(used)
register int    used;
{
    register LINE   *lp;
    register int    size;
    char *malloc();

    size = (used+NBLOCK-1) & ~(NBLOCK-1);
    if (size == 0)                          /* Assume that an empty */
      size = NBLOCK;                  /* line is for type-in. */

    if ((lp = (LINE *) malloc(sizeof(LINE)+(size*sizeof(CELL)))) == NULL) {
	emlwrite("Cannot allocate %d bytes", (void *)size);
	return (NULL);
    }

    lp->l_size = size;
    lp->l_used = used;
    return (lp);
}

/*
 * Delete line "lp". Fix all of the links that might point at it (they are
 * moved to offset 0 of the next line. Unlink the line from whatever buffer it
 * might be in. Release the memory. The buffers are updated too; the magic
 * conditions described in the above comments don't hold here.
 */
lfree(lp)
register LINE   *lp;
{
    register BUFFER *bp;
    register WINDOW *wp;

    wp = wheadp;
    while (wp != NULL) {
	if (wp->w_linep == lp)
	  wp->w_linep = lp->l_fp;

	if (wp->w_dotp  == lp) {
	    wp->w_dotp  = lp->l_fp;
	    wp->w_doto  = 0;
	}

	if (wp->w_markp == lp) {
	    wp->w_markp = lp->l_fp;
	    wp->w_marko = 0;
	}

	wp = wp->w_wndp;
    }

    bp = bheadp;
    while (bp != NULL) {
	if (bp->b_nwnd == 0) {
	    if (bp->b_dotp  == lp) {
		bp->b_dotp = lp->l_fp;
		bp->b_doto = 0;
	    }

	    if (bp->b_markp == lp) {
		bp->b_markp = lp->l_fp;
		bp->b_marko = 0;
	    }
	}

	bp = bp->b_bufp;
    }

    lp->l_bp->l_fp = lp->l_fp;
    lp->l_fp->l_bp = lp->l_bp;
    free((char *) lp);
}


/*
 * This routine gets called when a character is changed in place in the current
 * buffer. It updates all of the required flags in the buffer and window
 * system. The flag used is passed as an argument; if the buffer is being
 * displayed in more than 1 window we change EDIT t HARD. Set MODE if the
 * mode line needs to be updated (the "*" has to be set).
 */
lchange(flag)
register int    flag;
{
    register WINDOW *wp;

    if (curbp->b_nwnd != 1)                 /* Ensure hard.         */
      flag = WFHARD;

    if ((curbp->b_flag&BFCHG) == 0) {       /* First change, so     */
	if(Pmaster == NULL)
	  flag |= WFMODE;                 /* update mode lines.   */
	curbp->b_flag |= BFCHG;
    }

    wp = wheadp;
    while (wp != NULL) {
	if (wp->w_bufp == curbp)
	  wp->w_flag |= flag;
	wp = wp->w_wndp;
    }
}


/*
 * insert spaces forward into text
 * default flag and numeric argument 
 */
insspace(f, n)	
int f, n;
{
    linsert(n, ' ');
    backchar(f, n);
}

/*
 * Insert "n" copies of the character "c" at the current location of dot. In
 * the easy case all that happens is the text is stored in the line. In the
 * hard case, the line has to be reallocated. When the window list is updated,
 * take special care; I screwed it up once. You always update dot in the
 * current window. You update mark, and a dot in another window, if it is
 * greater than the place where you did the insert. Return TRUE if all is
 * well, and FALSE on errors.
 */
linsert(n, c)
int n, c;
{
    register LINE   *dotp;
    register int     doto;
    register WINDOW *wp;

    if (curbp->b_mode&MDVIEW)	/* don't allow this command if	*/
      return(rdonly());	/* we are in read only mode	*/

    dotp = curwp->w_dotp;
    doto = curwp->w_doto;
    lchange(WFEDIT);

    if(!geninsert(&(curwp->w_dotp), &(curwp->w_doto), curbp->b_linep,
                  c, (curwp->w_markp) ? 1 : 0, n))
      return(FALSE);

    wp = wheadp;                            /* Update windows       */
    while (wp != NULL) {
	if (wp->w_linep == dotp)
	  wp->w_linep = wp->w_dotp;

	if (wp->w_imarkp == dotp) {	/* added for internal mark */
	    wp->w_imarkp = wp->w_dotp;
	    if (wp->w_imarko > doto)
	      wp->w_imarko += n;
	}

	if (wp->w_markp == dotp) {
	    wp->w_markp = dotp;
	    if (wp->w_marko > doto)
	      wp->w_marko += n;
	}
	wp = wp->w_wndp;
    }

    return (TRUE);
}


/*
 * geninsert - do the actual work of inserting a character into
 *             the list of lines.
 */
int
geninsert(dotp, doto, linep, c, attb, n)
LINE **dotp, *linep;
short *doto;
int    c, attb, n;
{
    register LINE  *lp1;
    register LINE  *lp2;
    register CELL  *cp1;
    register CELL  *cp2;
    CELL ac;

    ac.a = attb;
    if (*dotp == linep) {			/* At the end: special  */
	if (*doto != 0) {
	    emlwrite("Programmer botch: geninsert", NULL);
	    return (FALSE);
	}

	if ((lp1=lalloc(n)) == NULL)		/* Allocate new line    */
	  return (FALSE);

	lp2 = (*dotp)->l_bp;                /* Previous line        */
	lp2->l_fp = lp1;                /* Link in              */
	lp1->l_fp = *dotp;
	(*dotp)->l_bp = lp1;
	lp1->l_bp = lp2;
	*doto = n;
	*dotp = lp1;
	ac.c  = ((char)c & 0xff);
	cp1   = &(*dotp)->l_text[0];
        while(n--)
	  *cp1++ = ac;

	return (TRUE);
    }

    if ((*dotp)->l_used+n > (*dotp)->l_size) {      /* Hard: reallocate     */
	if ((lp1=lalloc((*dotp)->l_used+n)) == NULL)
	  return (FALSE);

	cp1 = &(*dotp)->l_text[0];
	cp2 = &lp1->l_text[0];
	while (cp1 != &(*dotp)->l_text[*doto])
	  *cp2++ = *cp1++;

	cp2 += n;
	while (cp1 != &(*dotp)->l_text[(*dotp)->l_used])
	  *cp2++ = *cp1++;

	(*dotp)->l_bp->l_fp = lp1;
	lp1->l_fp = (*dotp)->l_fp;
	(*dotp)->l_fp->l_bp = lp1;
	lp1->l_bp = (*dotp)->l_bp;

	/* global may be keeping track of mark/imark */
	if(wheadp){
	    if (wheadp->w_imarkp == *dotp)
	      wheadp->w_imarkp = lp1;

	    if (wheadp->w_markp == *dotp)
	      wheadp->w_markp = lp1;
	}

	free((char *) (*dotp));
	*dotp = lp1;
    } else {                                /* Easy: in place       */
	(*dotp)->l_used += n;
	cp2 = &(*dotp)->l_text[(*dotp)->l_used];
	cp1 = cp2-n;
	while (cp1 != &(*dotp)->l_text[*doto])
	  *--cp2 = *--cp1;
    }

    ac.c = ((char)c & 0xff);
    while(n--)					/* add the chars */
      (*dotp)->l_text[(*doto)++] = ac;
    return(TRUE);
}


/*
 * Insert a newline into the buffer at the current location of dot in the
 * current window. The funny ass-backwards way it does things is not a botch;
 * it just makes the last line in the file not a special case. Return TRUE if
 * everything works out and FALSE on error (memory allocation failure). The
 * update of dot and mark is a bit easier then in the above case, because the
 * split forces more updating.
 */
lnewline()
{
    register CELL   *cp1;
    register CELL   *cp2;
    register LINE   *lp1;
    register LINE   *lp2;
    register int    doto;
    register WINDOW *wp;

    if (curbp->b_mode&MDVIEW)	/* don't allow this command if	*/
      return(rdonly());	/* we are in read only mode	*/

    lchange(WFHARD);
    lp1  = curwp->w_dotp;                   /* Get the address and  */
    doto = curwp->w_doto;                   /* offset of "."        */
    if ((lp2=lalloc(doto)) == NULL)         /* New first half line  */
      return (FALSE);

    cp1 = &lp1->l_text[0];                  /* Shuffle text around  */
    cp2 = &lp2->l_text[0];
    while (cp1 != &lp1->l_text[doto])
      *cp2++ = *cp1++;

    cp2 = &lp1->l_text[0];
    while (cp1 != &lp1->l_text[lp1->l_used])
      *cp2++ = *cp1++;

    lp1->l_used -= doto;
    lp2->l_bp = lp1->l_bp;
    lp1->l_bp = lp2;
    lp2->l_bp->l_fp = lp2;
    lp2->l_fp = lp1;
    wp = wheadp;                            /* Windows              */
    while (wp != NULL) {
	if (wp->w_linep == lp1)
	  wp->w_linep = lp2;

	if (wp->w_dotp == lp1) {
	    if (wp->w_doto < doto)
	      wp->w_dotp = lp2;
	    else
	      wp->w_doto -= doto;
	}

	if (wp->w_imarkp == lp1) { 	     /* ADDED for internal mark */
	    if (wp->w_imarko < doto)
	      wp->w_imarkp = lp2;
	    else
	      wp->w_imarko -= doto;
	}

	if (wp->w_markp == lp1) {
	    if (wp->w_marko < doto)
	      wp->w_markp = lp2;
	    else
	      wp->w_marko -= doto;
	}
	wp = wp->w_wndp;
    }

    return (TRUE);
}


/*
 * This function deletes "n" bytes, starting at dot. It understands how do deal
 * with end of lines, etc. It returns TRUE if all of the characters were
 * deleted, and FALSE if they were not (because dot ran into the end of the
 * buffer. The "kflag" is TRUE if the text should be put in the kill buffer.
 */
ldelete(n, kflag)
int n, kflag;
{
    register CELL   *cp1;
    register CELL   *cp2;
    register LINE   *dotp;
    register int    doto;
    register int    chunk;
    register WINDOW *wp;

    if (curbp->b_mode&MDVIEW)	/* don't allow this command if	*/
      return(rdonly());	/* we are in read only mode	*/

    while (n != 0) {
	dotp = curwp->w_dotp;
	doto = curwp->w_doto;
	if (dotp == curbp->b_linep)     /* Hit end of buffer.   */
	  return (FALSE);
	chunk = dotp->l_used-doto;      /* Size of chunk.       */
	if (chunk > n)
	  chunk = n;
	if (chunk == 0) {               /* End of line, merge.  */
	    lchange(WFHARD);
	    if (ldelnewline() == FALSE
		|| (kflag!=FALSE && kinsert('\n')==FALSE))
	      return (FALSE);
	    --n;
	    continue;
	}

	lchange(WFEDIT);
	cp1 = &dotp->l_text[doto];      /* Scrunch text.        */
	cp2 = cp1 + chunk;
	if (kflag != FALSE) {           /* Kill?                */
	    while (cp1 != cp2) {
		if (kinsert(cp1->c) == FALSE)
		  return (FALSE);
		++cp1;
	    }
	    cp1 = &dotp->l_text[doto];
	}

	while (cp2 != &dotp->l_text[dotp->l_used])
	  *cp1++ = *cp2++;

	dotp->l_used -= chunk;
	wp = wheadp;                    /* Fix windows          */
	while (wp != NULL) {
	    if (wp->w_dotp==dotp && wp->w_doto>=doto) {
		wp->w_doto -= chunk;
		if (wp->w_doto < doto)
		  wp->w_doto = doto;
	    }

	    if (wp->w_markp==dotp && wp->w_marko>=doto) {
		wp->w_marko -= chunk;
		if (wp->w_marko < doto)
		  wp->w_marko = doto;
	    }

	    if (wp->w_imarkp==dotp && wp->w_imarko>=doto) {
		wp->w_imarko -= chunk;
		if (wp->w_imarko < doto)
		  wp->w_imarko = doto;
	    }

	    wp = wp->w_wndp;
	}
	n -= chunk;
    }

    return (TRUE);
}

/*
 * Delete a newline. Join the current line with the next line. If the next line
 * is the magic header line always return TRUE; merging the last line with the
 * header line can be thought of as always being a successful operation, even
 * if nothing is done, and this makes the kill buffer work "right". Easy cases
 * can be done by shuffling data around. Hard cases require that lines be moved
 * about in memory. Return FALSE on error and TRUE if all looks ok. Called by
 * "ldelete" only.
 */
ldelnewline()
{
    register CELL   *cp1;
    register CELL   *cp2;
    register LINE   *lp1;
    register LINE   *lp2;
    register LINE   *lp3;
    register WINDOW *wp;

    if (curbp->b_mode&MDVIEW)	/* don't allow this command if	*/
      return(rdonly());	/* we are in read only mode	*/

    lp1 = curwp->w_dotp;
    lp2 = lp1->l_fp;
    if (lp2 == curbp->b_linep) {            /* At the buffer end.   */
	if (lp1->l_used == 0)           /* Blank line.          */
	  lfree(lp1);
	return (TRUE);
    }

    if (lp2->l_used <= lp1->l_size-lp1->l_used) {
	cp1 = &lp1->l_text[lp1->l_used];
	cp2 = &lp2->l_text[0];
	while (cp2 != &lp2->l_text[lp2->l_used])
	  *cp1++ = *cp2++;

	wp = wheadp;
	while (wp != NULL) {
	    if (wp->w_linep == lp2)
	      wp->w_linep = lp1;
	    if (wp->w_dotp == lp2) {
		wp->w_dotp  = lp1;
		wp->w_doto += lp1->l_used;
	    }
	    if (wp->w_markp == lp2) {
		wp->w_markp  = lp1;
		wp->w_marko += lp1->l_used;
	    }
	    wp = wp->w_wndp;
	}
	lp1->l_used += lp2->l_used;
	lp1->l_fp = lp2->l_fp;
	lp2->l_fp->l_bp = lp1;
	free((char *) lp2);
	return (TRUE);
    }

    if ((lp3=lalloc(lp1->l_used+lp2->l_used)) == NULL)
      return (FALSE);

    cp1 = &lp1->l_text[0];
    cp2 = &lp3->l_text[0];
    while (cp1 != &lp1->l_text[lp1->l_used])
      *cp2++ = *cp1++;

    cp1 = &lp2->l_text[0];
    while (cp1 != &lp2->l_text[lp2->l_used])
      *cp2++ = *cp1++;

    lp1->l_bp->l_fp = lp3;
    lp3->l_fp = lp2->l_fp;
    lp2->l_fp->l_bp = lp3;
    lp3->l_bp = lp1->l_bp;
    wp = wheadp;
    while (wp != NULL) {
	if (wp->w_linep==lp1 || wp->w_linep==lp2)
	  wp->w_linep = lp3;
	if (wp->w_dotp == lp1)
	  wp->w_dotp  = lp3;
	else if (wp->w_dotp == lp2) {
	    wp->w_dotp  = lp3;
	    wp->w_doto += lp1->l_used;
	}
	if (wp->w_markp == lp1)
	  wp->w_markp  = lp3;
	else if (wp->w_markp == lp2) {
	    wp->w_markp  = lp3;
	    wp->w_marko += lp1->l_used;
	}
	wp = wp->w_wndp;
    }

    free((char *) lp1);
    free((char *) lp2);
    return (TRUE);
}

/*
 * Delete all of the text saved in the kill buffer. Called by commands when a
 * new kill context is being created. The kill buffer array is released, just
 * in case the buffer has grown to immense size. No errors.
 */
kdelete()
{
    if (kbufp != NULL) {
	free((char *) kbufp);
	kbufp = NULL;
	kused = 0;
	ksize = 0;
    }
}

/*
 * Insert a character to the kill buffer, enlarging the buffer if there isn't
 * any room. Always grow the buffer in chunks, on the assumption that if you
 * put something in the kill buffer you are going to put more stuff there too
 * later. Return TRUE if all is well, and FALSE on errors.
 */

kinsert(c)
    int c;
{
    register char   *nbufp;
    char *realloc();
    char *malloc();

    if (kused == ksize) {
	if (ksize == 0)	/* first time through? */
	  nbufp = malloc(KBLOCK);	/* alloc the first block */
	else	/* or re allocate a bigger block */
	  nbufp = realloc(kbufp, ksize+KBLOCK);
	if (nbufp == NULL)		/* abort if it fails */
	  return(FALSE);
	kbufp  = nbufp;		/* point our global at it */
	ksize += KBLOCK;	/* and adjust the size */
    }

    kbufp[kused++] = c;
    return (TRUE);
}


/*
 * This function gets characters from the kill buffer. If the character index
 * "n" is off the end, it returns "-1". This lets the caller just scan along
 * until it gets a "-1" back.
 */
kremove(n)
int n;
{
    if (n >= kused)
      return (-1);
    else
      return (kbufp[n] & 0xFF);
}
 else {                                /* Easy: in place       */
	(*dotp)->l_used += n;
	cp2 = &(*dotp)->l_text[(*dotp)->l_used];
	cp1 = cp2-n;
	while (cp1 != &(*dotp)->l_text[*doto])
	  *--cp2 = *--cp1;
    }

    ac.c = ((char)c & 0xff);
    while(n--)					/* add the chars */
      (*dDarkNET-1.08/pico.BBS/main.c                                                                           644   21270   21270        16326  5672472721  10544                                                                                                                                                                                                                                                                                                                                                                      #if	!defined(lint) && !defined(DOS)
static char rcsid[] = "$Id: main.c,v 4.12 1994/09/12 18:31:47 mikes Exp $";
#endif
/*
 * Program:	Main stand-alone Pine Composer routines
 *
 *
 * Michael Seibel
 * Networks and Distributed Computing
 * Computing and Communications
 * University of Washington
 * Administration Builiding, AG-44
 * Seattle, Washington, 98195, USA
 * Internet: mikes@cac.washington.edu
 *
 * Please address all bugs and comments to "pine-bugs@cac.washington.edu"
 *
 * Copyright 1991-1994  University of Washington
 *
 *  Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee to the University of
 * Washington is hereby granted, provided that the above copyright notice
 * appears in all copies and that both the above copyright notice and this
 * permission notice appear in supporting documentation, and that the name
 * of the University of Washington not be used in advertising or publicity
 * pertaining to distribution of the software without specific, written
 * prior permission.  This software is made available "as is", and
 * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
 * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
 * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
 * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 * Pine and Pico are trademarks of the University of Washington.
 * No commercial use of these trademarks may be made without prior
 * written permission of the University of Washington.
 *
 *
 * WEEMACS/PICO NOTES:
 *
 * 08 Jan 92 - removed PINE defines to simplify compiling
 *
 * 08 Apr 92 - removed PINE stub calls
 *
 */

#include        <stdio.h>
#include	<setjmp.h>
#include	"osdep.h"	/* operating system dependent includes */
#include	"pico.h"	/* pine composer definitions */
#include        "estruct.h"	/* global structures and defines */
#include	"efunc.h"	/* function declarations and sans name table */
#include	"edef.h"	/* global definitions */


/*
 * this isn't defined in the library, because it's a pine global
 * which we use for GetKey's timeout
 */
int	timeout = 0;			/* global timeout value		*/
int	lang = 0;

/*
 * function key mappings
 */
static int fkm[12][2] = {
    { F1,  (CTRL|'G')},
    { F2,  (CTRL|'X')},
    { F3,  (CTRL|'O')},
    { F4,  (CTRL|'J')},
    { F5,  (CTRL|'R')},
    { F6,  (CTRL|'W')},
    { F7,  (CTRL|'Y')},
    { F8,  (CTRL|'V')},
    { F9,  (CTRL|'K')},
    { F10, (CTRL|'U')},
    { F11, (CTRL|'C')},
#ifdef	SPELLER
    { F12, (CTRL|'T')}
#else
    { F12, (CTRL|'D')}
#endif
};


/*
 * main standalone pico routine
 */
#ifdef _WINDOWS
app_main (argc, argv)
#else
main(argc, argv)
#endif
char    *argv[];
{
    register int    c;
    register int    f;
    register int    n;
    register BUFFER *bp;
    register int    carg;		/* current arg to scan 		*/
    int	     viewflag = FALSE;		/* are we starting in view mode?*/
    int	     starton = 0;		/* where's dot to begin with?	*/
    char     bname[NBUFN];		/* buffer name of file to read	*/
    char    *clerr = NULL;		/* garbage on command line	*/
    
    Pmaster = NULL;			/* turn OFF composer functionality */

    /*
     * Read command line flags before initializing, otherwise, we never
     * know to init for f_keys...
     */
    carg = 1;
    while(carg < argc){
	if(argv[carg][0] == '-'){
	    switch(argv[carg][1]){
	      case 'k':
		lang = 1;		/* KOREAN */
		break;
	      case 'v':			/* -v for View File */
	      case 'V':
		viewflag = !viewflag;
		break;
	      case 'f':			/* -f for function key use */
		gmode ^= MDFKEY;
		break;
	      case 'n':			/* -n for new mail notification */
		timeout = 180;
		if(argv[carg][2] != '\0')
		  if((timeout = atoi(&argv[carg][2])) < 30)
		    timeout = 180;
		break;
	      case 't':			/* special shutdown mode */
		gmode ^= MDTOOL;
		rebindfunc(wquit, quickexit);
		break;
	      case 'z':			/* -z to suspend */
		gmode ^= MDSSPD;
		break;
	      case 'w':			/* -w turn off word wrap */
		gmode ^= MDWRAP;
		break;
#if	defined(DOS)
	      case 'c':			/* -c[nr][fb] colors */
		if(carg + 1 < argc){
		    if(argv[carg][2] == 'n'){
			if(argv[carg][3] == 'f')
			  pico_nfcolor(argv[++carg]);
			else if(argv[carg][3] == 'b')
			  pico_nbcolor(argv[++carg]);
		    }
		    else if(argv[carg][2] == 'r'){
			if(argv[carg][3] == 'f')
			  pico_rfcolor(argv[++carg]);
			else if(argv[carg][3] == 'b')
			  pico_rbcolor(argv[++carg]);
		    }
		}
		else{
		    clerr = "insufficient args for \"-c\"";
		    break;
		}
		break;
#endif
	      default:			/* huh? */
		clerr = argv[carg];
		break;
	    }
	    carg++;
	}
	else if(argv[carg][0] == '+'){	/* leading '+' is special */
	    starton = atoi(&argv[carg][1]);
	    carg++;
	}
	else				/* pick up file name later... */
	  break;
    }

    if(!vtinit())			/* Displays.            */
	exit(1);

    menu_init();
    bind_init();

    strcpy(bname, "main");		/* default buffer name */
    edinit(bname);			/* Buffers, windows.   */

    update();				/* let the user know we are here */

#ifdef	_WINDOWS
    mswin_allowpaste(MSWIN_PASTE_FULL);
    mswin_setclosetext("Use the ^X command to exit Pico.");
    mswin_allowexit (MSWIN_EXIT_SENDCHAR, NULL, 0x18);
#endif

#if	TERMCAP
    if(kpadseqs == NULL){		/* will arrow keys work ? */
	(*term.t_putchar)('\007');
	emlwrite("Warning: keypad keys may non-functional", NULL);
    }
#endif	/* TERMCAP */

    if(carg < argc){			/* Any file to edit? */

	makename(bname, argv[carg]);	/* set up a buffer for this file */

	bp = curbp;			/* read in first file */
	makename(bname, argv[carg]);
	strcpy(bp->b_bname, bname);
	strcpy(bp->b_fname, argv[carg]);
	if (readin(argv[carg], (viewflag==FALSE)) == ABORT) {
	    strcpy(bp->b_bname, "main");
	    strcpy(bp->b_fname, "");
	}
	bp->b_dotp = bp->b_linep;
	bp->b_doto = 0;

	if (viewflag)			/* set the view mode */
	  bp->b_mode |= MDVIEW;
    }

    /* setup to process commands */
    lastflag = 0;			/* Fake last flags.     */
    curbp->b_mode |= gmode;		/* and set default modes*/

    curwp->w_flag |= WFMODE;		/* and force an update	*/

    if(timeout)
      emlwrite("Checking for new mail every %D seconds", (void *)timeout);

    if(clerr){				/* post any errors on command line */
	if(mpresf)			/* show earlier message though! */
	  sleep(2);
	emlwrite("\007Unknown option: %s", clerr);
    }

    forwline(0, starton - 1);		/* move dot to specified line */

    while(1){

	update();			/* Fix up the screen    */

#if	defined(DOS) && defined(MOUSE)
	register_mfunc(pico_mouse, 2, 0,term.t_nrow-3,term.t_ncol);
#endif
	c = GetKey();	

#ifdef DELETED
	if(timeout && (c == NODATA || time_to_check())){
	    if(pico_new_mail())
	      emlwrite("You may possibly have new mail.", NULL);
	}
#endif

	if(c == NODATA)
	  continue;

	if(mpresf){			/* erase message line? */
	    if(mpresf++ > MESSDELAY)
	      mlerase();
	}

	f = FALSE;
	n = 1;

#if	defined(DOS) && defined(MOUSE)
	clear_mfunc();
#endif
	execute(normal(c, fkm, 1), f, n);	/* Do it.               */
    }
}
Distributed Computing
 * Computing and Communications
 * University of Washington
 * Administration Builiding, AG-44
 * Seattle, Washington, 98195, USA
 * Internet: mikes@cac.washington.edu
 *
 * Please address all bugs and comments to "pine-bugs@cac.washington.edu"
 *
 * Copyright 1991-1994  UnivDarkNET-1.08/pico.BBS/os_bsd.h                                                                         644   21270   21270         6163  5672463052  11051                                                                                                                                                                                                                                                                                                                                                                      #if	!defined(lint) && !defined(DOS)
static char rcsid_osh[] = "$Id: os_bsd.h,v 4.4 1994/09/22 21:59:15 mikes Exp $";
#endif
/*
 * Program:	Operating system dependent routines - 4.3 bsd
 *
 *
 * Michael Seibel
 * Networks and Distributed Computing
 * Computing and Communications
 * University of Washington
 * Administration Builiding, AG-44
 * Seattle, Washington, 98195, USA
 * Internet: mikes@cac.washington.edu
 *
 * Please address all bugs and comments to "pine-bugs@cac.washington.edu"
 *
 * Copyright 1991-1994  University of Washington
 *
 *  Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee to the University of
 * Washington is hereby granted, provided that the above copyright notice
 * appears in all copies and that both the above copyright notice and this
 * permission notice appear in supporting documentation, and that the name
 * of the University of Washington not be used in advertising or publicity
 * pertaining to distribution of the software without specific, written
 * prior permission.  This software is made available "as is", and
 * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
 * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
 * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
 * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 * Pine and Pico are trademarks of the University of Washington.
 * No commercial use of these trademarks may be made without prior
 * written permission of the University of Washington.
 *
 */

#ifndef	OSDEP_H
#define	OSDEP_H

#ifdef	dyn
#include	<strings.h>
#else
#include	<string.h>
#endif
#undef	CTRL
#include	<signal.h>
#include	<ctype.h>
#include	<sys/types.h>
#include	<sys/ioctl.h>		/* to get at the typeahead */
#include	<sys/stat.h>

/* Machine/OS definition			*/
#define V7      1                       /* V7 UN*X or Coherent or BSD4.2*/
#define JOB_CONTROL	1               /* OS has job control */

#ifdef	dyn
#define	strchr	index			/* Dynix doesn't know about strchr */
#define	strrchr	rindex
#endif	/* dyn */

extern struct KBSTREE *kpadseqs;
extern int kbseq();

#ifdef	termdef
#if	ANSI
#define NROW    25                      /* Screen size.                 */
#define NCOL    80                      /* Edit if you want to.         */
#endif
#else
#if	TERMCAP
extern struct KBSTREE *kpadseqs;
#endif	/* TERMCAP */
#endif

#ifdef	maindef
/*	possible names and paths of help files under different OSs	*/

char *pathname[] = {
	".picorc",
	"pico.hlp",
	"/usr/local/",
	"/usr/lib/",
	""
};

#define	NPNAMES	(sizeof(pathname)/sizeof(char *))

jmp_buf	got_hup;		/* stack environment to handle SIGHUP */
#endif

extern int errno;

/*
 * Mode passed chmod() to make tmp files exclusively user read/write-able
 */
#define	MODE_READONLY	(0600)

#endif	/* OSDEP_H */
                                                                                                                                                                                                                                                                                                                                                                                                             DarkNET-1.08/pico.BBS/os_dos.c                                                                         644   21270   21270        33645  5672463052  11106                                                                                                                                                                                                                                                                                                                                                                      /*
 * $Id: os_dos.c,v 4.25 1994/10/10 15:59:36 mikes Exp $
 *
 * Program:	Operating system dependent routines - MS DOS
 *
 *
 * Michael Seibel
 * Networks and Distributed Computing
 * Computing and Communications
 * University of Washington
 * Administration Builiding, AG-44
 * Seattle, Washington, 98195, USA
 * Internet: mikes@cac.washington.edu
 *
 * Please address all bugs and comments to "pine-bugs@cac.washington.edu"
 *
 * Copyright 1991-1994  University of Washington
 *
 *  Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee to the University of
 * Washington is hereby granted, provided that the above copyright notice
 * appears in all copies and that both the above copyright notice and this
 * permission notice appear in supporting documentation, and that the name
 * of the University of Washington not be used in advertising or publicity
 * pertaining to distribution of the software without specific, written
 * prior permission.  This software is made available "as is", and
 * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
 * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
 * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
 * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 * Pine and Pico are trademarks of the University of Washington.
 * No commercial use of these trademarks may be made without prior
 * written permission of the University of Washington.
 *
 *
 * Notes:
 *      - mouse support added (mss, 921215)
 *
 *  Portions of this code derived from MicroEMACS 3.10:
 *
 *	MSDOS.C:	Operating specific I/O and Spawning functions
 *			under the MS/PCDOS operating system
 *			for MicroEMACS 3.10
 *			(C)opyright 1988 by Daniel M. Lawrence
 *
 */

#include 	<stdio.h>
#include	<errno.h>
#include	<signal.h>
#include	<setjmp.h>
#include	<time.h>
#include	<fcntl.h>
#include	<io.h>
#include	<bios.h>

#include	"osdep.h"
#include	"estruct.h"
#include        "edef.h"
#include        "pico.h"
#include        "dos_gen.h"


/*
 * Internal functions...
 */
int   checkmouse();
void  invert_label(int, MENUITEM *);
int   enhanced_keybrd(void);
int   dont_interrupt(void);
int   interrupt_ok(void);
int   kbseq(int *);
int   specialkey(unsigned int);
void  do_alarm_signal(void);
void  do_hup_signal(void);
char *pfnexpand(char *, int);
int   ssleep(long);
int   sleep(int);


/*
 * Useful global def's
 */
static int    enhncd = 0;		/* keyboard of enhanced variety? */
union  REGS   rg;
struct SREGS  segreg;

static	int oldbut;			/* Previous state of mouse buttons */
static	unsigned short oldbreak;	/* Original state of break key */
static	char ptmpfile[128];		/* popen temp file */


/*
 * Include generic DOS/Windows routines
 */
#include	"dos_gen.c"


/*
 * DISable ctrl-break interruption
 */
dont_interrupt()
{
    /* get original value, to be restored later... */
    rg.h.ah = 0x33;		/* control-break check dos call */
    rg.h.al = 0;		/* get the current state */
    rg.h.dl = 0;		/* pre-set it OFF */
    intdos(&rg, &rg);		/* go for it! */
    oldbreak = rg.h.dl;
    /* kill the ctrl-break interupt */
    rg.h.ah = 0x33;		/* control-break check dos call */
    rg.h.al = 1;		/* set the current state */
    rg.h.dl = 0;		/* set it OFF */
    intdos(&rg, &rg);		/* go for it! */
}


/*
 * re-enable ctrl-break interruption
 */
interrupt_ok()
{
    /* restore the ctrl-break interupt */
    rg.h.ah = 0x33;		/* control-break check dos call */
    rg.h.al = 1;		/* set to new state */
    rg.h.dl = oldbreak;		/* set it to its original value */
    intdos(&rg, &rg);	/* go for it! */
}


/*
 * return true if an enhanced keyboard is present
 */
enhanced_keybrd()
{
    /* and check for extended keyboard */
    rg.h.ah = 0x05;
    rg.x.cx = 0xffff;
    int86(BIOS_KEYBRD, &rg, &rg);
    rg.h.ah = 0x10;
    int86(BIOS_KEYBRD, &rg, &rg);
    return(rg.x.ax == 0xffff);
}


/*
 * This function is called once to set up the terminal device streams.
 */
ttopen()
{
    dont_interrupt();			/* don't allow interrupt */
    enhncd = enhanced_keybrd();		/* check for extra keys */
#if	MOUSE
    init_mouse();
#else	/* !MOUSE */
    mexist = 0;
#endif	/* MOUSE */
    return(1);
}

#ifdef	MOUSE
/* 
 * init_mouse - check for and initialize mouse driver...
 */
init_mouse()
{
    long miaddr;		/* mouse interupt routine address */

    if(mexist)
      return(TRUE);

    /* check if the mouse drive exists first */
    rg.x.ax = 0x3533;		/* look at the interrupt 33 address */
    intdosx(&rg, &rg, &segreg);
    miaddr = (((long)segreg.es) << 16) + (long)rg.x.bx;
    if (miaddr == 0 || *(char *)miaddr == 0xcf) {
	mexist = FALSE;
	return(TRUE);
    }

    /* and then check for the mouse itself */
    rg.x.ax = 0;			/* mouse status flag */
    int86(BIOS_MOUSE, &rg, &rg);	/* check for the mouse interupt */
    mexist = (rg.x.ax != 0);
    nbuttons = rg.x.bx;

    if (mexist == FALSE)
	return(TRUE);

    /* if the mouse exists.. get it in the upper right corner */
    rg.x.ax = 4;			/* set mouse cursor position */
    rg.x.cx = (term.t_ncol/2) << 3;	/* Center of display... */
    rg.x.dx = 1 << 3;			/* Second line down */
    int86(BIOS_MOUSE, &rg, &rg);

    /* and set its attributes */
    rg.x.ax = 10;		/* set text cursor */
    rg.x.bx = 0;		/* software text cursor please */
    rg.x.cx = 0x77ff;	/* screen mask */
    rg.x.dx = 0x7700;	/* cursor mask */
    int86(BIOS_MOUSE, &rg, &rg);
    return(TRUE);
}


/*
 * mouseon - call made available for programs calling pico to turn ON the
 *           mouse cursor.
 */
void
mouseon()
{
    rg.x.ax = 1;			/* Show Cursor */
    int86(BIOS_MOUSE, &rg, &rg); 
}


/*
 * mouseon - call made available for programs calling pico to turn OFF the
 *           mouse cursor.
 */
void
mouseoff()
{
    rg.x.ax = 2;			/* Hide Cursor */
    int86(BIOS_MOUSE, &rg, &rg);
}
#endif


/*
 * This function gets called just before we go back home to the command
 * interpreter.
 */
ttclose()
{
    if(!Pmaster)
      interrupt_ok();

    return(1);
}


/*
 * Flush terminal buffer. Does real work where the terminal output is buffered
 * up. A no-operation on systems where byte at a time terminal I/O is done.
 */
ttflush()
{
    return(1);
}


/*
 * specialkey - return special key definition
 */
specialkey(kc)
unsigned  kc;
{
    switch(kc){
	case 0x3b00 : return(F1);
	case 0x3c00 : return(F2);
	case 0x3d00 : return(F3);
	case 0x3e00 : return(F4);
	case 0x3f00 : return(F5);
	case 0x4000 : return(F6);
	case 0x4100 : return(F7);
	case 0x4200 : return(F8);
	case 0x4300 : return(F9);
	case 0x4400 : return(F10);
	case 0x8500 : return(F11);
	case 0x8600 : return(F12);
	case 0x4800 : return(K_PAD_UP);
	case 0x5000 : return(K_PAD_DOWN);
	case 0x4b00 : return(K_PAD_LEFT);
	case 0x4d00 : return(K_PAD_RIGHT);
	case 0x4700 : return(K_PAD_HOME);
	case 0x4f00 : return(K_PAD_END);
	case 0x4900 : return(K_PAD_PREVPAGE);
	case 0x5100 : return(K_PAD_NEXTPAGE);
	case 0x5300 : return(K_PAD_DELETE);
	case 0x48e0 : return(K_PAD_UP);			/* grey key version */
	case 0x50e0 : return(K_PAD_DOWN);		/* grey key version */
	case 0x4be0 : return(K_PAD_LEFT);		/* grey key version */
	case 0x4de0 : return(K_PAD_RIGHT);		/* grey key version */
	case 0x47e0 : return(K_PAD_HOME);		/* grey key version */
	case 0x4fe0 : return(K_PAD_END);		/* grey key version */
	case 0x49e0 : return(K_PAD_PREVPAGE);		/* grey key version */
	case 0x51e0 : return(K_PAD_NEXTPAGE);		/* grey key version */
	case 0x53e0 : return(K_PAD_DELETE);		/* grey key version */
	default     : return(NODATA);
    }
}


/*
 * Read a character from the terminal, performing no editing and doing no echo
 * at all. Also mouse events are forced into the input stream here.
 */
ttgetc()
{
    return(_bios_keybrd(enhncd ? _NKEYBRD_READ : _KEYBRD_READ));
}


/*
 * ctrlkey - used to check if the key hit was a control key.
 */
ctrlkey()
{
    return(_bios_keybrd(enhncd ? _NKEYBRD_SHIFTSTATUS : _KEYBRD_SHIFTSTATUS)
            & 0x04);
}


/*
 * win_multiplex - give DOS in a window a shot at the CPU
 */
win_multiplex()
{
    rg.x.ax = 0x1680;
    int86(DOS_MULTIPLEX, &rg, &rg);
}


/*
 * Read in a key.
 * Do the standard keyboard preprocessing. Convert the keys to the internal
 * character set.  Resolves escape sequences and returns no-op if global
 * timeout value exceeded.
 */
GetKey()
{
    unsigned ch = 0, lch, intrupt = 0;
    long timein;

    if(mexist || timeout){
	timein = time(0L);
#ifdef	MOUSE
	if(mexist){
	    rg.x.ax = 1;			/* Show Cursor */
	    int86(BIOS_MOUSE, &rg, &rg); 
	}
#endif
	while(!_bios_keybrd(enhncd ? _NKEYBRD_READY : _KEYBRD_READY)){
#if	MOUSE
	    if(timeout && time(0L) >= timein+timeout){
		if(mexist){
		    rg.x.ax = 2;		/* Hide Cursor */
		    int86(BIOS_MOUSE, &rg, &rg);
		}
		return(NODATA);
	    }

	    if(checkmouse(&ch)){		/* something happen ?? */
		if(mexist){
		    rg.x.ax = 2;		/* Hide Cursor */
		    int86(BIOS_MOUSE, &rg, &rg);
		}
		curwp->w_flag |= WFHARD;
		return(ch);
	    }
#else
	    if(time(0L) >= timein+timeout)
	      return(NODATA);
#endif	/* MOUSE */

	    /*
	     * Surrender the CPU...
	     */
	    if(!intrupt++)
	      win_multiplex();
        }
#ifdef	MOUSE
	if(mexist){
	    rg.x.ax = 2;			/* Hide Cursor */
	    int86(BIOS_MOUSE, &rg, &rg);
	}
#endif	/* MOUSE */
    }

    ch  = (*term.t_getchar)();
    lch = (ch&0xff);
    return((lch && (lch != 0xe0 || !(ch & 0xff00))) 
            ? (lch < ' ') ? (CTRL|(lch + '@')) 
                          : (lch == ' ' && ctrlkey()) ? (CTRL|'@') : lch
            : specialkey(ch));
}


#if	MOUSE
/* 
 * checkmouse - look for mouse events in key menu and return 
 *              appropriate value.
 */
int
checkmouse(ch)
unsigned *ch;
{
    register int k;		/* current bit/button of mouse */
    int mcol;			/* current mouse column */
    int mrow;			/* current mouse row */
    int sstate;			/* current shift key status */
    int newbut;			/* new state of the mouse buttons */
    int rv = 0;

    if(!mexist)
	return(FALSE);

    /* check to see if any mouse buttons are different */
    rg.x.ax = 3;		/* Get button status and mouse position */
    int86(BIOS_MOUSE, &rg, &rg);
    newbut = rg.x.bx;
    mcol = rg.x.cx >> 3;
    mrow = (rg.x.dx >> 3);

    /* only notice changes */
    if (oldbut == newbut)
	return(FALSE);

    if (mcol < 0)		/* only on screen presses are legit! */
	mcol = 0;
    if (mrow < 0)
	mrow = 0;

    sstate = 0;			/* get the shift key status as well */
    rg.h.ah = 2;
    int86(BIOS_KEYBRD, &rg, &rg);
    sstate = rg.h.al;

    for (k=1; k != (1 << nbuttons); k = k<<1) {
	/* For each button on the mouse */
	if ((oldbut&k) != (newbut&k)) {
	    if(k == 1){
		static int oindex;
		int i = 0;

		if(newbut&k)			/* button down */
		  oindex = -1;

		if(mfunc.action && M_ACTIVE(mrow, mcol, &mfunc)){
		    unsigned long r;

		    if((r = (*mfunc.action)(newbut&k, mrow, mcol))&0xffff){
			*ch = (unsigned)((r>>16)&0xffff);
			rv  = TRUE;
		    }
		}
		else{
		    while(1){	/* see if we understand event */
			if(i >= 12){
			    i = -1;
			    break;
			}

			if(M_ACTIVE(mrow, mcol, &menuitems[i]))
			  break;

			i++;
		    }

		    if(newbut&k){			/* button down */
			oindex = i;			/* remember where */
			if(i != -1)			/* invert label */
			  invert_label(1, &menuitems[i]);
		    }
		    else{				/* button up */
			if(oindex != -1){
			    if(i == oindex){
				*ch = menuitems[i].val;
				rv = 1;
			    }
			}
		    }
		}

		if(!(newbut&k) && oindex != -1)
		  invert_label(0, &menuitems[oindex]);	/* restore label */
	    }

	    oldbut = newbut;
	    return(rv);
	}
    }

    return(FALSE);
}


/*
 * invert_label - highlight the label of the given menu item.
 */
void
invert_label(state, m)
int state;
MENUITEM *m;
{
    int i, j, r, c, p;
    char *lp;
    int old_state = getrevstate();

    if(m->val == mnoop)
      return;

    rg.h.ah = 3;				/* get cursor position */
    int86(BIOS_VIDEO, &rg, &rg);
    p = rg.h.bh;
    c = rg.h.dl;
    r = rg.h.dh;
    rg.x.ax = 2;				/* Hide Cursor */
    int86(BIOS_MOUSE, &rg, &rg);
    (*term.t_move)(m->tl.r, m->tl.c);
    (*term.t_rev)(state);
    for(i = m->tl.r; i <= m->br.r; i++)
      for(j = m->tl.c; j <= m->br.c; j++)
	if(i == m->lbl.r && j == m->lbl.c){	/* show label?? */
	    lp = m->label;
	    while(*lp && j++ < m->br.c)
	      (*term.t_putchar)(*lp++);

	    continue;
	}
	else
	  (*term.t_putchar)(' ');

    (*term.t_rev)(old_state);
    rg.h.ah = 2;
    rg.h.bh = p;
    rg.h.dh = r;
    rg.h.dl = c;
    int86(BIOS_VIDEO, &rg, &rg);		/* restore old position */
    rg.x.ax = 1;				/* Show Cursor */
    int86(BIOS_MOUSE, &rg, &rg);
}
#endif	/* MOUSE */


/*
 * alt_editor - fork off an alternate editor for mail message composition
 *
 *  NOTE: Not yet used under DOS
 */
alt_editor(f, n)
{
    return(-1);
}


/*
 *  bktoshell - suspend and wait to be woken up
 */
bktoshell()		/* suspend MicroEMACS and wait to wake up */
{
    int i;
    char *shell;

    (*term.t_move)(term.t_nrow, 0);
    if(system((shell = getenv("COMSPEC")) ? shell : "command") == -1)
      emlwrite("Error loading %s", shell ? shell : "COMMAND.COM");
    else
      refresh(0, 1);			/* redraw */
}


/*
 * P_open - run the given command in a sub-shell returning a file pointer
 *	    from which to read the output
 *
 * note:
 *	For OS's other than unix, you will have to rewrite this function.
 *	Hopefully it'll be easy to exec the command into a temporary file, 
 *	and return a file pointer to that opened file or something.
 */
FILE *P_open(c)
char *c;
{
    char cmdbuf[NLINE];
    sprintf(ptmpfile, tmpnam(NULL));
    sprintf(cmdbuf, "%s > %s", c, ptmpfile);
    if(system(cmdbuf) == -1){
	unlink(ptmpfile);
	return(NULL);
    }

    return(fopen(ptmpfile, "r"));
}



/*
 * P_close - close the given descriptor
 *
 */
P_close(fp)
FILE *fp;
{
    fclose(fp);			/* doesn't handle return codes */
    unlink(ptmpfile);
    return(0);;
}
ams calling pico to turn OFF the
 *           mouse cursor.
 */
void
mouseoff()
{
    rg.x.DarkNET-1.08/pico.BBS/os_dos.h                                                                         644   21270   21270         6020  5672503547  11062                                                                                                                                                                                                                                                                                                                                                                      /*
 * $Id: os_dos.h,v 4.10 1994/09/22 21:59:44 mikes Exp $
 *
 * Program:	Operating system dependent routines - Ultrix 4.1
 *
 *
 * Michael Seibel
 * Networks and Distributed Computing
 * Computing and Communications
 * University of Washington
 * Administration Builiding, AG-44
 * Seattle, Washington, 98195, USA
 * Internet: mikes@cac.washington.edu
 *
 * Please address all bugs and comments to "pine-bugs@cac.washington.edu"
 *
 * Copyright 1991-1994  University of Washington
 *
 *  Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee to the University of
 * Washington is hereby granted, provided that the above copyright notice
 * appears in all copies and that both the above copyright notice and this
 * permission notice appear in supporting documentation, and that the name
 * of the University of Washington not be used in advertising or publicity
 * pertaining to distribution of the software without specific, written
 * prior permission.  This software is made available "as is", and
 * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
 * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
 * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
 * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 * Pine and Pico are trademarks of the University of Washington.
 * No commercial use of these trademarks may be made without prior
 * written permission of the University of Washington.
 *
 */

#ifndef	OSDEP_H
#define	OSDEP_H

#include	<stdlib.h>
#include	<string.h>
#include	<dos.h>
#include	<direct.h>
#include	<search.h>
#undef	CTRL
#include	<ctype.h>
#include	<sys/types.h>
#include	<sys/stat.h>

/* define machine specifics */
#define	IBMPC	0

#ifdef	PCTCP
#define	sleep	_sleep
#define	_O_RDONLY O_RDONLY
#endif

/*
 *  IBM PC ROM BIOS Services used
 */
#define	BIOS_VIDEO	0x10
#define	BIOS_KEYBRD	0x16
#define	BIOS_MOUSE	0x33
#define	DOS_MULTIPLEX	0x2f


/*
 * type qsort expects
 */
#define	QSType	void
#define QcompType const void


/*
 * File name separators, char and string
 */
#define	C_FILESEP	'\\'
#define	S_FILESEP	"\\"


/*
 * What and where the tool that checks spelling is located.  If this is
 * undefined, then the spelling checker is not compiled into pico.
 */
#undef	SPELLER


/*
 * Mode passed chmod() to make tmp files exclusively user read/write-able
 */
#define	MODE_READONLY	(S_IREAD | S_IWRITE)


#ifdef	maindef
/*	possible names and paths of help files under different OSs	*/

char *pathname[] = {
	"picorc",
	"pico.hlp",
	"\\usr\\local\\",
	"\\usr\\lib\\",
	""
};

#define	NPNAMES	(sizeof(pathname)/sizeof(char *))

jmp_buf got_hup;

extern struct KBSTREE *kpadseqs = NULL;

#endif
#endif	/* !OSDEP_H */
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                DarkNET-1.08/pico.BBS/os_unix.h                                                                        644   21270   21270        11523  5672507175  11305                                                                                                                                                                                                                                                                                                                                                                      /*
 * $Id: os_unix.h,v 4.22 1994/10/10 23:29:12 mikes Exp $
 *
 * Program:	Operating system dependent routines - Ultrix 4.1
 *
 *
 * Michael Seibel
 * Networks and Distributed Computing
 * Computing and Communications
 * University of Washington
 * Administration Builiding, AG-44
 * Seattle, Washington, 98195, USA
 * Internet: mikes@cac.washington.edu
 *
 * Please address all bugs and comments to "pine-bugs@cac.washington.edu"
 *
 * Copyright 1991-1994  University of Washington
 *
 *  Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee to the University of
 * Washington is hereby granted, provided that the above copyright notice
 * appears in all copies and that both the above copyright notice and this
 * permission notice appear in supporting documentation, and that the name
 * of the University of Washington not be used in advertising or publicity
 * pertaining to distribution of the software without specific, written
 * prior permission.  This software is made available "as is", and
 * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
 * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
 * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
 * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 * Pine and Pico are trademarks of the University of Washington.
 * No commercial use of these trademarks may be made without prior
 * written permission of the University of Washington.
 *
 */

#ifndef	OSDEP_H
#define	OSDEP_H

#if	defined(dyn) || defined(AUX)
#include	<strings.h>
#else
#include	<string.h>
#endif

#undef	CTRL
#include	<signal.h>
#if	defined (ptx) || defined(sv4)
/* DYNIX/ptx signal semantics are AT&T/POSIX; the sigset() call sets
   the handler permanently, more like BSD signal(). */
#define signal(s,f) sigset (s, f)
#endif

/* signal handling is broken in the delivered SCO shells, so punt on 
   suspending the current session */
#if defined(sco) && defined(SIGTSTP)
#undef SIGTSTP
#endif

#include	<ctype.h>
#include	<sys/types.h>

#if	defined(POSIX) || defined(aix) || defined(COHERENT) || defined(isc) || defined(sv3)
#include	<dirent.h>
#else
#include	<sys/dir.h>
#endif

#if	defined(sco)
#include	<sys/stream.h>
#include	<sys/ptem.h>
#endif

#include	<sys/stat.h>

/*
 * 3b1 definition requirements
 */
#if	defined(ct)
#define opendir(dn)	fopen(dn, "r")
#define closedir(dirp)	fclose(dirp)
typedef struct
	{
	int	dd_fd;			/* file descriptor */
	int	dd_loc;			/* offset in block */
	int	dd_size;		/* amount of valid data */
	char	*dd_buf;		/* directory block */
	}	DIR;			/* stream data from opendir() */
#endif

/* Machine/OS definition			*/
#if	defined(ptx) || defined(sgi) || defined(sv4)
#define TERMINFO	1               /* Use TERMINFO                  */
#else
#define TERMCAP		1               /* Use TERMCAP                  */
#endif

/*
 * type qsort() expects
 */
#if	defined(nxt) || defined(neb)
#define	QSType	  void
#define QcompType const void
#else
#define	QSType	  int
#define QcompType void
#endif

/*
 * File name separator, as a char and string
 */
#define	C_FILESEP	'/'
#define	S_FILESEP	"/"

/*
 * Place where mail gets delivered (for pico's new mail checking)
 */
#if	defined(sv3) || defined(ct) || defined(isc) || defined(AUX) || defined(sgi)
#define	MAILDIR		"/usr/mail"
#else
#define	MAILDIR		"/usr/spool/mail"
#endif


/*
 * What and where the tool that checks spelling is located.  If this is
 * undefined, then the spelling checker is not compiled into pico.
 */
#ifdef DELETED
#if	defined(COHERENT) || defined(AUX)
#define SPELLER         "/bin/spell"
#else
#define	SPELLER		"/usr/bin/spell"
#endif
#endif

/* memcpy() is no good for overlapping blocks.  If that's a problem, use
 * the memmove() in ../c-client
 */
#if	defined (ptx) || defined(sv4) || defined(sco) || defined(isc) || defined(AUX)
#define bcopy(a,b,s) memcpy (b, a, s)
#endif

/* memmove() is a built-in for AIX 3.2 xlc. */
#if	defined (a32) || defined(COHERENT)
#define bcopy(a,b,s) memmove (b, a, s)
#endif

#if	defined(dyn)
#define	strchr	index			/* Dynix doesn't know about strchr */
#define	strrchr	rindex
#endif	/* dyn */

extern struct KBSTREE *kpadseqs;
extern int kbseq();

#if	TERMCAP
extern struct KBSTREE *kpadseqs;
#endif	/* TERMCAP */

#if	defined(bsd) || defined(nxt) || defined(dyn)
#ifdef	ANSI
extern char *getcwd(char *, int);
#else
extern char *getcwd();
#endif
#endif

#if	defined(COHERENT)
#define void char
#endif

/*
 * Mode passed chmod() to make tmp files exclusively user read/write-able
 */
#define	MODE_READONLY	(0600)

#endif	/* OSDEP_H */
                                                                                                                                                                             DarkNET-1.08/pico.BBS/pico.c                                                                           644   21270   21270        52331  5672463052  10543                                                                                                                                                                                                                                                                                                                                                                      #if	!defined(lint) && !defined(DOS)
static char rcsid[] = "$Id: pico.c,v 4.32 1994/08/18 00:24:40 mikes Exp $";
#endif
/*
 * Program:	Main Pine Composer routines
 *
 *
 * Michael Seibel
 * Networks and Distributed Computing
 * Computing and Communications
 * University of Washington
 * Administration Builiding, AG-44
 * Seattle, Washington, 98195, USA
 * Internet: mikes@cac.washington.edu
 *
 * Please address all bugs and comments to "pine-bugs@cac.washington.edu"
 *
 * Copyright 1991-1994  University of Washington
 *
 *  Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee to the University of
 * Washington is hereby granted, provided that the above copyright notice
 * appears in all copies and that both the above copyright notice and this
 * permission notice appear in supporting documentation, and that the name
 * of the University of Washington not be used in advertising or publicity
 * pertaining to distribution of the software without specific, written
 * prior permission.  This software is made available "as is", and
 * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
 * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
 * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
 * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 * Pine and Pico are trademarks of the University of Washington.
 * No commercial use of these trademarks may be made without prior
 * written permission of the University of Washington.
 *
 *
 * WEEMACS/PICO NOTES:
 *
 * 01 Nov 89 - MicroEmacs 3.6 vastly pared down and becomes a function call 
 * 	       weemacs() and plugged into the Pine mailer.  Lots of unused
 *	       MicroEmacs code laying around.
 *
 * 17 Jan 90 - weemacs() became weemacs() the composer.  Header editing
 *	       functions added.
 *
 * 09 Sep 91 - weemacs() renamed pico() for the PIne COmposer.
 *
 */


/*
 * This program is in public domain; written by Dave G. Conroy.
 * This file contains the main driving routine, and some keyboard processing
 * code, for the MicroEMACS screen editor.
 *
 * REVISION HISTORY:
 *
 * 1.0  Steve Wilhite, 30-Nov-85
 *      - Removed the old LK201 and VT100 logic. Added code to support the
 *        DEC Rainbow keyboard (which is a LK201 layout) using the the Level
 *        1 Console In ROM INT. See "rainbow.h" for the function key defs
 *      Steve Wilhite, 1-Dec-85
 *      - massive cleanup on code in display.c and search.c
 *
 * 2.0  George Jones, 12-Dec-85
 *      - Ported to Amiga.
 *
 * 3.0  Daniel Lawrence, 29-Dec-85
 *	16-apr-86
 *	- updated documentation and froze development for 3.6 net release
 */

#include        <stdio.h>
#include	<setjmp.h>

/* make global definitions not external */
#define	maindef

#include	"osdep.h"	/* operating system dependent includes */
#include	"pico.h"	/* PIne COmposer definitions */
#include        "estruct.h"	/* global structures and defines */
#include	"efunc.h"	/* function declarations and name table	*/
#include	"edef.h"	/* global definitions */
#include	"ebind.h"	/* default key bindings */


#ifdef	ANSI
    int  func_init(void);
    void breplace(void *);
    int  insline(LINE **, short *);
#else
    int  func_init();
    void breplace();
    int  insline();
#endif


/*
 * function key mappings
 */
static int pfkm[12][2] = {
    { F1,  (CTRL|'G')},
    { F2,  (CTRL|'C')},
    { F3,  (CTRL|'X')},
    { F4,  (CTRL|'J')},
    { F5,  (CTRL|'R')},
    { F6,  (CTRL|'W')},
    { F7,  (CTRL|'Y')},
    { F8,  (CTRL|'V')},
    { F9,  (CTRL|'K')},
    { F10, (CTRL|'U')},
    { F11, (CTRL|'O')},
#ifdef	SPELLER
    { F12, (CTRL|'T')}
#else
    { F12, (CTRL|'D')}
#endif
};


/*
 * flag for the various functions in pico() to set when ready
 * for pico() to return...
 */
int      pico_all_done = 0;
jmp_buf  finstate;
char    *pico_anchor = NULL;
extern struct headerentry *headents;

/*
 * pico - the main routine for Pine's composer.
 *
 */
pico(pm)
PICO *pm;
{
    register int    c;
    register int    f;
    register int    n;
    int      i;
    char     bname[NBUFN];		/* buffer name of file to read */
    extern   struct on_display ods;

    Pmaster       = pm;
    gmode	  = MDWRAP;
    gmode        |= pm->pine_flags;/* high 4 bits rsv'd by pine composer */
    pico_all_done = 0;

    if(!vtinit())			/* Init Displays.      */
      return(COMP_CANCEL);

    strcpy(bname, "main");		/* default buffer name */
    edinit(bname);			/* Buffers, windows.   */

    InitMailHeader(pm);			/* init mail header structure */
    (*Pmaster->clearcur)();

    /* setup to process commands */
    lastflag = 0;			/* Fake last flags.     */
    curbp->b_mode |= gmode;		/* and set default modes*/

    pico_anchor = (char *)malloc((strlen(Pmaster->pine_anchor) + 1)
				 * sizeof(char));
    if(pico_anchor)
      strcpy(pico_anchor, Pmaster->pine_anchor);

    if(pm->msgtext)
      breplace(pm->msgtext);

#ifdef	_WINDOWS
    mswin_allowpaste(MSWIN_PASTE_FULL);
#endif

    pico_all_done = setjmp(finstate);	/* jump out of HUP handler ? */

    if(gmode&MDALTNOW){
	while(1){
	    if((pm->pine_flags & P_BODY) /* begin editing the header? */
	       && alt_editor(0, 1) < 0)	/* magically enter user's editor */
	      break;			/* if problem, drop into pico */

	    update();			/* paint screen, n' start editing... */
	    HeaderEditor((pm->pine_flags & (P_HEADEND|P_BODY)) ? 2 : 0, 0);
	    if(pico_all_done)
	      break;

	    pm->pine_flags |= P_BODY;	/* make sure we enter alt ed next */
	}
    }
    else if(!pico_all_done){
	if(pm->pine_flags & P_BODY){	/* begin editing the header? */
	    ArrangeHeader();		/* line up pointers */
	}
	else{
	    update();			/* paint screen, */
	    HeaderEditor((pm->pine_flags & P_HEADEND) ? 2 : 0, 0);
	}
    }

    while(1){
	if(pico_all_done){
#ifdef	_WINDOWS
	    mswin_allowpaste(MSWIN_PASTE_DISABLE);
#endif
	    c = anycb() ? BUF_CHANGED : 0;
	    switch(pico_all_done){	/* prepare for/handle final events */
	      case COMP_EXIT :		/* already confirmed */
		packheader();
		c |= COMP_EXIT;
		break;

	      case COMP_CANCEL :	/* also already confirmed */
		c = COMP_CANCEL;
		break;

	      case COMP_GOTHUP:
		/* 
		 * pack up and let caller know that we've received a SIGHUP
		 */
		if(ComposerEditing)		/* expand addr if needed */
		  call_builder(&headents[ods.cur_e]);

		packheader();
		c |= COMP_GOTHUP;
		break;

	      case COMP_SUSPEND :
	      default:			/* safest if internal error */
		packheader();
		c |= COMP_SUSPEND;
		break;
	    }

	    free(pico_anchor);
	    vttidy();			/* clean up tty modes */
	    zotdisplay();		/* blast display buffers */
	    zotedit();
	    return(c);
	}
	update();			/* Fix up the screen    */

#if	defined(DOS) && defined(MOUSE)
	register_mfunc(pico_mouse, 2, 0, term.t_nrow-3, term.t_ncol);
#endif
	c = GetKey();	

	if(c == NODATA || time_to_check()){	/* new mail ? */
	    if((*Pmaster->newmail)(&i, 0, c == NODATA ? 0 : 2) >= 0){
		mlerase();
		(*Pmaster->showmsg)(c);
		mpresf = 1;
	    }

	    if(i || mpresf){		/* let em know cursor moved */
		movecursor(0, 0);
		(*Pmaster->clearcur)();
	    }
	}

	if(c == NODATA)		/* no op, getkey timed out */
	  continue;

	if (mpresf != FALSE) {		/* message stay around only  */
	    if (mpresf++ > NMMESSDELAY)	/* so long! */
	      mlerase();
	}

	f = FALSE;			/* vestigial */
	n = 1;
	
#if	defined(DOS) && defined(MOUSE)
	clear_mfunc();
#endif
	execute(normal(c, pfkm, 2), f, n);	/* Do it.               */
    }
}

/*
 * Initialize all of the buffers and windows. The buffer name is passed down
 * as an argument, because the main routine may have been told to read in a
 * file by default, and we want the buffer name to be right.
 */

/*
 * For the pine composer, we don't want to take over the whole screen
 * for editing.  the first some odd lines are to be used for message 
 * header information editing.
 */
edinit(bname)
char    bname[];
{
    register BUFFER *bp;
    register WINDOW *wp;

    if(Pmaster)
      func_init();

    bp = bfind(bname, TRUE, 0);             /* First buffer         */
    wp = (WINDOW *) malloc(sizeof(WINDOW)); /* First window         */

    if (bp==NULL || wp==NULL){
	if(Pmaster)
	  return(0);
	else
	  exit(1);
    }

    curbp  = bp;                            /* Make this current    */
    wheadp = wp;
    curwp  = wp;
    wp->w_wndp  = NULL;                     /* Initialize window    */
    wp->w_bufp  = bp;
    bp->b_nwnd  = 1;                        /* Displayed.           */
    wp->w_linep = bp->b_linep;
    wp->w_dotp  = bp->b_linep;
    wp->w_doto  = 0;
    wp->w_markp = NULL;
    wp->w_marko = 0;

    if(Pmaster){
	wp->w_toprow = COMPOSER_TOP_LINE;
	wp->w_ntrows = term.t_nrow - COMPOSER_TOP_LINE - 2;
	fillcol = (term.t_ncol > 80) ? 77 : term.t_ncol - 6;
    }
    else{
        wp->w_toprow = 2;
        wp->w_ntrows = term.t_nrow-4;           /* "-1" for mode line.  */
	fillcol = term.t_ncol - 6;              /* set fill column */
    }

    wp->w_force = 0;
    wp->w_flag  = WFMODE|WFHARD;            /* Full.                */
}


/*
 * This is the general command execution routine. It handles the fake binding
 * of all the keys to "self-insert". It also clears out the "thisflag" word,
 * and arranges to move it to the "lastflag", so that the next command can
 * look at it. Return the status of command.
 */
execute(c, f, n)
int c, f, n;
{
    register KEYTAB *ktp;
    register int    status;

    ktp = (Pmaster) ? &keytab[0] : &pkeytab[0];

    while (ktp->k_fp != NULL) {
	if (ktp->k_code == c) {

	    if(lastflag&CFFILL){
		curwp->w_flag |= WFMODE;
		if(Pmaster == NULL)
		  sgarbk = TRUE;
	    }

	    thisflag = 0;
	    status   = (*ktp->k_fp)(f, n);
	    lastflag = thisflag;

	    return (status);
	}
	++ktp;
    }

#ifdef	DOS
    if (c>=0x20 && c<=0xFF) {
#else
    if ((c>=0x20 && c<=0x7E)                /* Self inserting.      */
        ||  (c>=0xA0 && c<=0xFE)) {
#endif

	if (n <= 0) {                   /* Fenceposts.          */
	    lastflag = 0;
	    return (n<0 ? FALSE : TRUE);
	}
	thisflag = 0;                   /* For the future.      */

	/* if we are in overwrite mode, not at eol,
	   and next char is not a tab or we are at a tab stop,
	   delete a char forword			*/
	if (curwp->w_bufp->b_mode & MDOVER &&
	    curwp->w_doto < curwp->w_dotp->l_used &&
	    (lgetc(curwp->w_dotp, curwp->w_doto).c != '\t' ||
	     (curwp->w_doto) % 8 == 7))
	  ldelete(1, FALSE);

	/* do the appropriate insertion */
	/* pico never does C mode, this is simple */
	status = linsert(n, c);

	/*
	 * Check to make sure we didn't go off of the screen
	 * with that character.  If so wrap the line...
	 * note: in pico,  fillcol and wrap-mode are always set and 
	 * 	 wrapword behaves somewhat differently
	 */
	if(((llength(curwp->w_dotp)+2 >= ((Pmaster && term.t_ncol > 80)
	                                       ? 77 : term.t_ncol))
	    || (c == ' ' && getccol(FALSE) > fillcol))
	   && (curwp->w_bufp->b_mode & MDWRAP))
	  wrapword();

	lastflag = thisflag;
	return (status);
    }
    
    if(c&CTRL)
      emlwrite("\007Unknown Command: ^%c", (void *)(c&0xff));
    else
      emlwrite("\007Unknown Command", NULL);

    lastflag = 0;                           /* Fake last flags.     */
    return (FALSE);
}



/*
 * Fancy quit command, as implemented by Norm. If the any buffer has
 * changed do a write on that buffer and exit emacs, otherwise simply exit.
 */
quickexit(f, n)
int f, n;
{
    register BUFFER *bp;	/* scanning pointer to buffers */

    bp = bheadp;
    while (bp != NULL) {
	if ((bp->b_flag&BFCHG) != 0	/* Changed.             */
	    && (bp->b_flag&BFTEMP) == 0) {	/* Real.                */
	    curbp = bp;		/* make that buffer cur	*/
	    filesave(f, n);
	}
	bp = bp->b_bufp;			/* on to the next buffer */
    }
    wquit(f, n);                             /* conditionally quit   */
}



/* 
 * abort_composer - ask the question here, then go quit or 
 *                  return FALSE
 */
abort_composer(f, n)
int f, n;
{
    switch(mlyesno("Cancelling will abandon your mail message.  Cancel", 
		    FALSE)){
      case TRUE:
	pico_all_done = COMP_CANCEL;
	return(TRUE);

      case ABORT:
	emlwrite("\007Cancel Cancelled", NULL);
	break;

      default:
	mlerase();
    }
    return(FALSE);
}


/*
 * suspend_composer - return to pine with what's been edited so far
 */
suspend_composer(f, n)
int f, n;
{
    pico_all_done = COMP_SUSPEND;
}



/*
 * Quit command. If an argument, always quit. Otherwise confirm if a buffer
 * has been changed and not written out. Normally bound to "C-X C-C".
 */
wquit(f, n)
int f, n;
{
    register int    s;

    if(Pmaster){
	char *prompt;
	int   defans;

	/*
	 * if we're not in header, show some of it as we verify sending...
	 */
	setimark(FALSE, 1);
	if(ComposerTopLine == COMPOSER_TOP_LINE){
	    gotobob(FALSE, 1);
	    update();
	}

	if(AttachError()){
	    prompt = "\007Problem with attachments!  Send anyway";
	    defans = FALSE;
	}
	else{
	    prompt = "Send message";
	    defans = TRUE;
	}

	switch(mlyesno(prompt, defans)){
	  case TRUE:
	    pico_all_done = COMP_EXIT;
	    return(TRUE);
	  case ABORT:
	    emlwrite("Send cancelled", NULL);
	    break;
	  default:
	    mlerase();
	}

	swapimark(FALSE, 1);
    }
    else{
        if (f != FALSE                          /* Argument forces it.  */
        || anycb() == FALSE                     /* All buffers clean.   */
						/* User says it's OK.   */
        || (s=mlyesno("Save modified buffer (ANSWERING \"No\" WILL DESTROY CHANGES)", -1)) == FALSE) {
                vttidy();
                exit(0);
        }

	if(s == TRUE){
	    if(filewrite(0,1) == TRUE)
	      wquit(1, 0);
	}
	else if(s == ABORT){
	    emlwrite("Exit cancelled", NULL);
	}
        return(s);
    }

    return(FALSE);
}


/*
 * Abort.
 * Beep the beeper. Kill off any keyboard macro, etc., that is in progress.
 * Sometimes called as a routine, to do general aborting of stuff.
 */
ctrlg(f, n)
int f, n;
{
    emlwrite("Cancelled", NULL);
    return (ABORT);
}


/* tell the user that this command is illegal while we are in
 *  VIEW (read-only) mode
 */
rdonly()
{
    (*term.t_beep)();
    emlwrite("Key illegal in VIEW mode", NULL);
    return(FALSE);
}



/*
 * reset all globals to their initial values
 */
func_init()
{
    extern int    vtrow;
    extern int    vtcol;
    extern int    lbound;
    extern int    ttrow;
    extern int    ttcol;

    /*
     * re-initialize global buffer type variables ....
     */
    fillcol = (term.t_ncol > 80) ? 77 : term.t_ncol - 6;
    eolexist = TRUE;
    revexist = FALSE;
    sgarbf = TRUE;
    mpresf = FALSE;
    mline_open = FALSE;
    ComposerEditing = FALSE;

    /*
     * re-initialize hardware display variables ....
     */
    vtrow = vtcol = lbound = 0;
    ttrow = ttcol = HUGE;

    pat[0] = '\0';
}


/*
 * pico_help - help function for standalone composer
 */
pico_help(text, title, i)
char *text[], *title;
int i;
{
    register    int numline = 0;
    char        **p;
 
    p = text;
    while(*p++ != NULL) 
      numline++;
    return(wscrollw(COMPOSER_TOP_LINE, term.t_nrow-1, text, numline));

}



#if     TERMCAP
/*
 * zottree() - kills the key pad function key search tree
 *                and frees all lines associated with it!!!
 */
zottree(nodeptr)
struct	KBSTREE	*nodeptr;
{
    if(nodeptr != NULL){
	zottree(nodeptr->left);
	zottree(nodeptr->down);
	free((char *) nodeptr);
    }
}
#endif


/*
 * zotedit() - kills the buffer and frees all lines associated with it!!!
 */
zotedit()
{
#ifdef	OLDWAY
    register int	s;

    /*
     * clean up the lines and buffer ...
     */
    curbp->b_flag &= ~BFCHG;

    if ((s=bclear(curbp)) != TRUE)		/* Blow text away.      */
      return(s);
#else
    wheadp->w_linep = wheadp->w_dotp = wheadp->w_markp = NULL;
    bheadp->b_linep = bheadp->b_dotp = bheadp->b_markp = NULL;
#endif

    free((char *) wheadp);			/* clean up window */
    wheadp = NULL;
    curwp  = NULL;

    free((char *) bheadp);			/* clean up buffers */
    bheadp = NULL;
    curbp  = NULL;

    zotheader();				/* blast header lines */

#ifdef	OLDWAY
    zotdisplay();				/* blast display buffers */
#else
    kdelete();					/* blast kill buffer */
#endif

#if     TERMCAP
    zottree(kpadseqs);
    kpadseqs = NULL;
#endif
}


/* 
 * Below are functions for use outside pico to manipulate text
 * in a pico's native format (circular linked list of lines).
 *
 * The idea is to streamline pico use by making it fairly easy
 * for outside programs to prepare text intended for pico's use.
 * The simple char * alternative is messy as it requires two copies
 * of the same text, and isn't very economic in limited memory
 * situations (THANKS BELLEVUE-BILLY.).
 */
typedef struct picotext {
    LINE *linep;
    LINE *dotp;
    short doto;
    short crinread;
} PICOTEXT;

#define PT(X)	((PICOTEXT *)(X))

/*
 * pico_get - return window struct pointer used as a handle
 *            to the other pico_xxx routines.
 */
void *
pico_get()
{
   PICOTEXT *wp = NULL;
   LINE     *lp = NULL;

   if(wp = (PICOTEXT *)malloc(sizeof(PICOTEXT))){
       wp->crinread = 0;
       if((lp = lalloc(0)) == NULL){
	   free(wp);
	   return(NULL);
       }

       wp->dotp = wp->linep = lp->l_fp = lp->l_bp = lp;
       wp->doto = 0;
   }
   else
     emlwrite("Can't allocate space for text", NULL);

   return((void *)wp);
}

/*
 * pico_give - free resources and give up picotext struct
 */
void
pico_give(w)
void *w;
{
    register LINE *lp;
    register LINE *fp;

    fp = lforw(PT(w)->linep);
    while((lp = fp) != PT(w)->linep){
        fp = lforw(lp);
	free(lp);
    }
    free(PT(w)->linep);
    free((PICOTEXT *)w);
}

/*
 * pico_readc - return char at current point.  Up to calling routines
 *              to keep cumulative count of chars.
 */
int
pico_readc(w, c)
void          *w;
unsigned char *c;
{
    int rv     = 0;

    if(PT(w)->crinread){
	*c = '\012';				/* return LF */
	PT(w)->crinread = 0;
	rv++;
    }
    else if(PT(w)->doto < llength(PT(w)->dotp)){ /* normal char to return */
        *c = (unsigned char) lgetc(PT(w)->dotp, (PT(w)->doto)++).c;
	rv++;
    }
    else if(lforw(PT(w)->dotp) != PT(w)->linep){ /* return line break */
	PT(w)->dotp = lforw(PT(w)->dotp);
	PT(w)->doto = 0;
#if	defined(DOS)
	*c = '\015';
	PT(w)->crinread++;
#else
	*c = '\012';				/* return local eol! */
#endif
	rv++;
    }						/* else no chars to return */

    return(rv);
}


/*
 * pico_writec - write a char into picotext and advance pointers.
 *               Up to calling routines to keep track of total chars
 *               written
 */
int
pico_writec(w, c)
void *w;
int   c;
{
    int   rv = 0;

    if(c == '\r')				/* ignore CR's */
      rv++;					/* so fake it */
    else if(c == '\n'){				/* insert newlines on LF */
	
	if(PT(w)->linep == PT(w)->dotp){	/* special case */
	    if(!insline(&(PT(w)->dotp), &(PT(w)->doto)))
	      return(0);
	}

	if(!insline(&(PT(w)->dotp), &(PT(w)->doto)))
	  return(0);

        rv++;
    }
    else
      rv = geninsert(&(PT(w)->dotp), &(PT(w)->doto), PT(w)->linep, c, 0, 1);

    return((rv) ? 1 : 0);			/* return number written */
}


/*
 * pico_puts - just write the given string into the text
 */
int
pico_puts(w, s)
void *w;
char *s;
{
    while(*s != '\0')
      pico_writec(w, (int)*s++);
}


/*
 * pico_seek - position dotp and dot at requested location
 */
int
pico_seek(w, offset, orig)
void *w;
long  offset;
int   orig;
{
    register LINE *lp;

    PT(w)->crinread = 0;
    switch(orig){
      case 0 :				/* SEEK_SET */
	PT(w)->dotp = lforw(PT(w)->linep);
	PT(w)->doto = 0;
      case 1 :				/* SEEK_CUR */
	lp = PT(w)->dotp;
	while(lp != PT(w)->linep){
	    if(offset <= llength(lp)){
		PT(w)->doto = (int)offset;
		PT(w)->dotp = lp;
		break;
	    }

	    offset -= ((long)llength(lp)
#ifdef	DOS
		       + 2L);
#else
		       + 1L);
#endif
	    lp = lforw(lp);
	}
        break;

      case 2 :				/* SEEK_END */
	PT(w)->dotp = lback(PT(w)->linep);
	PT(w)->doto = llength(PT(w)->dotp);
	break;
      default :
        return(-1);
    }

    return(0);
}


/*
 * pico_replace - replace whatever's in the associated text with
 *                the given string
 */
int
pico_replace(w, s)
void *w;
char *s;
{
    return(0);
}

/*
 * breplace - replace the current window's text with the given 
 *            LINEs
 */
void
breplace(w)
void *w;
{
    register LINE *lp;
    register LINE *fp;

    fp = lforw(curbp->b_linep);
    while((lp = fp) != curbp->b_linep){		/* blast old lines */
        fp = lforw(lp);
	free(lp);
    }
    free(curbp->b_linep);

    curbp->b_linep  = PT(w)->linep;			/* arrange pointers */

    curwp->w_linep = lforw(curbp->b_linep);
    curwp->w_dotp  = lforw(curbp->b_linep);
    curwp->w_doto  = 0;
    curwp->w_markp = curwp->w_imarkp = NULL;
    curwp->w_marko = curwp->w_imarko = 0;

    curbp->b_dotp   = curwp->w_dotp;
    curbp->b_doto   = curbp->b_marko  = 0;
    curbp->b_markp  = NULL;

    curwp->w_flag |= WFHARD;
}


/*
 * generic line insert function.
 */
insline(dotp, doto)
LINE **dotp;
short *doto;
{
    register LINE *lp;

    if((lp = lalloc(0)) == NULL){
	emlwrite("Can't allocate space for more characters",NULL);
	return(FALSE);
    }

    lp->l_fp = (*dotp)->l_fp;
    lp->l_bp = (*dotp);
    lp->l_fp->l_bp = (*dotp)->l_fp = lp;
    (*dotp) = lp;
    (*doto) = 0;
    return(TRUE);
}
LL);
	    break;
	  default:
	    mlerase();
	}

	swapimark(FALSE, 1);
    }
    else{
        if (f != FALSE                          /* Argument forces it.  */
        || anycb() == FALSE                     /* All buffers clean.   */
						/* User says it's OK.   */
        || (s=mlyesno("SaDarkNET-1.08/pico.BBS/pico.h                                                                           644   21270   21270        23576  5672504031  10552                                                                                                                                                                                                                                                                                                                                                                      /*
 * $Id: pico.h,v 4.24 1994/09/27 16:21:49 mikes Exp $
 *
 * Program:	pico.h - definitions for Pine's composer library
 *
 *
 * Michael Seibel
 * Networks and Distributed Computing
 * Computing and Communications
 * University of Washington
 * Administration Builiding, AG-44
 * Seattle, Washington, 98195, USA
 * Internet: mikes@cac.washington.edu
 *
 * Please address all bugs and comments to "pine-bugs@cac.washington.edu"
 *
 * Copyright 1991-1994  University of Washington
 *
 *  Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee to the University of
 * Washington is hereby granted, provided that the above copyright notice
 * appears in all copies and that both the above copyright notice and this
 * permission notice appear in supporting documentation, and that the name
 * of the University of Washington not be used in advertising or publicity
 * pertaining to distribution of the software without specific, written
 * prior permission.  This software is made available "as is", and
 * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
 * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
 * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
 * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 * Pine and Pico are trademarks of the University of Washington.
 * No commercial use of these trademarks may be made without prior
 * written permission of the University of Washington.
 *
 */

#ifndef	PICO_H
#define	PICO_H
/*
 * Defined for attachment support
 */
#define	ATTACHMENTS	1


/*
 * defs of return codes from pine mailer composer.
 */
#define	BUF_CHANGED	0x01
#define	COMP_CANCEL	0x02
#define	COMP_EXIT	0x04
#define	COMP_FAILED	0x08
#define	COMP_SUSPEND	0x10
#define	COMP_GOTHUP	0x20


/*
 * top line from the top of the screen for the editor to do 
 * its stuff
 */
#define	COMPOSER_TOP_LINE	2
#define	COMPOSER_TITLE_LINE	0



/*
 * definitions of Mail header structures 
 */
struct hdr_line {
        char text[256];
        struct  hdr_line        *next;
        struct  hdr_line        *prev;
};
 
 
/* 
 *  This structure controls the header line items on the screen.  An
 * instance of this should be created and passed in as an argument when
 * pico is called. The list is terminated by an entry with the name
 * element NULL.
 */
 
struct headerentry {
        char     *prompt;
	char	 *name;
#ifdef	DOS
	short	  help;
#else
	char	**help;
#endif
        int	  prlen;
        int	  maxlen;
        char    **realaddr;
        int     (*builder)();        /* Function to verify/canonicalize val */
	struct headerentry        *affected_entry;
				     /* entry builder's 4th arg affects     */
        char   *(*selector)();       /* Browser for possible values         */
        char     *key_label;         /* Key label for key to call browser   */
        unsigned  display_it:1;	     /* field is to be displayed by default */
        unsigned  break_on_comma:1;  /* Field breaks on commas              */
        unsigned  is_attach:1;       /* Special case field for attachments  */
        unsigned  rich_header:1;     /* Field is part of rich header        */
        unsigned  only_file_chars:1; /* Field is a file name                */
        unsigned  single_space:1;    /* Crush multiple spaces into one      */
        unsigned  sticky:1;          /* Can't change this via affected_entry*/
        struct    hdr_line        *hd_text;
};


/*
 * structure to keep track of header display
 */
struct on_display {
    int			 p_off;			/* offset into line */
    int			 p_len;			/* length of line   */
    int			 p_line;		/* physical line on screen */
    int			 top_e;			/* topline's header entry */
    struct hdr_line	*top_l;			/* top line on display */
    int			 cur_e;			/* current header entry */
    struct hdr_line	*cur_l;			/* current hd_line */
};						/* global on_display struct */


/*
 * Structure to handle attachments
 */
typedef struct pico_atmt {
    char *description;
    char *filename;
    char *size;
    char *id;
    unsigned short flags;
    struct pico_atmt *next;
} PATMT;


/*
 * Flags for attachment handling
 */
#define	A_FLIT	0x0001			/* Accept literal file and size      */
#define	A_ERR	0x0002			/* Problem with specified attachment */


/*
 * Master pine composer structure.  Right now there's not much checking
 * that any of these are pointing to something, so pine must have them pointing
 * somewhere.
 */
typedef struct pico_struct {
    void  *msgtext;			/* ptrs to malloc'd arrays of char */
    char  *pine_anchor;			/* ptr to pine anchor line */
    char  *pine_version;		/* string containing Pine's version */
    char  *alt_ed;			/* name of alternate editor or NULL */
    PATMT *attachments;			/* linked list of attachments */
    unsigned pine_flags;		/* entry mode flags */
    void  (*helper)();			/* Pine's help function  */
    int   (*showmsg)();			/* Pine's display_message */
    void  (*clearcur)();		/* Pine's clear cursor position func */
    void  (*keybinit)();		/* Pine's keyboard initializer  */
    int   (*raw_io)();			/* Pine's Raw() */
    long  (*newmail)();			/* Pine's report_new_mail */
#ifdef	DOS
    short search_help;
    short ins_help;
    short composer_help;
    short browse_help;
#else
    char  **search_help;
    char  **ins_help;
    char  **composer_help;
    char  **browse_help;
#endif
    struct headerentry *headents;
} PICO;

/*
 * various flags that they may passed to PICO
 */
#define	P_LOCALLF	0x8000		/* use local vs. NVT EOL	   */
#define	P_BODY		0x4000		/* start composer in body	   */
#define	P_HEADEND	0x2000		/* start composer at end of header */
#define	P_FKEYS		MDFKEY		/* run in function key mode 	   */
#define	P_SECURE	MDSCUR		/* run in restricted (demo) mode   */
#define	P_SUSPEND	MDSSPD		/* allow ^Z suspension		   */
#define	P_ADVANCED	MDADVN		/* enable advanced features	   */
#define	P_CURDIR	MDCURDIR	/* use current dir for lookups	   */
#define	P_ALTNOW	MDALTNOW	/* enter alt ed with hesitation	   */

/*
 * definitions for various PICO modes 
 */
#define	MDWRAP		0x0001		/* word wrap			*/
#define	MDSPELL		0x0002		/* spell error parcing		*/
#define	MDEXACT		0x0004		/* Exact matching for searches	*/
#define	MDVIEW		0x0008		/* read-only buffer		*/
#define MDOVER		0x0010		/* overwrite mode		*/
#define MDFKEY		0x0020		/* function key  mode		*/
#define MDSCUR		0x0040		/* secure (for demo) mode	*/
#define MDSSPD		0x0080		/* suspendable mode		*/
#define MDADVN		0x0100		/* Pico's advanced mode		*/
#define MDTOOL		0x0200		/* "tool" mode (quick exit)	*/
#define MDBRONLY	0x0400		/* indicates standalone browser	*/
#define MDCURDIR	0x0800		/* use current dir for lookups	*/
#define MDALTNOW	0x1000		/* enter alt ed with hesitation */


/*
 * Main defs 
 */
#ifdef	maindef
PICO	*Pmaster = NULL;		/* composer specific stuff */
char	*version = "2.5";		/* PICO version number */
#else
extern PICO *Pmaster;			/* composer specific stuff */
extern char *version;			/* pico version! */
#endif


/*
 * Flags for FileBrowser call
 */
#define FB_READ		0x0001		/* Looking for a file to read. */
#define FB_SAVE		0x0002		/* Looking for a file to save. */


/*
 * number of keystrokes to delay removing an error message, or new mail
 * notification
 */
#define	MESSDELAY	25
#define	NMMESSDELAY	60


/*
 * defs for keypad and function keys...
 */
#define K_PAD_UP        0x0811
#define K_PAD_DOWN      0x0812
#define K_PAD_RIGHT     0x0813
#define K_PAD_LEFT      0x0814
#define K_PAD_PREVPAGE  0x0815
#define K_PAD_NEXTPAGE	0x0816
#define K_PAD_HOME	0x0817
#define K_PAD_END	0x0818
#define K_PAD_DELETE	0x0819
#define BADESC          0x0820
#define NODATA          0x08FF
 
/*
 * defines for function keys
 */
#define F1      0x1001                  /* Functin key one              */
#define F2      0x1002                  /* Functin key two              */
#define F3      0x1003                  /* Functin key three            */
#define F4      0x1004                  /* Functin key four             */
#define F5      0x1005                  /* Functin key five             */
#define F6      0x1006                  /* Functin key six              */
#define F7      0x1007                  /* Functin key seven            */
#define F8      0x1008                  /* Functin key eight            */
#define F9      0x1009                  /* Functin key nine             */
#define F10     0x100A                  /* Functin key ten              */
#define F11     0x100B                  /* Functin key eleven           */
#define F12     0x100C                  /* Functin key twelve           */

/*
 * useful function definitions
 */
#ifdef	ANSI
int   pico(PICO *);
void *pico_get(void);
void  pico_give(void *);
int   pico_readc(void *, unsigned char *);
int   pico_writec(void *, int);
int   pico_puts(void *, char *);
int   pico_seek(void *, long, int);
int   pico_replace(void *, char *);
#ifdef	DOS
int   pico_nfsetcolor(char *);
int   pico_nbsetcolor(char *);
int   pico_rfsetcolor(char *);
int   pico_rbsetcolor(char *);
#endif
#else
int   pico();
void *pico_get();
void  pico_give();
int   pico_readc();
int   pico_writec();
int   pico_puts();
int   pico_seek();
int   pico_replace();
#endif

#define myisprint(c) (((unsigned char)(c)>=0xa1&&(unsigned char)(c)<=0xfe)||(isp
#define myisspace(c) ((c)==' '||(c)=='\t'||(c)=='\n'||(c)=='\r')
#define myisdigit(c) ((c)>='0'&&(c)<='9')
#define myisalpha(c) (((unsigned char)(c)>='A'&&(unsigned char)(c)<='Z')|| \
                        ((unsigned char)(c)>='a'&&(unsigned char)(c)<='z'))
#define ishangul(c) ((unsigned char)(c)>=0xa1&&(unsigned char)(c)<=0xfe)
#define myislower(c) ((c)>='a'&&(c)<='z')
#define myisupper(c) ((c)>='A'&&(c)<='Z')


#endif	/* PICO_H */
on;		/* string containing Pine's version */
    char  *alt_ed;			/* name of alternate editor or NULL */
    PATMT *attachments;			DarkNET-1.08/pico.BBS/random.c                                                                         644   21270   21270        23346  5672511354  11074                                                                                                                                                                                                                                                                                                                                                                      #if	!defined(lint) && !defined(DOS)
static char rcsid[] = "$Id: random.c,v 4.6 1994/07/15 23:33:52 mikes Exp $";
#endif
/*
 * Program:	Random routines
 *
 *
 * Michael Seibel
 * Networks and Distributed Computing
 * Computing and Communications
 * University of Washington
 * Administration Builiding, AG-44
 * Seattle, Washington, 98195, USA
 * Internet: mikes@cac.washington.edu
 *
 * Please address all bugs and comments to "pine-bugs@cac.washington.edu"
 *
 * Copyright 1991-1994  University of Washington
 *
 *  Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee to the University of
 * Washington is hereby granted, provided that the above copyright notice
 * appears in all copies and that both the above copyright notice and this
 * permission notice appear in supporting documentation, and that the name
 * of the University of Washington not be used in advertising or publicity
 * pertaining to distribution of the software without specific, written
 * prior permission.  This software is made available "as is", and
 * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
 * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
 * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
 * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 * Pine and Pico are trademarks of the University of Washington.
 * No commercial use of these trademarks may be made without prior
 * written permission of the University of Washington.
 *
 */
/*
 * This file contains the command processing functions for a number of random
 * commands. There is no functional grouping here, for sure.
 */

#include        <stdio.h>
#include	"estruct.h"
#include	"pico.h"
#include        "edef.h"

#ifdef	ANSI
    int getccol(int);
#else
    int getccol();
#endif

int     tabsize;                        /* Tab size (0: use real tabs)  */

/*
 * Set fill column to n.
 */
setfillcol(f, n)
int f, n;
{
    char	numbuf[16];
    register int s;

    sprintf(numbuf,"%d",fillcol);
    s = mlreplyd("Set fill column to : ", numbuf, 4, QDEFLT, NULL);
    fillcol = atoi(numbuf);
    return(s);
}


/*
 * Display the current position of the cursor, in origin 1 X-Y coordinates,
 * the character that is under the cursor (in octal), and the fraction of the
 * text that is before the cursor. The displayed column is not the current
 * column, but the column that would be used on an infinite width display.
 * Normally this is bound to "C-X =".
 */
showcpos(f, n)
int f, n;
{
    register LINE   *clp;
    register long   nch;
    register int    cbo;
    register long   nbc;
    register int    lines;
    register int    thisline;
    char     buffer[80];
    extern int lang;

    clp = lforw(curbp->b_linep);            /* Grovel the data.     */
    cbo = 0;
    nch = 0L;
    lines = 0;
    for (;;) {
	if (clp==curwp->w_dotp && cbo==curwp->w_doto) {
	    thisline = lines;
	    nbc = nch;
	}
	if (cbo == llength(clp)) {
	    if (clp == curbp->b_linep)
	      break;
	    clp = lforw(clp);
	    cbo = 0;
	    lines++;
	} else
	  ++cbo;
	++nch;
    }

    if (lang)
      sprintf(buffer,"%d ÁÙÁß %d Â°ÁÙ (%d%%%%), %ld ±ÛÀÚÁß %ld ¹øÂ° (%d%%%%)",
	    lines+1, thisline+1, (int)((100L*(thisline+1))/(lines+1)),
	    nch, nbc, (nch) ? (int)((100L*nbc)/nch) : 0);
    else
      sprintf(buffer,"line %d of %d (%d%%%%), character %ld of %ld (%d%%%%)",
	    thisline+1, lines+1, (int)((100L*(thisline+1))/(lines+1)),
	    nbc, nch, (nch) ? (int)((100L*nbc)/nch) : 0);
    emlwrite(buffer, NULL);
    return (TRUE);
}


/*
 * Return current column.  Stop at first non-blank given TRUE argument.
 */
getccol(bflg)
int bflg;
{
    register int c, i, col;

    col = 0;
    for (i=0; i<curwp->w_doto; ++i) {
	c = lgetc(curwp->w_dotp, i).c;
	if (c!=' ' && c!='\t' && bflg)
	  break;

	if (c == '\t')
	  col |= 0x07;
	else if (c<0x20 || c==0x7F)
	  ++col;

	++col;
    }

    return(col);
}



/*
 * Set tab size if given non-default argument (n <> 1).  Otherwise, insert a
 * tab into file.  If given argument, n, of zero, change to true tabs.
 * If n > 1, simulate tab stop every n-characters using spaces. This has to be
 * done in this slightly funny way because the tab (in ASCII) has been turned
 * into "C-I" (in 10 bit code) already. Bound to "C-I".
 */
tab(f, n)
{
    if (n < 0)
      return (FALSE);

    if (n == 0 || n > 1) {
	tabsize = n;
	return(TRUE);
    }

    if (! tabsize)
      return(linsert(1, '\t'));

    return(linsert(tabsize - (getccol(FALSE) % tabsize), ' '));
}


/*
 * Insert a newline. Bound to "C-M".
 */
newline(f, n)
{
    register int    s;

    if (curbp->b_mode&MDVIEW)	/* don't allow this command if	*/
      return(rdonly());	/* we are in read only mode	*/

    if (n < 0)
      return (FALSE);

    if(optimize && (curwp->w_dotp != curwp->w_bufp->b_linep)){
	int l;

	if(worthit(&l)){
	    if(curwp->w_doto != 0)
	      l++;
	    scrolldown(curwp, l, n);
	}
    }

    /* if we are in C mode and this is a default <NL> */
    /* pico's never in C mode */

    /* insert some lines */
    while (n--) {
	if ((s=lnewline()) != TRUE)
	  return (s);
    }
    return (TRUE);
}



/*
 * Delete forward. This is real easy, because the basic delete routine does
 * all of the work. Watches for negative arguments, and does the right thing.
 * If any argument is present, it kills rather than deletes, to prevent loss
 * of text if typed with a big argument. Normally bound to "C-D".
 */
forwdel(f, n)
{
    if (curbp->b_mode&MDVIEW)	/* don't allow this command if	*/
      return(rdonly());	/* we are in read only mode	*/

    if (n < 0)
      return (backdel(f, -n));

    if(optimize && (curwp->w_dotp != curwp->w_bufp->b_linep)){
	int l;

	if(worthit(&l) && curwp->w_doto == llength(curwp->w_dotp))
	  scrollup(curwp, l+1, 1);
    }

    if (f != FALSE) {                       /* Really a kill.       */
	if ((lastflag&CFKILL) == 0)
	  kdelete();
	thisflag |= CFKILL;
    }

    return (ldelete(n, f));
}



/*
 * Delete backwards. This is quite easy too, because it's all done with other
 * functions. Just move the cursor back, and delete forwards. Like delete
 * forward, this actually does a kill if presented with an argument. Bound to
 * both "RUBOUT" and "C-H".
 */
backdel(f, n)
{
    register int    s;

    if (curbp->b_mode&MDVIEW)	/* don't allow this command if	*/
      return(rdonly());	/* we are in read only mode	*/

    if (n < 0)
      return (forwdel(f, -n));

    if(optimize && curwp->w_dotp != curwp->w_bufp->b_linep){
	int l;
	
	if(worthit(&l) && curwp->w_doto == 0 &&
	   lback(curwp->w_dotp) != curwp->w_bufp->b_linep){
	    if(l == curwp->w_toprow)
	      scrollup(curwp, l+1, 1);
	    else if(llength(lback(curwp->w_dotp)) == 0)
	      scrollup(curwp, l-1, 1);
	    else
	      scrollup(curwp, l, 1);
	}
    }

    if (f != FALSE) {                       /* Really a kill.       */
	if ((lastflag&CFKILL) == 0)
	  kdelete();

	thisflag |= CFKILL;
    }

    if ((s=backchar(f, n)) == TRUE)
      s = ldelete(n, f);

    return (s);
}



/*
 * killtext - delete the line that the cursor is currently in.
 *	      a greatly pared down version of its former self.
 */
killtext(f, n)
int f, n;
{
    register int	chunk;

    if (curbp->b_mode&MDVIEW)       /* don't allow this command if  */
      return(rdonly());       /* we are in read only mode     */

    if(optimize && (curwp->w_dotp != curwp->w_bufp->b_linep)){
	int l;
	
	if(worthit(&l))
	  scrollup(curwp, l, 1);
    }

    if ((lastflag&CFKILL) == 0)             /* Clear kill buffer if */
      kdelete();                      /* last wasn't a kill.  */

    thisflag |= CFKILL;
    curwp->w_doto = 0;		/* wack from the beginning of line */
    chunk = llength(curwp->w_dotp) + 1;	/* for the whole length. */
    return(ldelete(chunk, TRUE));
}


/*
 * Yank text back from the kill buffer. This is really easy. All of the work
 * is done by the standard insert routines. All you do is run the loop, and
 * check for errors. Bound to "C-Y".
 */
yank(f, n)
int f, n;
{
    register int    c;
    register int    i;
    extern   int    kused;

    if (curbp->b_mode&MDVIEW)	/* don't allow this command if	*/
      return(rdonly());	/* we are in read only mode	*/

    if (n < 0)
      return (FALSE);

    if(optimize && (curwp->w_dotp != curwp->w_bufp->b_linep)){
	int l;

	if(worthit(&l) && !(lastflag&CFFILL)){
	    register int  t = 0; 
	    register int  i = 0;
	    register int  ch;

	    while((ch=kremove(i++)) >= 0)
	      if(ch == '\n')
		t++;
	    if(t+l < curwp->w_toprow+curwp->w_ntrows)
	      scrolldown(curwp, l, t);
	}
    }

    if(lastflag&CFFILL)		/* if last command was fillpara() */
      gotobop(FALSE, 1);		/* then go to the top of the para */
					/* then splat out the saved buffer */
    while (n--) {
	i = 0;
	while ((c=kremove(i)) >= 0) {
	    if (c == '\n') {
		if (lnewline(FALSE, 1) == FALSE)
		  return (FALSE);
	    } else {
		if (linsert(1, c) == FALSE)
		  return (FALSE);
	    }

	    ++i;
	}
    }

    if(lastflag&CFFILL){            /* if last command was fillpara() */
	register LINE *botline;     /* blast the filled paragraph */
	register LINE *topline;
	register int  done = 0;
	
	kdelete();
	topline = curwp->w_dotp;
	gotoeop(FALSE, 1);
	botline = lforw(curwp->w_dotp);
	curwp->w_dotp = topline;
	if(topline != botline){
	    while(!done){
		if(lforw(curwp->w_dotp) == botline)
		  done++;
		curwp->w_doto = 0;
		ldelete((llength(curwp->w_dotp) + 1), FALSE);
	    }
	}
	curwp->w_flag |= WFMODE;
	
	if(Pmaster == NULL){
	    sgarbk = TRUE;
	    emlwrite("");
	}
    }

    return (TRUE);
}
                                                                                                                                                                                                                                                                                          DarkNET-1.08/pico.BBS/region.c                                                                         644   21270   21270        22141  5672511534  11067                                                                                                                                                                                                                                                                                                                                                                      #if	!defined(lint) && !defined(DOS)
static char rcsid[] = "$Id: region.c,v 4.12 1994/07/07 01:29:01 mikes Exp $";
#endif
/*
 * Program:	Region management routines
 *
 *
 * Michael Seibel
 * Networks and Distributed Computing
 * Computing and Communications
 * University of Washington
 * Administration Builiding, AG-44
 * Seattle, Washington, 98195, USA
 * Internet: mikes@cac.washington.edu
 *
 * Please address all bugs and comments to "pine-bugs@cac.washington.edu"
 *
 * Copyright 1991-1994  University of Washington
 *
 *  Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee to the University of
 * Washington is hereby granted, provided that the above copyright notice
 * appears in all copies and that both the above copyright notice and this
 * permission notice appear in supporting documentation, and that the name
 * of the University of Washington not be used in advertising or publicity
 * pertaining to distribution of the software without specific, written
 * prior permission.  This software is made available "as is", and
 * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
 * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
 * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
 * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 * Pine and Pico are trademarks of the University of Washington.
 * No commercial use of these trademarks may be made without prior
 * written permission of the University of Washington.
 *
 */
/*
 * The routines in this file
 * deal with the region, that magic space
 * between "." and mark. Some functions are
 * commands. Some functions are just for
 * internal use.
 */
#include        <stdio.h>
#include	"estruct.h"
#include	"pico.h"
#include        "edef.h"

/*
 * Kill the region. Ask "getregion"
 * to figure out the bounds of the region.
 * Move "." to the start, and kill the characters.
 * Bound to "C-W".
 */
killregion(f, n)
{
    REGION          region;
    static long     times = 1L;
    static long     backoff = 4L;
    extern int lang;

    if (curbp->b_mode&MDVIEW)		/* don't allow this command if	*/
      return(rdonly());			/* we are in read only mode	*/

    if (getregion(&region) != TRUE){
	if((lastflag&CFKILL) == 0){
	    if (lang)
	      emlwrite("ÁÙ Áö¿ü¾î¿ä.%s", !(times % backoff) ? 
		     " (Could also use ctrl-^ to mark text for cutting)" : "");
	    else
	      emlwrite("Line Deleted.%s", !(times % backoff) ? 
		     " (Could also use ctrl-^ to mark text for cutting)" : "");

	    if(!(times++ % backoff)) 	/* if message shown, reset backoff */
	      backoff = backoff << 1;
	}
	
	return (killtext(f, n));
    }else {
	mlerase();
    }

    if ((lastflag&CFKILL) == 0)		/* This is a kill type  */
      kdelete();			/* command, so do magic */

    thisflag |= CFKILL;			/* kill buffer stuff.   */
    curwp->w_dotp = region.r_linep;
    curwp->w_doto = region.r_offset;
    curwp->w_markp = NULL;
#ifdef	_WINDOWS
    mswin_allowcopycut(NULL);
#endif

    if(ldelete((int)region.r_size, TRUE)){
	if(curwp->w_dotp == curwp->w_linep && curwp->w_dotp == curbp->b_linep){
	    curwp->w_force = 0;		/* Center dot. */
	    curwp->w_flag |= WFFORCE;
	}

	return(TRUE);
    }

    return (FALSE);
}


/*
 * Copy all of the characters in the
 * region to the kill buffer. Don't move dot
 * at all. This is a bit like a kill region followed
 * by a yank. Bound to "M-W".
 */
copyregion(f, n)
{
    register LINE   *linep;
    register int    loffs;
    register int    s;
    REGION          region;

    if ((s=getregion(&region)) != TRUE)
      return (s);

    if ((lastflag&CFKILL) == 0)		/* Kill type command.   */
      kdelete();

    thisflag |= CFKILL;
    linep = region.r_linep;		/* Current line.        */
    loffs = region.r_offset;		/* Current offset.      */
    while (region.r_size--) {
	if (loffs == llength(linep)) {  /* End of line.         */
	    if ((s=kinsert('\n')) != TRUE)
	      return (s);
	    linep = lforw(linep);
	    loffs = 0;
	} else {                        /* Middle of line.      */
	    if ((s=kinsert(lgetc(linep, loffs).c)) != TRUE)
	      return (s);
	    ++loffs;
	}
    }

    return (TRUE);
}


/*
 * Lower case region. Zap all of the upper
 * case characters in the region to lower case. Use
 * the region code to set the limits. Scan the buffer,
 * doing the changes. Call "lchange" to ensure that
 * redisplay is done in all buffers. Bound to
 * "C-X C-L".
 */
lowerregion(f, n)
{
    register LINE   *linep;
    register int    loffs;
    register int    c;
    register int    s;
    REGION          region;
    CELL            ac;

    ac.a = 0;
    if (curbp->b_mode&MDVIEW)	/* don't allow this command if	*/
      return(rdonly());	/* we are in read only mode	*/

    if ((s=getregion(&region)) != TRUE)
      return (s);

    lchange(WFHARD);
    linep = region.r_linep;
    loffs = region.r_offset;
    while (region.r_size--) {
	if (loffs == llength(linep)) {
	    linep = lforw(linep);
	    loffs = 0;
	} else {
	    c = lgetc(linep, loffs).c;
	    if (c>='A' && c<='Z'){
		ac.c = c+'a'-'A';
		lputc(linep, loffs, ac);
	    }
	    ++loffs;
	}
    }

    return (TRUE);
}

/*
 * Upper case region. Zap all of the lower
 * case characters in the region to upper case. Use
 * the region code to set the limits. Scan the buffer,
 * doing the changes. Call "lchange" to ensure that
 * redisplay is done in all buffers. Bound to
 * "C-X C-L".
 */
upperregion(f, n)
{
    register LINE   *linep;
    register int    loffs;
    register int    c;
    register int    s;
    REGION          region;
    CELL            ac;

    ac.a = 0;
    if (curbp->b_mode&MDVIEW)	/* don't allow this command if	*/
      return(rdonly());	/* we are in read only mode	*/

    if ((s=getregion(&region)) != TRUE)
      return (s);

    lchange(WFHARD);
    linep = region.r_linep;
    loffs = region.r_offset;
    while (region.r_size--) {
	if (loffs == llength(linep)) {
	    linep = lforw(linep);
	    loffs = 0;
	} else {
	    c = lgetc(linep, loffs).c;
	    if (c>='a' && c<='z'){
		ac.c = c - 'a' + 'A';
		lputc(linep, loffs, ac);
	    }
	    ++loffs;
	}
    }

    return (TRUE);
}

/*
 * This routine figures out the
 * bounds of the region in the current window, and
 * fills in the fields of the "REGION" structure pointed
 * to by "rp". Because the dot and mark are usually very
 * close together, we scan outward from dot looking for
 * mark. This should save time. Return a standard code.
 * Callers of this routine should be prepared to get
 * an "ABORT" status; we might make this have the
 * conform thing later.
 */
getregion(rp)
register REGION *rp;
{
    register LINE   *flp;
    register LINE   *blp;
    int    fsize;
    register int    bsize;

    if (curwp->w_markp == NULL) {
	return (FALSE);
    }

    if (curwp->w_dotp == curwp->w_markp) {
	rp->r_linep = curwp->w_dotp;
	if (curwp->w_doto < curwp->w_marko) {
	    rp->r_offset = curwp->w_doto;
	    rp->r_size = curwp->w_marko-curwp->w_doto;
	} else {
	    rp->r_offset = curwp->w_marko;
	    rp->r_size = curwp->w_doto-curwp->w_marko;
	}
	return (TRUE);
    }

    blp = curwp->w_dotp;
    bsize = curwp->w_doto;
    flp = curwp->w_dotp;
    fsize = llength(flp)-curwp->w_doto+1;
    while (flp!=curbp->b_linep || lback(blp)!=curbp->b_linep) {
	if (flp != curbp->b_linep) {
	    flp = lforw(flp);
	    if (flp == curwp->w_markp) {
		rp->r_linep = curwp->w_dotp;
		rp->r_offset = curwp->w_doto;
		rp->r_size = fsize+curwp->w_marko;
		return (TRUE);
	    }

	    fsize += llength(flp)+1;
	}

	if (lback(blp) != curbp->b_linep) {
	    blp = lback(blp);
	    bsize += llength(blp)+1;
	    if (blp == curwp->w_markp) {
		rp->r_linep = blp;
		rp->r_offset = curwp->w_marko;
		rp->r_size = bsize - curwp->w_marko;
		return (TRUE);
	    }
	}
    }

    emlwrite("Bug: lost mark", NULL);
    return (FALSE);
}


/*
 * set the highlight attribute accordingly on all characters in region
 */
markregion(attr)
    int attr;
{
    register LINE   *linep;
    register int    loffs;
    register int    s;
    REGION          region;
    CELL            ac;

    if ((s=getregion(&region)) != TRUE)
      return (s);

    lchange(WFHARD);
    linep = region.r_linep;
    loffs = region.r_offset;
    while (region.r_size--) {
	if (loffs == llength(linep)) {
	    linep = lforw(linep);
	    loffs = 0;
	} else {
	    ac = lgetc(linep, loffs);
	    ac.a = attr;
	    lputc(linep, loffs, ac);
	    ++loffs;
	}
    }

    return (TRUE);
}


/*
 * clear all the attributes of all the characters in the buffer?
 * this is real dumb.  Movement with mark set needs to be smarter!
 */
unmarkbuffer()
{
    register LINE   *linep;
    register int     n;
    CELL c;

    linep = curwp->w_linep;
    while(lforw(linep) != curwp->w_linep){
	n = llength(linep);
	for(n=0; n < llength(linep); n++){
	    c = lgetc(linep, n);
	    c.a = 0;
	    lputc(linep, n, c);
	}

	linep = lforw(linep);
    }
    
}
ITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
 * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
 * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN DarkNET-1.08/pico.BBS/search.c                                                                         644   21270   21270        26646  5672510624  11066                                                                                                                                                                                                                                                                                                                                                                      #if	!defined(lint) && !defined(DOS)
static char rcsid[] = "$Id: search.c,v 4.7 1994/08/03 03:05:03 mikes Exp $";
#endif
/*
 * Program:	Searching routines
 *
 *
 * Michael Seibel
 * Networks and Distributed Computing
 * Computing and Communications
 * University of Washington
 * Administration Builiding, AG-44
 * Seattle, Washington, 98195, USA
 * Internet: mikes@cac.washington.edu
 *
 * Please address all bugs and comments to "pine-bugs@cac.washington.edu"
 *
 * Copyright 1991-1994  University of Washington
 *
 *  Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee to the University of
 * Washington is hereby granted, provided that the above copyright notice
 * appears in all copies and that both the above copyright notice and this
 * permission notice appear in supporting documentation, and that the name
 * of the University of Washington not be used in advertising or publicity
 * pertaining to distribution of the software without specific, written
 * prior permission.  This software is made available "as is", and
 * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
 * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
 * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
 * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 * Pine and Pico are trademarks of the University of Washington.
 * No commercial use of these trademarks may be made without prior
 * written permission of the University of Washington.
 *
 */
/*
 * The functions in this file implement commands that search in the forward
 * and backward directions. There are no special characters in the search
 * strings. Probably should have a regular expression search, or something
 * like that.
 *
 */

#include        <stdio.h>
#include	"osdep.h"
#include	"estruct.h"
#include	"pico.h"
#include        "edef.h"

#ifdef	ANSI
    int eq(int, int);
    int expandp(char *, char *, int);
#else
    int eq();
    int expandp();
#endif


/*
 * Search forward. Get a search string from the user, and search, beginning at
 * ".", for the string. If found, reset the "." to be just after the match
 * string, and [perhaps] repaint the display. Bound to "C-S".
 */

/*	string search input parameters	*/

#define	PTBEG	1	/* leave the point at the begining on search */
#define	PTEND	2	/* leave the point at the end on search */




static char *SearchHelpText[] = {
"Help for Search Command",
" ",
"\tEnter the words or characters you would like to search",
"~\tfor, then press ~R~e~t~u~r~n.  The search then takes place.",
"\tWhen the characters or words that you entered ",
"\tare found, the buffer will be redisplayed with the cursor ",
"\tat the beginning of the selected text.",
" ",
"\tThe most recent string for which a search was made is",
"\tdisplayed in the \"Search\" prompt between the square",
"\tbrackets.  This string is the default search prompt.",
"~        Hitting only ~R~e~t~u~r~n or at the prompt will cause the",
"\tsearch to be made with the default value.",
"  ",
"\tThe text search is not case sensitive, and will examine the",
"\tentire message.",
"  ",
"\tShould the search fail, a message will be displayed.",
"  ",
"End of Search Help.",
"  ",
NULL
};


/*
 * Compare two characters. The "bc" comes from the buffer. It has it's case
 * folded out. The "pc" is from the pattern.
 */
eq(bc, pc)
int bc;
int pc;
{
    if ((curwp->w_bufp->b_mode & MDEXACT) == 0){
	if (bc>='a' && bc<='z')
	  bc -= 0x20;

	if (pc>='a' && pc<='z')
	  pc -= 0x20;
    }

    return(bc == pc);
}


forwsearch(f, n)
{
    extern int lang;
    register int status;
    int wrapt = FALSE;
    char show[512];

    /* resolve the repeat count */
    if (n == 0)
      n = 1;

    if (n < 1)			/* search backwards */
      return(0);

    /* ask the user for the text of a pattern */
    while(1){
	if (lang) {
	  if ((status = readpattern("Ã£¾î")) == TRUE){
	    break;
	  }
	} else {
	  if ((status = readpattern("Search")) == TRUE){
	    break;
	  }
	}
	    switch(status){
	      case HELPCH:			/* help requested */
		if(Pmaster)
		  (*Pmaster->helper)(Pmaster->search_help,
				     "Help for Searching", 1);
		else
		  pico_help(SearchHelpText, "Help for Searching", 1);
	      case (CTRL|'L'):			/* redraw requested */
		refresh(FALSE, 1);
		update();
		break;
	      case  (CTRL|'V'):
		gotoeob(0, 1);
		mlerase();
		curwp->w_flag |= WFMODE;
		return(TRUE);
	      case (CTRL|'Y'):
		gotobob(0, 1);
		mlerase();
		curwp->w_flag |= WFMODE;
		return(TRUE);
	      default:
		curwp->w_flag |= WFMODE;
		if(status == ABORT)
		  emlwrite("Search Cancelled", NULL);
		else
		  mlerase();
		return(FALSE);
	    }
    }

    curwp->w_flag |= WFMODE;

    /*
     * This code is kind of dumb.  What I want is successive C-W 's to 
     * move dot to successive occurences of the pattern.  So, if dot is
     * already sitting at the beginning of the pattern, then we'll move
     * forward a char before beginning the search.  We'll let the
     * automatic wrapping handle putting the dot back in the right 
     * place...
     */
    status = 0;		/* using "status" as int temporarily! */
    while(1){
	if(pat[status] == '\0'){
	    forwchar(0, 1);
	    break;		/* find next occurance! */
	}

	if(status + curwp->w_doto >= llength(curwp->w_dotp) ||
	   !eq(pat[status],lgetc(curwp->w_dotp, curwp->w_doto + status).c))
	  break;		/* do nothing! */
	status++;
    }

    /* search for the pattern */
    
    while (n-- > 0) {
	if((status = forscan(&wrapt,&pat[0],PTBEG)) == FALSE)
	  break;
    }

    /* and complain if not there */
    if (status == FALSE){
	expandp(&pat[0], &show[0], 50);
	if (lang)
	  emlwrite("\"%s\" ¾ø³×¿ä", show);
	else
	  emlwrite("\"%s\" not found", show);
    } 
    else if(wrapt == TRUE){
	if (lang)
	  emlwrite("ÇÑ¹ÙÄû µ¹¾Ò¾î¿ä");
	else
	  emlwrite("Search Wrapped");
    }
    else if(status == TRUE)
      emlwrite("");

    return(status);
}


/*
 * Read a pattern. Stash it in the external variable "pat". The "pat" is not
 * updated if the user types in an empty line. If the user typed an empty line,
 * and there is no old pattern, it is an error. Display the old pattern, in the
 * style of Jeff Lomicka. There is some do-it-yourself control expansion.
 * change to using <ESC> to delemit the end-of-pattern to allow <NL>s in
 * the search string.
 */
readpattern(prompt)
char *prompt;
{
	extern int lang;
	register int s;
	char	     tpat[NPAT+20];
	KEYMENU	     menu_pat[3];

	menu_pat[0].name  = "^Y";
	if (lang)
	  menu_pat[0].label = "Ã¹Â°ÁÙ";
	else
	  menu_pat[0].label = "FirstLine";
	menu_pat[1].name  = "^V";
	if (lang)
	  menu_pat[1].label = "¸¶Áö¸·ÁÙ";
	else
	  menu_pat[1].label = "LastLine";
	menu_pat[2].name  = NULL;

	strcpy(tpat, prompt);	/* copy prompt to output string */
        if(pat[0] != '\0'){
	    strcat(tpat, " [");	/* build new prompt string */
	    expandp(&pat[0], &tpat[strlen(tpat)], NPAT/2);	/* add old pattern */
	    strcat(tpat, "]");
        }
	strcat(tpat, " : ");

	s = mlreplyd(tpat, tpat, NPAT, QNORML|QPAGE, menu_pat);

	if (s == TRUE)				/* Specified */
		strcpy(pat, tpat);
	else if (s == FALSE && pat[0] != 0)	/* CR, but old one */
		s = TRUE;

	return(s);
}


forscan(wrapt,patrn,leavep)	/*	search forward for a <patrn>	*/
int	*wrapt;		/* boolean indicating search wrapped */
char *patrn;		/* string to scan for */
int leavep;		/* place to leave point
				PTBEG = begining of match
				PTEND = at end of match		*/

{
	register LINE *curline;		/* current line during scan */
	register int curoff;		/* position within current line */
	register LINE *lastline;	/* last line position during scan */
	register int lastoff;		/* position within last line */
	register int c;			/* character at current position */
	register LINE *matchline;	/* current line during matching */
	register int matchoff;		/* position in matching line */
	register char *patptr;		/* pointer into pattern */
	register int stopoff;		/* offset to stop search */
	register LINE *stopline;	/* line to stop search */

	*wrapt = FALSE;

	/*
	 * the idea is to set the character to end the search at the 
	 * next character in the buffer.  thus, let the search wrap
	 * completely around the buffer.
	 * 
	 * first, test to see if we are at the end of the line, 
	 * otherwise start searching on the next character. 
	 */
	if(curwp->w_doto == llength(curwp->w_dotp)){
		/*
		 * dot is not on end of a line
		 * start at 0 offset of the next line
		 */
		stopoff = curoff  = 0;
		stopline = curline = lforw(curwp->w_dotp);
		if (curwp->w_dotp == curbp->b_linep)
		  *wrapt = TRUE;
	}
	else{
		stopoff = curoff  = curwp->w_doto;
		stopline = curline = curwp->w_dotp;
	}

	/* scan each character until we hit the head link record */

	/*
	 * maybe wrapping is a good idea
	 */
	while (curline){

	    if (curline == curbp->b_linep)
	        *wrapt = TRUE;

		/* save the current position in case we need to
		   restore it on a match			*/

		lastline = curline;
		lastoff = curoff;

		/* get the current character resolving EOLs */

		if (curoff == llength(curline)) {	/* if at EOL */
			curline = lforw(curline);	/* skip to next line */
			curoff = 0;
			c = '\n';			/* and return a <NL> */
		} else
			c = lgetc(curline, curoff++).c;	/* get the char */

		/* test it against first char in pattern */
		if (eq(c, patrn[0]) != FALSE) {	/* if we find it..*/
			/* setup match pointers */
			matchline = curline;
			matchoff = curoff;
			patptr = &patrn[0];

			/* scan through patrn for a match */
			while (*++patptr != 0) {
				/* advance all the pointers */
				if (matchoff == llength(matchline)) {
					/* advance past EOL */
					matchline = lforw(matchline);
					matchoff = 0;
					c = '\n';
				} else
					c = lgetc(matchline, matchoff++).c;

				/* and test it against the pattern */
				if (eq(*patptr, c) == FALSE)
					goto fail;
			}

			/* A SUCCESSFULL MATCH!!! */
			/* reset the global "." pointers */
			if (leavep == PTEND) {	/* at end of string */
				curwp->w_dotp = matchline;
				curwp->w_doto = matchoff;
			} else {		/* at begining of string */
				curwp->w_dotp = lastline;
				curwp->w_doto = lastoff;
			}
			curwp->w_flag |= WFMOVE; /* flag that we have moved */
			return(TRUE);

		}
fail:;			/* continue to search */
		if((curline == stopline) && (curoff == stopoff))
			break;			/* searched everywhere... */
	}
	/* we could not find a match */

	return(FALSE);
}

/* 	expandp:	expand control key sequences for output		*/

expandp(srcstr, deststr, maxlength)

char *srcstr;	/* string to expand */
char *deststr;	/* destination of expanded string */
int maxlength;	/* maximum chars in destination */

{
	char c;		/* current char to translate */

	/* scan through the string */
	while ((c = *srcstr++) != 0) {
		if (c == '\n') {		/* its an EOL */
			*deststr++ = '<';
			*deststr++ = 'N';
			*deststr++ = 'L';
			*deststr++ = '>';
			maxlength -= 4;
		} else if (c < 0x20 || c == 0x7f) {	/* control character */
			*deststr++ = '^';
			*deststr++ = c ^ 0x40;
			maxlength -= 2;
		} else if (c == '%') {
			*deststr++ = '%';
			*deststr++ = '%';
			maxlength -= 2;

		} else {			/* any other character */
			*deststr++ = c;
			maxlength--;
		}

		/* check for maxlength */
		if (maxlength < 4) {
			*deststr++ = '$';
			*deststr = '\0';
			return(FALSE);
		}
	}
	*deststr = '\0';
	return(TRUE);
}
{
	    forwchar(0, 1);
	    break;		/* find next occurance! */
	}

	if(status + curwp->w_dDarkNET-1.08/pico.BBS/spell.c                                                                          644   21270   21270        16171  5672463052  10732                                                                                                                                                                                                                                                                                                                                                                      #if	!defined(lint) && !defined(DOS)
static char rcsid[] = "$Id: spell.c,v 4.8 1994/03/24 18:22:57 mikes Exp $";
#endif
/*
 * Program:	spell.c
 *
 *
 * Michael Seibel
 * Networks and Distributed Computing
 * Computing and Communications
 * University of Washington
 * Administration Builiding, AG-44
 * Seattle, Washington, 98195, USA
 * Internet: mikes@cac.washington.edu
 *
 * Please address all bugs and comments to "pine-bugs@cac.washington.edu"
 *
 * Copyright 1991-1994  University of Washington
 *
 *  Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee to the University of
 * Washington is hereby granted, provided that the above copyright notice
 * appears in all copies and that both the above copyright notice and this
 * permission notice appear in supporting documentation, and that the name
 * of the University of Washington not be used in advertising or publicity
 * pertaining to distribution of the software without specific, written
 * prior permission.  This software is made available "as is", and
 * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
 * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
 * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
 * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 * Pine and Pico are trademarks of the University of Washington.
 * No commercial use of these trademarks may be made without prior
 * written permission of the University of Washington.
 *
 */

#include <stdio.h>
#include "osdep.h"
#include "estruct.h"
#ifdef	SPELLER
#include "edef.h"
#include "pico.h"

#ifdef	ANSI
    void chword(char *, char *);
    int  movetoword(char *);
#else
    void chword();
    int  movetoword();
#endif


#define  NSHLINES  12

static char *spellhelp[] = {
  "Spell Check Help",
  " ",
  "\tThe spell checker examines all words in the text.  It then",
  "\toffers each misspelled word for correction while simultaneously",
  "\thighlighting it in the text.  To leave a word unchanged simply",
  "~\thit ~R~e~t~u~r~n at the edit prompt.  If a word has been corrected,",
  "\teach occurrence of the incorrect word is offered for replacement.",
  " ",
  "~\tSpell checking can be cancelled at any time by typing ~^~C (~F~3)",
  "\tafter exiting help.",
  " ",
  "End of Spell Check Help",
  " ",
  NULL
};


static char *pinespellhelp[] = {
  "Spell Check Help",
  " ",
  "\tThe spell checker examines all words in the text.  It then",
  "\toffers each misspelled word for correction while simultaneously",
  "\thighlighting it in the text.  To leave a word unchanged simply",
  "\thit Return at the edit prompt.  If a word has been corrected,",
  "\teach occurrence of the incorrect word is offered for replacement.",
  " ",
  "\tSpell checking can be cancelled at any time by typing ^C (F3)",
  "\tafter exiting help.",
  " ",
  "End of Spell Check Help",
  " ",
  NULL
};



/*
 * spell() - check for potentially missspelled words and offer them for
 *           correction
 */
spell(f, n)
{
    int    status, next, ret;
    FILE   *p;
    char   *b, *sp, *fn;
    char   wb[NLINE], cb[NLINE];
    char   *writetmp();
    FILE   *P_open();

    setimark(0, 1);
    emlwrite("Checking spelling..."); 		/* greetings */

    if((fn = writetmp(0, 0)) == NULL){
	emlwrite("Can't write temp file for spell checker");
	return(-1);
    }
    if((sp = (char *)getenv("SPELL")) == NULL)
      sp = SPELLER;

    sprintf(cb, "( %s ) < %s", sp, fn);		/* pre-use buffer! */
    if((p = P_open(cb)) == NULL){ 		/* read output from command */
	unlink(fn);
	emlwrite("Can't fork spell checker", NULL);
	return(-1);
    }

    ret = 1;
    while(fgets(wb, NLINE, p) != NULL && ret){
	if((b = (char *)strchr(wb,'\n')) != NULL)
	  *b = '\0';
	strcpy(cb, wb);

	gotobob(0, 1);

	status = TRUE;
	next = 1;

	while(status){
	    if(next++)
	      if(movetoword(wb) != TRUE)
		break;

	    update();
	    (*term.t_rev)(1);
	    pputs(wb, 1);			/* highlight word */
	    (*term.t_rev)(0);

	    if(strcmp(cb, wb)){
		char prompt[2*NLINE + 32];
		sprintf(prompt, "Replace \"%s\" with \"%s\"", wb, cb);
		status=mlyesno(prompt, TRUE);
	    }
	    else
	      status=mlreplyd("Edit a replacement: ", cb, NLINE, QDEFLT, NULL);


	    curwp->w_flag |= WFMOVE;		/* put cursor back */
	    sgarbk = 0;				/* fake no-keymenu-change! */
	    update();
	    pputs(wb, 0);			/* un-highlight */

	    switch(status){
	      case TRUE:
		chword(wb, cb);			/* correct word    */
	      case FALSE:
		update();			/* place cursor */
		break;
	      case ABORT:
		emlwrite("Spell Checking Cancelled", NULL);
		ret = FALSE;
		status = FALSE;
		break;
	      case HELPCH:
		if(Pmaster)
		  (*Pmaster->helper)(pinespellhelp, 
				     "Help with Spelling Checker", 1);
		else
		  pico_help(spellhelp, "Help with Spelling Checker", 1);
	      case (CTRL|'L'):
		next = 0;			/* don't get next word */
		sgarbf = TRUE;			/* repaint full screen */
		update();
		status = TRUE;
		continue;
	      default:
		emlwrite("Huh?");		/* shouldn't get here, but.. */
		status = TRUE;
		sleep(1);
		break;
	    }
	    forwword(0, 1);			/* goto next word */
	}
    }
    P_close(p);					/* clean up */
    unlink(fn);
    swapimark(0, 1);
    curwp->w_flag |= WFHARD|WFMODE;
    sgarbk = TRUE;

    if(ret)
      emlwrite("Done checking spelling");
    return(ret);
}




/* 
 * chword() - change the given word, wp, pointed to by the curwp->w_dot 
 *            pointers to the word in cb
 */
void
chword(wb, cb)
  char *wb;					/* word buffer */
  char *cb;					/* changed buffer */
{
    ldelete(strlen(wb), 0);			/* not saved in kill buffer */
    while(*cb != '\0')
      linsert(1, *cb++);

    curwp->w_flag |= WFEDIT;
}




/* 
 * movetoword() - move to the first occurance of the word w
 *
 *	returns:
 *		TRUE upon success
 *		FALSE otherwise
 */
movetoword(w)
  char *w;
{
    int      i;
    int      ret  = FALSE;
    int	     olddoto;
    LINE     *olddotp;
    register int   off;				/* curwp offset */
    register LINE *lp;				/* curwp line   */

    olddoto = curwp->w_doto;			/* save where we are */
    olddotp = curwp->w_dotp;

    curwp->w_bufp->b_mode |= MDEXACT;		/* case sensitive */
    while(forscan(&i, w, 1) == TRUE){
	if(i)
	  break;				/* wrap NOT allowed! */

	lp  = curwp->w_dotp;			/* for convenience */
	off = curwp->w_doto;

	/*
	 * We want to minimize the number of substrings that we report
	 * as matching a misspelled word...
	 */
	if(off == 0 || !myisalpha(lgetc(lp, off - 1).c)){
	    off += strlen(w);
	    if((!myisalpha(lgetc(lp, off).c) || off == llength(lp)) 
	       && lgetc(lp, 0).c != '>'){
		ret = TRUE;
		break;
	    }
	}

	forwchar(0, 1);				/* move on... */

    }
    curwp->w_bufp->b_mode ^= MDEXACT;		/* case insensitive */

    if(ret == FALSE){
	curwp->w_dotp = olddotp;
	curwp->w_doto = olddoto;
    }
    else
      curwp->w_flag |= WFHARD;

    return(ret);
}
#endif	/* SPELLER */
                                                                                                                                                                                                                                                                                                                                                                                                       DarkNET-1.08/pico.BBS/tcap.c                                                                           644   21270   21270        30654  5672475612  10551                                                                                                                                                                                                                                                                                                                                                                      #if	!defined(lint) && !defined(DOS)
static char rcsid[] = "$Id: tcap.c,v 4.13 1994/03/17 01:00:06 mikes Exp $";
#endif
/*
 * Program:	Display routines
 *
 *
 * Michael Seibel
 * Networks and Distributed Computing
 * Computing and Communications
 * University of Washington
 * Administration Builiding, AG-44
 * Seattle, Washington, 98195, USA
 * Internet: mikes@cac.washington.edu
 *
 * Please address all bugs and comments to "pine-bugs@cac.washington.edu"
 *
 * Copyright 1991-1994  University of Washington
 *
 *  Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee to the University of
 * Washington is hereby granted, provided that the above copyright notice
 * appears in all copies and that both the above copyright notice and this
 * permission notice appear in supporting documentation, and that the name
 * of the University of Washington not be used in advertising or publicity
 * pertaining to distribution of the software without specific, written
 * prior permission.  This software is made available "as is", and
 * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
 * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
 * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
 * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 * Pine and Pico are trademarks of the University of Washington.
 * No commercial use of these trademarks may be made without prior
 * written permission of the University of Washington.
 *
 */
/*	tcap:	Unix V5, V7 and BS4.2 Termcap video driver
		for MicroEMACS
*/

#define	termdef	1			/* don't define "term" external */

#include	<stdio.h>
#include        <signal.h>
#include	"osdep.h"
#include	"estruct.h"
#include        "edef.h"

#if TERMCAP
#include        "pico.h"

#define NROW    24
#define NCOL    80
#define	MARGIN	8
#define	SCRSIZ	64
#define BEL     0x07
#define ESC     0x1B

extern int      ttopen();
extern int      ttgetc();
extern int      ttputc();
extern int      ttflush();
extern int      ttclose();
extern int      tcapmove();
extern int      tcapeeol();
extern int      tcapeeop();
extern int      tcapbeep();
extern int	tcaprev();
extern int      tcapopen();
extern int      tcapclose();
extern int      tput();
extern char     *tgoto();

#define TCAPSLEN 315
char tcapbuf[TCAPSLEN];
char *UP, PC, *CM, *CE, *CL, *SO, *SE;
/* 
 * PICO extentions 
 */
char	*DL,			/* delete line */
	*AL,			/* insert line */
	*CS,			/* define a scrolling region, vt100 */
	*IC,			/* insert character, preferable to : */
	*IM,			/* set insert mode and, */
	*EI,			/* end insert mode */
	*DC,			/* delete character */
	*DM,			/* set delete mode and, */
	*ED,			/* end delete mode */
	*SF,			/* scroll text up */
	*SR,			/* scroll text down */
	*TI,			/* string to start termcap */
        *TE;			/* string to end termcap */

char *KU, *KD, *KL, *KR;
char *KPPU, *KPPD, *KPHOME, *KPEND;

struct KBSTREE *kpadseqs = NULL;

TERM term = {
        NROW-1,
        NCOL,
	MARGIN,
	SCRSIZ,
        tcapopen,
        tcapclose,
        ttgetc,
        ttputc,
        ttflush,
        tcapmove,
        tcapeeol,
        tcapeeop,
        tcapbeep,
        tcaprev
};


tcapopen()
{
    char   *t, *p, *tgetstr();
    char    tcbuf[1024];
    char   *tv_stype;
    char    err_str[72];
    char   *getenv();

    ttgetwinsz();

    /*
     * determine the terminal's communication speed and decide
     * if we need to do optimization ...
     */
/*
    optimize = ttisslow();
*/
    optimize = TRUE;

    if ((tv_stype = getenv("TERM")) == NULL){
	if(Pmaster){
	    return(FALSE);
	}
	else{
	    puts("Environment variable TERM not defined!");
	    exit(1);
	}
    }

    if((tgetent(tcbuf, tv_stype)) != 1){
	if(Pmaster){
	    return(FALSE);
	}
	else{
	    sprintf(err_str, "Unknown terminal type %s!", tv_stype);
	    puts(err_str);
	    exit(1);
	}
    }

    p = tcapbuf;
    t = tgetstr("pc", &p);
    if(t)
      PC = *t;

    CL = tgetstr("cl", &p);
    CM = tgetstr("cm", &p);
    CE = tgetstr("ce", &p);
    UP = tgetstr("up", &p);
    SE = tgetstr("se", &p);
    SO = tgetstr("so", &p);
    DL = tgetstr("dl", &p);
    AL = tgetstr("al", &p);
    CS = tgetstr("cs", &p);
    IC = tgetstr("ic", &p);
    IM = tgetstr("im", &p);
    EI = tgetstr("ei", &p);
    DC = tgetstr("dc", &p);
    DM = tgetstr("dm", &p);
    ED = tgetstr("ed", &p);
    SF = tgetstr("sf", &p);
    SR = tgetstr("sr", &p);
    TI = tgetstr("ti", &p);
    TE = tgetstr("te", &p);

    eolexist = (CE != NULL);	/* will we be able to use clear to EOL? */
    revexist = (SO != NULL);
    if(DC == NULL && (DM == NULL || ED == NULL))
      delchar = FALSE;
    if(IC == NULL && (IM == NULL || EI == NULL))
      inschar = FALSE;
    if((CS==NULL || SF==NULL || SR==NULL) && (DL==NULL || AL==NULL))
      scrollexist = FALSE;

    if(CL == NULL || CM == NULL || UP == NULL){
	if(Pmaster == NULL){
	    puts("Incomplete termcap entry\n");
	    exit(1);
	}
    }
    else{
	KPPU   = tgetstr("kP", &p);
	KPPD   = tgetstr("kN", &p);
	KPHOME = tgetstr("kh", &p);
	KU     = tgetstr("ku", &p);
	KD     = tgetstr("kd", &p);
	KL     = tgetstr("kl", &p);
	KR     = tgetstr("kr", &p);
	if(KU != NULL && (KL != NULL && (KR != NULL && KD != NULL))){
	    kpinsert(KU,K_PAD_UP);
	    kpinsert(KD,K_PAD_DOWN);
	    kpinsert(KL,K_PAD_LEFT);
	    kpinsert(KR,K_PAD_RIGHT);

	    if(KPPU != NULL)
	      kpinsert(KPPU,K_PAD_PREVPAGE);
	    if(KPPD != NULL)
	      kpinsert(KPPD,K_PAD_NEXTPAGE);
	    if(KPHOME != NULL)
	      kpinsert(KPHOME,K_PAD_HOME);
	}
    }

    /*
     * add default keypad sequences to the trie...
     */
    if(gmode&MDFKEY){
	/*
	 * Initialize UW-modified NCSA telnet to use it's functionkeys
	 */
	if(Pmaster == NULL){
	    puts("\033[99h");
	}

	/*
	 * this is sort of a hack, but it allows us to use
	 * the function keys on pc's running telnet
	 */

	/* 
	 * UW-NDC/UCS vt10[02] application mode.
	 */
	kpinsert("OP",F1);
	kpinsert("OQ",F2);
	kpinsert("OR",F3);
	kpinsert("OS",F4);
	kpinsert("Op",F5);
	kpinsert("Oq",F6);
	kpinsert("Or",F7);
	kpinsert("Os",F8);
	kpinsert("Ot",F9);
	kpinsert("Ou",F10);
	kpinsert("Ov",F11);
	kpinsert("Ow",F12);

	/*
	 * special keypad functions
	 */
	kpinsert("[4J",K_PAD_PREVPAGE);
	kpinsert("[3J",K_PAD_NEXTPAGE);
	kpinsert("[2J",K_PAD_HOME);
	kpinsert("[N",K_PAD_END);

	/* 
	 * ANSI mode.
	 */
	kpinsert("[=a",F1);
	kpinsert("[=b",F2);
	kpinsert("[=c",F3);
	kpinsert("[=d",F4);
	kpinsert("[=e",F5);
	kpinsert("[=f",F6);
	kpinsert("[=g",F7);
	kpinsert("[=h",F8);
	kpinsert("[=i",F9);
	kpinsert("[=j",F10);
	kpinsert("[=k",F11);
	kpinsert("[=l",F12);
    }

    kpinsert("OA",K_PAD_UP);	/* DEC vt100, ANSI and cursor key mode. */
    kpinsert("OB",K_PAD_DOWN);
    kpinsert("OD",K_PAD_LEFT);
    kpinsert("OC",K_PAD_RIGHT);

    kpinsert("[A",K_PAD_UP);	/* DEC vt100, ANSI, cursor key mode reset. */
    kpinsert("[B",K_PAD_DOWN);
    kpinsert("[D",K_PAD_LEFT);
    kpinsert("[C",K_PAD_RIGHT);

    kpinsert("A",K_PAD_UP);	/* DEC vt52 mode. */
    kpinsert("B",K_PAD_DOWN);
    kpinsert("D",K_PAD_LEFT);
    kpinsert("C",K_PAD_RIGHT);

    kpinsert("[215z",K_PAD_UP); /* Sun Console sequences. */
    kpinsert("[221z",K_PAD_DOWN);
    kpinsert("[217z",K_PAD_LEFT);
    kpinsert("[219z",K_PAD_RIGHT);

    if (p >= &tcapbuf[TCAPSLEN]){
	if(Pmaster == NULL){
	    puts("Terminal description too big!\n");
	    exit(1);
	}
    }

    ttopen();

    if(TI && !Pmaster) {
	putpad(TI);			/* any init termcap requires */
	if (CS)
	  putpad(tgoto(CS, term.t_nrow, 0)) ;
    }
}


tcapclose()
{
    if(!Pmaster){
	if(gmode&MDFKEY)
	  puts("\033[99l");		/* reset UW-NCSA telnet keys */

	if(TE)				/* any cleanup termcap requires */
	  putpad(TE);
    }

    ttclose();
}



#define	newnode()	(struct KBSTREE *)malloc(sizeof(struct KBSTREE))
/*
 * kbinsert - insert a keystroke escape sequence into the global search
 *	      structure.
 */
kpinsert(kstr, kval)
char	*kstr;
int	kval;
{
    register	char	*buf;
    register	struct KBSTREE *temp;
    register	struct KBSTREE *trail;

    if(kstr == NULL)
      return;

    temp = trail = kpadseqs;
    if(kstr[0] == '\033')
      buf = kstr+1;			/* can the ^[ character */ 
    else
      buf = kstr;

    for(;;) {
	if(temp == NULL){
	    temp = newnode();
	    temp->value = *buf;
	    temp->func = 0;
	    temp->left = NULL;
	    temp->down = NULL;
	    if(kpadseqs == NULL)
	      kpadseqs = temp;
	    else
	      trail->down = temp;
	}
	else{				/* first entry */
	    while((temp != NULL) && (temp->value != *buf)){
		trail = temp;
		temp = temp->left;
	    }

	    if(temp == NULL){   /* add new val */
		temp = newnode();
		temp->value = *buf;
		temp->func = 0;
		temp->left = NULL;
		temp->down = NULL;
		trail->left = temp;
	    }
	}

	if (*(++buf) == '\0'){
	    break;
	}
	else{
	    trail = temp;
	    temp = temp->down;
	}
    }
    
    if(temp != NULL)
      temp->func = kval;
}



/*
 * tcapinsert - insert a character at the current character position.
 *              IC takes precedence.
 */
tcapinsert(ch)
register char	ch;
{
    if(IC != NULL){
	putpad(IC);
	ttputc(ch);
    }
    else{
	putpad(IM);
	ttputc(ch);
	putpad(EI);
    }
}


/*
 * tcapdelete - delete a character at the current character position.
 */
tcapdelete()
{
    if(DM == NULL && ED == NULL)
      putpad(DC);
    else{
	putpad(DM);
	putpad(DC);
	putpad(ED);
    }
}


/*
 * o_scrolldown - open a line at the given row position.
 *                use either region scrolling or deleteline/insertline
 *                to open a new line.
 */
o_scrolldown(row, n)
register int row;
register int n;
{
    register int i;

    if(CS != NULL){
	putpad(tgoto(CS, term.t_nrow - 3, row));
	tcapmove(row, 0);
	for(i = 0; i < n; i++)
	  putpad( (SR != NULL && *SR != '\0') ? SR : "\n" );
	putpad(tgoto(CS, term.t_nrow, 0));
	tcapmove(row, 0);
    }
    else{
	/*
	 * this code causes a jiggly motion of the keymenu when scrolling
	 */
	for(i = 0; i < n; i++){
	    tcapmove(term.t_nrow - 3, 0);
	    putpad(DL);
	    tcapmove(row, 0);
	    putpad(AL);
	}
#ifdef	NOWIGGLYLINES
	/*
	 * this code causes a sweeping motion up and down the display
	 */
	tcapmove(term.t_nrow - 2 - n, 0);
	for(i = 0; i < n; i++)
	  putpad(DL);
	tcapmove(row, 0);
	for(i = 0; i < n; i++)
	  putpad(AL);
#endif
    }
}


/*
 * o_scrollup - open a line at the given row position.
 *              use either region scrolling or deleteline/insertline
 *              to open a new line.
 */
o_scrollup(row, n)
register int row;
register int n;
{
    register int i;

    if(CS != NULL){
	putpad(tgoto(CS, term.t_nrow - 3, row));
	/* setting scrolling region moves cursor to home */
	tcapmove(term.t_nrow-3, 0);
	for(i = 0;i < n; i++)
	  putpad((SF == NULL || SF[0] == '\0') ? "\n" : SF);
	putpad(tgoto(CS, term.t_nrow, 0));
	tcapmove(2, 0);
    }
    else{
	for(i = 0; i < n; i++){
	    tcapmove(row, 0);
	    putpad(DL);
	    tcapmove(term.t_nrow - 3, 0);
	    putpad(AL);
	}
#ifdef  NOWIGGLYLINES
	/* see note above */
	tcapmove(row, 0);
	for(i = 0; i < n; i++)
	  putpad(DL);
	tcapmove(term.t_nrow - 2 - n, 0);
	for(i = 0;i < n; i++)
	  putpad(AL);
#endif
    }
}


/*
 * o_insert - use termcap info to optimized character insert
 *            returns: true if it optimized output, false otherwise
 */
o_insert(c)
char c;
{
    if(inschar){
	tcapinsert(c);
	return(1);			/* no problems! */
    }

    return(0);				/* can't do it. */
}


/*
 * o_delete - use termcap info to optimized character insert
 *            returns true if it optimized output, false otherwise
 */
o_delete()
{
    if(delchar){
	tcapdelete();
	return(1);			/* deleted, no problem! */
    }

    return(0);				/* no dice. */
}


tcapmove(row, col)
register int row, col;
{
    putpad(tgoto(CM, col, row));
}


tcapeeol()
{
    putpad(CE);
}


tcapeeop()
{
    putpad(CL);
}


tcaprev(state)		/* change reverse video status */
int state;	        /* FALSE = normal video, TRUE = reverse video */
{
    static int cstate = FALSE;

    if(state == cstate)		/* no op if already set! */
      return(0);

    if(cstate = state){		/* remember last setting */
	if (SO != NULL)
	  putpad(SO);
    } 
    else{
	if (SE != NULL)
	  putpad(SE);
    }
}


tcapbeep()
{
    ttputc(BEL);
}


putpad(str)
char    *str;
{
    tputs(str, 1, ttputc);
}


putnpad(str, n)
char    *str;
{
    tputs(str, n, ttputc);
}

#else

hello()
{
}

#endif /* TERMCAP */
 &p);
    CS = tgetstr("cs", &p);
    IC = tgetstr("ic", &p);
    IM = tgetstr("im",DarkNET-1.08/pico.BBS/tinfo.c                                                                          644   21270   21270        30575  5672475640  10744                                                                                                                                                                                                                                                                                                                                                                      #if	!defined(lint) && !defined(DOS)
static char rcsid[] = "$Id: tinfo.c,v 4.12 1994/03/17 01:00:14 mikes Exp $";
#endif
/*
 * Program:	Display routines
 *
 *
 * Donn Cave
 * Networks and Distributed Computing
 * Computing and Communications
 * University of Washington
 * Administration Builiding, AG-44
 * Seattle, Washington, 98195, USA
 * Internet: donn@cac.washington.edu
 *
 * Please address all bugs and comments to "pine-bugs@cac.washington.edu"
 *
 * Copyright 1991-1994  University of Washington
 *
 *  Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee to the University of
 * Washington is hereby granted, provided that the above copyright notice
 * appears in all copies and that both the above copyright notice and this
 * permission notice appear in supporting documentation, and that the name
 * of the University of Washington not be used in advertising or publicity
 * pertaining to distribution of the software without specific, written
 * prior permission.  This software is made available "as is", and
 * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
 * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
 * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
 * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 * Pine and Pico are trademarks of the University of Washington.
 * No commercial use of these trademarks may be made without prior
 * written permission of the University of Washington.
 *
 */
/*
 *      tinfo - substitute for tcap, on systems that have terminfo.
 */

#define	termdef	1			/* don't define "term" external */

#include	<stdio.h>
#include        <signal.h>
#include	"osdep.h"
#include	"estruct.h"
#include        "edef.h"
#include        "pico.h"

extern char *tigetstr ();

#define NROW    24
#define NCOL    80
#define	MARGIN	8
#define	SCRSIZ	64
#define BEL     0x07
#define ESC     0x1B

extern int      ttopen();
extern int      ttgetc();
extern int      ttputc();
extern int      ttflush();
extern int      ttclose();

static int      tinfomove();
static int      tinfoeeol();
static int      tinfoeeop();
static int      tinfobeep();
static int	tinforev();
static int      tinfoopen();
static int      tinfoclose();

extern int      tput();
extern char     *tgoto();

static int      kpinsert();
static int      putpad();

static char *UP, PC, *CM, *CE, *CL, *SO, *SE;
/* 
 * PICO extentions 
 */
static char *DL,			/* delete line */
	*AL,			/* insert line */
	*CS,			/* define a scrolling region, vt100 */
	*IC,			/* insert character, preferable to : */
	*IM,			/* set insert mode and, */
	*EI,			/* end insert mode */
	*DC,			/* delete character */
	*DM,			/* set delete mode and, */
	*ED,			/* end delete mode */
	*SF,			/* scroll text up */
	*SR,			/* scroll text down */
	*TI,			/* string to start termcap */
        *TE;			/* string to end termcap */

static char *KU, *KD, *KL, *KR;
static char *KPPU, *KPPD, *KPHOME, *KPEND;

struct KBSTREE *kpadseqs = NULL;

TERM term = {
        NROW-1,
        NCOL,
	MARGIN,
	SCRSIZ,
        tinfoopen,
        tinfoclose,
        ttgetc,
        ttputc,
        ttflush,
        tinfomove,
        tinfoeeol,
        tinfoeeop,
        tinfobeep,
        tinforev
};


static tinfoopen()
{
    char  *t;
    char  *getenv();

    ttgetwinsz();

    /*
     * determine the terminal's communication speed and decide
     * if we need to do optimization ...
     */
    optimize = TRUE;
/*
    optimize = ttisslow();
*/

    if (Pmaster) {
	/*
	 *		setupterm() automatically retrieves the value
	 *		of the TERM variable.
	 */
	int err;
	setupterm (0, 1, &err);
	if (err != 1) return FALSE;
    }
    else {
	/*
	 *		setupterm() issues a message and exits, if the
	 *		terminfo data base is gone or the term type is
	 *		unknown, if arg2 is 0.
	 */
	setupterm (0, 1, 0);
    }

    t = tigetstr("pad");
    if(t)
      PC = *t;

    CL = tigetstr("clear");
    CM = tigetstr("cup");
    CE = tigetstr("el");
    UP = tigetstr("cuu1");
    SE = tigetstr("rmso");
    SO = tigetstr("smso");
    DL = tigetstr("dl1");
    AL = tigetstr("il1");
    CS = tigetstr("csr");
    IC = tigetstr("ich1");
    IM = tigetstr("smir");
    EI = tigetstr("rmir");
    DC = tigetstr("dch1");
    DM = tigetstr("smdc");
    ED = tigetstr("rmdc");
    SF = tigetstr("ind");
    SR = tigetstr("ri");
    TI = tigetstr("smcup");
    TE = tigetstr("rmcup");

    eolexist = (CE != NULL);	/* will we be able to use clear to EOL? */
    revexist = (SO != NULL);	/* will be able to use reverse video */
    if(DC == NULL && (DM == NULL || ED == NULL))
      delchar = FALSE;
    if(IC == NULL && (IM == NULL || EI == NULL))
      inschar = FALSE;
    if((CS==NULL || SF==NULL || SR==NULL) && (DL==NULL || AL==NULL))
      scrollexist = FALSE;

    if(CL == NULL || CM == NULL || UP == NULL){
	if(Pmaster == NULL){
	    puts("Incomplete terminfo entry\n");
	    exit(1);
	}
    }
    else{
	KPPU   = tigetstr("kpp");
	KPPD   = tigetstr("knp");
	KPHOME = tigetstr("khome");
	KU = tigetstr("kcuu1");
	KD = tigetstr("kcud1");
	KL = tigetstr("kcub1");
	KR = tigetstr("kcuf1");
	if(KU != NULL && (KL != NULL && (KR != NULL && KD != NULL))){
	    kpinsert(KU,K_PAD_UP);
	    kpinsert(KD,K_PAD_DOWN);
	    kpinsert(KL,K_PAD_LEFT);
	    kpinsert(KR,K_PAD_RIGHT);

	    if(KPPU != NULL)
	      kpinsert(KPPU,K_PAD_PREVPAGE);
	    if(KPPD != NULL)
	      kpinsert(KPPD,K_PAD_NEXTPAGE);
	    if(KPHOME != NULL)
	      kpinsert(KPHOME,K_PAD_HOME);
	}
    }

    /*
     * add default keypad sequences to the trie...
     */
    if(gmode&MDFKEY){
	/*
	 * Initialize UW-modified NCSA telnet to use its functionkeys
	 */
	if(Pmaster == NULL){
	    puts("\033[99h");
	}

	/*
	 * this is sort of a hack [no kidding], but it allows us to use
	 * the function keys on pc's running telnet
	 */

	/* 
	 * UW-NDC/UCS vt10[01] application mode.
	 */
	kpinsert("OP",F1);
	kpinsert("OQ",F2);
	kpinsert("OR",F3);
	kpinsert("OS",F4);
	kpinsert("Op",F5);
	kpinsert("Oq",F6);
	kpinsert("Or",F7);
	kpinsert("Os",F8);
	kpinsert("Ot",F9);
	kpinsert("Ou",F10);
	kpinsert("Ov",F11);
	kpinsert("Ow",F12);

	/*
	 * special keypad functions
	 */
	kpinsert("[4J",K_PAD_PREVPAGE);
	kpinsert("[3J",K_PAD_NEXTPAGE);
	kpinsert("[2J",K_PAD_HOME);
	kpinsert("[N",K_PAD_END);

	/* 
	 * ANSI mode.
	 */
	kpinsert("[=a",F1);
	kpinsert("[=b",F2);
	kpinsert("[=c",F3);
	kpinsert("[=d",F4);
	kpinsert("[=e",F5);
	kpinsert("[=f",F6);
	kpinsert("[=g",F7);
	kpinsert("[=h",F8);
	kpinsert("[=i",F9);
	kpinsert("[=j",F10);
	kpinsert("[=k",F11);
	kpinsert("[=l",F12);
    }

    /*
     * DEC vt100, ANSI and cursor key mode.
     */
    kpinsert("OA",K_PAD_UP);
    kpinsert("OB",K_PAD_DOWN);
    kpinsert("OD",K_PAD_LEFT);
    kpinsert("OC",K_PAD_RIGHT);

    /*
     * DEC vt100, ANSI and cursor key mode reset.
     */
    kpinsert("[A",K_PAD_UP);
    kpinsert("[B",K_PAD_DOWN);
    kpinsert("[D",K_PAD_LEFT);
    kpinsert("[C",K_PAD_RIGHT);

    /*
     * DEC vt52 mode.
     */
    kpinsert("A",K_PAD_UP);
    kpinsert("B",K_PAD_DOWN);
    kpinsert("D",K_PAD_LEFT);
    kpinsert("C",K_PAD_RIGHT);

    /*
     * Sun Console sequences.
     */
    kpinsert("[215z",K_PAD_UP);
    kpinsert("[221z",K_PAD_DOWN);
    kpinsert("[217z",K_PAD_LEFT);
    kpinsert("[219z",K_PAD_RIGHT);

    ttopen();

    if(TI && !Pmaster){
	putpad(TI);			/* any init terminfo requires */
	if(CS)
	  putpad(tgoto(CS, term.t_nrow, 0));
    }
}


static tinfoclose()
{
    if(!Pmaster){
	if(gmode&MDFKEY)
	  puts("\033[99l");		/* reset UW-NCSA telnet keys */

	if(TE)				/* any clean up terminfo requires */
	  putpad(TE);
    }

    ttclose();
}


#define	newnode()	(struct KBSTREE *)malloc(sizeof(struct KBSTREE))
/*
 * kbinsert - insert a keystroke escape sequence into the global search
 *	      structure.
 */
static kpinsert(kstr, kval)
char	*kstr;
int	kval;
{
    register	char	*buf;
    register	struct KBSTREE *temp;
    register	struct KBSTREE *trail;

    if(kstr == NULL)
      return;

    temp = trail = kpadseqs;
    if(kstr[0] == '\033')
      buf = kstr+1;			/* can the ^[ character */ 
    else
      buf = kstr;

    for(;;) {
	if(temp == NULL){
	    temp = newnode();
	    temp->value = *buf;
	    temp->func = 0;
	    temp->left = NULL;
	    temp->down = NULL;
	    if(kpadseqs == NULL)
	      kpadseqs = temp;
	    else
	      trail->down = temp;
	}
	else{				/* first entry */
	    while((temp != NULL) && (temp->value != *buf)){
		trail = temp;
		temp = temp->left;
	    }
	    if(temp == NULL){   /* add new val */
		temp = newnode();
		temp->value = *buf;
		temp->func = 0;
		temp->left = NULL;
		temp->down = NULL;
		trail->left = temp;
	    }
	}

	if (*(++buf) == '\0'){
	    break;
	}
	else{
	    trail = temp;
	    temp = temp->down;
	}
    }

    if(temp != NULL)
      temp->func = kval;
}


/*
 * tinfoinsert - insert a character at the current character position.
 *               IC takes precedence.
 */
tinfoinsert(ch)
register char	ch;
{
    if(IC != NULL){
	putpad(IC);
	ttputc(ch);
    }
    else{
	putpad(IM);
	ttputc(ch);
	putpad(EI);
    }
}


/*
 * tinfodelete - delete a character at the current character position.
 */
tinfodelete()
{
    if(DM == NULL && ED == NULL)
      putpad(DC);
    else{
	putpad(DM);
	putpad(DC);
	putpad(ED);
    }
}


/*
 * o_scrolldown() - open a line at the given row position.
 *               use either region scrolling or deleteline/insertline
 *               to open a new line.
 */
o_scrolldown(row, n)
register int row;
register int n;
{
    register int i;

    if(CS != NULL){
	putpad(tgoto(CS, term.t_nrow - 3, row));
	tinfomove(row, 0);
	for(i = 0; i < n; i++)
	  putpad( (SR != NULL && *SR != '\0') ? SR : "\n" );
	putpad(tgoto(CS, term.t_nrow, 0));
	tinfomove(row, 0);
    }
    else{
	/*
	 * this code causes a jiggly motion of the keymenu when scrolling
	 */
	for(i = 0; i < n; i++){
	    tinfomove(term.t_nrow - 3, 0);
	    putpad(DL);
	    tinfomove(row, 0);
	    putpad(AL);
	}
#ifdef	NOWIGGLYLINES
	/*
	 * this code causes a sweeping motion up and down the display
	 */
	tinfomove(term.t_nrow - 2 - n, 0);
	for(i = 0; i < n; i++)
	  putpad(DL);
	tinfomove(row, 0);
	for(i = 0; i < n; i++)
	  putpad(AL);
#endif
    }
}


/*
 * o_scrollup() - open a line at the given row position.
 *               use either region scrolling or deleteline/insertline
 *               to open a new line.
 */
o_scrollup(row, n)
register int row;
register int n;
{
    register int i;

    if(CS != NULL){
	putpad(tgoto(CS, term.t_nrow - 3, row));
	/* setting scrolling region moves cursor to home */
	tinfomove(term.t_nrow-3, 0);
	for(i = 0;i < n; i++)
	  putpad((SF == NULL || SF[0] == '\0') ? "\n" : SF);
	putpad(tgoto(CS, term.t_nrow, 0));
	tinfomove(2, 0);
    }
    else{
	for(i = 0; i < n; i++){
	    tinfomove(row, 0);
	    putpad(DL);
	    tinfomove(term.t_nrow - 3, 0);
	    putpad(AL);
	}
#ifdef  NOWIGGLYLINES
	/* see note above */
	tinfomove(row, 0);
	for(i = 0; i < n; i++)
	  putpad(DL);
	tinfomove(term.t_nrow - 2 - n, 0);
	for(i = 0;i < n; i++)
	  putpad(AL);
#endif
    }
}



/*
 * o_insert - use terminfo to optimized character insert
 *            returns: true if it optimized output, false otherwise
 */
o_insert(c)
char c;
{
    if(inschar){
	tinfoinsert(c);
	return(1);			/* no problems! */
    }

    return(0);				/* can't do it. */
}


/*
 * o_delete - use terminfo to optimized character insert
 *            returns true if it optimized output, false otherwise
 */
o_delete()
{
    if(delchar){
	tinfodelete();
	return(1);			/* deleted, no problem! */
    }

    return(0);				/* no dice. */
}


static tinfomove(row, col)
register int row, col;
{
    putpad(tgoto(CM, col, row));
}


static tinfoeeol()
{
    putpad(CE);
}


static tinfoeeop()
{
        putpad(CL);
}


static tinforev(state)		/* change reverse video status */
int state;	                /* FALSE = normal video, TRUE = rev video */
{
    static int cstate = FALSE;

    if(state == cstate)		/* no op if already set! */
      return(0);

    if(cstate = state){		/* remember last setting */
	if (SO != NULL)
	  putpad(SO);
    } else {
	if (SE != NULL)
	  putpad(SE);
    }
}


static tinfobeep()
{
    ttputc(BEL);
}


static putpad(str)
char    *str;
{
    tputs(str, 1, ttputc);
}


static putnpad(str, n)
char    *str;
{
    tputs(str, n, ttputc);
}
                                                                                                                                   DarkNET-1.08/pico.BBS/window.c                                                                         644   21270   21270         5117  5672463052  11100                                                                                                                                                                                                                                                                                                                                                                      #if	!defined(lint) && !defined(DOS)
static char rcsid[] = "$Id: window.c,v 4.3 1994/02/25 18:36:33 hubert Exp $";
#endif
/*
 * Program:	Window management routines
 *
 *
 * Michael Seibel
 * Networks and Distributed Computing
 * Computing and Communications
 * University of Washington
 * Administration Builiding, AG-44
 * Seattle, Washington, 98195, USA
 * Internet: mikes@cac.washington.edu
 *
 * Please address all bugs and comments to "pine-bugs@cac.washington.edu"
 *
 * Copyright 1991-1994  University of Washington
 *
 *  Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee to the University of
 * Washington is hereby granted, provided that the above copyright notice
 * appears in all copies and that both the above copyright notice and this
 * permission notice appear in supporting documentation, and that the name
 * of the University of Washington not be used in advertising or publicity
 * pertaining to distribution of the software without specific, written
 * prior permission.  This software is made available "as is", and
 * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
 * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
 * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
 * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 * Pine and Pico are trademarks of the University of Washington.
 * No commercial use of these trademarks may be made without prior
 * written permission of the University of Washington.
 *
 */
/*
 * Window management. Some of the functions are internal, and some are
 * attached to keys that the user actually types.
 */

#include        <stdio.h>
#include        "estruct.h"
#include        "pico.h"
#include	"edef.h"
#include	"osdep.h"


/*
 * Refresh the screen. With no argument, it just does the refresh. With an
 * argument it recenters "." in the current window. Bound to "C-L".
 */
refresh(f, n)
  int f, n;
{
    /*
     * since pine mode isn't using the traditional mode line, sgarbf isn't
     * enough.
     */
    if(Pmaster)
        curwp->w_flag |= WFMODE;

    if (f == FALSE)
        sgarbf = TRUE;
    else{
        curwp->w_force = 0;             /* Center dot. */
        curwp->w_flag |= WFFORCE;
    }

    return (TRUE);
}
                                                                                                                                                                                                                                                                                                                                                                                                                                                 DarkNET-1.08/pico.BBS/word.c                                                                           644   21270   21270        37144  5672463052  10571                                                                                                                                                                                                                                                                                                                                                                      #if	!defined(lint) && !defined(DOS)
static char rcsid[] = "$Id: word.c,v 4.4 1994/02/25 18:36:33 hubert Exp $";
#endif
/*
 * Program:	Word at a time routines
 *
 *
 * Michael Seibel
 * Networks and Distributed Computing
 * Computing and Communications
 * University of Washington
 * Administration Builiding, AG-44
 * Seattle, Washington, 98195, USA
 * Internet: mikes@cac.washington.edu
 *
 * Please address all bugs and comments to "pine-bugs@cac.washington.edu"
 *
 * Copyright 1991-1994  University of Washington
 *
 *  Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee to the University of
 * Washington is hereby granted, provided that the above copyright notice
 * appears in all copies and that both the above copyright notice and this
 * permission notice appear in supporting documentation, and that the name
 * of the University of Washington not be used in advertising or publicity
 * pertaining to distribution of the software without specific, written
 * prior permission.  This software is made available "as is", and
 * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
 * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
 * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
 * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 * Pine and Pico are trademarks of the University of Washington.
 * No commercial use of these trademarks may be made without prior
 * written permission of the University of Washington.
 *
 */
/*
 * The routines in this file implement commands that work word at a time.
 * There are all sorts of word mode commands. If I do any sentence and/or
 * paragraph mode commands, they are likely to be put in this file.
 */

#include        <stdio.h>
#include        "estruct.h"
#include        "pico.h"
#include        <ctype.h>
#include	"edef.h"
#include	"osdep.h"


/* Word wrap on n-spaces. Back-over whatever precedes the point on the current
 * line and stop on the first word-break or the beginning of the line. If we
 * reach the beginning of the line, jump back to the end of the word and start
 * a new line.  Otherwise, break the line at the word-break, eat it, and jump
 * back to the end of the word.
 * Returns TRUE on success, FALSE on errors.
 */
wrapword()
{
    register int   cnt = 0;	/* size of word wrapped to next line */
    register int   bp;

    if(curwp->w_doto <= 0)		/* no line to wrap? */
      return(FALSE);

    /* 
     * back up until we aren't in a word,
     * and make sure there is a break in the line
     */
    bp = llength(curwp->w_dotp);	/* start at end of line */
    do{
	if(--bp <= 0)			/* no place to break the line! */
	  return(FALSE);
	
	switch(cnt){
	  case 0:			/* break BEFORE fillcol */
	    if(bp > fillcol)
	      break;
	    else
	      cnt++;

	  case 1:			/* find first breakable word */
	    if(myisspace(lgetc(curwp->w_dotp, bp).c))
	      break;
	    else
	      cnt++;

	  case 2:			/* and break in front of it */
	    if(!myisspace(lgetc(curwp->w_dotp, bp).c))
	      break;
	    else
	      cnt = 10;

	  default:
	    break;
	}
    }
    while(cnt != 10);

    /* bp now points to the last character to remain on this line! */
    cnt = curwp->w_doto - ++bp;
    curwp->w_doto = bp;
    
    if(!lnewline())			/* break the line */
      return(FALSE);

    /*
     * if there's a line below, it doesn't start with whitespace 
     * and there's room for this line...
     */
    if(lforw(curwp->w_dotp) != curbp->b_linep 
       && llength(lforw(curwp->w_dotp)) 
       && !myisspace(lgetc(lforw(curwp->w_dotp), 0).c)
       && (llength(curwp->w_dotp) + llength(lforw(curwp->w_dotp)) < fillcol)){
	gotoeol(0, 1);			/* then pull text up from below */
	if(lgetc(curwp->w_dotp, curwp->w_doto - 1).c != ' ')
	  linsert(1, ' ');

	forwdel(0, 1);
	gotobol(0, 1);
    }

    if(!forwchar(0, cnt < 0 ? cnt-1 : cnt)) /* restore dot (account for NL) */
      return(FALSE);

    return(TRUE);
}


/*
 * Move the cursor backward by "n" words. All of the details of motion are
 * performed by the "backchar" and "forwchar" routines. Error if you try to
 * move beyond the buffers.
 */
backword(f, n)
{
        if (n < 0)
                return (forwword(f, -n));
        if (backchar(FALSE, 1) == FALSE)
                return (FALSE);
        while (n--) {
                while (inword() == FALSE) {
                        if (backchar(FALSE, 1) == FALSE)
                                return (FALSE);
                }
                while (inword() != FALSE) {
                        if (backchar(FALSE, 1) == FALSE)
                                return (FALSE);
                }
        }
        return (forwchar(FALSE, 1));
}

/*
 * Move the cursor forward by the specified number of words. All of the motion
 * is done by "forwchar". Error if you try and move beyond the buffer's end.
 */
forwword(f, n)
{
        if (n < 0)
                return (backword(f, -n));
        while (n--) {
#if	NFWORD
                while (inword() != FALSE) {
                        if (forwchar(FALSE, 1) == FALSE)
                                return (FALSE);
                }
#endif
                while (inword() == FALSE) {
                        if (forwchar(FALSE, 1) == FALSE)
                                return (FALSE);
                }
#if	NFWORD == 0
                while (inword() != FALSE) {
                        if (forwchar(FALSE, 1) == FALSE)
                                return (FALSE);
                }
#endif
        }
	return(TRUE);
}

#ifdef	MAYBELATER
/*
 * Move the cursor forward by the specified number of words. As you move,
 * convert any characters to upper case. Error if you try and move beyond the
 * end of the buffer. Bound to "M-U".
 */
upperword(f, n)
{
        register int    c;
	CELL            ac;

	ac.a = 0;
	if (curbp->b_mode&MDVIEW)	/* don't allow this command if	*/
		return(rdonly());	/* we are in read only mode	*/
        if (n < 0)
                return (FALSE);
        while (n--) {
                while (inword() == FALSE) {
                        if (forwchar(FALSE, 1) == FALSE)
                                return (FALSE);
                }
                while (inword() != FALSE) {
                        c = lgetc(curwp->w_dotp, curwp->w_doto).c;
                        if (c>='a' && c<='z') {
                                ac.c = (c -= 'a'-'A');
                                lputc(curwp->w_dotp, curwp->w_doto, ac);
                                lchange(WFHARD);
                        }
                        if (forwchar(FALSE, 1) == FALSE)
                                return (FALSE);
                }
        }
        return (TRUE);
}

/*
 * Move the cursor forward by the specified number of words. As you move
 * convert characters to lower case. Error if you try and move over the end of
 * the buffer. Bound to "M-L".
 */
lowerword(f, n)
{
        register int    c;
	CELL            ac;

	ac.a = 0;
	if (curbp->b_mode&MDVIEW)	/* don't allow this command if	*/
		return(rdonly());	/* we are in read only mode	*/
        if (n < 0)
                return (FALSE);
        while (n--) {
                while (inword() == FALSE) {
                        if (forwchar(FALSE, 1) == FALSE)
                                return (FALSE);
                }
                while (inword() != FALSE) {
                        c = lgetc(curwp->w_dotp, curwp->w_doto).c;
                        if (c>='A' && c<='Z') {
                                ac.c (c += 'a'-'A');
                                lputc(curwp->w_dotp, curwp->w_doto, ac);
                                lchange(WFHARD);
                        }
                        if (forwchar(FALSE, 1) == FALSE)
                                return (FALSE);
                }
        }
        return (TRUE);
}

/*
 * Move the cursor forward by the specified number of words. As you move
 * convert the first character of the word to upper case, and subsequent
 * characters to lower case. Error if you try and move past the end of the
 * buffer. Bound to "M-C".
 */
capword(f, n)
{
        register int    c;
	CELL	        ac;

	ac.a = 0;
	if (curbp->b_mode&MDVIEW)	/* don't allow this command if	*/
		return(rdonly());	/* we are in read only mode	*/
        if (n < 0)
                return (FALSE);
        while (n--) {
                while (inword() == FALSE) {
                        if (forwchar(FALSE, 1) == FALSE)
                                return (FALSE);
                }
                if (inword() != FALSE) {
                        c = lgetc(curwp->w_dotp, curwp->w_doto).c;
                        if (c>='a' && c<='z') {
			    ac.c = (c -= 'a'-'A');
			    lputc(curwp->w_dotp, curwp->w_doto, ac);
			    lchange(WFHARD);
                        }
                        if (forwchar(FALSE, 1) == FALSE)
                                return (FALSE);
                        while (inword() != FALSE) {
                                c = lgetc(curwp->w_dotp, curwp->w_doto).c;
                                if (c>='A' && c<='Z') {
				    ac.c = (c += 'a'-'A');
				    lputc(curwp->w_dotp, curwp->w_doto, ac);
				    lchange(WFHARD);
                                }
                                if (forwchar(FALSE, 1) == FALSE)
                                        return (FALSE);
                        }
                }
        }
        return (TRUE);
}

/*
 * Kill forward by "n" words. Remember the location of dot. Move forward by
 * the right number of words. Put dot back where it was and issue the kill
 * command for the right number of characters. Bound to "M-D".
 */
delfword(f, n)
{
        register int    size;
        register LINE   *dotp;
        register int    doto;

	if (curbp->b_mode&MDVIEW)	/* don't allow this command if	*/
		return(rdonly());	/* we are in read only mode	*/
        if (n < 0)
                return (FALSE);
        dotp = curwp->w_dotp;
        doto = curwp->w_doto;
        size = 0;
        while (n--) {
#if	NFWORD
		while (inword() != FALSE) {
			if (forwchar(FALSE,1) == FALSE)
				return(FALSE);
			++size;
		}
#endif
                while (inword() == FALSE) {
                        if (forwchar(FALSE, 1) == FALSE)
                                return (FALSE);
                        ++size;
                }
#if	NFWORD == 0
                while (inword() != FALSE) {
                        if (forwchar(FALSE, 1) == FALSE)
                                return (FALSE);
                        ++size;
                }
#endif
        }
        curwp->w_dotp = dotp;
        curwp->w_doto = doto;
        return (ldelete(size, TRUE));
}

/*
 * Kill backwards by "n" words. Move backwards by the desired number of words,
 * counting the characters. When dot is finally moved to its resting place,
 * fire off the kill command. Bound to "M-Rubout" and to "M-Backspace".
 */
delbword(f, n)
{
        register int    size;

	if (curbp->b_mode&MDVIEW)	/* don't allow this command if	*/
		return(rdonly());	/* we are in read only mode	*/
        if (n < 0)
                return (FALSE);
        if (backchar(FALSE, 1) == FALSE)
                return (FALSE);
        size = 0;
        while (n--) {
                while (inword() == FALSE) {
                        if (backchar(FALSE, 1) == FALSE)
                                return (FALSE);
                        ++size;
                }
                while (inword() != FALSE) {
                        if (backchar(FALSE, 1) == FALSE)
                                return (FALSE);
                        ++size;
                }
        }
        if (forwchar(FALSE, 1) == FALSE)
                return (FALSE);
        return (ldelete(size, TRUE));
}
#endif	/* MAYBELATER */

/*
 * Return TRUE if the character at dot is a character that is considered to be
 * part of a word. The word character list is hard coded. Should be setable.
 */
inword()
{
        register int    c;

        if (curwp->w_doto == llength(curwp->w_dotp))
                return (FALSE);
        c = lgetc(curwp->w_dotp, curwp->w_doto).c;

        if (c>='a' && c<='z')
                return (TRUE);
        if (c>='A' && c<='Z')
                return (TRUE);
        if (c>='0' && c<='9')
                return (TRUE);
        return (FALSE);
}

fillpara(f, n)	/* Fill the current paragraph according to the current
		   fill column						*/

int f, n;	/* deFault flag and Numeric argument */

{
	register int c;			/* current char durring scan	*/
	register int wordlen;		/* length of current word	*/
	register int clength;		/* position on line during fill	*/
	register int i;			/* index during word copy	*/
	register int newlength;		/* tentative new line length	*/
	register int eopflag;		/* Are we at the End-Of-Paragraph? */
	register int firstflag;		/* first word? (needs no space)	*/
	register LINE *eopline;		/* pointer to line just past EOP */
	register int dotflag;		/* was the last char a period?	*/
	char wbuf[NSTRING];		/* buffer for current word	*/


	if (curbp->b_mode&MDVIEW)	/* don't allow this command if	*/
		return(rdonly());	/* we are in read only mode	*/
	if (fillcol == 0) {	/* no fill column set */
		mlwrite("No fill column set");
		return(FALSE);
	}

	/* record the pointer to the line just past the EOP */
	gotoeop(FALSE, 1);
	eopline = lforw(curwp->w_dotp);

	/* and back to the beginning of the paragraph */
	gotobop(FALSE, 1);

	/* let yank() know that it may be restoring a paragraph */
	thisflag |= CFFILL;

	if(Pmaster == NULL)
	  sgarbk = TRUE;

        curwp->w_flag |= WFMODE;
	kdelete();

	/* initialize various info */
	clength = curwp->w_doto;
	if (clength && curwp->w_dotp->l_text[0].c == TAB)
		clength = 8;
	wordlen = 0;
	dotflag = FALSE;

	/* scan through lines, filling words */
	firstflag = TRUE;
	eopflag = FALSE;

	while (!eopflag) {
		/* get the next character in the paragraph */
		if (curwp->w_doto == llength(curwp->w_dotp)) {

			c = ' ';
			if (lforw(curwp->w_dotp) == eopline)
				eopflag = TRUE;
			kinsert('\n');
		} else {
			c = lgetc(curwp->w_dotp, curwp->w_doto).c;
			kinsert(c);
		}

		/* and then delete it */
		ldelete(1, FALSE);

		/* if not a separator, just add it in */
		if (c != ' ' && c != '	') {
			/* 
			 * don't want to limit ourselves to only '.'
			 */
			dotflag = (int)strchr(".?!:;\"", c);	/* dot ? */
			if (wordlen < NSTRING - 1)
				wbuf[wordlen++] = c;
		} else if (wordlen) {
			/* at a word break with a word waiting */
			/* calculate tantitive new length with word added */
			newlength = clength + 1 + wordlen;
			if (newlength <= fillcol) {
				/* add word to current line */
				if (!firstflag) {
					linsert(1, ' '); /* the space */
					++clength;
				}
				firstflag = FALSE;
			} else {
				/* start a new line */
				lnewline();
				clength = 0;
			}

			/* and add the word in in either case */
			for (i=0; i<wordlen; i++) {
				linsert(1, wbuf[i]);
				++clength;
			}

			/*  Strategy:  Handle 3 cases:
			 *     1. if . at end of line put extra space after it
			 *     2. if . and only 1 space, leave only one space 
			 *     3. if . and more than 1 space, leave 2 spaces
			 *
			 *  So, we know the current c is a space. if then 
			 *  is no next c or the next c is a ' ' then we 
			 *  need to insert a space else don't do it.
			 */
			if (dotflag &&
		           ((curwp->w_doto == llength(curwp->w_dotp)) || 
			   (' ' == lgetc(curwp->w_dotp, curwp->w_doto).c))){
				linsert(1, ' ');
				++clength;
			}
			wordlen = 0;
		}
	}

	/* and add a last newline for the end of our new paragraph */
	lnewline();
}
>w_dotp, curwp->w_doto).c;
                        if (c>='A' && c<='Z') {
                                ac.c (c += 'a'-'A');
                                lputc(curwp->w_dotp, curwp->w_doto, ac);
                                lchange(WFHARD);
                        }
                        if (forwchar(FALSE, 1) == FALSE)
                                return (FALSE);
                }
        }
   DarkNET-1.08/pico.BBS/os_unix.c                                                                        644   21270   21270       102055  5672505145  11314                                                                                                                                                                                                                                                                                                                                                                      #if	!defined(lint) && !defined(DOS)
static char rcsid[] = "$Id: os_unix.c,v 4.51 1994/10/10 23:28:56 mikes Exp $";
#endif
/*
 * Program:	Operating system dependent routines - Ultrix 4.1
 *
 *
 * Michael Seibel
 * Networks and Distributed Computing
 * Computing and Communications
 * University of Washington
 * Administration Builiding, AG-44
 * Seattle, Washington, 98195, USA
 * Internet: mikes@cac.washington.edu
 *
 * Please address all bugs and comments to "pine-bugs@cac.washington.edu"
 *
 * Copyright 1991-1994  University of Washington
 *
 *  Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee to the University of
 * Washington is hereby granted, provided that the above copyright notice
 * appears in all copies and that both the above copyright notice and this
 * permission notice appear in supporting documentation, and that the name
 * of the University of Washington not be used in advertising or publicity
 * pertaining to distribution of the software without specific, written
 * prior permission.  This software is made available "as is", and
 * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
 * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
 * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
 * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 * Pine and Pico are trademarks of the University of Washington.
 * No commercial use of these trademarks may be made without prior
 * written permission of the University of Washington.
 *
 *
 * Notes:
 *
 * - SGI IRIX 4.0.1 port by:
 *       johnb@edge.cis.mcmaster.ca,  2 April 1992
 *
 * - Dynix/PTX port by:
 *       Donn Cave, UCS/UW, 15 April 1992
 *
 * - 3B2, 3b1/7300, SCO ports by:
 *       rll@felton.felton.ca.us, 7 Feb. 1993
 *
 * - Probably have to break this up into separate os_type.c files since
 *   the #ifdef's are getting a bit cumbersome.
 *
 */

#include 	<stdio.h>
#include	<errno.h>
#include	<setjmp.h>
#ifndef s40
#include	<time.h>
#endif
#include	<pwd.h>
#if	defined(sv4) || defined(ptx)
#include	<stropts.h>
#include	<poll.h>
#endif
#if	defined(POSIX)
#include	<termios.h>
#if	defined(a32) || defined(cvx)
#include	<sys/ioctl.h>
#endif
#else
#if	defined(sv3) || defined(sgi) || defined(isc) || defined(ct)
#include	<termio.h>
#if	defined(isc)
#include	<sys/sioctl.h>
#include        <sys/bsdtypes.h>
#endif
#else
#include	<sgtty.h>
#endif	/* sv3 || sgi || isc */
#endif	/* POSIX */

#include	"osdep.h"
#include        "pico.h"
#include	"estruct.h"
#include        "edef.h"
#include        "efunc.h"
#include	<fcntl.h>
#include	<sys/wait.h>
#include	<sys/file.h>
#include	<sys/types.h>
#include	<sys/time.h>
#if	defined(a32)
#include	<sys/select.h>
#endif


/*
 * Immediately below are includes and declarations for the 3 basic
 * terminal drivers supported; POSIX, SysVR3, and BSD
 */
#ifdef	POSIX

struct termios nstate,
		ostate;
#else
#if	defined(sv3) || defined(sgi) || defined(isc)

struct termio nstate,
              ostate;

#else
struct  sgttyb  ostate;				/* saved tty state */
struct  sgttyb  nstate;				/* values for editor mode */
struct  ltchars	oltchars;			/* old term special chars */
struct  ltchars	nltchars = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
struct  tchars	otchars;			/* old term special chars */
struct  tchars	ntchars = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };

#endif	/* sv3 || sgi || isc */
#endif	/* POSIX */

#if	defined(sv3) || defined(ct)
/*
 * Windowing structure to support JWINSIZE/TIOCSWINSZ/TIOCGWINSZ 
 */
#define ENAMETOOLONG	78

struct winsize {
	unsigned short ws_row;       /* rows, in characters*/
	unsigned short ws_col;       /* columns, in character */
	unsigned short ws_xpixel;    /* horizontal size, pixels */
	unsigned short ws_ypixel;    /* vertical size, pixels */
};
#endif

#ifdef	bsd
int	errno;					/* ya, I know... */
#endif

#if	(defined(bsd) || defined(dyn) || defined(ct)) && !defined(LINUX)
#define	SIGTYPE int
#else
#define	SIGTYPE	void
#endif


#ifdef	ANSI
    int      kbseq(int *);
    SIGTYPE  do_hup_signal();
    SIGTYPE  rtfrmshell();
#ifdef	TIOCGWINSZ
    SIGTYPE  winch_handler();
#endif
#else
    int      kbseq();
    SIGTYPE  do_hup_signal();
    SIGTYPE  rtfrmshell();
#ifdef	TIOCGWINSZ
    SIGTYPE  winch_handler();
#endif
#endif


/*
 * for alt_editor arg[] building
 */
#define	MAXARGS	10

/*
 * ttopen - this function is called once to set up the terminal device 
 *          streams.  if called as pine composer, don't mess with
 *          tty modes, but set signal handlers.
 */
ttopen()
{
    if(Pmaster == NULL){
#ifdef	POSIX
	tcgetattr (0, &ostate);
	tcgetattr (0, &nstate);
	nstate.c_lflag &= ~(ISIG | ICANON | ECHO | IEXTEN);
	nstate.c_iflag &= ~ICRNL;
	nstate.c_oflag &= ~(ONLCR | OPOST);
	nstate.c_cc[VMIN] = 1;
	nstate.c_cc[VTIME] = 0;
	tcsetattr (0, TCSADRAIN, &nstate);
#else
#if	defined(sv3) || defined(sgi) || defined(isc) || defined(ct)
	(void) ioctl(0, TCGETA, &ostate);
	(void) ioctl(0, TCGETA, &nstate);	/** again! **/

	nstate.c_lflag &= ~(ICANON | ISIG | ECHO);	/* noecho raw mode  */
	nstate.c_oflag &= ~(OPOST | ONLCR);
	nstate.c_iflag &= ~ICRNL;
	    
	nstate.c_cc[VMIN] = '\01';  /* minimum # of chars to queue  */
	nstate.c_cc[VTIME] = '\0'; /* minimum time to wait for input */
	(void) ioctl(0, TCSETA, &nstate);
#else
	ioctl(0, TIOCGETP, &ostate);		/* save old state */
	ioctl(0, TIOCGLTC, &oltchars);		/* Save old lcharacters */
	ioctl(0, TIOCGETC, &otchars);		/* Save old characters */
	ioctl(0, TIOCGETP, &nstate);		/* get base of new state */
	nstate.sg_flags |= RAW;
	nstate.sg_flags &= ~(ECHO|CRMOD);	/* no echo for now... */
	ioctl(0, TIOCSETP, &nstate);		/* set mode */

	ioctl(0, TIOCSLTC, &nltchars);		/* put new lcharacter into K */
	ioctl(0, TIOCSETC, &ntchars);		/* put new character into K */
#endif	/* sv3 */
#endif	/* POSIX */
    }

    signal(SIGHUP,  do_hup_signal);	/* deal with SIGHUP */
    signal(SIGTERM, do_hup_signal);	/* deal with SIGTERM */
#ifdef	SIGTSTP
    signal(SIGTSTP, SIG_DFL);
#endif
#ifdef	TIOCGWINSZ
    signal(SIGWINCH, winch_handler); /* window size changes */
#endif
    return(1);
}



/*
 * ttclose - this function gets called just before we go back home to 
 *           the command interpreter.  If called as pine composer, don't
 *           worry about modes, but set signals to default, pine will 
 *           rewire things as needed.
 */
ttclose()
{
    if(Pmaster){
	signal(SIGHUP, SIG_DFL);
#ifdef	SIGCONT
	signal(SIGCONT, SIG_DFL);
#endif
#ifdef	TIOCGWINSZ
	signal(SIGWINCH, SIG_DFL);
#endif
    }
    else{
#ifdef	POSIX
	tcsetattr (0, TCSADRAIN, &ostate);
#else
#if	defined(sv3) || defined(sgi) || defined(isc) || defined(ct)
        ioctl(0, TCSETA, &ostate);
#else
	ioctl(0, TIOCSETP, &ostate);
	ioctl(0, TIOCSLTC, &oltchars);
	ioctl(0, TIOCSETC, &otchars);

	/*
	 * This works around a really weird problem.  On slow speed lines,
	 * if an exit happens with some number of characters still to be
	 * written in the terminal driver, one or more characters will 
	 * be changed when they finally get drained.  This can be reproduced
	 * on a 2400bps line, writing a multi-line buffer on exit using
	 * a vt100 type terminal.  It turns out the last char in the
	 * escape sequence turning off reverse video was getting changed
	 * from 'm' to ' '.  I said it was weird.
	 */
	if(ostate.sg_ospeed <= B2400)
	  sleep(1);
#endif	/* sv3 || sgi || isc */
#endif	/* POSIX */
    }

    return(1);
}


/*
 * ttspeed - return TRUE if tty line speed < 9600 else return FALSE
 */
ttisslow()
{
#if	defined(POSIX)
    struct termios tty;

    return((tcgetattr (1, &tty) == 0) ? cfgetospeed (&tty) < B9600 : FALSE);
#else
#if	defined(sv3) || defined(sgi) || defined(isc)
    struct termio tty;

    return((tcgetattr (1, &tty) == 0) ? cfgetospeed (&tty) < B9600 : FALSE);
#else
    struct  sgttyb tty;

    return((ioctl(1, TIOCGETP, &tty) == 0) ? tty.sg_ospeed < B9600 : FALSE);
#endif
#endif
}


/*
 * ttgetwinsz - set global rows and columns values and return
 */
ttgetwinsz()
{
#ifdef TIOCGWINSZ
    struct winsize win;

    if (ioctl(0, TIOCGWINSZ, &win) == 0) {
        term.t_ncol = (win.ws_col) ? win.ws_col : 80;
        term.t_nrow = (win.ws_row) ? win.ws_row - 1 : 23;
    }
#endif
}


/*
 * ttputc - Write a character to the display. 
 */
ttputc(c)
{
    return(putc(c, stdout));
}


/*
 * ttflush - flush terminal buffer. Does real work where the terminal 
 *           output is buffered up. A no-operation on systems where byte 
 *           at a time terminal I/O is done.
 */
ttflush()
{
    return(fflush(stdout));
}


/*
 * ttgetc - Read a character from the terminal, performing no editing 
 *          and doing no echo at all.
 */
ttgetc()
{
    unsigned char c;
    int i;

    if((i = read(0, &c, 1)) <= 0){
	if(i == 0 && errno == EINTR)		/* only acceptable failure */
	  return(NODATA);
	else
	  kill(getpid(), SIGHUP);		/* fake a hup */
    }
    else
      return((int)c);
}


#if	TYPEAH
/* 
 * typahead - Check to see if any characters are already in the
 *	      keyboard buffer
 */
typahead()
{
    int x;	/* holds # of pending chars */

    return((ioctl(0,FIONREAD,&x) < 0) ? 0 : x);
}
#endif


/*
 * GetKey - Read in a key.
 * Do the standard keyboard preprocessing. Convert the keys to the internal
 * character set.  Resolves escape sequences and returns no-op if global
 * timeout value exceeded.
 */
GetKey()
{
    int    c;

    if(timeout){
	/*
	 * simple use of select/poll here to handle requested timeouts
	 * while waiting for keyboard input...
	 */
#if	defined(ptx) || defined(sv4)
	struct pollfd pollfd;
	int    rv;

	pollfd.fd     = 0;
	pollfd.events = POLLIN;
	while((rv = poll(&pollfd, 1, timeout * 1000)) < 0 && errno == EAGAIN)
	  ;
#else
	struct timeval ts;
	fd_set readfds;
	int    rv;

	FD_ZERO(&readfds);		/* blank out all bits */
	FD_SET(0, &readfds);		/* set stdin's bit */
	ts.tv_sec  = timeout;		/* set the timeout */
	ts.tv_usec = 0;

	rv = select(1, &readfds, 0, &readfds, &ts); /* read stdin */
#endif
	if(rv < 0){
	    if(errno == EINTR){		/* interrupted? */
		return(NODATA);		/* return like we timed out */
	    }
	    else{
		emlwrite("\007Problem reading from keyboard!", NULL);
		kill(getpid(), SIGHUP);	/* Bomb out (saving our work)! */
	    }
	}
	else if(rv == 0)
	  return(NODATA);		/* we really did time out */
    }

    if ((c = (*term.t_getchar)()) == METACH) { /* Apply M- prefix      */
	int status;
	    
	/*
	 * this code should intercept special keypad keys
	 */
	switch(status = kbseq(&c)){
	  case 0 : 	/* no dice */
	    return(c);
	  case  K_PAD_UP		:
	  case  K_PAD_DOWN		:
	  case  K_PAD_RIGHT		:
	  case  K_PAD_LEFT		:
	  case  K_PAD_PREVPAGE	:
	  case  K_PAD_NEXTPAGE	:
	  case  K_PAD_HOME		:
	    return(status);
	  case F1  :
	  case F2  :
	  case F3  :
	  case F4  :
	  case F5  :
	  case F6  :
	  case F7  :
	  case F8  :
	  case F9  :
	  case F10 :
	  case F11 :
	  case F12 :
	    return(status);
	  case BADESC :
	    if(c == '\033'){
		c = (*term.t_getchar)();
		if(islower(c))	/* canonicalize c */
		  c = toupper(c);

		return((isalpha(c) || c == '@' || (c >= '[' && c <= '_'))
		       ? (CTRL | c) : c);
	    }

	  default :				/* punt the whole thing	*/
	    (*term.t_beep)();
	    break;
	}
    }

    if (c>=0x00 && c<=0x1F)                 /* C0 control -> C-     */
      c = CTRL | (c+'@');

    return (c);

}



/* 
 * kbseq - looks at an escape sequence coming from the keyboard and 
 *         compares it to a trie of known keyboard escape sequences, and
 *         performs the function bound to the escape sequence.
 * 
 *         returns: BADESC, the escaped function, or 0 if not found.
 */
kbseq(c)
int	*c;
{
    register char	b;
    register int	first = 1;
    register struct	KBSTREE	*current = kpadseqs;

    if(kpadseqs == NULL)			/* bag it */
      return(BADESC);

    while(1){
	*c = b = (*term.t_getchar)();

	while(current->value != b){
	    if(current->left == NULL){		/* NO MATCH */
		if(first)
		  return(BADESC);
		else
		  return(0);
	    }
	    current = current->left;
	}

	if(current->down == NULL)		/* match!!!*/
	  return(current->func);
	else
	  current = current->down;

	first = 0;
    }
}



/*
 * alt_editor - fork off an alternate editor for mail message composition 
 *              if one is configured and passed from pine.  If not, only
 *              ask for the editor if advanced user flag is set, and 
 *              suggest environment's EDITOR value as default.
 */
alt_editor(f, n)
{
    char   eb[NLINE];				/* buf holding edit command */
    char   *fn;					/* tmp holder for file name */
    char   *cp;
    char   *args[MAXARGS];			/* ptrs into edit command */
    char   *writetmp();
    int	   child, pid, i, done = 0;
    long   l;
#if	defined(POSIX) || defined(sv3) || defined(COHERENT) || defined(isc) || defined(neb)
    int    stat;
#else
    union  wait stat;
#endif
    FILE   *p;
    SIGTYPE (*ohup)(), (*oint)(), (*osize)(), (*ostop)(), (*ostart)();

    if(Pmaster == NULL)
      return(-1);

    if(gmode&MDSCUR){
	emlwrite("Alternate editor not available in restricted mode", NULL);
	return(-1);
    }

    if(Pmaster->alt_ed == NULL){
	if(!(gmode&MDADVN)){
	    emlwrite("\007Unknown Command",NULL);
	    return(-1);
	}

	if(getenv("EDITOR"))
	  strcpy(eb, (char *)getenv("EDITOR"));
	else
	  *eb = '\0';

	while(!done){
	    pid = mlreplyd("Which alternate editor ? ",eb,NLINE,QDEFLT,NULL);

	    switch(pid){
	      case ABORT:
		return(-1);
	      case HELPCH:
		emlwrite("no alternate editor help yet", NULL);

/* take sleep and break out after there's help */
		sleep(3);
		break;
	      case (CTRL|'L'):
		sgarbf = TRUE;
		update();
		break;
	      case TRUE:
	      case FALSE:			/* does editor exist ? */
		if(*eb == '\0'){		/* leave silently? */
		    mlerase();
		    return(-1);
		}

		done++;
		break;
	      default:
		break;
	    }
	}
    }
    else
      strcpy(eb, Pmaster->alt_ed);

    if((fn=writetmp(0, 1)) == NULL){		/* get temp file */
	emlwrite("Problem writing temp file for alt editor", NULL);
	return(-1);
    }

    strcat(eb, " ");
    strcat(eb, fn);

    cp = eb;
    for(i=0; *cp != '\0';i++){			/* build args array */
	if(i < MAXARGS){
	    args[i] = NULL;			/* in case we break out */
	}
	else{
	    emlwrite("Too many args for command!", NULL);
	    return(-1);
	}

	while(isspace(*cp))
	  if(*cp != '\0')
	    cp++;
	  else
	    break;

	args[i] = cp;

	while(!isspace(*cp))
	  if(*cp != '\0')
	    cp++;
	  else
	    break;

	if(*cp != '\0')
	  *cp++ = '\0';
    }

    args[i] = NULL;

    if(Pmaster)
      (*Pmaster->raw_io)(0);			/* turn OFF raw mode */

    emlwrite("Invoking alternate editor...", NULL);

    if(child=fork()){			/* wait for the child to finish */
	ohup = signal(SIGHUP, SIG_IGN);	/* ignore signals for now */
	oint = signal(SIGINT, SIG_IGN);
#ifdef	TIOCGWINSZ
        osize = signal(SIGWINCH, SIG_IGN);
#endif

/*
 * BUG - wait should be made non-blocking and mail_pings or something 
 * need to be done in the loop to keep the imap stream alive
 */
	while((pid=(int)wait(&stat)) != child)
	  ;

	signal(SIGHUP, ohup);	/* restore signals */
	signal(SIGINT, oint);
#ifdef	TIOCGWINSZ
        signal(SIGWINCH, osize);
#endif
    }
    else{				/* spawn editor */
	signal(SIGHUP, SIG_DFL);	/* let editor handle signals */
	signal(SIGINT, SIG_DFL);
#ifdef	TIOCGWINSZ
        signal(SIGWINCH, SIG_DFL);
#endif
	if(execvp(args[0], args) < 0)
	  exit(1);
    }

    if(Pmaster)
      (*Pmaster->raw_io)(1);		/* turn ON raw mode */

    /*
     * replace edited text with new text 
     */
    curbp->b_flag &= ~BFCHG;		/* make sure old text gets blasted */
    readin(fn, 0);			/* read new text overwriting old */
    unlink(fn);				/* blast temp file */
    curbp->b_flag |= BFCHG;		/* mark dirty for packbuf() */
    ttopen();				/* reset the signals */
    refresh(0, 1);			/* redraw */
    return(0);
}



/*
 *  bktoshell - suspend and wait to be woken up
 */
bktoshell()		/* suspend MicroEMACS and wait to wake up */
{
#ifdef	SIGTSTP
    int pid;

    if(!(gmode&MDSSPD)){
	emlwrite("\007Unknown command: ^Z", NULL);
	return;
    }

    if(Pmaster){
	(*Pmaster->raw_io)(0);	/* actually in pine source */

	movecursor(term.t_nrow, 0);
	printf("\n\n\nUse \"fg\" to return to Pine\n");

    }
    else
      vttidy();

    movecursor(term.t_nrow, 0);
    peeol();
    (*term.t_flush)();

    signal(SIGCONT, rtfrmshell);	/* prepare to restart */
    signal(SIGTSTP, SIG_DFL);			/* prepare to stop */
    kill(0, SIGTSTP);
#endif
}


/* 
 * rtfrmshell - back from shell, fix modes and return
 */
SIGTYPE
rtfrmshell()
{
#ifdef	SIGCONT
    signal(SIGCONT, SIG_DFL);

    if(Pmaster){
	(*Pmaster->raw_io)(1);			/* actually in pine source */
	(*Pmaster->keybinit)(gmode&MDFKEY);	/* using f-keys? */
    }

    ttopen();

#ifdef	TIOCGWINSZ
    {
	struct winsize win;
	extern int resize_pico();

	/*
	 * refit pico of window size changed....
	 */
	if (ioctl(0, TIOCGWINSZ, &win) == 0) {
	    if (win.ws_col && win.ws_row)
	      resize_pico(win.ws_row - 1, win.ws_col);
	}
    }
#endif

    sgarbf = TRUE;
    curwp->w_flag = WFHARD;
    refresh(0, 1);
#endif
}



/*
 * do_hup_signal - jump back in the stack to where we can handle this
 */
SIGTYPE
do_hup_signal()
{
    signal(SIGHUP,  SIG_IGN);			/* ignore further SIGHUP's */
    signal(SIGTERM, SIG_IGN);			/* ignore further SIGTERM's */
    if(Pmaster){
	extern jmp_buf finstate;

	longjmp(finstate, COMP_GOTHUP);
    }
    else{
	/*
	 * if we've been interrupted and the buffer is changed,
	 * save it...
	 */
	if(anycb() == TRUE){			/* time to save */
	    if(curbp->b_fname[0] == '\0'){	/* name it */
		strcpy(curbp->b_fname, "pico.save");
	    }
	    else{
		strcat(curbp->b_fname, ".save");
	    }
	    writeout(curbp->b_fname);
	}
	vttidy();
	exit(1);
    }
}


/*
 * big bitmap of ASCII characters allowed in a file name
 * (needs reworking for other char sets)
 */
unsigned char okinfname[32] = {
      0,    0, 			/* ^@ - ^G, ^H - ^O  */
      0,    0,			/* ^P - ^W, ^X - ^_  */
      0,    0x17,		/* SP - ' ,  ( - /   */
      0xff, 0xc0,		/*  0 - 7 ,  8 - ?   */
      0x7f, 0xff,		/*  @ - G ,  H - O   */
      0xff, 0xe1,		/*  P - W ,  X - _   */
      0x7f, 0xff,		/*  ` - g ,  h - o   */
      0xff, 0xf6,		/*  p - w ,  x - DEL */
      0,    0, 			/*  > DEL   */
      0,    0,			/*  > DEL   */
      0,    0, 			/*  > DEL   */
      0,    0, 			/*  > DEL   */
      0,    0 			/*  > DEL   */
};


/*
 * fallowc - returns TRUE if c is allowable in filenames, FALSE otw
 */
fallowc(c)
char c;
{
    return(okinfname[c>>3] & 0x80>>(c&7));
}


/*
 * fexist - returns TRUE if the file exists with mode passed in m, 
 *          FALSE otherwise.  By side effect returns length of file in l
 */
fexist(file, m, l)
char *file;
char *m;					/* files mode: r, w or rw */
long *l;
{
    struct stat	sbuf;

    if(l)
      *l = 0L;

    if(stat(file, &sbuf) < 0){
	switch(errno){
	  case ENOENT :				/* File not found */
	    return(FIOFNF);
#ifdef	ENAMETOOLONG
	  case ENAMETOOLONG :			/* Name is too long */
	    return(FIOLNG);
#endif
	  default:				/* Some other error */
	    return(FIOERR);
	}
    }

    if(l)
      *l = sbuf.st_size;

    if((sbuf.st_mode&S_IFMT) == S_IFDIR)
      return(FIODIR);

    if(m[0] == 'r')				/* read access? */
      return((S_IREAD&sbuf.st_mode) ? FIOSUC : FIONRD);
    else if(m[0] == 'w')			/* write access? */
      return((S_IWRITE&sbuf.st_mode) ? FIOSUC : FIONWT);
    else if(m[0] == 'x')			/* execute access? */
      return((S_IEXEC&sbuf.st_mode) ? FIOSUC : FIONEX);
    return(FIOERR);				/* what? */
}


/*
 * isdir - returns true if fn is a readable directory, false otherwise
 *         silent on errors (we'll let someone else notice the problem;)).
 */
isdir(fn, l)
char *fn;
long *l;
{
    struct stat sbuf;

    if(l)
      *l = 0;

    if(stat(fn, &sbuf) < 0)
      return(0);

    if(l)
      *l = sbuf.st_size;
    return((sbuf.st_mode&S_IFMT) == S_IFDIR);
}


#if	defined(bsd) || defined(nxt) || defined(dyn)
/*
 * getcwd - NeXT uses getwd()
 */
char *
getcwd(pth, len)
char *pth;
int   len;
{
    extern char *getwd();

    return(getwd(pth));
}
#endif


/*
 * gethomedir - returns the users home directory
 *              Note: home is malloc'd for life of pico
 */
char *
gethomedir(l)
int *l;
{
    static char *home = NULL;
    static short hlen = 0;

    if(home == NULL){
	char buf[NLINE];
	strcpy(buf, "~");
	fixpath(buf, NLINE);		/* let fixpath do the work! */
	hlen = strlen(buf);
	if((home = (char *)malloc((hlen + 1) * sizeof(char))) == NULL){
	    emlwrite("Problem allocating space for home dir", NULL);
	    return(0);
	}

	strcpy(home, buf);
    }

    if(l)
      *l = hlen;

    return(home);
}


/*
 * homeless - returns true if given file does not reside in the current
 *            user's home directory tree. 
 */
homeless(f)
char *f;
{
    char *home;
    int   len;

    home = gethomedir(&len);
    return(strncmp(home, f, len));
}



/*
 * errstr - return system error string corresponding to given errno
 *          Note: strerror() is not provided on all systems, so it's 
 *          done here once and for all.
 */
char *
errstr(err)
int err;
{
#ifndef	neb
    extern char *sys_errlist[];
#endif
    extern int  sys_nerr;

    return((err >= 0 && err < sys_nerr) ? sys_errlist[err] : NULL);
}



/*
 * getfnames - return all file names in the given directory in a single 
 *             malloc'd string.  n contains the number of names
 */
char *
getfnames(dn, n)
char *dn;
int  *n;
{
    long           l;
    char          *names, *np, *p;
    struct stat    sbuf;
#if	defined(ct)
    FILE          *dirp;
    char           fn[DIRSIZ+1];
#else
    DIR           *dirp;			/* opened directory */
#endif
#if	defined(POSIX) || defined(aix) || defined(COHERENT) || defined(isc) || defined(sv3)
    struct dirent *dp;
#else
    struct direct *dp;
#endif

    *n = 0;

    if(stat(dn, &sbuf) < 0){
	switch(errno){
	  case ENOENT :				/* File not found */
	    emlwrite("\007File not found: \"%s\"", dn);
	    break;
#ifdef	ENAMETOOLONG
	  case ENAMETOOLONG :			/* Name is too long */
	    emlwrite("\007File name too long: \"%s\"", dn);
	    break;
#endif
	  default:				/* Some other error */
	    emlwrite("\007Error getting file info: \"%s\"", dn);
	    break;
	}
	return(NULL);
    } 
    else{
	l = sbuf.st_size;
	if((sbuf.st_mode&S_IFMT) != S_IFDIR){
	    emlwrite("\007Not a directory: \"%s\"", dn);
	    return(NULL);
	}
    }

    if((names=(char *)malloc(sizeof(char)*l)) == NULL){
	emlwrite("\007Can't malloc space for file names", NULL);
	return(NULL);
    }

    errno = 0;
    if((dirp=opendir(dn)) == NULL){
	char buf[NLINE];
	sprintf(buf,"\007Can't open \"%s\": %s", dn, errstr(errno));
	emlwrite(buf, NULL);
	free((char *)names);
	return(NULL);
    }

    np = names;

#if	defined(ct)
    while(fread(&dp, sizeof(struct direct), 1, dirp) > 0) {
    /* skip empty slots with inode of 0 */
	if(dp.d_ino == 0)
	     continue;
	(*n)++;                     /* count the number of active slots */
	(void)strncpy(fn, dp.d_name, DIRSIZ);
	fn[14] = '\0';
	p = fn;
	while((*np++ = *p++) != '\0')
	  ;
    }
#else
    while((dp = readdir(dirp)) != NULL){
	(*n)++;
	p = dp->d_name;
	while((*np++ = *p++) != '\0')
	  ;
    }
#endif

    closedir(dirp);					/* shut down */
    return(names);
}


/*
 * fioperr - given the error number and file name, display error
 */
void
fioperr(e, f)
int  e;
char *f;
{
    switch(e){
      case FIOFNF:				/* File not found */
	emlwrite("\007File \"%s\" not found", f);
	break;
      case FIOEOF:				/* end of file */
	emlwrite("\007End of file \"%s\" reached", f);
	break;
      case FIOLNG:				/* name too long */
	emlwrite("\007File name \"%s\" too long", f);
	break;
      case FIODIR:				/* file is a directory */
	emlwrite("\007File \"%s\" is a directory", f);
	break;
      case FIONWT:
	emlwrite("\007Write permission denied: %s", f);
	break;
      case FIONRD:
	emlwrite("\007Read permission denied: %s", f);
	break;
      case FIONEX:
	emlwrite("\007Execute permission denied: %s", f);
	break;
      default:
	emlwrite("\007File I/O error: %s", f);
    }
}



/*
 * pfnexpand - pico's function to expand the given file name if there is 
 *	       a leading '~'
 */
char *pfnexpand(fn, len)
char *fn;
int  len;
{
    struct passwd *pw;
    register char *x, *y, *z;
    char name[20];
    
    if(*fn == '~') {
        for(x = fn+1, y = name; *x != '/' && *x != '\0'; *y++ = *x++);
        *y = '\0';
        if(x == fn + 1) 
          pw = getpwuid(getuid());
        else
          pw = getpwnam(name);
        if(pw == NULL)
          return(NULL);
        if(strlen(pw->pw_dir) + strlen(fn) > len) {
            return(NULL);
        }
	/* make room for expanded path */
	for(z=x+strlen(x),y=fn+strlen(x)+strlen(pw->pw_dir);
	    z >= x;
	    *y-- = *z--);
	/* and insert the expanded address */
	for(x=fn,y=pw->pw_dir; *y != '\0'; *x++ = *y++);
    }
    return(fn);
}



/*
 * fixpath - make the given pathname into an absolute path
 */
fixpath(name, len)
char *name;
int  len;
{
    register char *shft;

    /* filenames relative to ~ */
    if(!((name[0] == '/')
          || (name[0] == '.'
              && (name[1] == '/' || (name[1] == '.' && name[2] == '/'))))){
	if(Pmaster && !(gmode&MDCURDIR)
                   && (*name != '~' && strlen(name)+2 <= len)){

	    for(shft = strchr(name, '\0'); shft >= name; shft--)
	      shft[2] = *shft;

	    name[0] = '~';
	    name[1] = '/';
	}

	pfnexpand(name, len);
    }
}


/*
 * compresspath - given a base path and an additional directory, collapse
 *                ".." and "." elements and return absolute path (appending
 *                base if necessary).  
 *
 *                returns  1 if OK, 
 *                         0 if there's a problem
 *                         new path, by side effect, if things went OK
 */
compresspath(base, path, len)
char *base, *path;
int  len;
{
    register int i;
    int  depth = 0;
    char *p;
    char *stack[32];
    char  pathbuf[NLINE];

#define PUSHD(X)  (stack[depth++] = X)
#define POPD()    ((depth > 0) ? stack[--depth] : "")

    if(*path == '~'){
	fixpath(path, len);
	strcpy(pathbuf, path);
    }
    else if(*path != C_FILESEP)
      sprintf(pathbuf, "%s%c%s", base, C_FILESEP, path);
    else
      strcpy(pathbuf, path);

    p = &pathbuf[0];
    for(i=0; pathbuf[i] != '\0'; i++){		/* pass thru path name */
	if(pathbuf[i] == '/'){
	    if(p != pathbuf)
	      PUSHD(p);				/* push dir entry */

	    p = &pathbuf[i+1];			/* advance p */
	    pathbuf[i] = '\0';			/* cap old p off */
	    continue;
	}

	if(pathbuf[i] == '.'){			/* special cases! */
	    if(pathbuf[i+1] == '.' 		/* parent */
	       && (pathbuf[i+2] == '/' || pathbuf[i+2] == '\0')){
		if(!strcmp(POPD(), ""))		/* bad news! */
		  return(0);

		i += 2;
		p = (pathbuf[i] == '\0') ? "" : &pathbuf[i+1];
	    }
	    else if(pathbuf[i+1] == '/' || pathbuf[i+1] == '\0'){
		i++;
		p = (pathbuf[i] == '\0') ? "" : &pathbuf[i+1];
	    }
	}
    }

    if(*p != '\0')
      PUSHD(p);					/* get last element */

    path[0] = '\0';
    for(i = 0; i < depth; i++){
	strcat(path, S_FILESEP);
	strcat(path, stack[i]);
    }

    return(1);					/* everything's ok */
}


/*
 * tmpname - return a temporary file name in the given buffer
 */
void
tmpname(name)
char *name;
{
    sprintf(name, "/tmp/pico.%d", getpid());	/* tmp file name */
}


/*
 * Take a file name, and from it
 * fabricate a buffer name. This routine knows
 * about the syntax of file names on the target system.
 * I suppose that this information could be put in
 * a better place than a line of code.
 */
void
makename(bname, fname)
char    bname[];
char    fname[];
{
    register char   *cp1;
    register char   *cp2;

    cp1 = &fname[0];
    while (*cp1 != 0)
      ++cp1;

    while (cp1!=&fname[0] && cp1[-1]!='/')
      --cp1;

    cp2 = &bname[0];
    while (cp2!=&bname[NBUFN-1] && *cp1!=0 && *cp1!=';')
      *cp2++ = *cp1++;

    *cp2 = 0;
}


/*
 * copy - copy contents of file 'a' into a file named 'b'.  Return error
 *        if either isn't accessible or is a directory
 */
copy(a, b)
char *a, *b;
{
    int    in, out, n, rv = 0;
    char   *cb;
    struct stat tsb, fsb;
    extern int  errno;

    if(stat(a, &fsb) < 0){		/* get source file info */
	emlwrite("Can't Copy: %s", errstr(errno));
	return(-1);
    }

    if(!(fsb.st_mode&S_IREAD)){		/* can we read it? */
	emlwrite("\007Read permission denied: %s", a);
	return(-1);
    }

    if((fsb.st_mode&S_IFMT) == S_IFDIR){ /* is it a directory? */
	emlwrite("\007Can't copy: %s is a directory", a);
	return(-1);
    }

    if(stat(b, &tsb) < 0){		/* get dest file's mode */
	switch(errno){
	  case ENOENT:
	    break;			/* these are OK */
	  default:
	    emlwrite("\007Can't Copy: %s", errstr(errno));
	    return(-1);
	}
    }
    else{
	if(!(tsb.st_mode&S_IWRITE)){	/* can we write it? */
	    emlwrite("\007Write permission denied: %s", b);
	    return(-1);
	}

	if((tsb.st_mode&S_IFMT) == S_IFDIR){	/* is it directory? */
	    emlwrite("\007Can't copy: %s is a directory", b);
	    return(-1);
	}

	if(fsb.st_dev == tsb.st_dev && fsb.st_ino == tsb.st_ino){
	    emlwrite("\007Identical files.  File not copied", NULL);
	    return(-1);
	}
    }

    if((in = open(a, O_RDONLY)) < 0){
	emlwrite("Copy Failed: %s", errstr(errno));
	return(-1);
    }

    if((out=creat(b, fsb.st_mode&0xfff)) < 0){
	emlwrite("Can't Copy: %s", errstr(errno));
	close(in);
	return(-1);
    }

    if((cb = (char *)malloc(NLINE*sizeof(char))) == NULL){
	emlwrite("Can't allocate space for copy buffer!", NULL);
	close(in);
	close(out);
	return(-1);
    }

    while(1){				/* do the copy */
	if((n = read(in, cb, NLINE)) < 0){
	    emlwrite("Can't Read Copy: %s", errstr(errno));
	    rv = -1;
	    break;			/* get out now */
	}

	if(n == 0)			/* done! */
	  break;

	if(write(out, cb, n) != n){
	    emlwrite("Can't Write Copy: %s", errstr(errno));
	    rv = -1;
	    break;
	}
    }

    free(cb);
    close(in);
    close(out);
    return(rv);
}


/*
 * Open a file for writing. Return TRUE if all is well, and FALSE on error
 * (cannot create).
 */
ffwopen(fn)
char    *fn;
{
    extern FILE *ffp;

    if ((ffp=fopen(fn, "w")) == NULL) {
        emlwrite("Cannot open file for writing", NULL);
        return (FIOERR);
    }

    return (FIOSUC);
}


/*
 * Close a file. Should look at the status in all systems.
 */
ffclose()
{
    extern FILE *ffp;

    if (fclose(ffp) != FALSE) {
        emlwrite("Error closing file", NULL);
        return(FIOERR);
    }

    return(FIOSUC);
}


/*
 * P_open - run the given command in a sub-shell returning a file pointer
 *	    from which to read the output
 *
 * note:
 *	For OS's other than unix, you will have to rewrite this function.
 *	Hopefully it'll be easy to exec the command into a temporary file, 
 *	and return a file pointer to that opened file or something.
 */
FILE *P_open(s)
char *s;
{
    return(popen(s, "r"));
}



/*
 * P_close - close the given descriptor
 *
 */
P_close(fp)
FILE *fp;
{
    return(pclose(fp));
}



/*
 * worthit - generic sort of test to roughly gage usefulness of using 
 *           optimized scrolling.
 *
 * note:
 *	returns the line on the screen, l, that the dot is currently on
 */
worthit(l)
int *l;
{
    int i;			/* l is current line */
    unsigned below;		/* below is avg # of ch/line under . */

    *l = doton(&i, &below);
    below = (i > 0) ? below/(unsigned)i : 0;

    return(below > 3);
}



/*
 * pico_new_mail - just checks mtime and atime of mail file and notifies user 
 *	           if it's possible that they have new mail.
 */
pico_new_mail()
{
    int ret = 0;
    static time_t lastchk = 0;
    struct stat sbuf;
    char   inbox[256], *p;

    if(p = (char *)getenv("MAIL"))
      sprintf(inbox, p);
    else
      sprintf(inbox,"%s/%s", MAILDIR, getlogin());

    if(stat(inbox, &sbuf) == 0){
	ret = sbuf.st_atime <= sbuf.st_mtime &&
	  (lastchk < sbuf.st_mtime && lastchk < sbuf.st_atime);
	lastchk = sbuf.st_mtime;
	return(ret);
    }
    else
      return(ret);
}



/*
 * time_to_check - checks the current time against the last time called 
 *                 and returns true if the elapsed time is > timeout
 */
time_to_check()
{
    static time_t lasttime = 0L;

    if(!timeout)
      return(FALSE);

    if(time((long *) 0) - lasttime > (time_t)timeout){
	lasttime = time((long *) 0);
	return(TRUE);
    }
    else
      return(FALSE);
}


/*
 * sstrcasecmp - compare two pointers to strings case independently
 */
sstrcasecmp(s1, s2)
QcompType *s1, *s2;
{
    register char *a, *b;

    a = *(char **)s1;
    b = *(char **)s2;
    while(toupper(*a) == toupper(*b++))
	if(*a++ == '\0')
	  return(0);

    return(toupper(*a) - toupper(*--b));
}


#ifdef	TIOCGWINSZ
/*
 * winch_handler - handle window change signal
 */
SIGTYPE winch_handler()
{
    struct winsize win;
    extern int resize_pico();

    signal(SIGWINCH, winch_handler);

    if (ioctl(0, TIOCGWINSZ, &win) == 0) {
	if (win.ws_col && win.ws_row)
	  resize_pico(win.ws_row - 1, win.ws_col);
    }
}
#endif	/* TIOCGWINSZ */


#if	defined(sv3) || defined(ct)
/* Placed by rll to handle the rename function not found in AT&T */
rename(oldname, newname)
    char *oldname;
    char *newname;
{
    int rtn;

    if ((rtn = link(oldname, newname)) != 0) {
	perror("Was not able to rename file.");
	return(rtn);
    }

    if ((rtn = unlink(oldname)) != 0)
      perror("Was not able to unlink file.");

    return(rtn);
}
#endif
ame != '~' && strlen(name)+2 <= len)){

	    for(shft = strchr(name, '\0'); shft >= name; shft--)
	      shft[2] = *shft;

	    name[0] = '~';
	    name[1] = '/';
	}

	pfnexpand(name, len);
    }
}


/*
 * compresspath - given a base path and an additional directory, collapse
 *                ".." and "." elements and return absolute path (appending
 *                base if necessary).  
 *
 *                returns  1 if OK, 
 *                         0 if thDarkNET-1.08/pico.BBS/cc5.sol                                                                          755   21270   21270         4603  5672463053  10621                                                                                                                                                                                                                                                                                                                                                                      #!/sbin/sh
#	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T
#	  All Rights Reserved

#	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T
#	The copyright notice above does not evidence any
#	actual or intended publication of such source code.

#ident	"@(#)cc.sh	1.8	92/05/26 SMI"	/* SVr4.0 1.4	*/

#		PROPRIETARY NOTICE (Combined)
#
#This source code is unpublished proprietary information
#constituting, or derived under license from AT&T's UNIX(r) System V.
#In addition, portions of such source code were derived from Berkeley
#4.3 BSD under license from the Regents of the University of
#California.
#
#
#
#		Copyright Notice 
#
#Notice of copyright on this source code product does not indicate 
#publication.
#
#	(c) 1986,1987,1988,1989  Sun Microsystems, Inc
#	(c) 1983,1984,1985,1986,1987,1988,1989  AT&T.
#	          All rights reserved.

# cc command for BSD compatibility package:
#
#	BSD compatibility package header files (/usr/ucbinclude)
#	are included before SVr4 default (/usr/include) files but 
#       after any directories specified on the command line via 
#	the -I option.  Thus, the BSD header files are included
#	next to last, and SVr4 header files are searched last.
#	
#	BSD compatibility package libraries (/usr/ucblib) are
#	searched next to third to last.  SVr4 default libraries 
#	(/usr/ccs/lib and /usr/lib) are searched next to last
#
#	Because the BSD compatibility package C library does not 
#	contain all the C library routines of /usr/ccs/lib/libc.a, 
#	the BSD package C library is named /usr/ucblib/libucb.a
#	and is passed explicitly to cc.  This ensures that libucb.a 
#	will be searched first for routines and that 
#	/usr/ccs/lib/libc.a will be searched afterwards for routines 
#	not found in /usr/ucblib/libucb.a.  Also because sockets is    
#       provided in libc under BSD, /usr/lib/libsocket and /usr/lib/nsl
#       are also included as default libraries.
#
#	NOTE: the -Y L, and -Y U, options of cc are not valid 

if [ -f /usr/ccs/bin/ucbcc ]
then
	# get the directory where ucbcc points to and set the LD_LIBRARY_PATH
	# to that directory so as to get the necessary libraries.
	cclink=`/usr/bin/ls -ln /usr/ccs/bin/ucbcc | awk '{print $11}'`
	ccdir=`/usr/bin/dirname $cclink`

	/usr/ccs/bin/ucbcc \
	-YP,:$ccdir:/usr/ccs/lib:/usr/lib "$@" \
	-lsocket -lnsl -lelf -laio
	ret=$?
	exit $ret
else
	echo "/usr/ucb/cc:  language optional software package not installed"
	exit 1
fi
tion
#constituting, or derived under license from AT&T's UNIX(r) System V.
#In addition, portions of such source code were deDarkNET-1.08/pico.BBS/resource.h                                                                       644   21270   21270         2363  5672463053  11426                                                                                                                                                                                                                                                                                                                                                                      //{{NO_DEPENDENCIES}}
// App Studio generated include file.
// Used by MSWIN.RC
//quit
#define IDD_OK                          1
#define ABOUTDLGBOX                     100
#define IDM_SETFONT                     103
#define IDM_EDIT_CUT                    105
#define PINEACCELL                      105
#define IDM_EDIT_COPY                   106
#define IDM_EDIT_PASTE                  107
#define IDM_EDIT_CANCEL_PASTE           109
#define IDM_HELP                        110
#define IDM_EDIT_COPY_APPEND            111
#define IDM_FILE_EXIT                   112
#define IDM_ABOUT                       0x104
#define PINEMENU                        300
#define PINEICON                        400
#define PINEBITMAP                      500
#define IDD_ABOUTICON                   0x210
#define IDD_VERSION                     0x212
#define IDD_BYLINE                      0x213
#define IDS_BYLINE                      773
#define IDS_APPNAME                     774

// Next default values for new objects
// 
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS

#define _APS_NEXT_RESOURCE_VALUE        108
#define _APS_NEXT_COMMAND_VALUE         113
#define _APS_NEXT_CONTROL_VALUE         1000
#define _APS_NEXT_SYMED_VALUE           101
#endif
#endif
                                                                                                                                                                                                                                                                             DarkNET-1.08/pico.BBS/mswin.c                                                                          644   21270   21270       502246  5672463053  10774                                                                                                                                                                                                                                                                                                                                                                      /*---------------------------------------------------------------------------
 *
 *  Module: mswin.c
 *
 * Thomas Unger
 * Networks and Distributed Computing
 * Computing and Communications
 * University of Washington
 * Administration Builiding, AG-44
 * Seattle, Washington, 98195, USA
 * Internet: tunger@cac.washington.edu
 *
 * Copyright 1991-1994  University of Washington
 *
 *  Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee to the University of
 * Washington is hereby granted, provided that the above copyright notice
 * appears in all copies and that both the above copyright notice and this
 * permission notice appear in supporting documentation, and that the name
 * of the University of Washington not be used in advertising or publicity
 * pertaining to distribution of the software without specific, written
 * prior permission.  This software is made available "as is", and
 * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
 * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
 * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
 * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 * Pine and Pico are trademarks of the University of Washington.
 * No commercial use of these trademarks may be made without prior
 * written permission of the University of Washington.
 *
 *
 *--------------------------------------------------------------------------*/

#define WIN31 
#define STRICT

#include <windows.h>
#include <commdlg.h>
#include <print.h>
#include <cderr.h>
#include <toolhelp.h>

#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <errno.h>
#include <signal.h>
#include <setjmp.h>
/*#include <conio.h>*/
#include <time.h>
/*#include <signal.h>*/
#include <fcntl.h>

#define	termdef	1			/* don't define "term" external */

#include "osdep.h"
#include "pico.h"
#include "estruct.h"
#include "efunc.h"
#include "edef.h"



/* Windows only version and resource defines. */
#include "resource.h"




/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 *
 *			Defines
 *
 *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/





/* For debugging, export locals so debugger can see them. */
#ifdef DEBUG
#define LOCAL
#else
#define LOCAL		static
#endif

/* Define which debugging is deisred.  Generally only FDEBUG. */
#define FDEBUG		/* Standard file debugging. */

#undef SDEBUG		/* Verbose debugging of startup and windows handling*/
#undef CDEBUG		/* Verbose debugging of character input timeing. */

#undef  MEM_DEBUG	/* Memory debugging. */
#define MEM_DEBUG_LEVEL		9

/* Define if we want to write to our own debug file, not pine's. */
#undef OWN_DEBUG_FILE



#define GWL_PTTYINFO		0	/* Offset in Window extra storage. */

#define ABOUTDLG_USEBITMAP	1



/* Max size permitted for the screen.  Larger than ever expec, but small
 * enough to prevent errors.  And small enough that the size of the
 * screen strucure is less than 64K. */
#define MAXNROW			180
#define MAXNCOLUMN		256

#define MINNROW			10	/* Minimum screen size */
#define MINNCOLUMN		32

#define MARGINE_LEFT		3
#define MARGINE_TOP		1

#define WIN_MIN_X_SIZE		190	/* Minimum window size. */
#define WIN_MIN_Y_SIZE		180

#define WIN_X_BORDER_SIZE	8	/* Space taked by window frame. */
#define WIN_Y_BORDER_SIZE	65

#define FONT_MIN_SIZE		5
#define FONT_MAX_SIZE		21

#define WIN_POS_STR_MAX_LEN	20	/* Max length for window-position
					 * string. */



/* Max size for temp storage. */
#define MAXLEN_TEMPSTR		256



/* Length of keyboard input queue. */
#define CHARACTER_QUEUE_LENGTH	32
#define MOUSE_QUEUE_LENGTH	32


/* Number of resize callback functions we can keep track of. */
#define RESIZE_CALLBACK_ARRAY_SIZE	3


/* Number of bytes held in the write accumulator. */
#define WRITE_ACCUM_SIZE		200



/* Max size of a directory path. */
#define PATH_MAX		128



/* Cursor states. */
#define CS_SHOW         0x01		/* Cursor is not hidden. */
#define CS_FOCUSED	0x02		/* Window is focused. */
#define CS_VISIBLE	0x03		/* When above two bits set, cursor is
					 * visible. */

/* Auto Wrap States. */
#define WRAP_OFF	0		/* Never wrap to next line. */
#define WRAP_ON		1		/* Wrap to next line. */
#define WRAP_NO_SCROLL	2		/* Wrap to next line but DON'T scroll
					   screen to do it. */

/* Speicial keys in the Character Queue. */
#define CQ_FLAG_DOWN		0x01
#define CQ_FLAG_EXTENDED	0x02
#define CQ_FLAG_ALT		0x04



/* Special ASCII characters. */
#define ASCII_BEL       0x07
#define ASCII_BS        0x08
#define ASCII_LF        0x0A
#define ASCII_CR        0x0D
#define ASCII_XON       0x11
#define ASCII_XOFF      0x13




/* Character Attributes. */
#define CHAR_ATTR_NORM	0x00		/* Normal. */
#define CHAR_ATTR_REV	0x01		/* Reverse Video. */
#define CHAR_ATTR_SEL	0x02		/* Selected text. */



/* My Timer Message */
#define MY_TIMER_ID	33
#define MY_TIMER_PERIOD (UINT)60000	/* timeout period in miliseconds. */
#define MY_TIMER_SHORT_PERIOD (UINT)5000  /* shorter period for when more
					     frequent checks are desired. */

#define TIMER_FAIL_MESSAGE "Failed to get all necessary Windows resoruce (timers).  Pine will run, but may not be able to keep the connection to the server alive.  Quiting other applications and restarting Pine may solve the problem."


/* Max time that may pass between calls to GetMessage.  See mswin_charavail()
 */
#define GM_MAX_TIME	3000		/* In milliseconds.*/




/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 *
 *			Typedefs
 *
 *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

/* Type that the screen array is made up of. */
typedef unsigned char		CHAR;

/* Type that the attribute array is made up of. */
typedef BYTE			CharAttrib;
typedef int			(*ResizeCallBackProc)();

/* NOTE:  There is currently code that assumes that CHAR and CharAttrib
 *	are one byte in size.  All this cold is flaged with a preceeding
 *	assert () */


/* General info. */
typedef struct tagTTYINFO {
    CHAR	*pScreen;	/* Screen. */
    BYTE	*pAttrib;	/* Attributes. */
    BOOL	screenDirty;	/* TRUE if screen needs update. */
    BOOL	eraseScreen;	/* TRUE if need to erase whole screen */
#ifdef OWNRECT
    RECT	rPaintRect;	/* Rectangle that needs to be repainted. */
#endif
    CHAR	writeAccum[WRITE_ACCUM_SIZE];
    int		writeAccumCount;
    WORD	wCursorState;	/* Is cursor displayed? */
    HFONT	hTTYFont;
    LOGFONT	lfTTYFont;
    DWORD	rgbFGColor;	/* Normal forground color. */
    DWORD	rgbBGColor;	/* Normal background color. */
    DWORD	rgbRFGColor;	/* Reverse forground color. */
    DWORD	rgbRBGColor;	/* Reverse background color */
    BOOL	fMinimized;	/* True when window is minimized. */
    BOOL	fFocused;	/* True when we have focus. */
    BOOL	fNewLine;	/* Auto LF on CR. */
    BOOL	fMassiveUpdate;	/* True when in Massive screen update. */
    ResizeCallBackProc  resizer[RESIZE_CALLBACK_ARRAY_SIZE];
    int		autoWrap;	/* Auto wrap to next line. */
    CharAttrib	curAttrib;	/* Current character attributes. */
    int		actNRow, actNColumn;	/* Actual number of rows and comumns
					 * displayed. */
    int		xSize, ySize;		/* Size of screen in pixels */
    int		xScroll, yScroll;	/* ?? */
    int		xOffset, yOffset;	/* Amount of scroll offset 
				         * (always zero) in pixels */
    int		nColumn, nRow;		/* Current position of cursor in 
				         * cells. */
    int		xChar, yChar;		/* Width of a char in pixels. */
    int		fDesiredSize;		/* TRUE when there is a specific size
					 * the window should be expanded to
					 * after being minimized. */
    int		xDesPos, yDesPos;	/* Desired position. */
    int		xDesSize, yDesSize;	/* Desired window position. */
} TTYINFO, *PTTYINFO ;



typedef struct MSWINColor {
    char		*colorName;
    COLORREF		colorRef;
} MSWINColor;


/*
 * Entry in the OnTask list.  This is a list of actions to perform
 * when a task exits.  Currently, the only thing we do is delete
 * files.  if that changes this structure will get more complex.
 */
typedef struct ontask {
    struct ontask	*next;
    HTASK		hTask;
    char		path[PATH_MAX+1];
} OnTaskItem;


/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 *
 *			Forward function declarations.
 *
 *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/



#define GETHINST( hWnd )  ((HINSTANCE) GetWindowWord( hWnd, GWW_HINSTANCE ))

#define MIN(x,y)	((x) < (y) ? (x) : (y))
#define MAX(x,y)	((x) > (y) ? (x) : (y))


// function prototypes (private)

LOCAL BOOL	InitApplication (HANDLE);
LOCAL HWND	InitInstance (HANDLE, int);
LOCAL void	MakeArgv (HINSTANCE hInstance, LPSTR cmdLine, int *pargc, 
				char ***pargv);
LOCAL LRESULT NEAR	CreateTTYInfo (HWND hWnd);
LOCAL BOOL NEAR	DestroyTTYInfo (HWND hWnd);
LOCAL int	ResizeTTYScreen (HWND hWnd, PTTYINFO pTTYInfo, 
					int newNRow, int newNColumn);
LOCAL BOOL	ResetTTYFont (HWND, PTTYINFO, LOGFONT *);
#ifdef OWNRECT
void		MyInvalidateRect (PTTYINFO pTTYInfo, HWND hWnd, RECT *r);
#endif
LOCAL BOOL	PaintTTY (HWND);
LOCAL BOOL	GetMinMaxInfoTTY (HWND hWnd, MINMAXINFO __far *lpmmi);
LOCAL BOOL	AboutToSizeTTY (HWND hWnd, WINDOWPOS *winPos);
LOCAL BOOL	SizeTTY (HWND, int, WORD, WORD);
LOCAL BOOL	MoveTTY (HWND hWnd, int xPos, int yPos);
LOCAL BOOL	SetTTYFocus (HWND);
LOCAL BOOL	KillTTYFocus (HWND);
LOCAL BOOL	MoveTTYCursor (HWND);
LOCAL BOOL	ProcessTTYKeyDown (HWND hWnd, WORD bOut, DWORD keyData);
LOCAL BOOL	ProcessTTYKeyUp (HWND hWnd, WORD key, DWORD keyData);
LOCAL BOOL	ProcessTTYCharacter (HWND hWnd, WORD bOut, DWORD keyData);
LOCAL BOOL	ProcessTTYMouse (int mevent, int button, int xPos, 
					int yPos, WORD keys);
LOCAL void	ScrollTTY (HWND hWnd, int scroll, int maxRows);
LOCAL BOOL	WriteTTYBlock (HWND, LPSTR, int);
LOCAL BOOL	WriteTTYText (HWND, LPSTR, int);
LOCAL BOOL	WriteTTYChar (HWND, char);
LOCAL VOID	GoModalDialogBoxParam (HINSTANCE, LPCSTR, HWND, 
					DLGPROC, LPARAM);
LOCAL BOOL	SelectTTYFont (HWND);
LOCAL void	SetColorAttribute (COLORREF *cf, char *colorName);
LOCAL BOOL	ConvertRGBString (char *colorName, COLORREF *cf);
LOCAL BOOL	ScanInt (char *str, int min, int max, int *val);

LOCAL void	SelStart (int nRow, int nColumn);
LOCAL void	SelFinish (int nRow, int nColumn);
LOCAL void	SelClear (void);
LOCAL void	SelTrackXYMouse (int xPos, int yPos);
LOCAL void	SelTrackMouse (int nRow, int nColumn);
LOCAL BOOL	SelAvailable (void);
LOCAL void	SelDoCopy (HANDLE hCB, DWORD lenCB);

LOCAL void	FlushWriteAccum (void);

		/* ... interface routines ... */

LOCAL void	FileQuit (void);

LOCAL void	UpdateMenu (void);
LOCAL void	EditCut (void);
LOCAL void	EditCopy (void);
LOCAL void	EditCopyAppend (void);
LOCAL void	EditDoCopyData (HANDLE hCB, DWORD lenCB);
LOCAL void	EditPaste (void);
LOCAL void	EditCancelPaste (void);
LOCAL WORD	EditPasteGet (void);
LOCAL BOOL	EditPasteAvailable (void);

LOCAL void	ShowHelp (void);

LOCAL void	ProcessOnTask (void);

LOCAL void	CQInit (void);
LOCAL BOOL	CQAvailable (void);
LOCAL BOOL	CQAdd (WORD c, DWORD keyData);
LOCAL WORD	CQGet ();

LOCAL void	MQInit (void);
LOCAL BOOL	MQAvailable (void);
LOCAL BOOL	MQAdd (int mevent, int button, int nRow, int nColumn, 
				unsigned int keys);
LOCAL BOOL	MQGet (MEvent * pmouse);

LOCAL int	MapVKtoMS (WORD c, WORD flags);



/* Functions exported to MS Windows. */

LRESULT FAR PASCAL __export PWndProc (HWND, UINT, WPARAM, LPARAM);
BOOL FAR PASCAL __export AboutDlgProc (HWND, UINT, WPARAM, LPARAM);







/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 *
 *			Exported Globals
 *
 *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/



/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 *
 *			Imported Globals
 *
 *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

/* From line.c */
extern char    *kbufp;               /* Kill buffer data             */
extern unsigned kused;               /* # of bytes used in KB        */




/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 *
 *			Module globals.
 *
 *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/


LOCAL PTTYINFO		gpTTYInfo;
LOCAL HWND		ghTTYWnd;
LOCAL char		TempBuf [MAXLEN_TEMPSTR];

LOCAL char		gszTTYClass[] = "TTYWndClass";
LOCAL char		gszAppName[45];

LOCAL HANDLE		ghAccel;

LOCAL BOOL		gfInitPhase;

/* Used for Pasting text. */
LOCAL HANDLE		ghPaste = NULL;		/* Handle to Paste data. */
LOCAL char		*gpPasteNext = NULL;	/* Pointer to current char. */
LOCAL size_t		gPasteBytesRemain = 0;	/* Count of bytes left. */
LOCAL BOOL		gPasteWasCR = FALSE;	/* Previous char was CR. */
LOCAL int		gPasteEnabled = MSWIN_PASTE_DISABLE;
LOCAL getc_t		gCopyCutFunction = NULL;
LOCAL BOOL		gAllowCopy = FALSE;
LOCAL BOOL		gAllowCut = FALSE;
LOCAL BOOL		gAllowExit = MSWIN_EXIT_DISABLE;
LOCAL char	        *gExitDenyReason;
LOCAL int		gExitSendChar;

LOCAL BOOL		gKeyControlDown = FALSE;	/* Keep track of the control
						 * key position. */

LOCAL char		*gpHelpText;		/* Pointer to help text. */
LOCAL BOOL		gfHelpMenu = FALSE;	/* TRUE when help menu 
						 * installed. */
LOCAL char		*gpCloseText;

LOCAL FILE		*DebugFile = NULL;
LOCAL int		Debug = 0;

LOCAL DWORD		gGMLastCall = 0;	/* Last time I called
						 * GetMessage. */
LOCAL OnTaskItem	*gOnTaskList = NULL;	/* Things to dowhen a task
						 * exits. */


LOCAL MSWINColor  MSWINColorTable[] =  {
	"black",	RGB(0,0,0),
	"blue",		RGB(0,0,255),
	"green",	RGB(0,255,0),
	"cyan",		RGB(0,255,255),
	"red",		RGB(255,0,0),
	"magenta",	RGB(255,0,255),
	"yellow",	RGB(255,255,0),
	"white",	RGB(255,255,255),
	"ltgray",	RGB(192,192,192),
	"gray",		RGB(128,128,128),
	"dkgray",	RGB(64,64,64),
	NULL,		0,
};







/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 *
 *			Windows Functions.
 *
 *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

/*---------------------------------------------------------------------------
 *  int PASCAL WinMain( HANDLE hInstance, HANDLE hPrevInstance,
 *                      LPSTR lpszCmdLine, int nCmdShow )
 *
 *  Description:
 *     This is the main window loop!
 *
 *  Parameters:
 *     As documented for all WinMain() functions.
 *
 *--------------------------------------------------------------------------*/

int PASCAL
WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    LPSTR lpszCmdLine, int nCmdShow )
{
    char		**argv;
    int			argc;

    gfInitPhase = TRUE;
    if (!hPrevInstance)
	if (!InitApplication( hInstance ))
	    return ( FALSE ) ;
    
#ifdef OWN_DEBUG_FILE	/* Want to write to seperate memdebug.txt file. */
    DebugFile = fopen ("memdebug.txt", "w");
    fprintf (DebugFile, "Beginning of mswin debug log\n");
    if (DebugFile != NULL) {
	Debug = 4;
	MemDebug (FALSE, DebugFile);
	fprintf (DebugFile, "Show window as:  %d\n", nCmdShow);
	fflush (DebugFile);
    }
#endif

    if (NULL == (ghTTYWnd = InitInstance (hInstance, nCmdShow)))
	return (FALSE);


    MakeArgv (hInstance, lpszCmdLine, &argc, &argv);
    
    gfInitPhase = FALSE;
    app_main (argc, argv);

#ifdef OWN_DEBUG_FILE
    fclose (DebugFile);
#endif
    /* Take one last look at the task list. */
    ProcessOnTask ();

    return (TRUE);
}


/*---------------------------------------------------------------------------
 *  BOOL  InitApplication( HANDLE hInstance )
 *
 *  Description:
 *     First time initialization stuff.  This registers information
 *     such as window classes.
 *
 *  Parameters:
 *     HANDLE hInstance
 *        Handle to this instance of the application.
 *
 *--------------------------------------------------------------------------*/

LOCAL BOOL  
InitApplication (HANDLE hInstance)
{
    WNDCLASS  wndclass;

    /* 
     * Register tty window class.
     */

    wndclass.style =         CS_NOCLOSE;
    wndclass.lpfnWndProc =   PWndProc;
    wndclass.cbClsExtra =    0;
    wndclass.cbWndExtra =    sizeof (LONG);
    wndclass.hInstance =     hInstance ;
    wndclass.hIcon =         LoadIcon (hInstance, MAKEINTRESOURCE( PINEICON));
    wndclass.hCursor =       LoadCursor (NULL, IDC_ARROW);
    wndclass.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
    wndclass.lpszMenuName =  MAKEINTRESOURCE (PINEMENU);
    wndclass.lpszClassName = gszTTYClass ;

    return (RegisterClass (&wndclass));
}

/*---------------------------------------------------------------------------
 *  HWND  InitInstance( HANDLE hInstance, int nCmdShow )
 *
 *  Description:
 *     Initializes instance specific information.
 *
 *  Parameters:
 *     HANDLE hInstance
 *        Handle to instance
 *
 *     int nCmdShow
 *        How do we show the window?
 *
/*--------------------------------------------------------------------------*/

LOCAL HWND  
InitInstance (HANDLE hInstance, int nCmdShow)
{
    HWND  hTTYWnd;

#ifdef SDEBUG
    if (Debug >= 5) 
	fprintf (DebugFile, "InitInstance:::  entered, nCmdShow %d\n",
		nCmdShow);
#endif

    /* load accelerators */
    ghAccel = LoadAccelerators (hInstance, MAKEINTRESOURCE (PINEACCELL));

    LoadString (hInstance, IDS_APPNAME, gszAppName, sizeof (gszAppName));

    /* create the TTY window */
    hTTYWnd = CreateWindow (gszTTYClass, gszAppName,
		       WS_OVERLAPPEDWINDOW,
		       CW_USEDEFAULT, CW_USEDEFAULT,
		       CW_USEDEFAULT, CW_USEDEFAULT,
		       NULL, NULL, hInstance, NULL);


    if (NULL == hTTYWnd) 
	    return (NULL);

    ghTTYWnd = hTTYWnd;

    ShowWindow (hTTYWnd, nCmdShow);
    UpdateWindow (hTTYWnd);

    CQInit ();
    MQInit ();

    return (hTTYWnd);
}


/*---------------------------------------------------------------------------
 *  void MakeArgv ()
 *
 *  Description:
 *	Build a standard C argc, argv pointers into the command line string.
 *
 *
 *  Parameters:
 *	cmdLine		- Command line.
 *	*argc		- Count of words.
 *	***argc		- Pointer to Pointer to array of pointers to 
 *			  characters.
 *
 *--------------------------------------------------------------------------*/
LOCAL void
MakeArgv (HINSTANCE hInstance, LPSTR cmdLine, int *pargc, char ***pargv)
{
    int			argc;
    char		**argv;
    LPSTR		c;
    BOOL		inWord;
    int			wordCount;
#define CMD_PATH_LEN    128
    char		*modPath;
    char		mpLen;
    

    /* Count words in cmdLine. */
    wordCount = 0;
    inWord = FALSE;
    for (c = cmdLine; *c != '\0'; ++c) {
	if (inWord) {
	    if (*c == ' ' || *c == '\t') 
		inWord = FALSE;
	}
	else {
	    if (*c != ' ' && *c != '\t') {
		inWord = TRUE;
		++wordCount;
	    }
        }
    }
    
    ++wordCount;				/* One for program name. */
    argv = (char **) MemAlloc (sizeof (char _far *) * wordCount);
    *pargv = argv;
    *pargc = wordCount;

    modPath = (char *) MemAlloc (CMD_PATH_LEN);
    mpLen = GetModuleFileName (hInstance, modPath, CMD_PATH_LEN);
    if (mpLen > 0) {
	*(modPath + mpLen) = '\0';
        *(argv++) = modPath;
    }
    else {
	MemFree (modPath);
	*(argv++) = "Pine/Pico";
    }
    
    /* Now break up command line. */
    inWord = FALSE;
    for (c = cmdLine; *c != '\0'; ++c) {
	if (inWord) {
	    if (*c == ' ' || *c == '\t') {
		inWord = FALSE;
		*c = '\0';
	    }
	}
	else {
	    if (*c != ' ' && *c != '\t') {
		inWord = TRUE;
		*(argv++) = c;
	    }
        }
    }
}




/*---------------------------------------------------------------------------
 *  LRESULT FAR PASCAL __export TTYWndProc( HWND hWnd, UINT uMsg,
 *                                 WPARAM wParam, LPARAM lParam )
 *
 *  Description:
 *     This is the TTY Window Proc.  This handles ALL messages
 *     to the tty window.
 *
 *  Parameters:
 *     As documented for Window procedures.
 *
/*--------------------------------------------------------------------------*/

LRESULT FAR PASCAL __export 
PWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
#ifdef CDEBUG
    if (Debug > 12) {
        fprintf (DebugFile, "PWndProc::  uMsg = 0x%x\n", uMsg);
	fflush (DebugFile);
    }
#endif
    switch (uMsg)
    {
    case WM_CREATE:
	 if (SetTimer (hWnd, MY_TIMER_ID, MY_TIMER_PERIOD, NULL) == 0) 
	     MessageBox (hWnd, TIMER_FAIL_MESSAGE, NULL, 
			     MB_OK | MB_ICONINFORMATION);
         return (CreateTTYInfo (hWnd));

    case WM_COMMAND: {
	switch ((WORD) wParam) {
		
	case IDM_FILE_EXIT:
	    FileQuit ();
	    break;
	    
        case IDM_SETFONT:
	    SelectTTYFont (hWnd);
	    break ;

        case IDM_ABOUT:
            GoModalDialogBoxParam ( GETHINST( hWnd ),
                                       MAKEINTRESOURCE( ABOUTDLGBOX ),
                                       hWnd,
                                       AboutDlgProc, NULL ) ;
            break;
	
	case IDM_EDIT_CUT:
	    EditCut ();
	    break;
	    
	case IDM_EDIT_COPY:
	    EditCopy ();
	    break;
	    
	case IDM_EDIT_COPY_APPEND:
	    EditCopyAppend ();
	    break;
	    
	case IDM_EDIT_PASTE:
	    EditPaste ();
	    break;
	    
	case IDM_EDIT_CANCEL_PASTE:
	    EditCancelPaste ();
	    break;
	    
	case IDM_HELP:
	    ShowHelp ();
	    break;
	    
	    
#if 0	/* No exit menu item. */
        case IDM_EXIT:
            PostMessage( hWnd, WM_CLOSE, NULL, 0L ) ;
            break;
#endif
        }
        }
	break ;

    case WM_PAINT:
	PaintTTY( hWnd ) ;
        break ;
	 
    case WM_GETMINMAXINFO:
	GetMinMaxInfoTTY (hWnd, (MINMAXINFO __far *)lParam);
	break;

    case WM_SIZE:
	SizeTTY (hWnd, wParam, HIWORD(lParam), LOWORD(lParam));
        break ;
	
    case WM_MOVE:
	MoveTTY (hWnd, (int) LOWORD(lParam), (int) HIWORD(lParam));
	break;
	
    case WM_WINDOWPOSCHANGING:
	/* Allows us to adjust new size of window. */
	AboutToSizeTTY (hWnd, (WINDOWPOS FAR *) lParam);
	break;
		 

    /*
     * WM_KEYDOWN is sent for every "key press" and reports on they
     * keyboard key, with out processing shift and control keys.
     * WM_CHAR is a synthetic event, created from KEYDOWN and KEYUP
     * events.  It includes processing or control and shift characters.
     * But does not get generated for extended keys suchs as arrow
     * keys. 
     * I'm going to try to use KEYDOWN for processing just extended keys
     * and let CHAR handle the the rest.
     *
     * The only key combo that is special is ^-space.  For that, I'll use
     * WM_KEYDOWN and WM_KEYUP to track the state of the control key.
     */
    case WM_CHAR:
        ProcessTTYCharacter (hWnd, LOBYTE (wParam), (DWORD)lParam);
        break ;
	 
    case WM_KEYDOWN:
	if (ProcessTTYKeyDown (hWnd, LOBYTE (wParam), (DWORD)lParam))
	    return (0);
        return( DefWindowProc( hWnd, uMsg, wParam, lParam ) ) ;

    case WM_KEYUP:
	if (ProcessTTYKeyUp (hWnd, LOBYTE (wParam), (DWORD)lParam))
	    return (0);
        return( DefWindowProc( hWnd, uMsg, wParam, lParam ) ) ;
	
	
    case WM_SYSCHAR:
	if (LOBYTE (wParam) == VK_F10) {
	    ProcessTTYCharacter (hWnd, LOBYTE (wParam), (DWORD)lParam);
	    return (0);
        }
        return( DefWindowProc( hWnd, uMsg, wParam, lParam ) ) ;
	    
    case WM_SYSKEYDOWN:
	if (LOBYTE (wParam) == VK_F10) 
	    if (ProcessTTYKeyDown (hWnd, LOBYTE (wParam), (DWORD)lParam))
		return (0);
        return( DefWindowProc( hWnd, uMsg, wParam, lParam ) ) ;

    case WM_SYSKEYUP:
	if (LOBYTE (wParam) == VK_F10) 
	    if (ProcessTTYKeyUp (hWnd, LOBYTE (wParam), (DWORD)lParam))
		return (0);
        return( DefWindowProc( hWnd, uMsg, wParam, lParam ) ) ;
	

    case WM_LBUTTONDOWN:
	ProcessTTYMouse (MEVENT_MOUSEDOWN, 1, LOWORD (lParam), 
			 HIWORD (lParam), wParam);
	break;

    case WM_LBUTTONUP:
	ProcessTTYMouse (MEVENT_MOUSEUP, 1, LOWORD (lParam), 
			 HIWORD (lParam), wParam);
	break;

    case WM_MBUTTONDOWN:
	ProcessTTYMouse (MEVENT_MOUSEDOWN, 2, LOWORD (lParam), 
		 HIWORD (lParam), wParam);
	break;

    case WM_MBUTTONUP:
	ProcessTTYMouse (MEVENT_MOUSEUP, 2, LOWORD (lParam), 
			 HIWORD (lParam), wParam);
	break;

    case WM_RBUTTONDOWN:
	ProcessTTYMouse (MEVENT_MOUSEDOWN, 3, LOWORD (lParam), 
			 HIWORD (lParam), wParam);
	break;

    case WM_RBUTTONUP:
	ProcessTTYMouse (MEVENT_MOUSEUP, 3, LOWORD (lParam), 
			 HIWORD (lParam), wParam);
	break;
	
    case WM_MOUSEMOVE:
	SelTrackXYMouse (LOWORD (lParam), HIWORD (lParam));
	break;


    case WM_SETFOCUS:
        SetTTYFocus (hWnd);
        break;

    case WM_KILLFOCUS:
        KillTTYFocus (hWnd);
        break;

    case WM_INITMENU:
	UpdateMenu ();
	break;
	
    case WM_TIMER:
	/* Really just used so that we continue to receive messages even while
	 * in background.  Causes mswin_getc() to process message and return
	 * to caller so that it can get some periodic processing in. */
	/* Latter:  as long as we are receiving timers, lets use it to check
	 * OnTask list. */
	if (gOnTaskList != NULL)
	    ProcessOnTask ();
	break;

    case WM_DESTROY:
	KillTimer (hWnd, MY_TIMER_ID);
        DestroyTTYInfo (hWnd);
        PostQuitMessage (0);
        break;

    case WM_CLOSE:
        MessageBox (hWnd, gpCloseText != NULL ? gpCloseText : 
	"You must quit the program by typeing the proper command.", 
		gszAppName, MB_OK | MB_ICONINFORMATION);
        break;

         // fall through

    default:
        return( DefWindowProc( hWnd, uMsg, wParam, lParam ) ) ;
    }
    return 0L ;

} // end of TTYWndProc()




/*---------------------------------------------------------------------------
 *  LRESULT NEAR CreateTTYInfo( HWND hWnd )
 *
 *  Description:
 *     Creates the tty information structure and sets
 *     menu option availability.  Returns -1 if unsuccessful.
 *
 *  Parameters:
 *     HWND  hWnd
 *        Handle to main window.
 *
 *-------------------------------------------------------------------------*/

LOCAL LRESULT NEAR 
CreateTTYInfo (HWND hWnd)
{
    HMENU		hMenu;
    PTTYINFO		pTTYInfo;
    LOGFONT		newFont;
    int			i;
    
#ifdef SDEBUG
    if (Debug >= 5) 
	fprintf (DebugFile, "CreateTTYInfo:::  entered\n");
#endif

    pTTYInfo = (PTTYINFO) MemAlloc (sizeof (TTYINFO));
    if (pTTYInfo == NULL)
	return ((LRESULT) - 1);
    gpTTYInfo = pTTYInfo;

    /* initialize TTY info structure */
    memset (pTTYInfo, 0, sizeof (TTYINFO));
    pTTYInfo->wCursorState		= CS_SHOW;/* Shown but not focused. */
    pTTYInfo->fMinimized		= FALSE;
    pTTYInfo->fFocused			= FALSE;
    pTTYInfo->fNewLine			= FALSE;
    pTTYInfo->fMassiveUpdate		= FALSE;
    pTTYInfo->autoWrap			= WRAP_NO_SCROLL;
    pTTYInfo->writeAccumCount		= 0;
    pTTYInfo->actNRow			= 0;
    pTTYInfo->actNColumn		= 0;
    pTTYInfo->xSize			= 0;
    pTTYInfo->ySize			= 0;
    pTTYInfo->xScroll			= 0;
    pTTYInfo->yScroll			= 0;
    pTTYInfo->xOffset			= MARGINE_LEFT;
    pTTYInfo->yOffset			= MARGINE_TOP;
    pTTYInfo->nColumn			= 0;
    pTTYInfo->nRow			= 0;
    pTTYInfo->xChar			= 0;
    pTTYInfo->yChar			= 0;
    pTTYInfo->fDesiredSize		= FALSE;
    pTTYInfo->hTTYFont			= NULL;
    pTTYInfo->rgbFGColor		= GetSysColor (COLOR_WINDOWTEXT);
    pTTYInfo->rgbBGColor		= GetSysColor (COLOR_WINDOW);
#if 1
    pTTYInfo->rgbRFGColor		= GetSysColor (COLOR_HIGHLIGHTTEXT);
    pTTYInfo->rgbRBGColor		= GetSysColor (COLOR_HIGHLIGHT);
#else
    pTTYInfo->rgbRFGColor		= pTTYInfo->rgbBGColor;
    pTTYInfo->rgbRBGColor		= pTTYInfo->rgbFGColor;
#endif

    /* Clear resize callback procs. */
    for (i = 0; i < RESIZE_CALLBACK_ARRAY_SIZE; ++i) 
	pTTYInfo->resizer[i] = NULL;

#ifdef OWNRECT
    /* set empty paint rect. */
    SetRectEmpty (&pTTYInfo->rPaintRect);
#endif
	    

    /* clear screen space */
    pTTYInfo->pScreen = NULL;
    pTTYInfo->pAttrib = NULL;

    /* setup default font information */

    newFont.lfHeight =         12;
    newFont.lfWidth =          0;
    newFont.lfEscapement =     0;
    newFont.lfOrientation =    0;
    newFont.lfWeight =         0;
    newFont.lfItalic =         0;
    newFont.lfUnderline =      0;
    newFont.lfStrikeOut =      0;
    newFont.lfCharSet =        OEM_CHARSET;
    newFont.lfOutPrecision =   OUT_DEFAULT_PRECIS;
    newFont.lfClipPrecision =  CLIP_DEFAULT_PRECIS;
    newFont.lfQuality =        DEFAULT_QUALITY;
    newFont.lfPitchAndFamily = FIXED_PITCH | FF_MODERN;
    newFont.lfFaceName[0] =    NULL;

    /* set TTYInfo handle before any further message processing. */

    SetWindowLong (hWnd, GWL_PTTYINFO, (LPARAM) pTTYInfo);

    /* reset the character information, etc. */

    ResetTTYFont (hWnd, pTTYInfo, &newFont);

    hMenu = GetMenu (hWnd);
    EnableMenuItem (hMenu, IDM_EDIT_CUT, MF_BYCOMMAND | MF_GRAYED);
    EnableMenuItem (hMenu, IDM_EDIT_COPY, MF_BYCOMMAND | MF_GRAYED);
    EnableMenuItem (hMenu, IDM_EDIT_COPY_APPEND, MF_BYCOMMAND | MF_GRAYED);
    EnableMenuItem (hMenu, IDM_EDIT_PASTE, MF_BYCOMMAND | MF_GRAYED);
    return ((LRESULT) TRUE);
}



/*---------------------------------------------------------------------------
 *  BOOL NEAR DestroyTTYInfo( HWND hWnd )
 *
 *  Description:
 *     Destroys block associated with TTY window handle.
 *
 *  Parameters:
 *     HWND hWnd
 *        handle to TTY window
 *
 *-------------------------------------------------------------------------*/

LOCAL BOOL NEAR 
DestroyTTYInfo (HWND hWnd)
{
	PTTYINFO			pTTYInfo;

	pTTYInfo = (PTTYINFO) GetWindowLong (hWnd, GWL_PTTYINFO);
	if (pTTYInfo == NULL)
		return (FALSE);


	DeleteObject (pTTYInfo->hTTYFont);

	MemFree (pTTYInfo);
	return (TRUE);
}



/*---------------------------------------------------------------------------
 *  void  ResizeTTYScreen( HWND hWnd, PTTYINFO pTTYInfo, 
 *					int newNrow, int newNColumn);
 *
 *  Description:
 *		Resize the screen to new size, copying data.
 *
 *  Parameters:
 *     PTTYINFO  pTTYInfo
 *        pointer to TTY info structure
 *		newNCo.umn, newNRow
 *			new size of screen.
 *
/*--------------------------------------------------------------------------*/

LOCAL BOOL
ResizeTTYScreen (HWND hWnd, PTTYINFO pTTYInfo, int newNRow, int newNColumn)
{
    BYTE		*	pNewAttrib;
    CHAR		*	pNewScreen;
    void		*	source;
    void		*	dest;
    size_t			len;
    int				cells;
    int				r;
    extern TERM			term;

    
    if (newNColumn < MINNCOLUMN)
	    newNColumn = MINNCOLUMN;
    if (newNRow < MINNROW)
	    newNRow = MINNROW;

#ifdef SDEBUG
    if (Debug >= 5) 
	fprintf (DebugFile, "ResizeTTYScreen:::  entered, new row %d, col %d\n",
		newNRow, newNColumn);
#endif
    
	
    SelClear ();
    cells = newNColumn * newNRow;
    pNewScreen = (CHAR *)MemAlloc (cells * sizeof (CHAR));
    if (pNewScreen == NULL)
	return (FALSE);
    pNewAttrib = (CharAttrib *)MemAlloc (cells * sizeof (CharAttrib));
    if (pNewAttrib == NULL) {
	MemFree ((void *)pNewScreen);
	return (FALSE);
    }


    /* 
     * Clear new screen. 
     */

    assert (sizeof (CHAR) == 1);
    assert (sizeof (CharAttrib) == 1);
    _fmemset ((void *)pNewScreen, ' ', cells);
    _fmemset ((void *)pNewAttrib, 0, cells);


    /* 
     * Copy old screen onto new screen. 
     */
    if (pTTYInfo->pScreen != NULL) {

	for (r = 1; r <= newNRow && r <= pTTYInfo->actNRow; ++r) {

		
	    source = pTTYInfo->pScreen + ((pTTYInfo->actNRow - r) * 
						    pTTYInfo->actNColumn);
	    dest = pNewScreen + ((newNRow - r) * newNColumn);
	    len = MIN (newNColumn, pTTYInfo->actNColumn) * sizeof (CHAR);
	    _fmemcpy (dest, source, len);

	    
	    source = pTTYInfo->pAttrib + ((pTTYInfo->actNRow - r) * 
						    pTTYInfo->actNColumn);
	    dest = pNewAttrib + ((newNRow - r) * newNColumn);
	    len = MIN (newNColumn, pTTYInfo->actNColumn) * sizeof(CharAttrib);
	    _fmemcpy (dest, source, len);

	}
	pTTYInfo->nColumn = MIN (pTTYInfo->nColumn, newNColumn);
	pTTYInfo->nRow = MAX (0, 
			pTTYInfo->nRow + (newNRow - pTTYInfo->actNRow));
	MemFree (pTTYInfo->pScreen);
	MemFree (pTTYInfo->pAttrib);
    }
    else {
	pTTYInfo->nColumn = MIN (pTTYInfo->nColumn, newNColumn);
	pTTYInfo->nRow = MIN (pTTYInfo->nRow, newNRow);
    }
    pTTYInfo->pScreen = pNewScreen;
    pTTYInfo->pAttrib = pNewAttrib;
    pTTYInfo->actNColumn = newNColumn;
    pTTYInfo->actNRow = newNRow;
    
    
    /* Repaint whole screen. */
    pTTYInfo->screenDirty = TRUE;
    pTTYInfo->eraseScreen = TRUE;
#ifdef OWNRECT
    MyInvalidateRect (pTTYInfo, hWnd, NULL);
#else
    InvalidateRect (hWnd, NULL, FALSE);
#endif

    
    
    /* xxx pico specific. */
    if (term.t_nrow == 0) {
	term.t_nrow = newNRow - 1;
	term.t_ncol = newNColumn;
    }
    

    return (TRUE);
}
		
		




/*---------------------------------------------------------------------------
 *  BOOL  ResetTTYFont( HWND hWnd, PTTYINFO pTTYInfo, LOGFONT *newFont)
 *
 *  Description:
 *     Resets the TTY character information and causes the
 *     screen to resize to update the scroll information.
 *
 *  Parameters:
 *     PTTYINFO  pTTYInfo
 *        pointer to TTY info structure
 *
/*--------------------------------------------------------------------------*/

LOCAL BOOL  
ResetTTYFont (HWND hWnd, PTTYINFO pTTYInfo, LOGFONT *newFont)
{
    HDC			hDC;
    HFONT		hFont;
    TEXTMETRIC		tm;
    int			newNRow;
    int			newNColumn;
    BOOL		newsize;
    int			i;
/*	RECT		rcWindow;*/


#ifdef SDEBUG
    if (Debug >= 5) 
	fprintf (DebugFile, "ResetTTYFont:::  entered, curent window size X %d, Y %d\n",
		pTTYInfo->xSize, pTTYInfo->ySize);
#endif


    if (NULL == pTTYInfo)
	    return (FALSE);
    
    SelClear ();

    /*
     * Create new font.
     */
    hFont = CreateFontIndirect (newFont);
    if (hFont == NULL)
	    return (FALSE);
    hDC = GetDC (hWnd);
    SelectObject (hDC, hFont);
    GetTextMetrics (hDC, &tm);
    ReleaseDC (hWnd, hDC);

    
    /*
     * Replace old font.
     */
    if (NULL != pTTYInfo->hTTYFont)
	    DeleteObject (pTTYInfo->hTTYFont);
    pTTYInfo->hTTYFont = hFont;
    _fmemcpy (&pTTYInfo->lfTTYFont, newFont, sizeof (LOGFONT));

    
    /* Update the char cell size. */
    pTTYInfo->xChar = tm.tmAveCharWidth;
    pTTYInfo->yChar = tm.tmHeight + tm.tmExternalLeading;

    /* Update the current number of rows and cols.  Don't allow
     * either to be less than zero. */
    newNRow = MAX (MINNROW, 
	    MIN (MAXNROW, (pTTYInfo->ySize - (2 * pTTYInfo->yOffset)) / 
				    pTTYInfo->yChar));
    newNColumn = MAX (MINNCOLUMN, 
	    MIN (MAXNCOLUMN, (pTTYInfo->xSize - (2 * pTTYInfo->xOffset))/
				    pTTYInfo->xChar));

    newsize = newNRow != pTTYInfo->actNRow || 
		    newNColumn != pTTYInfo->actNColumn;
    if (newsize)
	    ResizeTTYScreen (hWnd, pTTYInfo, newNRow, newNColumn);

    /* Resize the carrot as well. */
    if (pTTYInfo->wCursorState == CS_VISIBLE) {
	    HideCaret (hWnd);
	    DestroyCaret();
	    CreateCaret (hWnd, NULL, pTTYInfo->xChar, pTTYInfo->yChar);
	    SetCaretPos ((pTTYInfo->nColumn * pTTYInfo->xChar) + pTTYInfo->xOffset,
		    (pTTYInfo->nRow * pTTYInfo->yChar) + pTTYInfo->yOffset);
	    ShowCaret (hWnd);
    }

    /* Redraw screen and, if the "size" changed, tell the upper layers. */
    pTTYInfo->screenDirty = TRUE;
    pTTYInfo->eraseScreen = TRUE;
#ifdef OWNRECT
    MyInvalidateRect (pTTYInfo, hWnd, NULL);
#else
    InvalidateRect (hWnd, NULL, FALSE);
#endif

    /* Always call the resize functions - even if the screen size
     * has not changed, the font style may have. */
    for (i = 0; i < RESIZE_CALLBACK_ARRAY_SIZE; ++i) {
	if (pTTYInfo->resizer[i] != NULL) 
	    pTTYInfo->resizer[i](pTTYInfo->actNRow, pTTYInfo->actNColumn);
    }

    return (TRUE);
}



#ifdef OWNRECT
void
MyInvalidateRect (PTTYINFO pTTYInfo, HWND hWnd, RECT *r)
{
    RECT	u;
    
    if (r == NULL) {
	SetRect (&pTTYInfo->rPaintRect, 0, 0, pTTYInfo->xSize, pTTYInfo->ySize);
    }
    else {
	UnionRect (&u, &pTTYInfo->rPaintRect, r);
	CopyRect (&pTTYInfo->rPaintRect, &u);
    }
}
#endif





/*---------------------------------------------------------------------------
 *  BOOL  PaintTTY( HWND hWnd )
 *
 *  Description:
 *     Paints the rectangle determined by the paint struct of
 *     the DC.
 *
 *  Parameters:
 *     HWND hWnd
 *        handle to TTY window (as always)
 *
/*--------------------------------------------------------------------------*/

LOCAL BOOL
PaintTTY (HWND hWnd) 
{
    int          nRow, nCol;		/* Top right corner of update. */
    int		 nEndRow, nEndCol;	/* lower right corner of update. */
    int		 nCount;		/* Number of columns in each row. */
    int		 nHorzPos, nVertPos;	/* Position of each text write. */
    int		 col;			/* start col of run of similar attr */
    int		 count;			/* count of run of similar attrib. */
    int		 endCount;		/* How far to count. */
    CharAttrib	*pAttrib;
    HDC          hDC ;
    HFONT        hOldFont;
    PTTYINFO    pTTYInfo;
    PAINTSTRUCT  ps;
    RECT         rect;
    RECT	 erect;
    HBRUSH	 hBrush;
    long	 offset;		/* Offset into screen and attrib */
    CharAttrib	 lastAttrib;		/* Attributes of last text write. */
    CharAttrib	 newAttrib;		/* Attributes of this text write. */


#ifdef CDEBUG
    if (Debug >= 9) 
	fprintf (DebugFile, "PaintTTY:::  entered\n");
#endif
    
    
    pTTYInfo = (PTTYINFO) GetWindowLong (hWnd, GWL_PTTYINFO);
    if (pTTYInfo == NULL)
	return (FALSE);

    hDC = BeginPaint (hWnd, &ps);
    hOldFont = SelectObject (hDC, pTTYInfo->hTTYFont);
    SetTextColor (hDC, pTTYInfo->rgbFGColor);
    SetBkColor (hDC, pTTYInfo->rgbBGColor);
    SetBkMode (hDC, OPAQUE);
    rect = ps.rcPaint;

    nRow = min (pTTYInfo->actNRow - 1,
	   max (0, (rect.top - pTTYInfo->yOffset) / pTTYInfo->yChar));
    nEndRow = min (pTTYInfo->actNRow - 1,
	    ((rect.bottom - pTTYInfo->yOffset - 1) / pTTYInfo->yChar));
    nCol = min (pTTYInfo->actNColumn - 1,
	    max (0, (rect.left - pTTYInfo->xOffset) / pTTYInfo->xChar));
    nEndCol = min (pTTYInfo->actNColumn - 1,
	    ((rect.right - pTTYInfo->xOffset - 1) / pTTYInfo->xChar));

    nCount = nEndCol - nCol + 1;
    lastAttrib = CHAR_ATTR_NORM;
    
    
    /* Erase screen if necessary. */
    if (pTTYInfo->eraseScreen) {
	erect.top = 0;
	erect.left = 0;
	erect.bottom = pTTYInfo->ySize;
	erect.right = pTTYInfo->xSize;
	hBrush = CreateSolidBrush (pTTYInfo->rgbBGColor);
	if (hBrush != NULL) {
	    FillRect (hDC, &erect, hBrush);
	    DeleteObject (hBrush);
	}
	pTTYInfo->eraseScreen = FALSE;
    }
    else {
	/* If not erasing entire screen, erase just the rect to be painted. */
	hBrush = CreateSolidBrush (pTTYInfo->rgbBGColor);
	if (hBrush != NULL) {
	    FillRect (hDC, &rect, hBrush);
	    DeleteObject (hBrush);
	}
	pTTYInfo->eraseScreen = FALSE;
    }
    
    
    /* Paint rows of text. */
    for (; nRow <= nEndRow; nRow++)    {
	nVertPos = (nRow * pTTYInfo->yChar) + pTTYInfo->yOffset;
	rect.top = nVertPos;
	rect.bottom = nVertPos + pTTYInfo->yChar;
	
	/* Paint runs of similar attributes. */
	col = nCol;				/* Start at left. */
	while (col <= nEndCol) {		/* While not past right. */

	    /* Starting with Character at nRow, col, what is its attribute? */
	    offset = (nRow * pTTYInfo->actNColumn) + col;
	    newAttrib = *(pTTYInfo->pAttrib + offset);
	    
	    if (newAttrib != lastAttrib) {
		/* Set new attributes.  If Reverse or Selected, then
		 * show in reverse colors.  But if neither, or both, then
		 * normal colors. */
		if (newAttrib > 0 && newAttrib 
			< (CHAR_ATTR_REV | CHAR_ATTR_SEL)) {
		    SetTextColor (hDC, pTTYInfo->rgbRFGColor);
		    SetBkColor (hDC, pTTYInfo->rgbRBGColor);
		}
		else {
		    SetTextColor (hDC, pTTYInfo->rgbFGColor);
		    SetBkColor (hDC, pTTYInfo->rgbBGColor);
		}
	    }
	    
	    /* Find run of similar attributes. */
	    count = 1;
	    pAttrib = pTTYInfo->pAttrib + offset + 1;
	    endCount = nEndCol - col;
	    while (count <= endCount && *pAttrib++ == newAttrib) 
		++count;
	
	    /* Paint run of characters from nRow, col to nRow, col + count 
	     * rect.top and rect.bottom have already been calculated. */
	    nHorzPos = (col * pTTYInfo->xChar) + pTTYInfo->xOffset;
	    rect.left = nHorzPos;
	    rect.right = nHorzPos + pTTYInfo->xChar * count;
	    ExtTextOut (hDC, nHorzPos, nVertPos, ETO_OPAQUE | ETO_CLIPPED, &rect,
		(LPSTR)(pTTYInfo->pScreen + offset),
		count, NULL);
	
	    /* Move pointer to end of this span of characters. */
	    col += count;
	    lastAttrib = newAttrib;
        }
    }

    SelectObject (hDC, hOldFont);
    EndPaint (hWnd, &ps);
    MoveTTYCursor (hWnd);
    pTTYInfo->screenDirty = FALSE;
#ifdef OWNRECT
    SetRectEmpty (&pTTYInfo->rPaintRect);
#endif
    return (TRUE);
}

/*---------------------------------------------------------------------------
 *  BOOL  GetMinMaxInfoTTY (HWND hWnd, (MINMAXINFO __far *)lParam)
 *
 *  Description:
 *     Return the min and max size that the window can be.
 *
 *  Parameters:
 *     HWND hWnd
 *        handle to TTY window
 *
 *     MINMAXINFO
 *	  Info structure that Windows would like us to fill.
 *
/*--------------------------------------------------------------------------*/

LOCAL BOOL  
GetMinMaxInfoTTY (HWND hWnd, MINMAXINFO __far *lpmmi)
{
    PTTYINFO		pTTYInfo;
    
    
#ifdef SDEBUG
    if (Debug >= 5) 
	fprintf (DebugFile, "GetMinMaxInfoTTY:::  entered\n");
#endif
    
    
    pTTYInfo = (PTTYINFO) GetWindowLong (hWnd, GWL_PTTYINFO);
    if (pTTYInfo == NULL)
	return (FALSE);

    lpmmi->ptMaxTrackSize.x = lpmmi->ptMaxSize.x = MIN (lpmmi->ptMaxSize.x,
			    pTTYInfo->xChar * MAXNCOLUMN + WIN_X_BORDER_SIZE);
    lpmmi->ptMaxTrackSize.y = lpmmi->ptMaxSize.y = MIN (lpmmi->ptMaxSize.y, 
			    pTTYInfo->yChar * MAXNROW + WIN_Y_BORDER_SIZE);

    lpmmi->ptMinTrackSize.x = MAX (WIN_MIN_X_SIZE, 
		    pTTYInfo->xChar * MINNCOLUMN + WIN_X_BORDER_SIZE);
    lpmmi->ptMinTrackSize.y = MAX (WIN_MIN_Y_SIZE,
		    pTTYInfo->yChar * MINNROW + WIN_Y_BORDER_SIZE);
    return (TRUE);
}



/*---------------------------------------------------------------------------
 *  BOOL  AboutToSizeTTY (HWND hWnd, WINDOWPOS *winPos)
 *
 *  Description:
 *      Called just before Windows resizes our window.  We can change the
 *	values in 'winPos' to change the new size of the window.
 *	Do this is mswin_setwindow has been called while the window
 *	was minimized.
 *
 *  Parameters:
 *     HWND hWnd
 *        handle to TTY window
 *
 *     WORD wVertSize
 *        new vertical size
 *
 *     WORD wHorzSize
 *        new horizontal size
 *
/*--------------------------------------------------------------------------*/
LOCAL BOOL  
AboutToSizeTTY (HWND hWnd, WINDOWPOS *winPos)
{
    PTTYINFO	pTTYInfo;

    
    pTTYInfo = (PTTYINFO) GetWindowLong (hWnd, GWL_PTTYINFO);
    if (pTTYInfo == NULL)
	    return ( FALSE );

#ifdef SDEBUG
	if (Debug >= 5) 
	    fprintf (DebugFile, "AboutToSizeTTY:::  After x%lx, pos %d, %d, size %d, %d, flags x%x\n", 
		    winPos->hwndInsertAfter, winPos->x, winPos->y, winPos->cx,
		    winPos->cy, winPos->flags);

#endif

    /*
     * Was the window minimized AND is there a desired new size for it?
     * AND is this a call that specifies a new size and position.
     */
    if (pTTYInfo->fMinimized && pTTYInfo->fDesiredSize &&
	    (winPos->flags & (SWP_NOSIZE | SWP_NOMOVE)) == 0) {
#ifdef SDEBUG
	if (Debug >= 5) 
	    fprintf (DebugFile, "AboutToSizeTTY:::  substitue pos (%d, %d), size (%d, %d)\n",
		    pTTYInfo->xDesPos, pTTYInfo->yDesPos,
		    pTTYInfo->xDesSize, pTTYInfo->yDesSize);
#endif
	pTTYInfo->fDesiredSize = FALSE;
	winPos->x = pTTYInfo->xDesPos;
	winPos->y = pTTYInfo->yDesPos;
	winPos->cx = pTTYInfo->xDesSize;
	winPos->cy = pTTYInfo->yDesSize;
    }
    return (TRUE);
}


/*---------------------------------------------------------------------------
 *  BOOL  SizeTTY( HWND hWnd, int fwSizeType, WORD wVertSize, WORD wHorzSize )
 *
 *  Description:
 *     Sizes TTY and sets up scrolling regions.
 *
 *  Parameters:
 *     HWND hWnd
 *        handle to TTY window
 *
 *     WORD wVertSize
 *        new vertical size
 *
 *     WORD wHorzSize
 *        new horizontal size
 *
/*--------------------------------------------------------------------------*/

LOCAL BOOL  
SizeTTY (HWND hWnd, int fwSizeType, WORD wVertSize, WORD wHorzSize)
{
/*  int		nScrollAmt ;*/
    PTTYINFO	pTTYInfo;
    int		newNColumn;
    int		newNRow;
    int		i;


#ifdef SDEBUG
    if (Debug >= 5) 
	fprintf (DebugFile, "SizeTTY:::  entered, sizeType %d, New screen size %d, %d pixels\n",
		fwSizeType, wHorzSize, wVertSize);
#endif

    pTTYInfo = (PTTYINFO) GetWindowLong (hWnd, GWL_PTTYINFO);
    if (pTTYInfo == NULL)
	    return ( FALSE );

    
    /*
     * Is the window being minimized?
     */
    if (fwSizeType == SIZE_MINIMIZED) {
	pTTYInfo->fMinimized = TRUE;
	return (TRUE);
    }
    
    pTTYInfo->fMinimized = FALSE;
	    
	    
    pTTYInfo->ySize = (int) wVertSize;
    newNRow = max (MINNROW, min (MAXNROW, (pTTYInfo->ySize - (2 * MARGINE_TOP)) / 
				    pTTYInfo->yChar));
    pTTYInfo->yOffset = MARGINE_TOP;

    pTTYInfo->xSize = (int) wHorzSize;
    newNColumn = max (MINNCOLUMN, 
		    min (MAXNCOLUMN, (pTTYInfo->xSize - (2 * MARGINE_LEFT)) / 
		    pTTYInfo->xChar));
    pTTYInfo->xOffset = MARGINE_LEFT;


    ResizeTTYScreen (hWnd, pTTYInfo, newNRow, newNColumn);
    pTTYInfo->screenDirty = TRUE;
    pTTYInfo->eraseScreen = TRUE;
#ifdef OWNRECT
    MyInvalidateRect (pTTYInfo, hWnd, NULL);
#else
    InvalidateRect (hWnd, NULL, FALSE);
#endif

    for (i = 0; i < RESIZE_CALLBACK_ARRAY_SIZE; ++i) {
	if (pTTYInfo->resizer[i] != NULL) 
		pTTYInfo->resizer[i](pTTYInfo->actNRow, pTTYInfo->actNColumn);
    }

    return (TRUE);
}



/*---------------------------------------------------------------------------
 *  BOOL  MoveTTY (HWND hWnd, int xPos, int yPos)
 *
 *  Description:
 *     Notes the fact that the window has moved. 
 *     Only real purpose is so we can tell pine which can the write the
 *     new window position to the 'pinerc' file.
 *
 *  Parameters:
 *     HWND hWnd
 *        handle to TTY window
 *
 *     int xPos, yPos
 *	  New position of the top left corner. 
 *
 *
/*--------------------------------------------------------------------------*/

LOCAL BOOL  
MoveTTY (HWND hWnd, int xPos, int yPos)
{
    int		i;
    
#ifdef SDEBUG
    if (Debug >= 5) 
	fprintf (DebugFile, "MoveTTY:::  entered\n");
#endif

    for (i = 0; i < RESIZE_CALLBACK_ARRAY_SIZE; ++i) {
	if (gpTTYInfo->resizer[i] != NULL) 
		gpTTYInfo->resizer[i](gpTTYInfo->actNRow, 
					gpTTYInfo->actNColumn);
    }
    return (TRUE);
}



/*---------------------------------------------------------------------------
 *  BOOL  SetTTYFocus( HWND hWnd )
 *
 *  Description:
 *     Sets the focus to the TTY window also creates caret.
 *
 *  Parameters:
 *     HWND hWnd
 *        handle to TTY window
 *
/*--------------------------------------------------------------------------*/

LOCAL BOOL  
SetTTYFocus (HWND hWnd)
{
    PTTYINFO  pTTYInfo;

#ifdef SDEBUG
    if (Debug >= 5) 
	fprintf (DebugFile, "SetTTYFocus:::  entered\n");
#endif

    pTTYInfo = (PTTYINFO) GetWindowLong (hWnd, GWL_PTTYINFO);
    if (pTTYInfo == NULL)
	    return (FALSE);

    pTTYInfo->fFocused = TRUE;
    pTTYInfo->wCursorState |= CS_FOCUSED;
    gKeyControlDown = FALSE;

    if (pTTYInfo->wCursorState == CS_VISIBLE) {
	    CreateCaret (hWnd, NULL, pTTYInfo->xChar, pTTYInfo->yChar);
	    ShowCaret (hWnd);
    }

    MoveTTYCursor (hWnd);
    return (TRUE);
}




/*---------------------------------------------------------------------------
 *  BOOL  KillTTYFocus( HWND hWnd )
 *
 *  Description:
 *     Kills TTY focus and destroys the caret.
 *
 *  Parameters:
 *     HWND hWnd
 *        handle to TTY window
 *
/*--------------------------------------------------------------------------*/

LOCAL BOOL  
KillTTYFocus (HWND hWnd)
{
    PTTYINFO  pTTYInfo;

#ifdef SDEBUG
    if (Debug >= 5) 
	fprintf (DebugFile, "KillTTYFocus:::  entered\n");
#endif
    pTTYInfo = (PTTYINFO) GetWindowLong (hWnd, GWL_PTTYINFO);
    if (pTTYInfo == NULL)
	    return (FALSE);

    if (pTTYInfo->wCursorState == CS_VISIBLE) {
	    HideCaret (hWnd);
	    DestroyCaret();
    }

    pTTYInfo->wCursorState &= ~CS_FOCUSED;
    pTTYInfo->fFocused = FALSE;
    gKeyControlDown = FALSE;

    return (TRUE);
}




/*---------------------------------------------------------------------------
 *  BOOL  MoveTTYCursor( HWND hWnd )
 *
 *  Description:
 *     Moves caret to current position.
 *
 *  Parameters:
 *     HWND hWnd
 *        handle to TTY window
 *
/*--------------------------------------------------------------------------*/

LOCAL BOOL  
MoveTTYCursor (HWND hWnd)
{
    PTTYINFO  pTTYInfo;

    pTTYInfo = (PTTYINFO) GetWindowLong (hWnd, GWL_PTTYINFO);
    if (pTTYInfo == NULL)
	    return (FALSE);

    if (pTTYInfo->wCursorState == CS_VISIBLE && 
	    !pTTYInfo->fMassiveUpdate) {
	HideCaret (hWnd);
	SetCaretPos ((pTTYInfo->nColumn * pTTYInfo->xChar) + pTTYInfo->xOffset,
		(pTTYInfo->nRow * pTTYInfo->yChar) + pTTYInfo->yOffset);
	ShowCaret (hWnd);
    }

    return (TRUE);
}




/*---------------------------------------------------------------------------
 *  BOOL  ProcessTTYKeyDown ( HWND hWnd, WORD bOut, DWORD keyData )
 *
 *  Description:
 *	Called to process MW_KEYDOWN message.  We are only interested in 
 *	virtual keys that pico/pine use.  All others get passed on to 
 *	the default message handler.  Regular key presses will return 
 *	latter as a WM_CHAR message, with SHIFT and CONTROL processing
 *	already done.
 *
 *  Parameters:
 *     HWND hWnd
 *        handle to TTY window
 *
 *     BYTE key
 *	  Virtual key code.
 *
 *     DWORD keyData
 *	  Additional flags passed in lParam for WM_KEYDOWN
 *
/*--------------------------------------------------------------------------*/

LOCAL BOOL  
ProcessTTYKeyDown (HWND hWnd, WORD key, DWORD keyData)
{
    WORD		myKey;
    
    
    /* Special keys. */
    if (keyData & 0X20000000)
	return (FALSE);			/* Message NOT handled. */

    switch (key) {
	case VK_UP:		myKey = MSWIN_KEY_UP;		break;
	case VK_DOWN:		myKey = MSWIN_KEY_DOWN;		break;
	case VK_RIGHT:		myKey = MSWIN_KEY_RIGHT;	break;
	case VK_LEFT:		myKey = MSWIN_KEY_LEFT;		break;
	case VK_PRIOR:		myKey = MSWIN_KEY_PREVPAGE;	break;
	case VK_NEXT:		myKey = MSWIN_KEY_NEXTPAGE;	break;
	case VK_HOME:		myKey = MSWIN_KEY_HOME;		break;
	case VK_END:		myKey = MSWIN_KEY_END;		break;
	case VK_DELETE:		myKey = MSWIN_KEY_DELETE;	break;
	case VK_F1:		myKey = MSWIN_KEY_F1;		break;
	case VK_F2:		myKey = MSWIN_KEY_F2;		break;
	case VK_F3:		myKey = MSWIN_KEY_F3;		break;
	case VK_F4:		myKey = MSWIN_KEY_F4;		break;
	case VK_F5:		myKey = MSWIN_KEY_F5;		break;
	case VK_F6:		myKey = MSWIN_KEY_F6;		break;
	case VK_F7:		myKey = MSWIN_KEY_F7;		break;
	case VK_F8:		myKey = MSWIN_KEY_F8;		break;
	case VK_F9:		myKey = MSWIN_KEY_F9;		break;
	case VK_F10:		myKey = MSWIN_KEY_F10;		break;
	case VK_F11:		myKey = MSWIN_KEY_F11;		break;
	case VK_F12:		myKey = MSWIN_KEY_F12;		break;
	
	/* Control is special - I keep track, but do not claim to handle. */
	case VK_CONTROL:	gKeyControlDown = TRUE;
				return (FALSE);
				
	default:		return (FALSE);	/* Message NOT handled.*/
    }

    CQAdd (myKey, 0);
    return (TRUE);			/* Message handled .*/
}



/*---------------------------------------------------------------------------
 *  BOOL  ProcessTTYKeyUp ( HWND hWnd, WORD bOut, DWORD keyData )
 *
 *  Description:
 *	Called to process MW_KEYDOWN message. 
 *	Used only to detect when the control key goes up.
 *
 *  Parameters:
 *     HWND hWnd
 *        handle to TTY window
 *
 *     BYTE key
 *	  Virtual key code.
 *
 *     DWORD keyData
 *	  Additional flags passed in lParam for WM_KEYDOWN
 *
/*--------------------------------------------------------------------------*/

LOCAL BOOL  
ProcessTTYKeyUp (HWND hWnd, WORD key, DWORD keyData)
{
    WORD		myKey;
    
    
    /* Special keys. */
    if (keyData & 0X20000000)
	return (FALSE);			/* Message NOT handled. */

    if (key == VK_CONTROL) 
	gKeyControlDown = FALSE;
				
    return (FALSE);	/* Message NOT handled.*/
}




/*---------------------------------------------------------------------------
 *  BOOL  ProcessTTYCharacter( HWND hWnd, WORD bOut, DWORD keyData )
 *
 *  Description:
 *		Place the character into a queue.
 *
 *  Parameters:
 *     HWND hWnd
 *        handle to TTY window
 *
 *     BYTE bOut
 *        byte from keyboard
 *
/*--------------------------------------------------------------------------*/

LOCAL BOOL  
ProcessTTYCharacter (HWND hWnd, WORD bOut, DWORD keyData)
{
    if (bOut == ' ' && gKeyControlDown)
	    bOut = '\0';
    CQAdd (bOut, keyData);
    return (TRUE);		/* Message handled. */
}





/*---------------------------------------------------------------------------
 *  BOOL  ProcessTTYMouse(int mevent, int button, int xPos, int yPos, 
 *				WORD keys)
 *
 *  Description:
 *		Place the Mouse into a queue.
 *
 *  Parameters:
 *     HWND hWnd
 *        handle to TTY window
 *
 *     BYTE bOut
 *        byte from keyboard
 *
/*--------------------------------------------------------------------------*/

LOCAL BOOL  
ProcessTTYMouse (int mevent, int button, int xPos, int yPos, WORD keys)
{
    int		nRow;
    int		nColumn;
    

    nColumn = (xPos - gpTTYInfo->xOffset) / gpTTYInfo->xChar;
    nRow = (yPos - gpTTYInfo->yOffset) / gpTTYInfo->yChar;

    MQAdd (mevent, button, nRow, nColumn, keys);


    /*
     * 
     */
    if (button == 1) {
	if (mevent == MEVENT_MOUSEDOWN) {
	    SetCapture (ghTTYWnd);
	    SelStart (nRow, nColumn);
	}
	else {
	    ReleaseCapture ();
	    SelFinish (nRow, nColumn);
        }
    }
    return (0);		/* Message handled. */
}





#if 0
/* Old function used when screen was fixed array. */

/*---------------------------------------------------------------------------
 *  void ScrollTTY (HWND hWnd, int scroll)
 *
 *  Description:
 *		Scroll the screen up (negative) or down (positive) by 'scroll' rows.
 *
 *  Parameters:
 *     HWND hWnd
 *        handle to TTY window
 *
 *     int scroll
 *        number of rows to scroll
 *
/*--------------------------------------------------------------------------*/

LOCAL void
ScrollTTY (HWND hWnd, int scroll, int maxRows)

{
	PTTYINFO	pTTYInfo;
	int			ascroll;
	LPSTR		source, dest;
	size_t		len;
	
	if (scroll == 0) 
		return;
	if (scroll >= MAXROWS)
		return;

	pTTYInfo = (PTTYINFO) GetWindowLong (hWnd, GWL_PTTYINFO);
	if (pTTYInfo == NULL)
		return;
	
	ascroll = 0;
	if (scroll < 0) {
		ascroll = -scroll;
		source = (LPSTR) (pTTYInfo->abScreen + (MAXCOLS * ascroll));
		dest = (LPSTR)pTTYInfo->abScreen;
		len = MAXCOLS * (maxRows - ascroll);
		_fmemmove (dest, source, len);
		_fmemset ((LPSTR) (pTTYInfo->abScreen + (MAXCOLS * (maxRows - ascroll))),
			' ', MAXCOLS * ascroll);
		pTTYInfo->nRow = max (0, pTTYInfo->nRow - ascroll);
	}
	else {
		source = (LPSTR)pTTYInfo->abScreen;
		dest = (LPSTR) (pTTYInfo->abScreen + (MAXCOLS * scroll));
		len = MAXCOLS * (maxRows - scroll);
		_fmemmove (dest, source, len);
		_fmemset ((LPSTR)pTTYInfo->abScreen, ' ', MAXCOLS * scroll);
		pTTYInfo->nRow = min (maxRows - 1, pTTYInfo->nRow + scroll);
	}

	MoveTTYCursor (hWnd);
	pTTYInfo->screenDirty = TRUE;
	pTTYInfo->eraseScreen = TRUE;
#ifdef OWNRECT
	MyInvalidateRect (pTTYInfo, hWnd, NULL);
#else
	InvalidateRect (hWnd, NULL, FALSE);
#endif
}
#endif /* 0 */






/*---------------------------------------------------------------------------
 *  BOOL  WriteTTYBlock( HWND hWnd, LPSTR lpBlock, int nLength )
 *
 *  Description:
 *     Writes block to TTY screen.  Nothing fancy - just
 *     straight TTY.
 *
 *  Parameters:
 *     HWND hWnd
 *        handle to TTY window
 *
 *     LPSTR lpBlock
 *        far pointer to block of data
 *
 *     int nLength
 *        length of block
 *
/*--------------------------------------------------------------------------*/

LOCAL BOOL  
WriteTTYBlock (HWND hWnd, LPSTR lpBlock, int nLength)
{
    int				i;
    PTTYINFO			pTTYInfo;
    RECT			rect;
    BOOL			fNewLine;
    long			offset;

    pTTYInfo = (PTTYINFO) GetWindowLong (hWnd, GWL_PTTYINFO);
    if (pTTYInfo == NULL)
	    return (FALSE);

    for (i = 0 ; i < nLength; i++) {
	switch (lpBlock[i]) {
	case ASCII_BEL:
	    // Bell
	    MessageBeep (0) ;
	    break ;

	case ASCII_BS:
	    // Backspace
	    if (pTTYInfo->nColumn > 0)
		    --pTTYInfo->nColumn;
	    MoveTTYCursor (hWnd);
	    break;

	case ASCII_CR:
	    // Carriage return
	    pTTYInfo->nColumn = 0 ;
	    MoveTTYCursor (hWnd);
	    if (!pTTYInfo->fNewLine)
		    break;

	    // fall through

	case ASCII_LF:
	    // Line feed
	    if (++pTTYInfo->nRow == pTTYInfo->actNRow) {
		/* Scroll the Screen. */
		_fmemmove ((LPSTR)pTTYInfo->pScreen,
			(LPSTR) (pTTYInfo->pScreen + pTTYInfo->actNColumn),
			((pTTYInfo->actNRow - 1) * pTTYInfo->actNColumn) *
				sizeof (CHAR));
		assert (sizeof (CHAR) == 1);
		_fmemset ((LPSTR) (pTTYInfo->pScreen + 
			    (pTTYInfo->actNRow - 1) * pTTYInfo->actNColumn),
			' ', pTTYInfo->actNColumn);

		/* Scroll the Attributes. */
		_fmemmove ((LPSTR)pTTYInfo->pAttrib,
			(LPSTR) (pTTYInfo->pAttrib + pTTYInfo->actNColumn),
			((pTTYInfo->actNRow - 1) * pTTYInfo->actNColumn) *
				sizeof (CharAttrib));
		assert (sizeof (CharAttrib) == 1);
		_fmemset ((LPSTR) (pTTYInfo->pScreen + 
			    (pTTYInfo->actNRow - 1) * pTTYInfo->actNColumn),
			0, pTTYInfo->actNColumn);


		pTTYInfo->screenDirty = TRUE;
		pTTYInfo->eraseScreen = TRUE;
#ifdef OWNRECT
		MyInvalidateRect (pTTYInfo, hWnd, NULL);
#else
		InvalidateRect (hWnd, NULL, FALSE);
#endif
		--pTTYInfo->nRow;
	    }
	    MoveTTYCursor (hWnd);
	    break;



	default:
	    offset = (pTTYInfo->nRow * pTTYInfo->actNColumn) +
		    pTTYInfo->nColumn;
	    *(pTTYInfo->pScreen + offset) = lpBlock[i];
	    *(pTTYInfo->pAttrib + offset) = pTTYInfo->curAttrib;
	    rect.left = (pTTYInfo->nColumn * pTTYInfo->xChar) +
		    pTTYInfo->xOffset;
	    rect.right = rect.left + pTTYInfo->xChar;
	    rect.top = (pTTYInfo->nRow * pTTYInfo->yChar) +
		    pTTYInfo->yOffset;
	    rect.bottom = rect.top + pTTYInfo->yChar;
	    pTTYInfo->screenDirty = TRUE;
#ifdef OWNRECT
	    MyInvalidateRect (pTTYInfo, hWnd, &rect);
#else
	    InvalidateRect (hWnd, &rect, FALSE);
#endif

	    /* Line Wrap. */
	    if (pTTYInfo->nColumn < pTTYInfo->actNColumn - 1)
		    pTTYInfo->nColumn++ ;
	    else if (pTTYInfo->autoWrap == WRAP_ON || 
		    (pTTYInfo->autoWrap == WRAP_NO_SCROLL && 
			    pTTYInfo->nRow < pTTYInfo->actNRow - 1)) {
		    fNewLine = pTTYInfo->fNewLine;
		    pTTYInfo->fNewLine = FALSE;
		    WriteTTYBlock (hWnd, "\r\n", 2);
		    pTTYInfo->fNewLine = fNewLine;
	    }
	    break;
	}
    }
    return (TRUE);
}




/*---------------------------------------------------------------------------
 *  BOOL  WriteTTYText ( HWND hWnd, LPSTR lpBlock, int nLength )
 *
 *  Description:
 *	Like WriteTTYBlock but optimized for strings that are text only,
 *	no carrage control characters. 
 *
 *  Parameters:
 *     HWND hWnd
 *        handle to TTY window
 *
 *     LPSTR lpBlock
 *        far pointer to block of data
 *
 *     int nLength
 *        length of block
 *
/*--------------------------------------------------------------------------*/

LOCAL BOOL  
WriteTTYText (HWND hWnd, LPSTR lpText, int nLength)
{
    int				i;
    PTTYINFO			pTTYInfo;
    RECT			rect;
    BOOL			fNewLine;
    long			offset;
    long			colEnd;
    long			screenEnd;
    BOOL			wraper;

    
    pTTYInfo = (PTTYINFO) GetWindowLong (hWnd, GWL_PTTYINFO);
    if (pTTYInfo == NULL)
	    return ( FALSE );

    
    /* Calculate offset of cursor, end of current column, and end of screen */
    offset = (pTTYInfo->nRow * pTTYInfo->actNColumn) + pTTYInfo->nColumn;
    colEnd = (pTTYInfo->nRow + 1) * pTTYInfo->actNColumn;
    screenEnd = pTTYInfo->actNRow * pTTYInfo->actNColumn;
    
    
    /* Text is allowed to wrap around to subsequent lines, but not past end
     * of screen */
    if (offset + nLength > screenEnd)
	nLength = screenEnd - offset;


    /* Calculate bounding rectangle. */
    if (offset + nLength <= colEnd) {
	/* Single line. */
	rect.left = (pTTYInfo->nColumn * pTTYInfo->xChar) + pTTYInfo->xOffset;
	rect.right = rect.left + (pTTYInfo->xChar * nLength);
	rect.top = (pTTYInfo->nRow * pTTYInfo->yChar) + pTTYInfo->yOffset;
	rect.bottom = rect.top + pTTYInfo->yChar;
    }
    else {
	/* Wraps across multiple lines.  Calculate one rect to cover all 
	 * lines. */
	rect.left = 0;
	rect.right = pTTYInfo->ySize;
	rect.top = (pTTYInfo->nRow * pTTYInfo->yChar) + pTTYInfo->yOffset;
	rect.bottom = ((((offset + nLength) / pTTYInfo->actNColumn) + 1) * 
			pTTYInfo->yChar) + pTTYInfo->yOffset;
    }
    
    
    /* Apply text and attributes to screen in one smooth motion. */
    _fmemcpy (pTTYInfo->pScreen + offset, lpText, nLength);
    _fmemset (pTTYInfo->pAttrib + offset, pTTYInfo->curAttrib, nLength);
    
    
    /* New cursor position. */
    offset += nLength;
    if (offset == screenEnd) {
	pTTYInfo->nRow = pTTYInfo->actNRow - 1;
	pTTYInfo->nColumn = pTTYInfo->actNColumn - 1;
    }
    else {
	pTTYInfo->nRow = offset / pTTYInfo->actNColumn;
	pTTYInfo->nColumn = offset % pTTYInfo->actNColumn;
    }
    
 
    /* Invalidate rectangle */
    pTTYInfo->screenDirty = TRUE;
#ifdef OWNRECT
    MyInvalidateRect (pTTYInfo, hWnd, &rect);
#else
    InvalidateRect (hWnd, &rect, FALSE);
#endif
    return (TRUE);
}


/*---------------------------------------------------------------------------
 *  BOOL  WriteTTYChar (HWND hWnd, char ch)
 *
 *  Description:
 *	Write a single character to the cursor position and advance the
 *	cursor.  Does not handle carage control.
 *
 *  Parameters:
 *     HWND hWnd
 *        handle to TTY window
 *
 *     char ch
 *	  character being written.
 *
/*--------------------------------------------------------------------------*/

LOCAL BOOL  
WriteTTYChar (HWND hWnd, char ch)
{
    int				i;
    PTTYINFO			pTTYInfo;
    RECT			rect;
    BOOL			fNewLine;
    long			offset;
    long			colEnd;
    long			screenEnd;
    BOOL			wraper;

    pTTYInfo = (PTTYINFO) GetWindowLong (hWnd, GWL_PTTYINFO);
    if (pTTYInfo == NULL)
	return (FALSE);

#if 0
   /* xxxx for debugging only to provide a bread point for updates to status
    * xxxx line. */
    if (pTTYInfo->nRow == pTTYInfo->actNRow - 3)
	wraper = TRUE;
#endif

    offset = (pTTYInfo->nRow * pTTYInfo->actNColumn) +
	    pTTYInfo->nColumn;
    
    *(pTTYInfo->pScreen + offset) = ch;
    *(pTTYInfo->pAttrib + offset) = pTTYInfo->curAttrib;

    rect.left = (pTTYInfo->nColumn * pTTYInfo->xChar) + pTTYInfo->xOffset;
    rect.right = rect.left + pTTYInfo->xChar;
    rect.top = (pTTYInfo->nRow * pTTYInfo->yChar) + pTTYInfo->yOffset;
    rect.bottom = rect.top + pTTYInfo->yChar;
    pTTYInfo->screenDirty = TRUE;
#ifdef OWNRECT
    MyInvalidateRect (pTTYInfo, hWnd, &rect);
#else
    InvalidateRect (hWnd, &rect, FALSE);
#endif
    
    

    /* Line Wrap. */
    if (pTTYInfo->nColumn < pTTYInfo->actNColumn - 1)
	pTTYInfo->nColumn++ ;
    else if ((pTTYInfo->autoWrap == WRAP_ON || 
	      pTTYInfo->autoWrap == WRAP_NO_SCROLL) && 
		    pTTYInfo->nRow < pTTYInfo->actNRow - 1) {
       pTTYInfo->nRow++;
       pTTYInfo->nColumn = 0;
    }
    return (TRUE);
}

/*---------------------------------------------------------------------------
 *  VOID  GoModalDialogBoxParam( HINSTANCE hInstance,
 *                                   LPCSTR lpszTemplate, HWND hWnd,
 *                                   DLGPROC lpDlgProc, LPARAM lParam )
 *
 *  Description:
 *     It is a simple utility function that simply performs the
 *     MPI and invokes the dialog box with a DWORD paramter.
 *
 *  Parameters:
 *     similar to that of DialogBoxParam() with the exception
 *     that the lpDlgProc is not a procedure instance
 *
/*--------------------------------------------------------------------------*/

LOCAL VOID  
GoModalDialogBoxParam( HINSTANCE hInstance, LPCSTR lpszTemplate,
                                 HWND hWnd, DLGPROC lpDlgProc, LPARAM lParam )
{
   DLGPROC  lpProcInstance ;

   lpProcInstance = (DLGPROC) MakeProcInstance( (FARPROC) lpDlgProc,
                                                hInstance ) ;
   DialogBoxParam( hInstance, lpszTemplate, hWnd, lpProcInstance, lParam ) ;
   FreeProcInstance( (FARPROC) lpProcInstance ) ;
}





/*---------------------------------------------------------------------------
 *  BOOL FAR PASCAL __export AboutDlgProc( HWND hDlg, UINT uMsg,
 *                                WPARAM wParam, LPARAM lParam )
 *
 *  Description:
 *     Simulates the Windows System Dialog Box.
 *
 *  Parameters:
 *     Same as standard dialog procedures.
 *
/*--------------------------------------------------------------------------*/

BOOL FAR PASCAL __export 
AboutDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
   switch (uMsg) {
      case WM_INITDIALOG:
      {
         int          idModeString ;
         char         szTemp [81];
         DWORD        dwFreeMemory, dwWinFlags ;
         WORD         wFreeResources, wRevision, wVersion ;

#ifdef ABOUTDLG_USEBITMAP
         // if we are using the bitmap, hide the icon

         ShowWindow( GetDlgItem( hDlg, IDD_ABOUTICON ), SW_HIDE ) ;
#endif
         // sets up the version number for Windows

         wVersion = LOWORD (GetVersion());
         switch (HIBYTE (wVersion)) {
            case 10:
               wRevision = 1;
               break;

            default:
               wRevision = 0;
               break;
         }
         wVersion &= 0xFF;

	 
         /* sets up version number for PINE */

         GetDlgItemText (hDlg, IDD_VERSION, szTemp, sizeof (szTemp));
         wsprintf (TempBuf, szTemp, mswin_majorver(), mswin_minorver(),
		   mswin_compilation_date());
         SetDlgItemText (hDlg, IDD_VERSION, (LPSTR) TempBuf);

         // get by-line

         LoadString (GETHINST (hDlg), IDS_BYLINE, TempBuf,
                     sizeof (TempBuf));
         SetDlgItemText (hDlg, IDD_BYLINE, TempBuf);

      }
      return ( TRUE ) ;

#ifdef ABOUTDLG_USEBITMAP
      // used to paint the bitmap

      case WM_PAINT:
      {
         HBITMAP      hBitMap ;
         HDC          hDC, hMemDC ;
         PAINTSTRUCT  ps ;

         // load bitmap and display it

         hDC = BeginPaint( hDlg, &ps ) ;
         if (NULL != (hMemDC = CreateCompatibleDC( hDC )))
         {
            hBitMap = LoadBitmap( GETHINST( hDlg ),
                                  MAKEINTRESOURCE( PINEBITMAP ) ) ;
            hBitMap = SelectObject( hMemDC, hBitMap ) ;
            BitBlt( hDC, 10, 10, 64, 64, hMemDC, 0, 0, SRCCOPY ) ;
            DeleteObject( SelectObject( hMemDC, hBitMap ) ) ;
            DeleteDC( hMemDC ) ;
         }
         EndPaint( hDlg, &ps ) ;
      }
      break ;
#endif

      case WM_COMMAND:
         if ((WORD) wParam == IDD_OK)
         {
            EndDialog( hDlg, TRUE ) ;
            return ( TRUE ) ;
         }
         break;
   }
   return ( FALSE ) ;

} // end of AboutDlgProc()









/*---------------------------------------------------------------------------
 *  BOOL  SelectTTYFont( HWND hDlg )
 *
 *  Description:
 *     Selects the current font for the TTY screen.
 *     Uses the Common Dialog ChooseFont() API.
 *
 *  Parameters:
 *     HWND hDlg
 *        handle to settings dialog
 *
/*--------------------------------------------------------------------------*/

BOOL  
LOCAL SelectTTYFont (HWND hWnd)
{
    CHOOSEFONT		cfTTYFont;
    LOGFONT		newFont;
    PTTYINFO		pTTYInfo;

    pTTYInfo = (PTTYINFO) GetWindowLong (hWnd, GWL_PTTYINFO);
    if (pTTYInfo == NULL)
	return (FALSE);

    _fmemcpy (&newFont, &gpTTYInfo->lfTTYFont, sizeof (LOGFONT));

    cfTTYFont.lStructSize    = sizeof (CHOOSEFONT);
    cfTTYFont.hwndOwner      = hWnd ;
    cfTTYFont.hDC            = NULL ;
    cfTTYFont.rgbColors      = pTTYInfo->rgbFGColor;
    cfTTYFont.lpLogFont      = &newFont;
    cfTTYFont.Flags          = CF_SCREENFONTS | CF_FIXEDPITCHONLY |
	    CF_EFFECTS | CF_INITTOLOGFONTSTRUCT | CF_ANSIONLY | 
	    CF_FORCEFONTEXIST | CF_LIMITSIZE;
    cfTTYFont.nSizeMin	     = FONT_MIN_SIZE;
    cfTTYFont.nSizeMax	     = FONT_MAX_SIZE;
    cfTTYFont.lCustData      = NULL ;
    cfTTYFont.lpfnHook       = NULL ;
    cfTTYFont.lpTemplateName = NULL ;
    cfTTYFont.hInstance      = GETHINST (hWnd);



    if (ChooseFont (&cfTTYFont)) {
	pTTYInfo->rgbFGColor = cfTTYFont.rgbColors;
	ResetTTYFont (hWnd, pTTYInfo, &newFont);
    }

    return (TRUE);
}



/*
 * Set a specific color (forground, background, reverse, normal) to
 * the color specified by name. 
 */
LOCAL void
SetColorAttribute (COLORREF *cf, char *colorName)
{
    MSWINColor		*ct;
    int			i;
    
    for (ct = MSWINColorTable; ct->colorName != NULL; ++ct) {
	if (strcmpi (colorName, ct->colorName) == 0) goto FoundColor;
    }
    
    /* color name not in table.  Try converting RGB string. */
    ConvertRGBString (colorName, cf);
    return;
    
FoundColor:
    *cf = ct->colorRef;

    /* Redraw screen. */
    gpTTYInfo->screenDirty = TRUE;
    gpTTYInfo->eraseScreen = TRUE;
#ifdef OWNRECT
    MyInvalidateRect (gpTTYInfo, hWnd, NULL);
#else
    InvalidateRect (ghTTYWnd, NULL, FALSE);
#endif
}



/*
 * Convert a string to an integer.
 */
LOCAL BOOL
ScanInt (char *str, int min, int max, int *val)
{
    BOOL	numberString;
    char	*c;
    int		v;
    
    
    if (str == NULL) return (FALSE);
    if (*str == '\0' || strlen (str) > 9) return (FALSE);
    numberString = TRUE;
    for (c = str; *c != '\0'; ++c) {
	if (!myisdigit(*c))
	    return (FALSE);
    }
    v = atoi (str);
    if (v < min || v > max) 
	return (FALSE);
    *val = v;
    return (TRUE);
}



/*
 * Convert a RGB string to a color ref.  The string should look like:
 *    rrr,ggg,bbb
 * where rrr, ggg, and bbb are numbers between 0 and 255 that represent
 * red, gree, and blue values.  Must be comma seperated.
 * Returns:
 *	TRUE	- Successfully converted string.
 *	FALSE	- Bad format, 'cf' unchanged.
 */

LOCAL BOOL
ConvertRGBString (char *colorName, COLORREF *cf)
{
    int		cv;
    char	*c;
    char	*s;
    char	*p;
    char	cpy[16];
    int		rgb[3];
   
    /* Some basic tests. */
    if (colorName == NULL) return (FALSE);		/* Not Null? */
    if (strlen (colorName) > 11) return (FALSE);	/* Not too long? */
    for (s = colorName; *s != '\0'; ++s) {
	if (!myisdigit (*s) && *s != ',') return (FALSE); /* Valid characters?*/
    }
    
    /* Work with a copy of string. */
    strcpy (cpy, colorName);
    s = cpy;				/* Start at beginning. */
    for (cv = 0; cv < 3; ++cv) {	/* Get three digits. */
	if (cv < 2) {			/* Expect only two commas. */
	    c = strchr (s, ',');		/* Find next comma. */
	    if (c == NULL) return (FALSE);
	    *c = '\0';
	}
	if (*s == ',' || *s == '\0') return (FALSE);
	if (strlen (s) > 3) return (FALSE);
	rgb[cv] = atoi (s);
	if (rgb[cv] < 0 || rgb[cv] > 255) return (FALSE);
	s = c + 1;
    }

    *cf = RGB (rgb[0], rgb[1], rgb[2]);
    printf ("%d, %d, %d  ", rgb[0], rgb[1], rgb[2]);
    return (TRUE);
}


/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 *
 *                  Mouse Selection routeins.
 *
 *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

LOCAL BOOL	SelSelected = FALSE;
LOCAL BOOL	SelTracking = FALSE;
LOCAL int	SelAnchorRow;
LOCAL int	SelAnchorCol;
LOCAL int	SelPointerRow;
LOCAL int	SelPointerCol;
typedef struct {
    CHAR	*pRow;
    int		len;
} CopyRow;

LOCAL void
SelRSet (int oStart, int oEnd)
{
    CharAttrib	*pca;
    
    for (pca = gpTTYInfo->pAttrib + oStart; oStart < oEnd; ++pca, ++oStart)
	*pca |= CHAR_ATTR_SEL;
}


LOCAL void
SelRClear (int oStart, int oEnd)
{
    CharAttrib	*pca;
    
    for (pca = gpTTYInfo->pAttrib + oStart; oStart < oEnd; ++pca, ++oStart)
	*pca &= ~CHAR_ATTR_SEL;
}


LOCAL void
SelRInvalidate (int oStart, int oEnd)
{
    RECT	rect;
    int		sRow, sCol;
    int		eRow, eCol;
    
    sRow = oStart / gpTTYInfo->actNColumn;
    sCol = oStart % gpTTYInfo->actNColumn;
    eRow = oEnd   / gpTTYInfo->actNColumn;
    eCol = oEnd   % gpTTYInfo->actNColumn;
    
    rect.top = (sRow * gpTTYInfo->yChar) + gpTTYInfo->yOffset;
    rect.bottom = ((eRow+1) * gpTTYInfo->yChar) + gpTTYInfo->yOffset;
    if (sRow == eRow) {
	rect.left = (sCol * gpTTYInfo->xChar) + gpTTYInfo->xOffset;
	rect.right = ((eCol+1) * gpTTYInfo->xChar) + gpTTYInfo->xOffset;
    } else {
	rect.left = gpTTYInfo->xOffset;
	rect.right = (gpTTYInfo->actNColumn * gpTTYInfo->xChar) + 
			gpTTYInfo->xOffset;
    }
    InvalidateRect (ghTTYWnd, &rect, FALSE);
}



/*
 * Start a mouse selection.
 */
LOCAL void
SelStart (int nRow, int nColumn)
{
    SelClear ();
    SelTracking = TRUE;
    SelSelected = TRUE;
    SelPointerRow = SelAnchorRow = nRow;
    SelPointerCol = SelAnchorCol = nColumn;
    return;
}


/*
 * Finish a mouse selection.
 */
LOCAL void
SelFinish (int nRow, int nColumn)
{
    if (nRow == SelAnchorRow && nColumn == SelAnchorCol) {
	/* Mouse up in same place it went down - no selection. */
	SelClear ();
    }
    else {
	/* Update screen selection and set final position of mouse
	 * then turn of mouse tracking.  Selection remains in effect
	 * until SelClear is called. */
	SelTrackMouse (nRow, nColumn);
	SelTracking = FALSE;
    }
}

LOCAL void
SelClear (void)
{
    int		a, p;
    int		s, e;
    CharAttrib	*pca;

    
    if (!SelSelected) 
	return;


    /* Convert the anchor and point coordinates to offsets then
     * order the offsets. */
    a = (SelAnchorRow * gpTTYInfo->actNColumn) + SelAnchorCol;
    p = (SelPointerRow * gpTTYInfo->actNColumn) + SelPointerCol;
    if (a < p) {
	s = a;
	e = p;
    } else {
	s = p;
	e = a;
    }

    /* Clear selected attribute of those cells in range. */
    SelRClear (s, e);
    SelRInvalidate (s, e);
    SelSelected = FALSE;
    SelTracking = FALSE;
}


/*
 * Update the position of the mouse point.
 */
LOCAL void
SelTrackXYMouse (int xPos, int yPos)
{
    int		nRow;
    int		nColumn;
    
    nColumn = (xPos - gpTTYInfo->xOffset) / gpTTYInfo->xChar;
    nRow = (yPos - gpTTYInfo->yOffset) / gpTTYInfo->yChar;

    SelTrackMouse (nRow, nColumn);
}


/*
 * Update the position of the mouse point.
 */
LOCAL void
SelTrackMouse (int nRow, int nColumn)
{
    int		a, p, n;
    int		s, e;
    
    if (!SelTracking)
	return;

    /* Constrain the cel position to be on the screen.  But allow
     * for the Column to be one past the right edge of the screen so
     * the user can select the right most cel of a row. */
    nColumn = max (0, nColumn);
    nColumn = min (gpTTYInfo->actNColumn, nColumn);
    nRow = max (0, nRow);
    nRow = min (gpTTYInfo->actNRow-1, nRow);


    /* Convert the anchor, previous mouse position, and new mouse
     * position to offsets. */
    a = (SelAnchorRow * gpTTYInfo->actNColumn) + SelAnchorCol;
    p = (SelPointerRow * gpTTYInfo->actNColumn) + SelPointerCol;
    n = (nRow * gpTTYInfo->actNColumn) + nColumn;
    
    /* If previous position same as current position, do nothing. */
    if (p == n)
	return;

    /* there are six possible orderings of the points, each with
     * a different action:
     *	order		clear		set		redraw
     *	n p a				n - p		n - p
     *	p n a		p - n				p - n
     *	p a n		p - a		a - n		p - n
     *	a p n				p - n		p - n
     *  a n p		n - p				n - p
     *  n a p		a - p		n - a		n - p
     */
    if (p < a) {
	if (n < a) {
	    if (n < p) {
		SelRSet (n, p);
		SelRInvalidate (n, p);
	    } else {
		SelRClear (p, n);
		SelRInvalidate (p, n);
	    }
	} else {
	    SelRClear (p, a);
	    SelRSet (a, n);
	    SelRInvalidate (p, n);
        }
    } else {
	if (n > a) {
	    if (n > p) {
		SelRSet (p, n);
		SelRInvalidate (p, n);
	    } else {
		SelRClear (n, p);
		SelRInvalidate (n, p);
	    }
	} else {
	    SelRClear (a, p);
	    SelRSet (n, a);
	    SelRInvalidate (n, p);
        }
    }

    /* Set new pointer. */
    SelPointerRow = nRow;
    SelPointerCol = nColumn;
}



LOCAL BOOL
SelAvailable (void)
{
    return (SelSelected);
}

/*
 * Copy screen data to clipboard.  Actually appends data from screen to 
 * existing handle so as we can implement a "Copy Append" to append to
 * existing clipboard data.  
 *
 * The screen does not have real line terminators.  We decide where the 
 * actual screen data ends by scanning the line (row) from end backwards
 * to find the first non-space.
 * 
 * I don't know how many bytes of data I'll be appending to the clipboard.
 * So I implemented in two passes.  The first finds all the row starts
 * and length while the second copies the data.
 */

LOCAL void
SelDoCopy (HANDLE hCB, DWORD lenCB)
{
    HANDLE		newCB;		/* Used in reallocation. */
    CHAR		*pCB;		/* Points to CB data. */	
    CHAR		*p2;		/* Temp pointer to screen data. */
    int			sRow, eRow;	/* Start and End Rows. */
    int			sCol, eCol;	/* Start and End columns. */
    int			row, c1, c2;	/* temp row and column indexes. */
    int			totalLen;	/* total len of new data. */
    CopyRow		*rowTable, *rp;	/* pointers to table of rows. */
    BOOL		noLastCRLF;
    

    if (OpenClipboard (ghTTYWnd)) {		/* ...and we get the CB. */
      if (EmptyClipboard ()) {		/* ...and clear previous CB.*/


	/* Find the start and end row and column. */
	if ( (SelAnchorRow * gpTTYInfo->actNColumn) + SelAnchorCol < 
	     (SelPointerRow * gpTTYInfo->actNColumn) + SelPointerCol) {
	    sRow = SelAnchorRow;
	    sCol = SelAnchorCol;
	    eRow = SelPointerRow;
	    eCol = SelPointerCol;
	}
	else {
	    sRow = SelPointerRow;
	    sCol = SelPointerCol;
	    eRow = SelAnchorRow;
	    eCol = SelAnchorCol;
	}

	/* Allocate a table in which we store info on rows. */
	rowTable = (CopyRow *) MemAlloc (sizeof (CopyRow) * (eRow-sRow+1));
	if (rowTable == NULL)
	    goto Fail1;

	/* Find the start and length of each row. */
	totalLen = 0;
	for (row = sRow, rp = rowTable; row <= eRow; ++row, ++rp) {
	    /* Find beginning and end columns, which depends on if
	     * this is the first or last row in the selection. */
	    c1 = (row == sRow ? sCol : 0);
	    c2 = (row == eRow ? eCol : gpTTYInfo->actNColumn);

	    /* Calculate pointer to beginning of this line. */
	    rp->pRow = gpTTYInfo->pScreen + 
		    ((row * gpTTYInfo->actNColumn) + c1);

	    /* Back down from end column to find first non space. 
	     * noLastCRLF indicates if it looks like the selection
	     * should include a CRLF on the end of the line.  It
	     * gets set for each line, but only the setting for the
	     * last line in the selection is remembered (which is all
	     * we're interested in). */
	    p2 = gpTTYInfo->pScreen + 
		    ((row * gpTTYInfo->actNColumn) + c2);
	    noLastCRLF = TRUE;
	    while (c2 > c1) {
		if (*(p2-1) != ' ')
		    break;
		noLastCRLF = FALSE;
		--c2;
		--p2;
	    }

	    /* Calculate size of line, then increment totalLen plus 2 for
	     * the CRLF which will terminate each line. */
	    rp->len = c2 - c1;
	    totalLen += rp->len + 2;
	}

	/* Reallocate the memory block.  Add one byte for null terminator. */
	newCB = GlobalReAlloc (hCB, lenCB + totalLen + 1, 0);
	if (newCB == NULL)
	    goto Fail2;
	hCB = newCB;

	pCB = GlobalLock (hCB);
	if (pCB == NULL)
	    goto Fail2;

	/* Append each of the rows, deliminated by a CRLF. */
	pCB += lenCB;
	for (row = sRow, rp = rowTable; row <= eRow; ++row, ++rp) {
	    if (rp->len > 0) {
		_fmemcpy (pCB, rp->pRow, rp->len);
		pCB += rp->len;
	    }
	    if (row < eRow || !noLastCRLF) {
		*pCB++ = ASCII_CR;
		*pCB++ = ASCII_LF;
	    }
	}
	*pCB = '\0';			/* Null terminator. */
	MemFree (rowTable);
	GlobalUnlock (hCB);

	/* Attempt to pass the data to the clipboard, then release clipboard
	 * and exit function. */
	if (SetClipboardData (CF_TEXT, hCB) == NULL)
		      /* Failed!  Free the data. */
		      GlobalFree (hCB);
	CloseClipboard ();
      }
    }
    return;
    
    
	/* Error exit. */
Fail2:	MemFree (rowTable);
Fail1:	GlobalFree (hCB);
	CloseClipboard ();
	return;
}




    

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 *
 *                  Upper Layer Screen routines.
 *
 *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

/*
 * Flush the write accumulator buffer.
 */
LOCAL void
FlushWriteAccum (void)
{
    if (gpTTYInfo->writeAccumCount > 0) {
	WriteTTYText (ghTTYWnd, gpTTYInfo->writeAccum, 
					gpTTYInfo->writeAccumCount);
	gpTTYInfo->writeAccumCount = 0;
    }
}



/*
 *	Called to get mouse event.
 */
int
WinGetMEvent (MEvent * pMouse)
{
	return (MQGet (pMouse));
}


/*
 *	Called in idle loops.   Dispatch messages but do not yeild control
 */
void
WinIdle (void)
{
    MSG		msg;
    DWORD	start;
    
    start = GetTickCount ();
#ifdef CDEBUG
    if (Debug > 16) 
	fprintf (DebugFile, "WinIdle:: Entered\n");
#endif
    if (PeekMessage (&msg, NULL, 0, 0, PM_NOYIELD | PM_REMOVE)) {
	if (ghAccel == NULL || 
		!TranslateAccelerator (ghTTYWnd, ghAccel, &msg)) {
	    TranslateMessage (&msg);
	    DispatchMessage (&msg);
	}
    }
#ifdef CDEBUG
    if (Debug > 16) 
	fprintf (DebugFile, "WinIdle::  Delay %ld msec\n",
		GetTickCount () - start);
#endif
}


/*
 * Set up debugging stuff.
 */
mswin_setdebug (int debug, FILE *debugfile)
{
    /* Accept new file only if we don't already have a file. */
    if (DebugFile == 0) {
	Debug = debug;
	DebugFile = debugfile;
	if (debug >= MEM_DEBUG_LEVEL) 
	    MemDebug (TRUE, DebugFile);
    }
}



/*
 * Set a callback for function 'ch'
 */
int
mswin_setresizecallback (int (*cb)())
{
    int		i;
    int		e;
    
    
    /*
     * Look through whole array for this call back function.  Don't
     * insert duplicate.  Also look for empty slot.
     */
    e = -1;
    for (i = 0; i < RESIZE_CALLBACK_ARRAY_SIZE; ++i) {
	if (gpTTYInfo->resizer[i] == cb) 
	    return (0);
        if (e == -1 && gpTTYInfo->resizer[i] == NULL) 
	    e = i;
    }
    
    /*
     * Insert in empty slot or return an error.
     */
    if (e != -1) {
	gpTTYInfo->resizer[e] = cb;
	return (0);
    }
    return (-1);
}

/*
 * Clear all instances of the callback function 'cb'
 */
int
mswin_clearresizecallback (int (*cb)())
{
    int		i;
    int		status;
    
    status = -1;
    for (i = 0; i < RESIZE_CALLBACK_ARRAY_SIZE; ++i) {
	if (gpTTYInfo->resizer[i] == cb) {
	    gpTTYInfo->resizer[i] = NULL;
	    status = 0;
	}
    }
    return (status);
}


void
mswin_beginupdate (void)
{
    gpTTYInfo->fMassiveUpdate = TRUE;
}



void
mswin_endupdate (void)
{
    gpTTYInfo->fMassiveUpdate = FALSE;
    MoveTTYCursor (ghTTYWnd);
}



int
mswin_setwindow (char *fontName, char *fontSize, char *fontStyle, 
	char *windowPosition)
{
    LOGFONT		newFont;
    int			newHeight;
    HDC			hDC;
    int			ppi;
    RECT		wndRect, cliRect;
    char		*c;
    char		*n;
    BOOL		numberString;
    int			wColumns, wRows;
    int			wXPos, wYPos;
    int			wXBorder, wYBorder;
    int			wXSize, wYSize;
    char		wp[WIN_POS_STR_MAX_LEN + 1];
    
    
#ifdef SDEBUG
    if (Debug >= 5) 
	fprintf (DebugFile, "mswin_setwindow:::  entered, minimized:  %d\n",
		gpTTYInfo->fMinimized);
#endif

    /* Require a font name to set font info. */
    if (fontName != NULL && *fontName != '\0' && 
	    strlen (fontName) <= LF_FACESIZE - 1) {
	    
	hDC = GetDC (ghTTYWnd);
	ppi = GetDeviceCaps (hDC, LOGPIXELSY);
	ReleaseDC (ghTTYWnd, hDC);

	/* Default height, then examin the requested fontSize. */
	newFont.lfHeight =  -MulDiv (12, ppi, 72);
	if (ScanInt (fontSize, FONT_MIN_SIZE, FONT_MAX_SIZE, &newHeight)){
	    newFont.lfHeight = -MulDiv (newHeight, ppi, 72);
        }
	
	/* Default font style, then read requested style. */
	newFont.lfWeight =         0;
	newFont.lfItalic =         0;
	if (fontStyle != NULL) {
	    _strlwr (fontStyle);
	    if (strstr (fontStyle, "bold"))
		newFont.lfWeight = FW_BOLD;
	    if (strstr (fontStyle, "italic"))
		newFont.lfItalic = 1;
	}
	
	/* Everything else takes the default. */
	newFont.lfWidth =          0;
	newFont.lfEscapement =     0;
	newFont.lfOrientation =    0;
	newFont.lfUnderline =      0;
	newFont.lfStrikeOut =      0;
	newFont.lfCharSet =        ANSI_CHARSET;
	newFont.lfOutPrecision =   OUT_DEFAULT_PRECIS;
	newFont.lfClipPrecision =  CLIP_DEFAULT_PRECIS;
	newFont.lfQuality =        DEFAULT_QUALITY;
	newFont.lfPitchAndFamily = FIXED_PITCH;
	_fstrcpy (newFont.lfFaceName, fontName);
	ResetTTYFont (ghTTYWnd, gpTTYInfo, &newFont);
    }
    
    /*
     * Set window position.  String format is:  CxR+X+Y
     * Where C is the number of columns, R is the number of rows,
     * and X and Y specify the top left corner of the window.
     */
    if (windowPosition != NULL && *windowPosition != '\0') {
	if (strlen(windowPosition) > WIN_POS_STR_MAX_LEN) return (0);
	_fstrcpy (wp, windowPosition);
	
	/* Look for Columns, deliminated by 'x'. */
	c = _fstrchr (wp, 'x');
	if (c == NULL) return (0);
	*c = '\0';
	if (!ScanInt (wp, 0, 9999, &wColumns))	return (0);

	/* Look for Rows, deliminated by '+'. */
	n = c + 1;
	c = _fstrchr (n, '+');
	if (c == NULL) return (0);
	*c = '\0';
	if (!ScanInt (n, 0, 9999, &wRows))	return (0);
	
	/* Look for X position, deliminated by '+'. */
	n = c + 1;
	c = _fstrchr (n, '+');
	if (c == NULL) return (0);
	*c = '\0';
	if (!ScanInt (n, 0, 9999, &wXPos))	return (0);
	
	/* And get Y position, deliminated by end of string. */
	n = c + 1;
	if (!ScanInt (n, 0, 9999, &wYPos))	return (0);
	
	
	/* Get the current window rect and client area. */
	GetWindowRect (ghTTYWnd, &wndRect);
	GetClientRect (ghTTYWnd, &cliRect);
	
	
	/* Calculate boarder sizes. */
	wXBorder = wndRect.right - wndRect.left - cliRect.right;
	wYBorder = wndRect.bottom - wndRect.top - cliRect.bottom;
	
	
	/* Calculate new window pos and size. */
	wXSize = wXBorder + (wColumns * gpTTYInfo->xChar) + 
						(2 * gpTTYInfo->xOffset);
	wYSize = wYBorder + (wRows * gpTTYInfo->yChar) + 
						(2 * gpTTYInfo->yOffset);
	
	
	/* If it fits on screen, move window. */
	GetWindowRect (GetDesktopWindow(), &wndRect);
	if (wXPos + wXSize > wndRect.right) return (0);
	if (wYPos + wYSize > wndRect.bottom) return (0);
	if (!gpTTYInfo->fMinimized) 
	    MoveWindow (ghTTYWnd, wXPos, wYPos, wXSize, wYSize, TRUE);
	else {
	    gpTTYInfo->fDesiredSize = TRUE;
	    gpTTYInfo->xDesPos = wXPos;
	    gpTTYInfo->yDesPos = wYPos;
	    gpTTYInfo->xDesSize = wXSize;
	    gpTTYInfo->yDesSize = wYSize;
	}
    }
    return (0);
}



/*
 * Retreive the current font name, font size, and window position
 * These get stored in the pinerc file and will be passed to 
 * mswin_setwindow() when pine starts up.  See pinerc for comments
 * on the format.
 */
int
mswin_getwindow (char *fontName, char *fontSize, char *fontStyle, 
	char *windowPosition)
{
    HDC			hDC;
    int			ppi;
    RECT		wndRect;
    
    if (fontName != NULL) {
	_fstrcpy (fontName, gpTTYInfo->lfTTYFont.lfFaceName);
    }

    if (fontSize != NULL) {
	hDC = GetDC (ghTTYWnd);
	ppi = GetDeviceCaps (hDC, LOGPIXELSY);
	ReleaseDC (ghTTYWnd, hDC);
	sprintf (fontSize, "%d", MulDiv (-gpTTYInfo->lfTTYFont.lfHeight,
					72, ppi));
    }
    if (fontStyle != NULL) {
	char		*sep[] = {"", ", "};
	int		iSep = 0;
	
	*fontStyle = '\0';
	if (gpTTYInfo->lfTTYFont.lfWeight >= FW_BOLD) {
	    strcat (fontStyle, "bold");
	    iSep = 1;
        }
	if (gpTTYInfo->lfTTYFont.lfItalic) {
	    strcat (fontStyle, sep[iSep]);
	    strcat (fontStyle, "italic");
        }
    }


    if (windowPosition != NULL) {
	GetWindowRect (ghTTYWnd, &wndRect);
	sprintf (windowPosition, "%dx%d+%d+%d", gpTTYInfo->actNColumn, 
		gpTTYInfo->actNRow, wndRect.left, wndRect.top);
    }
    return (0);
}



/*
 * Set the window help text.  Add or delete the Help menu item as needed.
 */
int
mswin_sethelptext (char *pHelpText)
{
    HMENU		hMenu;
    BOOL		brc;

    
    gpHelpText = pHelpText;

    hMenu = GetMenu (ghTTYWnd);
    if (gpHelpText == NULL) {
	if (gfHelpMenu) {
	    brc = DeleteMenu (hMenu, IDM_HELP, MF_BYCOMMAND);
	    DrawMenuBar (ghTTYWnd);
	}
	gfHelpMenu = FALSE;
    }
    else {
	if (!gfHelpMenu) {
	    brc = AppendMenu (hMenu, MF_STRING | MF_ENABLED, IDM_HELP, 
		    "&Help");
	    DrawMenuBar (ghTTYWnd);
	}
	gfHelpMenu = TRUE;
    }
    
}


/*
 * Set the text displayed when someone tries to close the application 
 * the wrong way.
 */
int
mswin_setclosetext (char *pCloseText)
{
    gpCloseText = pCloseText;
}


/*
 *	Called to see if there is a character available.
 */
int
mswin_charavail (void)
{
    MSG		msg;
    BOOL	ca, pa, ma;
    DWORD	start;
    
    /*
     * If there are no windows messages waiting for this app, GetMessage
     * can take a long time.  So before calling GetMessage check if
     * there is anything I should be doing.  If there is, then only
     * call PeekMessage.
     * BUT!  Don't let too much time elapse between calls to GetMessage
     * or we'll shut out other windows.
     */
    ca = CQAvailable ();
    pa = EditPasteAvailable ();
#ifdef CDEBUG
    start = GetTickCount ();
    if (Debug > 16) 
	fprintf (DebugFile, "mswin_charavail::  Entered, ca %d, pa %d\n",ca,pa);
#endif
    if ((ca || pa) && GetTickCount () < gGMLastCall + GM_MAX_TIME) 
        ma = PeekMessage (&msg, NULL, 0, 0, PM_NOYIELD | PM_REMOVE);
    else {
        ma = GetMessage (&msg, NULL, 0, 0);
	gGMLastCall = GetTickCount ();
    }
    if (ma) {
	if (ghAccel == NULL || 
		!TranslateAccelerator (ghTTYWnd, ghAccel, &msg)) {
	    TranslateMessage (&msg);
	    DispatchMessage (&msg);
	}
    }
#ifdef CDEBUG
    if (Debug > 16) 
	fprintf (DebugFile, "mswin_charavail::  Delay %ld msec\n",
		GetTickCount () - start);
#endif

    return (pa || ca || CQAvailable ());
}



	

/*
 *	Call to get next character.  Dispatch one message.
 */
int
mswin_getc (void)
{
    BOOL	ca, pa, ma;
    MSG		msg;
    DWORD	start;
    
    mswin_flush();
    
    

    /*
     * If there are no windows messages waiting for this app, GetMessage
     * can take a long time.  So before calling GetMessage check if
     * there is anything I should be doing.  If there is, then only
     * call PeekMessage.
     */
    ca = CQAvailable ();
    pa = EditPasteAvailable ();
#ifdef CDEBUG
    if (Debug > 16) {
	start = GetTickCount ();
	fprintf (DebugFile, "mswin_getc::  Entered, ca %d pa %d\n", ca, pa);
    }
#endif
    if ((ca || pa) && GetTickCount () < gGMLastCall + GM_MAX_TIME) 
        ma = PeekMessage (&msg, NULL, 0, 0, PM_NOYIELD | PM_REMOVE);
    else {
        ma = GetMessage (&msg, NULL, 0, 0);
	gGMLastCall = GetTickCount ();
    }
    if (ma) {
	if (ghAccel == NULL || 
		!TranslateAccelerator (ghTTYWnd, ghAccel, &msg)) {
	    TranslateMessage (&msg);
	    DispatchMessage (&msg);
	}
    }
#ifdef CDEBUG
    if (Debug > 16) 
	fprintf (DebugFile, "mswin_getc::  Delay %ld msec\n",
		GetTickCount () - start);
#endif


    if (pa) {
	SelClear ();
	return (EditPasteGet ());
    }
    if (ca || CQAvailable ()) {
	SelClear();
	return (CQGet ());
    }
    return (MSWIN_KEY_NODATA);
}




/*
 *	Like mswin_getc, but don't yeild control.
 */
int
mswin_getc_fast (void)
{
    MSG		msg;
    
    if (EditPasteAvailable ()) {
	SelClear ();
	return (EditPasteGet ());
    }
    if (CQAvailable ()) {
	SelClear ();
	return (CQGet ());
    }
    return (MSWIN_KEY_NODATA);
}







/*
 * ibmopen - open termnal
 */
int
mswin_open (void)
{
    /* This is a no-op.  All of this should have been set up already. */
    revexist = TRUE;
    return (0);
}


/*
 * ibmclose - Close terminal
 */
int
mswin_close (void)
{
    /* Another no-op. */
    return (0);
}




/*
 * ibmmove - Move cursor to...
 */
int
mswin_move (int row, int column)

{
    FlushWriteAccum ();
    if (row < 0 || row >= gpTTYInfo->actNRow)
	return (-1);
    if (column < 0 || column >= gpTTYInfo->actNColumn)
	return (-1);
    gpTTYInfo->nRow = row;
    gpTTYInfo->nColumn = column;
    MoveTTYCursor (ghTTYWnd);
    return (0);
}



int
mswin_getpos (int *row, int *column)
{
    FlushWriteAccum ();
    if (row == NULL || column == NULL)
	return (-1);
    *row = gpTTYInfo->nRow;
    *column = gpTTYInfo->nColumn;
    return (0);
}



int
mswin_getscreensize (int *row, int *column)
{
    if (row == NULL || column == NULL)
	return (-1);
    *row = gpTTYInfo->actNRow;
    *column = gpTTYInfo->actNColumn;
#ifdef SDEBUG
    if (Debug >= 5) 
	fprintf (DebugFile, "mswin_getscreensize::: reported size %d, %d\n",
		*row, *column);
#endif
    return (0);
}




int
mswin_showcursor (int show)
{
    int		wasShow;
    
    
    wasShow = (gpTTYInfo->wCursorState & CS_SHOW) != 0;
	
    if (show) {
	
	/* if the cursor was not already show, show it now. */
	if (!wasShow) {
	    gpTTYInfo->wCursorState |= CS_SHOW;

	    if (gpTTYInfo->wCursorState == CS_VISIBLE) {
		    CreateCaret (ghTTYWnd, NULL, gpTTYInfo->xChar, 
			    gpTTYInfo->yChar);
		    ShowCaret (ghTTYWnd);
	    }
	    MoveTTYCursor (ghTTYWnd);
        }
    }
    else {
	
	/* If the cursor is shown, hide it. */
	if (wasShow) {
	    if (gpTTYInfo->wCursorState == CS_VISIBLE) {
		HideCaret (ghTTYWnd);
		DestroyCaret();
	    }

	    gpTTYInfo->wCursorState &= ~CS_SHOW;
	}
    }

    return (wasShow);
}



int
mswin_puts (char *str)
{
    int			strLen;

    FlushWriteAccum ();
    if (str == NULL)
	return (-1);
    strLen = strlen (str);
    if (strLen > 0)
	WriteTTYText (ghTTYWnd, str, strLen);
    return (0);
}



int
mswin_putblock (char *str, int strLen)
{
    FlushWriteAccum ();
    if (str == NULL)
	return (-1);
    if (strLen > 0)
	WriteTTYText (ghTTYWnd, str, strLen);
    return (0);
}



/*
 * mswin_putc - put a character at the current position in the
 *	     current colors
 */

int
mswin_putc (int c)
{
    BYTE		cc;

    cc = (char)(c & 0xff);

    if (cc >= ' ') {
	/* Not carrage control. */
	gpTTYInfo->writeAccum[gpTTYInfo->writeAccumCount++] = cc;
	if (gpTTYInfo->writeAccumCount == WRITE_ACCUM_SIZE)
		FlushWriteAccum ();
    }
    else {
	/* Carrage control.  Need to flush write accumulator and
	 * write this char. */
	FlushWriteAccum ();
	WriteTTYBlock (ghTTYWnd, &cc, 1);
    }
    return (0);
}



/* 
 * ibmoutc - output a single character with the right attributes, but
 *           don't advance the cursor
 */
int
mswin_outc (char c)
{
    RECT	rect;
    long	offset;
    
    FlushWriteAccum ();
    
    switch (c) {
    case ASCII_BEL:
	MessageBeep (0);
	break;
	
    case ASCII_BS:
    case ASCII_CR:
    case ASCII_LF:
	/* Do nothing for these screen motion characters. */
	break;
	
	
    default:
	/* Paint character to screen. */
	offset = (gpTTYInfo->nRow * gpTTYInfo->actNColumn) + gpTTYInfo->nColumn;
	*(gpTTYInfo->pScreen + offset) = c;
	*(gpTTYInfo->pAttrib + offset) = gpTTYInfo->curAttrib;
	
	/* Invalidate rectange covering singel character. */
	rect.left = (gpTTYInfo->nColumn * gpTTYInfo->xChar) +
		gpTTYInfo->xOffset;
	rect.right = rect.left + gpTTYInfo->xChar;
	rect.top = (gpTTYInfo->nRow * gpTTYInfo->yChar) + 
		gpTTYInfo->yOffset;
	rect.bottom = rect.top + gpTTYInfo->yChar;
	gpTTYInfo->screenDirty = TRUE;
#ifdef OWNRECT
	MyInvalidateRect (gpTTYInfo, ghTTYWnd, &rect);
#else
	InvalidateRect (ghTTYWnd, &rect, FALSE);
#endif
	break;
    }
    return (0);
}



/*
 * mswin_delchar - delete character at cursor.  Shift end of line left.
 *	Cursor stays in position.
 */
int
mswin_delchar (void)
{
    CHAR	*cStart;
    CharAttrib	*aStart;
    long	length;
    RECT	rect;
    
    FlushWriteAccum ();
    
    /* From position right of cursor to end of line. */
    length = gpTTYInfo->actNColumn - (gpTTYInfo->nColumn + 1);

    /* Shift end of line. */
    if (length > 0) {
        cStart = gpTTYInfo->pScreen + (gpTTYInfo->nRow *gpTTYInfo->actNColumn)
				+ gpTTYInfo->nColumn;
	_fmemmove (cStart, cStart+1, (size_t) length);
        aStart = gpTTYInfo->pAttrib + (gpTTYInfo->nRow *gpTTYInfo->actNColumn)
			+ gpTTYInfo->nColumn;
        _fmemmove (aStart, aStart + 1, (size_t) length);
    }
    
    /* Clear last char in line. */
    *(cStart + length) = ' ';
    *(aStart + length) = CHAR_ATTR_NORM;

    /* Invalidate from cursor to end of line. */
    rect.left = (gpTTYInfo->nColumn * gpTTYInfo->xChar) + gpTTYInfo->xOffset;
    rect.right = gpTTYInfo->xSize;
    rect.top = (gpTTYInfo->nRow * gpTTYInfo->yChar) + gpTTYInfo->yOffset;
    rect.bottom = rect.top + gpTTYInfo->yChar;
    gpTTYInfo->screenDirty = TRUE;
#ifdef OWNRECT
    MyInvalidateRect (gpTTYInfo, ghTTYWnd, &rect);
#else
    InvalidateRect (ghTTYWnd, &rect, FALSE);
#endif

    return (0);
}



/*
 * mswin_inschar - insert character in current position.  Shift line
 *	to right and drop last char on line. 
 *	Cursor advances one 
 */
int
mswin_inschar (int c)
{
    CHAR	*cStart;
    CharAttrib	*aStart;
    long	length;
    RECT	rect;
    
    FlushWriteAccum ();
    
    /* From cursor to end of line - 1
    length = (gpTTYInfo->actNColumn - gpTTYInfo->nColumn) - 1;

    /* Shift end of line. */
    if (length > 0) {
        cStart = gpTTYInfo->pScreen + (gpTTYInfo->nRow *gpTTYInfo->actNColumn)
				+ gpTTYInfo->nColumn;
	_fmemmove (cStart+1, cStart, (size_t) length);
        aStart = gpTTYInfo->pAttrib + (gpTTYInfo->nRow *gpTTYInfo->actNColumn)
			+ gpTTYInfo->nColumn;
        _fmemmove (aStart+1, aStart, (size_t) length);
    }
    
    /* Insert new char. */
    *(cStart + length) = (char)(c & 0x00ff);
    *(aStart + length) = gpTTYInfo->curAttrib;

    /* Invalidate from cursor to end of line. */
    rect.left = (gpTTYInfo->nColumn * gpTTYInfo->xChar) + gpTTYInfo->xOffset;
    rect.right = gpTTYInfo->xSize;
    rect.top = (gpTTYInfo->nRow * gpTTYInfo->yChar) + gpTTYInfo->yOffset;
    rect.bottom = rect.top + gpTTYInfo->yChar;
    gpTTYInfo->screenDirty = TRUE;
#ifdef OWNRECT
    MyInvalidateRect (gpTTYInfo, ghTTYWnd, &rect);
#else
    InvalidateRect (ghTTYWnd, &rect, FALSE);
#endif
    
    /* move cursor forward one space. */
    if (gpTTYInfo->nColumn < gpTTYInfo->actNColumn - 1) {
	++gpTTYInfo->nColumn;
	MoveTTYCursor (ghTTYWnd);
    }

    return (0);
}



/*
 * ibmrev - change reverse video state
 */
int
mswin_rev (int state)
{
    int		curState;
    
    curState = (gpTTYInfo->curAttrib & CHAR_ATTR_REV);
    if ((state && !curState) || (!state && curState)) {
	FlushWriteAccum ();
	if (state) 
	    gpTTYInfo->curAttrib |= CHAR_ATTR_REV;
	else
	    gpTTYInfo->curAttrib &= ~CHAR_ATTR_REV;
    }
    return (0);
}
	


/*
 * Get current reverse video state. 
 */
int
mswin_getrevstate (void)
{
    return ((gpTTYInfo->curAttrib & CHAR_ATTR_REV) != 0);
}



/*
 * ibmeeol - erase to the end of the line
 */
int
mswin_eeol (void)
{
    CHAR	*cStart;
    CharAttrib	*aStart;
    long	length;
    RECT	rect;
    
    FlushWriteAccum ();
    
    /* From current position to end of line. */
    length = gpTTYInfo->actNColumn - gpTTYInfo->nColumn;		

    cStart = gpTTYInfo->pScreen + (gpTTYInfo->nRow * gpTTYInfo->actNColumn)
			+ gpTTYInfo->nColumn;
    _fmemset (cStart, ' ', (size_t) length);
    
    aStart = gpTTYInfo->pAttrib + (gpTTYInfo->nRow * gpTTYInfo->actNColumn)
			+ gpTTYInfo->nColumn;
    _fmemset (aStart, CHAR_ATTR_NORM, (size_t) length);

    rect.left = (gpTTYInfo->nColumn * gpTTYInfo->xChar) + 
	    gpTTYInfo->xOffset;
    rect.right = gpTTYInfo->xSize;
    rect.top = (gpTTYInfo->nRow * gpTTYInfo->yChar) + 
	    gpTTYInfo->yOffset;
    rect.bottom = rect.top + gpTTYInfo->yChar;
    gpTTYInfo->screenDirty = TRUE;
#ifdef OWNRECT
    MyInvalidateRect (gpTTYInfo, ghTTYWnd, &rect);
#else
    InvalidateRect (ghTTYWnd, &rect, FALSE);
#endif

    return (0);
}



/*
 * ibmeeop - clear from cursor to end of page
 */
int
mswin_eeop (void)
{
    CHAR	*cStart;
    CharAttrib	*aStart;
    long	length;
    RECT	rect;
    
    FlushWriteAccum ();
    /* From current position to end of screen. */

    cStart = gpTTYInfo->pScreen + (gpTTYInfo->nRow * gpTTYInfo->actNColumn)
			+ gpTTYInfo->nColumn;
    length = (gpTTYInfo->pScreen + (gpTTYInfo->actNColumn * gpTTYInfo->actNRow))
		    - cStart;
    _fmemset (cStart, ' ', (size_t) length);
    
    aStart = gpTTYInfo->pAttrib + (gpTTYInfo->nRow * gpTTYInfo->actNColumn)
			+ gpTTYInfo->nColumn;
    _fmemset (aStart, CHAR_ATTR_NORM, (size_t) length);

    
    /* Invalidate a rectangle that includes all of the current line down
     * to the bottom of the window. */
    rect.left = 0;
    rect.right = gpTTYInfo->xSize;
    rect.top = (gpTTYInfo->nRow * gpTTYInfo->yChar) + 
	    gpTTYInfo->yOffset;
    rect.bottom = gpTTYInfo->ySize;
    gpTTYInfo->screenDirty = TRUE;
#ifdef OWNRECT
    MyInvalidateRect (gpTTYInfo, ghTTYWnd, &rect);
#else
    InvalidateRect (ghTTYWnd, &rect, FALSE);
#endif

    return (0);
}



/*
 * ibmbeep - system beep...
 */
int
mswin_beep (void)
{
    MessageBeep (MB_OK);
    return (0);
}


/*
 * pause - wait in function for specified number of seconds.
 */
int
mswin_pause (int seconds)
{
    DWORD	stoptime;
    
    stoptime = GetTickCount () + (DWORD) seconds * 1000;
    while (stoptime > GetTickCount ()) 
	WinIdle ();
}
	


/*
 * ibmflush - Flush output to screen.
 *
 *	NOTE:  This function does not really wait for the changes to
 *	       be flushed to the screen because:
 *		1) If the part of the window in which the change was
 *		   made is off the screen we may never, ever receive
 *		   an update and will hang up in this function.
 *		2) It does not seem to matter that this function does
 *		   not really flush to the screen.
 *
 */
int
mswin_flush (void)
{
    FlushWriteAccum ();
    return (0);
}



/*
 * ibmflush - really flush output to screen.
 *
 *	But be careful:  if the changes made were off screen, 
 *	this function may never exit.
 */
int
mswin_really_flush (void)
{
    FlushWriteAccum ();
#ifdef OWNRECT
    if (gpTTYInfo->screenDirty) 
	InvalidateRect (ghTTYWnd, &gpTTYInfo->rPaintRect, FALSE);
#endif

    /* 
     * While the screen is dirty, Yeild to windows.
     * BUT, don't to this if the screen is minimized.
     */
    if (!gpTTYInfo->fMinimized) {
	while (gpTTYInfo->screenDirty) 
	    WinIdle ();
    }
    return (0);
}


/*
 * A replacement for fflush
 * relies on #define fflush mswin_fflush
 */
#undef fflush
int
mswin_fflush (FILE *f)
{
    if (f == stdout) {
	mswin_flush();
    }
    else
	fflush (f);
}



/*
 * Signals whether or not Paste should be turned on in the
 * menu bar.
 */
int
mswin_allowpaste (int on)
{
    HMENU		hMenu;
    
    hMenu = GetMenu (ghTTYWnd);
    gPasteEnabled = on;
    if(!IsClipboardFormatAvailable (CF_TEXT) || on == MSWIN_PASTE_DISABLE)
      EnableMenuItem (hMenu, IDM_EDIT_PASTE, (MF_BYCOMMAND | MF_GRAYED));
    else
      EnableMenuItem (hMenu, IDM_EDIT_PASTE, (MF_BYCOMMAND | MF_ENABLED));

}



/*
 * Signals whether or not Copy/Cut should be turned on in the
 * menu bar.
 */
int
mswin_allowcopy (getc_t copyfunc)
{
    HMENU		hMenu;

    hMenu = GetMenu (ghTTYWnd);
    gCopyCutFunction = copyfunc;
    gAllowCopy = (copyfunc != NULL);
}



/*
 * Signals whether or not Copy/Cut should be turned on in the
 * menu bar.
 */
int
mswin_allowcopycut (getc_t copyfunc)
{
    HMENU		hMenu;
    
    hMenu = GetMenu (ghTTYWnd);
    gCopyCutFunction = copyfunc;
    gAllowCopy = gAllowCut = (copyfunc != NULL);
}



int
mswin_allowexit (int allow, char *denyReason, int quitCmd)
{
    HMENU		hMenu;
    
    
    hMenu = GetMenu (ghTTYWnd);
    switch (allow) {
    case MSWIN_EXIT_DISABLE:
	gAllowExit = allow;
	break;
	
    case MSWIN_EXIT_DENY:
	gAllowExit = allow;
	gExitDenyReason = denyReason;
	break;

    case MSWIN_EXIT_SENDCHAR:
	gAllowExit = allow;
	gExitDenyReason = NULL;
	gExitSendChar = quitCmd;
	break;
    }
    return (0);
}




/*---------------------------------------------------------------------------
 *
 * Printing stuff
 *
 *-------------------------------------------------------------------------*/

/*
 * Printing globals
 */
LOCAL HDC	P_PrintDC;	/* Printer device context. */
LOCAL int	P_PageRows;	/* Number of rows we put on a page. */
LOCAL int	P_PageColumns;	/* Number of columns we put on a page. */
LOCAL int	P_RowHeight;	/* Hight of a row in printer pixels. */
LOCAL int	P_CurRow;	/* Current row, starting at zero */
LOCAL int	P_CurCol;	/* Current col, starting at zero. */
LOCAL int	P_TopOffset;	/* Top Margin offset, in pixels. */
LOCAL int	P_LeftOffset;	/* Top Margin offset, in pixels. */
LOCAL HFONT	P_hFont;	/* Handle to printing font. */
char		*P_LineText;	/* Pointer to line buffer. */




/*
 * Define the margin as number of lines at top and bottom of page. 
 * (might be better to define as a percent of verticle page size)
 */
#define VERTICLE_MARGIN		3	/* lines at top and bottom of page. */
#define HORIZONTAL_MARGIN	1	/* margine at left & right in chars */

/*
 * Several errors that can be reported. 
 */
#define PE_DIALOG_FAILED	1
#define PE_USER_CANCEL		2
#define PE_CANT_START_DOC	3
#define PE_OUT_OF_MEMORY	4
#define PE_GENERAL_ERROR	5
#define PE_OUT_OF_DISK		6
#define PE_PRINTER_NOT_FOUND	7
#define PE_PINE_INTERNAL	8
#define PE_FONT_FAILED		9


LOCAL struct pe_error_message {
	int		error_code;
	char		*error_message;
 } P_ErrorMessages[] = {
	{ PE_DIALOG_FAILED, "Print Dialog Failed"},
        { PE_USER_CANCEL, "User canceled" },
        { PE_CANT_START_DOC,	"Can't start document" },
	{ PE_OUT_OF_MEMORY,	"Out of memory" },
	{ PE_OUT_OF_DISK,	"Out of disk space" },
	{ PE_PRINTER_NOT_FOUND,	"Printer not found" },
	{ PE_PINE_INTERNAL,	"Pine internal error" },
	{ PE_FONT_FAILED,	"Failed to create font" },
	{ 0, NULL }};



/*
 * Send text in the line buffer to the printer.  
 * Advance to next page if necessary.
 */
LOCAL int
_print_send_line (void)
{
    int		status;
    
    status = 0;
    if (P_CurCol > 0) 
	TextOut (P_PrintDC, P_LeftOffset, 
				P_TopOffset + (P_CurRow * P_RowHeight), 
		P_LineText, P_CurCol);
    P_CurCol = 0;
    if (++P_CurRow >= P_PageRows) 
	status = _print_send_page ();
	
    return (status);
}

    

/*
 * Advance one page. 
 */
int
_print_send_page ()
{
    int		status;
    
    
    status = EndPage (P_PrintDC);
    if (status < 0)
	goto PrintError;
    P_CurRow = 0;
    StartPage (P_PrintDC);
    SelectObject (P_PrintDC, P_hFont);
    return (0);
    
    
PrintError:
    switch (status) {
    case SP_USERABORT:	return (PE_USER_CANCEL);
    case SP_OUTOFDISK:  return (PE_OUT_OF_DISK);
    case SP_OUTOFMEMORY:  return (PE_OUT_OF_MEMORY);
    default:
    case SP_ERROR:	return (PE_GENERAL_ERROR);
    }
}



/*
 * Map errors reported to my own error set.
 */
int
_print_map_dlg_error (DWORD error)
{
    switch (error) {
    case 0:			    return (PE_USER_CANCEL);
    case CDERR_MEMALLOCFAILURE:
    case CDERR_MEMLOCKFAILURE:
				    return (PE_OUT_OF_MEMORY);
    case PDERR_PRINTERNOTFOUND:
    case PDERR_NODEVICES:
				    return (PE_PRINTER_NOT_FOUND);
    case CDERR_STRUCTSIZE:
				    return (PE_PINE_INTERNAL);
    default:
				    return (PE_GENERAL_ERROR);
    }
}
	


/*
 * Get the printer ready.  Returns ZERO for success, or an error code that
 * can be passed to mswin_print_error() to get a text message.
 */
int
mswin_print_ready (char *docDesc)
{
    PRINTDLG		pd;
    DOCINFO		di;
    TEXTMETRIC		tm;
    HDC			hDC;
    int			fontSize;	/* Size in Points. */
    int			ppi;		/* Pixels per inch in device. */
    int			xChar;
    int			status;
    HFONT		oldFont;
    LOGFONT		newFont;
    
    
    status = 0;
    P_PrintDC = NULL;

    
    /*
     * Show print dialog.
     */
    pd.lStructSize = sizeof (pd);
    pd.hwndOwner = ghTTYWnd;
    pd.hDevMode = NULL;
    pd.hDevNames = NULL;
    pd.Flags = PD_ALLPAGES | PD_NOSELECTION | PD_NOPAGENUMS | 
	    PD_HIDEPRINTTOFILE | PD_RETURNDC;
    pd.nCopies = 1;
    if (PrintDlg (&pd) == 0) 
	return (_print_map_dlg_error (CommDlgExtendedError()));

    
    /*
     * Returns the device name which we could use to remember what printer 
     * they selected.  But instead, we just toss them.
     */
    if (pd.hDevNames)
	GlobalFree (pd.hDevNames);
    if (pd.hDevMode)
	GlobalFree (pd.hDevMode);

    /*
     * Get the device drawing context.
     * (does PringDlg() ever return success but fail to return a DC?)
     */
    if (pd.hDC != NULL) 
	P_PrintDC = pd.hDC;
    else {
        status = PE_DIALOG_FAILED;
	goto Done;
    }
    
    

    
    /*
     * Start Document
     */
    di.cbSize = sizeof (DOCINFO);
    di.lpszDocName = docDesc;		/* This appears in the print manager*/
    di.lpszOutput = NULL;		/* Could suply a file name to print
					   to. */
    if (StartDoc (P_PrintDC, &di) < 0) {
	DeleteDC (P_PrintDC);
	P_PrintDC = NULL;
	status = PE_CANT_START_DOC;
	goto Done;
    }
    
    /*
     * Get the current font size in points, then create a new font
     * of same size for printer.  Do the calculation using the actual
     * screen resolution instead of the logical resolution so that
     * we get pretty close to the same font size on the printer
     * as we see on the screen.
     */
    hDC = GetDC (ghTTYWnd);			/* Temp screen DC. */
    ppi = (int) ((float)GetDeviceCaps (hDC, VERTRES) / 
		((float) GetDeviceCaps (hDC, VERTSIZE) / 25.3636));
#ifdef FDEBUG
    if (Debug >= 8) {
	fprintf (DebugFile, "mswin_print_ready:  Screen res %d ppi, font height %d pixels\n",
	    ppi, -gpTTYInfo->lfTTYFont.lfHeight);
        fprintf (DebugFile, "                    Screen height %d pixel, %d mm\n",
		GetDeviceCaps (hDC, VERTRES), GetDeviceCaps (hDC, VERTSIZE));
    }
#endif
    ReleaseDC (ghTTYWnd, hDC);
    
    /* Convert from screen pixels to points. */
    fontSize = MulDiv (-gpTTYInfo->lfTTYFont.lfHeight, 72, ppi);
    ++fontSize;		/* Fudge a little. */
    
    
    /* Get printer resolution and convert form points to printer pixels. */
    ppi = GetDeviceCaps (P_PrintDC, LOGPIXELSY);
    newFont.lfHeight =  -MulDiv (fontSize, ppi, 72);

#ifdef FDEBUG
    if (Debug >= 8) {
        fprintf (DebugFile, "                    font Size %d points\n",
		fontSize);
	fprintf (DebugFile, "                    printer res %d ppi, font height %d pixels\n",
	    ppi, -newFont.lfHeight);
        fprintf (DebugFile, "                    paper height %d pixel, %d mm\n",
		GetDeviceCaps (P_PrintDC, VERTRES), 
		GetDeviceCaps (P_PrintDC, VERTSIZE));
    }
#endif
    
    /* Fill out rest of font description and request font. */
    newFont.lfWidth =          0;
    newFont.lfEscapement =     0;
    newFont.lfOrientation =    0;
    newFont.lfWeight =         0;
    newFont.lfItalic =         0;
    newFont.lfUnderline =      0;
    newFont.lfStrikeOut =      0;
    newFont.lfCharSet =        ANSI_CHARSET;
    newFont.lfOutPrecision =   OUT_DEFAULT_PRECIS;
    newFont.lfClipPrecision =  CLIP_DEFAULT_PRECIS;
    newFont.lfQuality =        DEFAULT_QUALITY;
    newFont.lfPitchAndFamily = FIXED_PITCH;
    _fstrcpy (newFont.lfFaceName, gpTTYInfo->lfTTYFont.lfFaceName);
    P_hFont = CreateFontIndirect (&newFont);
    if (P_hFont == NULL) {
	status = PE_FONT_FAILED;
	DeleteDC (P_PrintDC);
	goto Done;
    }
    
    
    /*
     * Start page.  
     * Must select font for each page or it returns to default.
     * Windows seems good about maping selected font to a font that 
     * will actually print on the printer.
     */
    StartPage (P_PrintDC);
    oldFont = SelectObject (P_PrintDC, P_hFont);
    
    
    /*
     * Find out about the font we got and set up page size and margins.
     * This assumes all pages are the same size - which seems reasonable.
     */
    GetTextMetrics (P_PrintDC, &tm);
    xChar = tm.tmAveCharWidth;			
    P_RowHeight = tm.tmHeight + tm.tmExternalLeading;
    
    /* HORZRES and VERTRES report size of page in printer pixels. */
    P_PageColumns = GetDeviceCaps (P_PrintDC, HORZRES) / xChar;
    P_PageRows = GetDeviceCaps (P_PrintDC, VERTRES) / P_RowHeight;
    
    /* We allow a margin at top and bottom measured in text rows. */
    P_PageRows -= VERTICLE_MARGIN * 2;
    P_TopOffset = VERTICLE_MARGIN * P_RowHeight;
    
    /* And allow for a left and right margine measured in characters. */
    P_PageColumns -= HORIZONTAL_MARGIN * 2;
    P_LeftOffset = HORIZONTAL_MARGIN * xChar;
    
    P_CurRow = 0;			/* Start counting at row 0. */
    P_CurCol = 0;			/* At character 0. */
    P_LineText = MemAlloc (P_PageColumns + 1);
    if (P_LineText == NULL) {
	EndDoc (P_PrintDC);
	DeleteObject (P_hFont);
	P_hFont = NULL;
	DeleteDC (P_PrintDC);
	P_PrintDC = NULL;
	status = PE_OUT_OF_MEMORY;
	goto Done;
    }
    
    
Done:
    return (status);
}



/* 
 * Called when printing is done.
 * xxx what happens if there is an error?  Will this get called?
 */
int
mswin_print_done (void)
{
    if (P_PrintDC != NULL) {
	if (P_LineText != NULL)
		MemFree (P_LineText);
	EndPage (P_PrintDC);
	EndDoc (P_PrintDC);
	DeleteObject (P_hFont);
	P_hFont = NULL;
	DeleteDC (P_PrintDC);
	P_PrintDC = NULL;
    }
    return (0);
}



/*
 * Return ponter to a text string that describes the erorr.
 */
char *
mswin_print_error (int error_code)
{
    int		i;
    
    for (i = 0; P_ErrorMessages[i].error_message != NULL; ++i) {
	if (P_ErrorMessages[i].error_code == error_code) 
	    return (P_ErrorMessages[i].error_message);
    }
    return ("(Unknow error)");
}




/*
 * Add a single character to the current line.  
 * Only handles CRLF carrage control.
 */
int
mswin_print_char (int c)
{
    int		status;
    
    status = 0;
    switch (c) {
    case ASCII_CR:
	break;

    case ASCII_LF:
	status = _print_send_line ();
	break;

    default:
	if (P_CurCol == P_PageColumns)
	    _print_send_line ();
        *(P_LineText + P_CurCol++) = (char) c;
	break;
    }
    return (status);
}
    



/*
 * Send a string to the printer.
 */
int
mswin_print_text (char *text)
{
    if (text != NULL) {
	while (*text) 
	    mswin_print_char (*(text++));
    }
}



#if 0
/*
 * Send a whole line to the printer.
 * Assume no carrage control in the line.
 */
int
mswin_print_line (char *line)
{
	
    int		status;
    int		linePos;
    int		lineLen;
    int		count;
    
    status = 0;
    lineLen = strlen (line);
    linePos = 0;
    
    /* Any text already in P_LineText is kept and appended to. */
    if (lineLen == 0) {
	/* If the line is empty, send that. */
	_print_send_line ();
    }
    else {
	/* Send the line to the printer.  Appending to anything that
	 * was already there, and wrapping to subsequent lines if
	 * there is more that will fit in one line. */
	while (lineLen > 0) {
	    count = min (lineLen - linePos, P_PageColumns - P_CurCol);
	    memcpy (P_LineText + P_CurCol, line + linePos, count);
	    P_CurCol += count;
	    linePos += count;
	    lineLen -= count;
	    _print_send_line ();
	}
    }
    return (0);
}
#endif








/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 *
 *        File dialog boxes.
 *
 *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
/*
 * Display a save file dialog box.
 *
 *	dir	>	directory to start search in
 *		<	directory finished in.
 *	fName	<	Name of file selectec
 *	nMaxFName	length of dir and fName.
 */
int
mswin_savefile (char *dir, char *fName, int nMaxFName)
{
    OPENFILENAME	ofn;
    char		filters[128];
    DWORD		rc;
    char		*p;
    size_t		l;


    /* Set filters array.  (pairs of null terminated strings, terminated
     * by a double null). */
    _fstrcpy (filters, "Text Files (*.txt)#*.txt#All Files (*.*)#*.*#");
    for (p = filters; *p != '\0'; ++p) {
	if (*p == '#')
	    *p = '\0';
    }



    /* Set up the BIG STRUCTURE. */
    _fmemset (&ofn, 0, sizeof(ofn));
    ofn.lStructSize = sizeof (OPENFILENAME);
    ofn.hwndOwner = ghTTYWnd;
    ofn.lpstrFilter = filters;
    ofn.lpstrCustomFilter = NULL;
    ofn.nFilterIndex = 1;
    ofn.lpstrFile = fName;
    ofn.nMaxFile = nMaxFName;
    ofn.lpstrFileTitle = NULL;
    ofn.nMaxFileTitle = 0;
    ofn.lpstrInitialDir = dir;
    ofn.lpstrTitle = "Save To File";
    ofn.Flags = OFN_NOREADONLYRETURN | 
		    OFN_OVERWRITEPROMPT | OFN_PATHMUSTEXIST;
    ofn.lpstrDefExt = "txt";

    if (GetSaveFileName (&ofn)) {
	    
	/* Copy directory name to dir. */
	strcpy (dir, fName);
	if (dir[ofn.nFileOffset-1] == '\\')
	    dir[ofn.nFileOffset-1] = '\0';
        else
	    dir[ofn.nFileOffset] = '\0';
	
	/* Move file name portion to beginning of fName buffer. */
	p = fName + ofn.nFileOffset;
	l = strlen (p) + 1;
	memmove (fName, p, l);
	return (0);
    }
    else {
	rc = CommDlgExtendedError ();
	return (-1);
    }
}




/*
 * Display an open file dialog box.
 *
 *	dir	>	directory to start search in
 *		<	directory finished in.
 *	fName	<	Name of file selectec
 *	nMaxFName	length of dir and fName.
 */
int
mswin_openfile (char *dir, char *fName, int nMaxFName)
{
    OPENFILENAME	ofn;
    char		filters[128];
    DWORD		rc;
    char		*p;
    size_t		l;


    /* Set filters array.  (pairs of null terminated strings, terminated
     * by a double null). */
    _fstrcpy (filters, "Text Files (*.txt)#*.txt#All Files (*.*)#*.*#");
    for (p = filters; *p != '\0'; ++p) {
	if (*p == '#')
	    *p = '\0';
    }
    
    

    /* Set up the BIG STRUCTURE. */
    _fmemset (&ofn, 0, sizeof(ofn));
    ofn.lStructSize = sizeof (OPENFILENAME);
    ofn.hwndOwner = ghTTYWnd;
    ofn.lpstrFilter = filters;
    ofn.lpstrCustomFilter = NULL;
    ofn.nFilterIndex = 1;
    ofn.lpstrFile = fName;
    ofn.nMaxFile = nMaxFName;
    ofn.lpstrFileTitle = NULL;
    ofn.nMaxFileTitle = 0;
    ofn.lpstrInitialDir = dir;
    ofn.lpstrTitle = "Select File";
    ofn.Flags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST;
    ofn.lpstrDefExt = "txt";

    if (GetOpenFileName (&ofn)) {
	    
	/* Copy directory name to dir. */
	strcpy (dir, fName);
	if (dir[ofn.nFileOffset-1] == '\\')
	    dir[ofn.nFileOffset-1] = '\0';
        else
	    dir[ofn.nFileOffset] = '\0';
	
	/* Move file name portion to beginning of fName buffer. */
	p = fName + ofn.nFileOffset;
	l = strlen (p) + 1;
	memmove (fName, p, l);
	return (0);
    }
    else {
	rc = CommDlgExtendedError ();
	return (-1);
    }
}
	
	




/*---------------------------------------------------------------------------
 */

/*
 * pico_XXcolor() - each function sets a particular attribute
 */
pico_nfcolor(s)
char *s;
{
    SetColorAttribute (&gpTTYInfo->rgbFGColor, s);
}

pico_nbcolor(s)
char *s;
{
    SetColorAttribute (&gpTTYInfo->rgbBGColor, s);
}

pico_rfcolor(s)
char *s;
{
    SetColorAttribute (&gpTTYInfo->rgbRFGColor, s);
}

pico_rbcolor(s)
char *s;
{
    SetColorAttribute (&gpTTYInfo->rgbRBGColor, s);
}





/*
 * Signal 
 */
void (__cdecl * __cdecl signal (int sig,void (__cdecl *hndlr)(int)))(int)

{
    return (SIG_IGN);
}



int
printf (const char *fmt, ...)
{
    va_list	marker;
    int		strLen;
    
    va_start (marker, fmt);
    _vsnprintf (TempBuf, MAXLEN_TEMPSTR, fmt, marker);
    
    FlushWriteAccum ();
    strLen = strlen (TempBuf);
    if (strLen > 0) {
        if (TempBuf[strLen-1] == ASCII_LF) {
	    TempBuf[strLen-1] == ASCII_CR;
	    TempBuf[strLen] == ASCII_LF;
	    TempBuf[++strLen] = '\0';
        }
	WriteTTYBlock (ghTTYWnd, TempBuf, strLen);
    }
    return (1);
}



/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 *
 *        File quit menu.
 *
 *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
LOCAL void
FileQuit (void)
{
    char		titleBuf[512];
    HMENU		hMenu;
    
    switch (gAllowExit) {
    case MSWIN_EXIT_DENY:
	if (gExitDenyReason != NULL) {
	    sprintf (titleBuf, "Quit %s", gszAppName);
	    MessageBox (ghTTYWnd, gExitDenyReason, titleBuf, 
		    MB_APPLMODAL | MB_OK | MB_ICONSTOP);
        }
	break;
	
    case MSWIN_EXIT_SENDCHAR:
	CQAdd (gExitSendChar, 0);
	break;
	
    default:
	/* Should not have been enabled, disable now. */
	hMenu = GetMenu (ghTTYWnd);
	EnableMenuItem (hMenu, IDM_FILE_EXIT, MF_BYCOMMAND | MF_GRAYED);
	break;
    }
}
	
	
    
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 *
 *        Cut, Copy, and Paste operations
 *
 *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/


/*
 * Gets called right before the menu is displayed so we can make
 * any last minute adjustments.
 */
LOCAL void
UpdateMenu (void)
{
    HMENU		hMenu;
    BOOL		brc;
    
    hMenu = GetMenu (ghTTYWnd);
    if (ghPaste == NULL) {
	/* 
	 * Not pasting.  If text is available on clipboard and we are
	 * at a place where we can paste, enable past menu option.
	 * Also check if we currently have a selection that can be copied
	 * or cut.  If so, we don't want to paste into a selection - it
	 * works but it is slow and probably not what the user intended.
	 */
	if (IsClipboardFormatAvailable (CF_TEXT) && gPasteEnabled && 
		gCopyCutFunction == NULL)
	    EnableMenuItem (hMenu, IDM_EDIT_PASTE, MF_BYCOMMAND | MF_ENABLED);
	else
	    EnableMenuItem (hMenu, IDM_EDIT_PASTE, MF_BYCOMMAND | MF_GRAYED);
	EnableMenuItem (hMenu, IDM_EDIT_CANCEL_PASTE, MF_BYCOMMAND | MF_GRAYED);
    }
    else {
	/* Currently pasting so disable paste and enable cancel paste. */
	EnableMenuItem (hMenu, IDM_EDIT_PASTE, MF_BYCOMMAND | MF_GRAYED);
	EnableMenuItem (hMenu, IDM_EDIT_CANCEL_PASTE, MF_BYCOMMAND | MF_ENABLED);
    }
    
    if (SelAvailable ()) {
	EnableMenuItem (hMenu, IDM_EDIT_CUT, MF_BYCOMMAND | MF_GRAYED);
	EnableMenuItem (hMenu, IDM_EDIT_COPY, MF_BYCOMMAND | MF_ENABLED);
	EnableMenuItem (hMenu, IDM_EDIT_COPY_APPEND, 
				MF_BYCOMMAND | MF_ENABLED);
    } else {
	if (gAllowCut)
	    EnableMenuItem (hMenu, IDM_EDIT_CUT, MF_BYCOMMAND | MF_ENABLED);
        else
	    EnableMenuItem (hMenu, IDM_EDIT_CUT, MF_BYCOMMAND | MF_GRAYED);

        if (gAllowCopy) {
	    EnableMenuItem (hMenu, IDM_EDIT_COPY, MF_BYCOMMAND | MF_ENABLED);
	    EnableMenuItem (hMenu, IDM_EDIT_COPY_APPEND, 
				MF_BYCOMMAND | MF_ENABLED);	
	}
        else {
	    EnableMenuItem (hMenu, IDM_EDIT_COPY, MF_BYCOMMAND | MF_GRAYED);
	    EnableMenuItem (hMenu, IDM_EDIT_COPY_APPEND, 
				MF_BYCOMMAND | MF_GRAYED);	
	}
    }
    
    
    if (gAllowExit == MSWIN_EXIT_SENDCHAR || 
	 (gAllowExit == MSWIN_EXIT_DENY && gExitDenyReason != NULL))
	EnableMenuItem (hMenu, IDM_FILE_EXIT, MF_BYCOMMAND | MF_ENABLED);
    else
	EnableMenuItem (hMenu, IDM_FILE_EXIT, MF_BYCOMMAND | MF_GRAYED);
    
}



/*
 * Cut region to kill buffer.
 */
LOCAL void
EditCut (void)
{
    HANDLE		hCB;
    
    if(gCopyCutFunction == kremove){
	hCB = GlobalAlloc (GMEM_MOVEABLE, 0);
	if (hCB != NULL) {
	    copyregion (1, 0);
	    EditDoCopyData (hCB, 0);
	    killregion (1, 0);	/* Kill Region. */
	    update ();		/* And update the screen */
        }
    }
}


/*
 * Copy region to kill buffer. 
 */
LOCAL void
EditCopy (void)
{
    HANDLE		hCB;
    
    if (SelAvailable()) {
	/* This is a copy of the windows selection. */
	hCB = GlobalAlloc (GMEM_MOVEABLE, 0);
	if (hCB != NULL) 
	    SelDoCopy (hCB, 0);
    } 
    else {
	    
	/* Otherwise, it's a Pico/Pine copy. */
	if(gCopyCutFunction == kremove){
	    copyregion (1, 0);
	}

	hCB = GlobalAlloc (GMEM_MOVEABLE, 0);
	if (hCB != NULL) 
	    EditDoCopyData (hCB, 0);
    }
}



/*
 * Called in responce to "Copy Append" menu command, when there is an active
 * Windows selection on the screen.
 */
LOCAL void
EditCopyAppend (void)
{
    HANDLE	hCB;
    HANDLE	hMyCopy;
    char	*pCB;
    char	*pMyCopy;
    size_t	cbSize;

    /* Attempt to copy clipboard data to my own handle. */
    hMyCopy = NULL;
    if (OpenClipboard (ghTTYWnd)) {		/* And can get clipboard. */
	hCB = GetClipboardData (CF_TEXT);
	if (hCB != NULL) {			/* And can get data. */
	    pCB = GlobalLock (hCB);
	    cbSize = strlen (pCB);		/* It's a null term string. */
	    hMyCopy = GlobalAlloc (GMEM_MOVEABLE, cbSize);
	    if (hMyCopy != NULL) {		/* And can get memory. */
		pMyCopy = GlobalLock (hMyCopy);
		if (pMyCopy != NULL) {
		    _fmemcpy (pMyCopy, pCB, cbSize);  /* Copy data. */
		    GlobalUnlock (hMyCopy);
		}
		else {
		    GlobalFree (hMyCopy);
		    hMyCopy = NULL;
		}
	    }
	    GlobalUnlock (hCB);
	}					/* GetClipboardData. */
	CloseClipboard ();
    }					/* OpenClipboard. */
    


    /* Now, if I got a copy, append current selection to that
     * and stuff it back into the clipboard. */
    if (hMyCopy != NULL) {
	if (SelAvailable ()) {
	    SelDoCopy (hMyCopy, cbSize);
	}
	else {
	    if(gCopyCutFunction == kremove) {
		copyregion (1, 0);
	    }
	    EditDoCopyData (hMyCopy, cbSize);
	}
    }
}









/*
 * Copy data from the kill buffer to the clipboard.  Handle LF->CRLF
 * translation if necessary.
 */
LOCAL void
EditDoCopyData (HANDLE hCB, DWORD lenCB)
{
    char		*pCB;
    char		*p;
    char		c;
    char		lastc = '\0';
    DWORD		cbSize;			/* Allocated size of hCB. */
    DWORD		i;
#define	BUF_INC	4096

    if (gCopyCutFunction != NULL) {		/* If there really is data. */
	if (OpenClipboard (ghTTYWnd)) {		/* ...and we get the CB. */
	    if (EmptyClipboard ()) {		/* ...and clear previous CB.*/
		pCB = GlobalLock (hCB);
		p = pCB + lenCB;
		cbSize = lenCB;
		/* Copy it. (BUG: change int arg) */
		for(i = 0L; (c = (*gCopyCutFunction)((int)i)) != -1; i++){
		    /*
		     * Rather than fix every function that might
		     * get called for character retrieval to supply
		     * CRLF EOLs, let's just fix it here.  The downside
		     * is a much slower copy for large buffers, but
		     * hey, what do they want?
		     */
		    if(lenCB + 2L >= cbSize){
			cbSize += BUF_INC;
			GlobalUnlock (hCB);
			hCB = GlobalReAlloc (hCB, cbSize, GMEM_MOVEABLE);
			if (hCB == NULL)
			  return;

			pCB = GlobalLock (hCB);
			p = pCB + lenCB;
		    }

		    if(c == ASCII_LF && lastc != ASCII_CR) {
		      *p++ = ASCII_CR;	/* insert CR before LF */
		      lenCB++;
		    }

		    *p++ = lastc = c;
		    lenCB++;
		}

		*p = '\0';
		GlobalUnlock (hCB);

		if (SetClipboardData (CF_TEXT, hCB) == NULL)
		  /* Failed!  Free the data. */
		  GlobalFree (hCB);
	    }
	    CloseClipboard (); 
        }
    }
}



/*
 * Get a handle to the current (text) clipboard and make my own copy.
 * Keep my copy locked because I'll be using it to read bytes from.
 */
LOCAL void
EditPaste (void)
{
    HANDLE	hCB;
    char	*pCB;
    char	*pPaste;
    size_t	cbSize;
   
    if (ghPaste == NULL) {		/* If we are not already pasting. */
	if (OpenClipboard (ghTTYWnd)) {		/* And can get clipboard. */
	    hCB = GetClipboardData (CF_TEXT);
	    if (hCB != NULL) {			/* And can get data. */
		pCB = GlobalLock (hCB);
		cbSize = strlen (pCB);		/* It's a null term string. */
		ghPaste = GlobalAlloc (GMEM_MOVEABLE, cbSize+1);
		if (ghPaste != NULL) {		/* And can get memory. */
		    gpPasteNext = GlobalLock (ghPaste);
		    _fmemcpy (gpPasteNext, pCB, cbSize+1);  /* Copy data. */
		    /* Keep ghPaste locked. */

		    /*
		     * If we're paste is enabled but limited to the first
		     * line of the clipboard, prune the paste buffer...
		     */
		    if(gPasteEnabled == MSWIN_PASTE_LINE
		       && (pPaste = strchr(gpPasteNext, ASCII_CR))){
			*pPaste = '\0';
			cbSize  = strlen(gpPasteNext);
		    }

		    gPasteBytesRemain = cbSize;
		    gPasteWasCR = FALSE;
#ifdef FDEBUG
		    if (Debug > 8) 
			fprintf (DebugFile, "EditPaste::  Paste %d bytes\n",
				    gPasteBytesRemain);
#endif
		}
		GlobalUnlock (hCB);
	    }
	    CloseClipboard ();
        }
    }
}






/*
 * Cancel an active paste operation.
 */
LOCAL void
EditCancelPaste (void)
{
    HANDLE	hCB;
    char	*pCB;
    char	*pPaste;
    size_t	cbSize;
   
    if (ghPaste != NULL) {	/* Must be pasting. */
	GlobalUnlock (ghPaste);	/* Then Unlock... */
	GlobalFree (ghPaste);	/* ...and free the paste buffer. */
	ghPaste = NULL;		/* Indicates no paste data. */
	gpPasteNext = NULL;		/* Just being tidy. */
	gPasteBytesRemain = 0;	/* ditto. */
#ifdef FDEBUG
	if (Debug > 8) 
	    fprintf (DebugFile, "EditCancelPaste::  Free Paste Data\n");
#endif
    }
}


/*
 * Get the next byte from the paste buffer.  If all bytes have been
 * retreived, free the paste buffer.
 * Map all CRLF sequence to a single CR.
 */
LOCAL WORD
EditPasteGet (void)
{
    int		b;
    
    b = MSWIN_KEY_NODATA;
    if (ghPaste != NULL) {		/* ghPaste tells if we are pasting. */
        if (gPasteBytesRemain > 0) {	/* Just in case... */
	    b = *gpPasteNext++;		/* Get one byte and move pointer. */
	    --gPasteBytesRemain;	/*    one less. */
	    if (gPasteWasCR && b == ASCII_LF) {
		if (gPasteBytesRemain) {
		    b = *gpPasteNext++;	/* Skip of LF. */
		    --gPasteBytesRemain;
	        }
		else 
		    b = MSWIN_KEY_NODATA;  /* Ignore last LF. */
	    }
	    gPasteWasCR = (b == ASCII_CR);
#ifdef FDEBUG
	    if (Debug > 8) 
		fprintf (DebugFile, "EditPasteGet::  char %c, gPasteWasCR %d, gPasteBytesRemain %d\n",
			b, gPasteWasCR, gPasteBytesRemain);
#endif
        }
	if (gPasteBytesRemain <= 0) {	/* All Done? */
	    GlobalUnlock (ghPaste);	/* Then Unlock... */
	    GlobalFree (ghPaste);	/* ...and free the paste buffer. */
	    ghPaste = NULL;		/* Indicates no paste data. */
	    gpPasteNext = NULL;		/* Just being tidy. */
	    gPasteBytesRemain = 0;	/* ditto. */
#ifdef FDEBUG
	    if (Debug > 8) 
		fprintf (DebugFile, "EditPasteGet::  Free Paste Data\n");
#endif
        }
    }
    return (b);
}


/*
 * Return true if Paste data is available.  If gpPaste != NULL then there
 * is paste data.
 */
LOCAL BOOL
EditPasteAvailable (void)
{
    return (ghPaste != NULL);
}





LOCAL void
ShowHelp (void)
{
    char	wndTitle[128];
    
    if (gpHelpText != NULL) {
	strcpy (wndTitle, gszAppName);
	strcat (wndTitle, " Help");
	MessageBox (ghTTYWnd, gpHelpText, "PC-Pine Help", 
		MB_OK | MB_ICONINFORMATION);
    }
}





/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 *
 *                  On Task processing
 *
 *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/


WINHAND
mswin_inst2task (WINHAND hModule)
{
    TASKENTRY		te;
    MODULEENTRY		me;
    BOOL		brc;
    

    memset (&te, 0, sizeof (te));
    te.dwSize = sizeof (te);
    
#ifdef FDEBUG
    if (Debug >= 8) 
	fprintf (DebugFile, "mswin_inst2task:  look for x%x\n", hModule);
#endif

    brc = TaskFirst (&te);
    while (brc) {
#ifdef FDEBUG
	if (Debug >= 8)
	    fprintf (DebugFile, "  task:  '%s', hTask x%x, module x%x, inst x%x\n", 
		    te.szModule, (UINT) te.hTask, (UINT) te.hModule, 
		    (UINT) te.hInst);
#endif
	if (te.hModule == (HMODULE)hModule)
	    return ((WINHAND)te.hTask);
	if (te.hInst == (HINSTANCE)hModule)
	    return ((WINHAND)te.hTask);
	brc = TaskNext (&te);
    }
    
    return (0);
}
    
    


/*
 * Register a file deletion operation when hTask goes away.
 */
int		
mswin_ontask_del (WINHAND hTask, char *path)
{
    OnTaskItem		*ot;
    BOOL		wasEmpty;
    
    ot = MemAlloc (sizeof (OnTaskItem));
    if (ot == NULL)
	return (-1);

    wasEmpty = (gOnTaskList == NULL);
    ot->hTask = (HTASK) hTask;
    strncpy (ot->path, path, PATH_MAX);
    ot->path[PATH_MAX] = '\0';
    ot->next = gOnTaskList;
    gOnTaskList = ot;
    if (wasEmpty)
	SetTimer (ghTTYWnd, MY_TIMER_ID, MY_TIMER_SHORT_PERIOD, NULL);
	
    return (0);
}



/*
 * Execute command and wait for the 
 */
int
mswin_exec_and_wait (char *whatsit, char *command)
{
    HTASK	hTask;
    MEvent	mouse;
    char	waitingFor[256];
    BOOL	brc;
    UINT	urc;
    int		rc;
    
    
    mswin_flush ();
    
    urc = WinExec (command, SW_SHOW);
#ifdef FDEBUG
    if (Debug >= 8) {
	fprintf (DebugFile, "mswin_exec_and_wait:  command '%s'\n", command);
	fprintf (DebugFile, "                      WinExec returns module x%x\n",
		urc);
    }
#endif

    if (urc < 32) 
	return ((int)urc);
    hTask = (HTASK) mswin_inst2task (urc);

#ifdef FDEBUG
    if (Debug >= 8) 
	fprintf (DebugFile, "mswin_exec_and_wait:  module maps to task x%x, wait for it to finish\n",
		(UINT) hTask);
#endif

    if (hTask == NULL)
	return (-1);
    
    sprintf (waitingFor, "%s is currently waiting for the %s (%s) to complete.  Click \"Cancel\" to stop waiting, or \"OK\" to continue waiting.",
	    gszAppName, whatsit, command);
    

    /*
     * Go into holding pattern until the other application terminates
     * or we are told to stop waiting.
     */
    while (IsTask (hTask)) {
	rc = mswin_getc();
	brc = WinGetMEvent (&mouse);

	if (rc != MSWIN_KEY_NODATA || 
		(brc && mouse.event == MEVENT_MOUSEDOWN)) {
	
	    rc = MessageBox (ghTTYWnd, waitingFor, whatsit, 
		    MB_ICONSTOP | MB_OKCANCEL);
	    SelClear ();
	    if (rc == IDCANCEL)
		 return (-2);
	}
    }
    if (gpTTYInfo->fMinimized) 
	ShowWindow (ghTTYWnd, SW_SHOWNORMAL);
    BringWindowToTop (ghTTYWnd);
    return (0);
}

    
	



LOCAL void
ProcessOnTask (void)
{
    OnTaskItem		*ot, *pot, *not;
    BOOL		wasEmpty;
    
    if (gOnTaskList == NULL) 
	return;

    /* Scann through list. */
    wasEmpty = (gOnTaskList == NULL);
    ot = gOnTaskList;
    while (ot != NULL) {
	not = ot->next;
	
	/* Task gone? */
	if (!IsTask (ot->hTask)) {

	    /* Perform action.*/
	    unlink (ot->path);
	    
	    /* Remove item. */
	    if (ot == gOnTaskList) {
		/* Remve from head of list. */
		gOnTaskList = not;
	    } else {
		/* Remove from middle of list - find previous. */
		for (pot = gOnTaskList; pot->next == ot; pot = pot->next);
		pot->next = not;
	    }
	    MemFree (ot);
        }
		
	ot = not;
    }
    if (!wasEmpty && gOnTaskList == NULL)
	SetTimer (ghTTYWnd, MY_TIMER_ID, MY_TIMER_PERIOD, NULL);
	
}
	     




/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 *
 *                  Character Queue
 *
 *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/


typedef struct {
	WORD	flags;
	WORD	c;
} CQEntry;

LOCAL CQEntry CQBuffer [CHARACTER_QUEUE_LENGTH];
LOCAL int CQHead;
LOCAL int CQTail;
LOCAL int CQCount;


/*---------------------------------------------------------------------------
 *  BOOL  CQInit ()
 *
 *  Description:
 *		Initialize the Character queue.
 *
 *  Parameters:
 *
 *
/*--------------------------------------------------------------------------*/
LOCAL void
CQInit (void)
{
	CQHead = 0;
	CQTail = 0;
	CQCount = 0;
}
 
 
/*---------------------------------------------------------------------------
 *  BOOL  CQAvailable (void)
 *
 *  Description:
 *		Return TRUE if there are characters in the queue.
 *
 *  Parameters:
 *
 *
/*--------------------------------------------------------------------------*/

LOCAL BOOL
CQAvailable (void)
{
	return (CQCount > 0);
}
 

 
/*---------------------------------------------------------------------------
 *  BOOL  CQAdd (WORD c, DWORC keyData)
 *
 *  Description:
 *		Add 'c' to the end of the character queue.
 *
 *  Parameters:
 *		return true if successfull.
 *
/*--------------------------------------------------------------------------*/

LOCAL BOOL
CQAdd (WORD c, DWORD keyData)
{
	if (CQCount == CHARACTER_QUEUE_LENGTH)
		return (FALSE);
	
	
	CQBuffer[CQTail].flags = 0;
	if ((keyData & 0x80000000) == 0)
	    CQBuffer[CQTail].flags |= CQ_FLAG_DOWN;
	if (keyData & 0x01000000)
	    CQBuffer[CQTail].flags |= CQ_FLAG_EXTENDED;
	if (keyData & 0x20000000)
	    CQBuffer[CQTail].flags |= CQ_FLAG_ALT;
	CQBuffer[CQTail].c = c;
	CQTail = (CQTail + 1) % CHARACTER_QUEUE_LENGTH;
	++CQCount;
	return (TRUE);
}
 
 
/*---------------------------------------------------------------------------
 *  int  CQGet ()
 *
 *  Description:
 *		Return the next byte from the head of the queue.  If there is
 *		no byte available, returns 0, which is indistinquishable from 
 *		'\0'.  So it is a good idea to call CQAvailable first.
 *
 *  Parameters:
 *		none.
 *
/*--------------------------------------------------------------------------*/

LOCAL WORD
CQGet ()
{
    WORD	c;

    if (CQCount == 0)
	return (0);

    c = CQBuffer[CQHead].c;
    CQHead = (CQHead + 1) % CHARACTER_QUEUE_LENGTH;
    --CQCount;
    return (c);
}


#if 0
/*---------------------------------------------------------------------------
 *
 *  LOCAL int MapVKtoMS (WORD c, WORD flags);
 *
 * Description:
 *	Map key received in WM_CHAR message to intermediate character code.
 *      which latter gets maped to a pico or pine character code.
 */
LOCAL int
MapVKtoMS (WORD c, WORD flags)
{
    /* Special keys. */
    if (flags & CQ_FLAG_ALT)
	return (MSWIN_KEY_NODATA);

    if (flags & CQ_FLAG_EXTENDED) {
	switch (c) {
	    case VK_UP:			return (MSWIN_KEY_UP);
	    case VK_DOWN:		return (MSWIN_KEY_DOWN);
	    case VK_RIGHT:		return (MSWIN_KEY_RIGHT);
	    case VK_LEFT:		return (MSWIN_KEY_LEFT);
	    case VK_PRIOR:		return (MSWIN_KEY_PREVPAGE);
	    case VK_NEXT:		return (MSWIN_KEY_NEXTPAGE);
	    case VK_HOME:		return (MSWIN_KEY_HOME);
	    case VK_END:		return (MSWIN_KEY_END);
	    case VK_DELETE:		return (MSWIN_KEY_DELETE);
	    case VK_F1:			return (MSWIN_KEY_F1);
	    case VK_F2:			return (MSWIN_KEY_F2);
	    case VK_F3:			return (MSWIN_KEY_F3);
	    case VK_F4:			return (MSWIN_KEY_F4);
	    case VK_F5:			return (MSWIN_KEY_F5);
	    case VK_F6:			return (MSWIN_KEY_F6);
	    case VK_F7:			return (MSWIN_KEY_F7);
	    case VK_F8:			return (MSWIN_KEY_F8);
	    case VK_F9:			return (MSWIN_KEY_F9);
	    case VK_F10:		return (MSWIN_KEY_F10);
	    case VK_F11:		return (MSWIN_KEY_F11);
	    case VK_F12:		return (MSWIN_KEY_F12);
	    default:			return (MSWIN_KEY_NODATA);
        }
    }
    
    /* Normal keys. */
    return (c);
}
#endif




/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 *
 *                  Mouse Event Queue
 *
 *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/



LOCAL MEvent MQBuffer [MOUSE_QUEUE_LENGTH];
LOCAL int MQHead;
LOCAL int MQTail;
LOCAL int MQCount;


/*---------------------------------------------------------------------------
 *  BOOL  MQInit ()
 *
 *  Description:
 *		Initialize the Character queue.
 *
 *  Parameters:
 *
 *
/*--------------------------------------------------------------------------*/
LOCAL void
MQInit (void)
{
	MQHead = 0;
	MQTail = 0;
	MQCount = 0;
}
 
 
/*---------------------------------------------------------------------------
 *  BOOL  MQAvailable (void)
 *
 *  Description:
 *		Return TRUE if there are characters in the queue.
 *
 *  Parameters:
 *
 *
/*--------------------------------------------------------------------------*/

LOCAL BOOL
MQAvailable (void)
{
	return (MQCount > 0);
}
 

 
/*---------------------------------------------------------------------------
 *  BOOL  MQAdd ()
 *
 *  Description:
 *		Add 'c' to the end of the character queue.
 *
 *  Parameters:
 *		return true if successfull.
 *
/*--------------------------------------------------------------------------*/

LOCAL BOOL
MQAdd (int mevent, int button, int nRow, int nColumn, unsigned int keys)
{
    if (MQCount == MOUSE_QUEUE_LENGTH)
	    return (FALSE);

    /* Constrain the cel to be on the screen. */
    nColumn = max (0, nColumn);
    nColumn = min (gpTTYInfo->actNColumn-1, nColumn);
    nRow = max (0, nRow);
    nRow = min (gpTTYInfo->actNRow-1, nRow);
    MQBuffer[MQTail].event = mevent;
    MQBuffer[MQTail].button = button;
    MQBuffer[MQTail].nRow = nRow;
    MQBuffer[MQTail].nColumn = nColumn;
    MQBuffer[MQTail].flags = (unsigned long) keys;
    MQTail = (MQTail + 1) % MOUSE_QUEUE_LENGTH;
    ++MQCount;
    return (TRUE);
}
 
 
/*---------------------------------------------------------------------------
 *  BOOL  MQGet ()
 *
 *  Description:
 *		Return the next byte from the head of the queue.  If there is
 *		no byte available, returns 0, which is indistinquishable from 
 *		'\0'.  So it is a good idea to call MQAvailable first.
 *
 *  Parameters:
 *		none.
 *
/*--------------------------------------------------------------------------*/

LOCAL BOOL
MQGet (MEvent * pMouse)
{

    if (MQCount == 0)
	return (FALSE);

    *pMouse = MQBuffer[MQHead];
    pMouse->flags = MQBuffer[MQHead].flags;
    MQHead = (MQHead + 1) % MOUSE_QUEUE_LENGTH;
    --MQCount;
    return (TRUE);
}





/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 *
 *                  Memory allocation routines.
 *
 *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

/*
 *	The plan is to allocate small blocks in the local heap and
 *	large blocks in the global heap.  The intention is to keep
 *	the number of global allocations to a minimum.
 *
 *	The boundry between small memory and large memory is
 *	controld by the constant SMALL_MEM_BOUNDRY.  Blocks smaller
 *	than SMALL_MEM_BOUNDRY go into the local heap.  This should
 *	be set large enough to capture the majority of small memory
 *	blocks in the local heap.  But if it is too large, the local 
 *	heap will fill up and we will end up allocating a lot of small
 *	blocks in the global heap.
 *
 *	Unfortunatly, pine seems to need a large stack.  With the
 *	stack, some global data, and the heap all cramed in to a 64K
 *	segment we end up with a heap that is smaller than ideal.
 *	This could be improved by reducing the size of the stack, or
 *	by moving the heap to a seperate memory block.  I did a little
 *	work on moving the heap, but was not successful.  My attepts
 *	can be seen in the function MemATest().
 *
 *	Currently (7/8/94) I've set the stack to 32K (in pine/makefile.win),
 *	the heap to 12K, and the small memory boundry to 32 bytes.
 *	Statistics on pine memory allocation suggest that it would be better
 *	to have a 25K local heap and a 95 byte small memory boundry.
 *
 *	Statistics on memory use can be gathered by logging memory debugging
 *	to a file, then running the following awk script:
 *
   # mem.awk
   #
   #	Looks through log and find blocks that were allocated but not
   #	freed uses block id numbers, rather than addresses, since this is
   #	more accurate (and since this is what block ids exist!)
   #
   #	awk may run out of memory if the logfile gets too big.  If this
   #	happens, then another strategy will be needed...
   #

   BEGIN {
	   FS = "[ ()]+";

	   b[0] = 16; b[1] = 32; b[2] = 64; b[3] = 96; b[4] = 128; 
	   b[5] = 256; b[6] = 512; b[7] = 1024; b[8] = 2048; 
	   b[9] = 4096; b[10] = 9600; b[11] = 20000; b[12] = 40000; 
	   b[13] = 80000; b[14] = 200000000; b[15] = 0; 
	   bcount = 15;
	   for (i = 0; i < bcount; ++i)
		   c[i] = 0;

	   maxmem = 0;		# Memory high water mark.
	   maxsmallmem = 0;	# Small block memory high water mark.

	   allocs = 0;		# Count of all allocations.
	   globalallocs = 0;	# count of allocations in the global heap.
   }

   {
	   if( $1 == "MemAlloc:" ) {
		   m[$5] = $0;		# remember the line, by ID
		   ++allocs;		# Count one allocations
		   if ($9 == 1) ++globalallocs; # Count one in the global heap.

		   # Find the bucket for byte size.
		   for (i = 0; i < bcount; ++i) {
			   if (b[i] > $7) {
				   ++c[i];
				   break;
			   }
		   }
	   }
	   else if( $1 == "MemFree:" ) {	# Freed block, forget the line.
		   delete m[$5];
	   }
	   else if ($1 == "Memory") {	# Tells us what memory use is up to.
		   if ($6 > maxmem) maxmem = $6;
	   }
	   else if ($1 == "Small") {	# What small memory use is up to.
		   if ($7 > maxsmallmem) maxsmallmem = $7;
	   }
   }


   END {
	   # Print line for every block allocated by not freed.
	   for( i in m ) {
		   print m[i]
	   }

	   # Print histogram of block size. 
	   cumulative = 0;
	   for (i = 0; i < bcount; ++i) {
		   cumulative += c[i];
		   printf "%9d : %5d  (%5d)\n", b[i], c[i], cumulative;
	   }

	   print;
	   print "Max memory use:        ", maxmem;
	   print "Max small memory use:  ", maxsmallmem;
	   print;
	   print "Local allocations   ", allocs - globalallocs;
	   print "Global allocations  ", globalallocs;
	   print "Total allocations   ", allocs;
   }

 *
 *	Each memory block is assigned a unique id.  This is only used
 *	to match allocations with frees in the debug log.
 */


#define GET_SEGMENT(x)		(0xffff & ((DWORD)(x) >> 16))
#define GET_OFFSET(x)		(0xffff & (DWORD)(x))

#ifdef MEM_DEBUG
static BOOL		MemDoDebug = FALSE;	/* Doing debugging. */
static FILE		*MemDebugFile = NULL;	/* File to write to. */
#endif

#undef malloc
#undef realloc
#undef free

void		MemATest (void);


/*
 * Define some standard functions and map to our functions.
 */
void *
malloc (size_t size)
{
	return (MemAlloc (size));
}


void __far *
_fmalloc (size_t size)
{
	return (MemAlloc (size));
}


void __far *
realloc (void *memblock, size_t size)
{
	return (MemRealloc (memblock, size));
}


void __far *
_frealloc (void *memblock, size_t size)
{
	return (MemRealloc (memblock, size));
}


void 
free (void *memblock)
{
	MemFree (memblock);
}

void 
_ffree (void *memblock)
{
	MemFree (memblock);
}


/*
 * Turn on memory debugging and specify file to write to.
 */
void
MemDebug (int debug, FILE *debugFile)
{
#ifdef MEM_DEBUG
    if (debugFile == NULL) {
	MemDoDebug = FALSE;
	MemDebugFile = NULL;
    }
    else {
	MemDoDebug = debug;
	MemDebugFile = debugFile;
	fprintf (MemDebugFile, "MemDebuging set on\n");
    }
#endif /* MEM_DEBUG */
}


#define SEGHEAP
#ifndef SEGHEAP
#define GUARD_LOW0		0xbbbb
#define GUARD_LOW		0x9999
#define GUARD_HIGH		0xaaaaaaaa

#define SMALL_MEM_BOUNDRY	32

#define HEAP_SIZE		32000


/* Memory block header.  Placed at beginning of each allocated block. */
typedef struct {			/*size  len */
    WORD		guard0;		/* 00 - 02 */
    HGLOBAL		handle;		/* 02 - 02 */
    short		globalBlk;	/* 04 - 02 */
    MemSize		size;		/* 06 - 04 */
    WORD		id;		/* 0A - 02 */
    WORD		guard1;		/* 0C - 02 */
} MemBlk;				/* Total size:  0E */

typedef MemBlk __far *	MemBlkPtr;


/* Memory high guard tailer.  Placed at end of each allocated block. */
typedef struct {
    unsigned long	guard1;
} MemHighGuard;

typedef MemHighGuard __far *MemHighGuardPtr;


/*
 * Memory allocation globals. 
 */
LOCAL WORD		MemID = 0;		/* Keep track of ID. */
LOCAL unsigned long	MemLocalFails = 0;
LOCAL BOOL		MemLocalFull = FALSE;	/* True when local heap full*/
#ifdef MEM_DEBUG
LOCAL unsigned long	MemInUse = 0;		/* Total bytes in use. */
LOCAL unsigned long	MemInUseMax = 0;	/* max in use at one time. */
LOCAL unsigned long	SmallMemInUse = 0;
LOCAL unsigned long	SmallMemInUseMax = 0;
#endif /* MEM_DEBUG */



/*
 * Allocate a memory block.
 * The file and line indicate where we are called from (for debugging)
 * but in pine these mostly point to a bottel neck routine and are
 * useless.
 */
MemPtr
_MemAlloc (MemSize size, char __far * file, int line)
{
    MemBlkPtr			pBlk;
    MemHighGuardPtr		pHG;
    HGLOBAL			hBlk;
    HLOCAL			hLBlk;
    UINT			totalSize;
    BYTE		__far *	pb;

    assert (size <= MEM_BLOCK_SIZE_MAX);
    

    /*
     * Calculate total size we need to allocate.
     */
    totalSize = (UINT)size + sizeof (MemBlk) + sizeof (MemHighGuard);
    
    
    pBlk = NULL;
    
    /*
     * If it's a small block and the local heap is not full, try 
     * allocating from the local heap. 
     */
    if (size <= SMALL_MEM_BOUNDRY && !MemLocalFull) {
	    
	/* Allocate block from local storage. */
	hLBlk = LocalAlloc (LMEM_MOVEABLE, totalSize);
	if (hLBlk != NULL) {

	    /* Lock block and dereference. */
	    pBlk = (MemBlkPtr) LocalLock (hLBlk);
	    if (pBlk != NULL) {
		pBlk->handle = hLBlk;
		pBlk->globalBlk = FALSE;
	    }
	    else 
	        LocalFree (hLBlk);
	}
	else {
	    ++MemLocalFails;
	    MemLocalFull = TRUE;
#ifdef MEM_DEBUG
	    if (MemDoDebug)
		fprintf (MemDebugFile, "Local Memory alloc failed, %lu fails, %lu bytes in use\n",
			MemLocalFails, SmallMemInUse);
#endif
	}
    }

    
    /* 
     * If it is a large block, or local alloc failed, we allocate from
     * global space. 
     */
    if (pBlk == NULL) {
	    
	/* Allocate block from global storage. */
	hBlk = GlobalAlloc (GMEM_MOVEABLE, totalSize);
	if (hBlk == NULL) 
	    return (NULL);


	/* Lock block and dereference. */
	pBlk = (MemBlkPtr) GlobalLock (hBlk);
	if (pBlk == NULL) {
	    GlobalFree (hBlk);
	    return (NULL);
	}
	pBlk->handle = hBlk;
	pBlk->globalBlk = TRUE;
    }


    
    /* Fill rest of header. */
    pBlk->guard0 = GUARD_LOW0;
    pBlk->size = size;
    pBlk->id = ++MemID;
    pBlk->guard1 = GUARD_LOW;

    
    /* Find address that will be returned to caller. */
    pb = (BYTE __far *) (pBlk + 1);

    
    /* Find high guard and fill. */
    pHG = (MemHighGuardPtr) (pb + size);
    pHG->guard1 = GUARD_HIGH;
    

    /* Debugging info... */
#ifdef MEM_DEBUG
    if (MemDoDebug) {
	if( !file ) file = "??";
	fprintf (MemDebugFile, "MemAlloc: addr(%lx) id(%u) size(%ld) global(%d)\n",
		pb, pBlk->id, (long)size, pBlk->globalBlk);
	fflush (MemDebugFile);
    }
    MemInUse += totalSize;
    if (MemInUse > MemInUseMax)
	MemInUseMax = MemInUse;
    if (size <= SMALL_MEM_BOUNDRY) {
	SmallMemInUse += totalSize;
	if (SmallMemInUse > SmallMemInUseMax)
	    SmallMemInUseMax = SmallMemInUse;
    }
#endif /* MEM_DEBUG */
	

    return ((MemPtr) pb);
}




/*
 * Free a block.
 */
int
_MemFree (MemPtr block, char __far *file, int line)
{
    MemBlkPtr		pBlk;
    MemHighGuardPtr	pHG;
    HGLOBAL		hBlk;
    HLOCAL		hLBlk;
    BOOL		brc;
    UINT		totalSize;
    
    if (block == NULL)
        return (0);


    /* Find header and high guard and check them. */
    pBlk = ((MemBlkPtr)block) - 1;
    pHG = (MemHighGuardPtr) ((char __far *)block + pBlk->size);
    
    totalSize = pBlk->size + sizeof (MemBlk) + sizeof (MemHighGuard);

    /* If these changed them someone wrote where the should not have. */
    assert (pBlk->guard0 == GUARD_LOW0);
    assert (pBlk->guard1 == GUARD_LOW);
    assert (pHG->guard1 == GUARD_HIGH);


    
#ifdef MEM_DEBUG    
    /* Deubgging info... */
    if (MemDoDebug) {
	if (pBlk->size <= SMALL_MEM_BOUNDRY && 
		SmallMemInUse == SmallMemInUseMax) 
	   fprintf (MemDebugFile, "Small memory usage is up to %lu\n", SmallMemInUseMax);
	if (MemInUse == MemInUseMax) 
	   fprintf (MemDebugFile, "Memory usage is up to %lu\n", MemInUseMax);
    }
    MemInUse -= totalSize;
    if (pBlk->size <= SMALL_MEM_BOUNDRY)
        SmallMemInUse -= totalSize;
    if (MemDoDebug) {
	fprintf (MemDebugFile, "MemFree: addr(%lx) id(%u)\n", 
		block, pBlk->id);
	fflush (MemDebugFile);
    }
#endif /* MEM_DEBUG */



    /*
     * Header indicates which block it came from
     */
    if (!pBlk->globalBlk) {
	/* Unlock block */
	hLBlk = pBlk->handle;
	brc = LocalUnlock (hLBlk);
	assert (!brc);

	/* And free block. */
	hLBlk = LocalFree (hLBlk);
	assert (hLBlk == NULL);
	MemLocalFull = FALSE;
    }
    else {
	/* Unlock block */
	hBlk = pBlk->handle;
	brc = GlobalUnlock (hBlk);
	assert (!brc);

	/* And free block. */
	hBlk = GlobalFree (hBlk);
	assert (hBlk == NULL);
    }
    return (0);
}




/*
 * Reallocate a memory block.  Simplistic approach.
 */
MemPtr
_MemRealloc (MemPtr block, MemSize size, char __far * file, int line)
{
    MemPtr	newBlock;
    
    
    newBlock = MemAlloc (size);
    if (newBlock == NULL)
	return (NULL);

    if (block != NULL) {
	_fmemcpy (newBlock, block , (size_t)MIN (size, MemBlkSize (block)));
	MemFree (block);
    }
	
    return (newBlock);
}
	
	

/*
 * Return the size of a memory block
 */
MemSize
MemBlkSize (MemPtr block)
{
    MemBlkPtr			pBlk;

    if (block == NULL) return (0);
    pBlk = ((MemBlkPtr)block) - 1;
    assert (pBlk->guard1 == GUARD_LOW);

    return (pBlk->size);
}


#ifdef MEM_DEBUG
struct testblock {
    struct testblock	__far * prev;
    HLOCAL			h;
};



void
MemATest (void)
{
    void    __near		*n;
    struct testblock __far	*p;
    struct testblock __far	*pnew;
    HLOCAL			hl;
    int				bcount;
    UINT			segment, start, end;
    void    __far		*f;
    HGLOBAL			hg;
    DWORD			dw;
    LOCALINFO			li;
    UINT			DataSeg;
    
#if 0  
    hg = GlobalAlloc (GMEM_FIXED, HEAP_SIZE);	/* Allocate global block */
    if (hg == NULL)
	return;
    f = GlobalLock (hg);			/* Lock and get pointer. */
    if (f == NULL) 
	goto Fail1;
    segment = (UINT) GET_SEGMENT (f);		/* Get segment and offsets. */
    start = (UINT) GET_OFFSET (f);
    end = start + HEAP_SIZE - 1;
    start += 16;
    if (!LocalInit (segment, start, end))		/* Init it as the local heap*/
	goto Fail2;
#endif
#if 0
    __asm MOV DataSeg,DS;			/* Get current DS. */
    __asm MOV DS,segment;			/* Set DS to new heap. */
    hl = LocalAlloc (0, SMALL_MEM_BOUNDRY);	/* Now allocate something. */
    __asm MOV DS,DataSeg;			/* Restore DS. */
    if (hl == NULL) 
	    return;
    n = LocalLock (hl);				/* Find where it is. */
    f = (void __far *)n;
    segment = GET_SEGMENT(f);			/* What Segment. */
    dw = GlobalHandle (segment);
    hg = (HGLOBAL) (dw & 0xffff);
    if (hg == NULL)
	    return;
    
    li.dwSize = sizeof (li);			/* What size. */
    if (!LocalInfo (&li, hg))
	    return;
    
    dw = GlobalSize (hg);
    f = GlobalLock (hg);
    GlobalUnlock (hg);
    
    LocalUnlock (hl);
    LocalFree (hl);

    
#endif
    
    
	
	
    p = NULL;
    pnew = NULL;
    bcount = 0;
	
    do {
	hl = LocalAlloc (0, SMALL_MEM_BOUNDRY);
	if (hl != NULL) {
	    ++bcount;
	    n = LocalLock (hl);
	    pnew = (struct testblock __far*) n;
	    pnew->h = hl;
	    pnew->prev = p;
	    p = pnew;
        }
    } while (hl != NULL);
    
    
    if (MemDebugFile != NULL)
	fprintf (MemDebugFile, "Allocated %d blocks of size %d\n",
	    bcount, SMALL_MEM_BOUNDRY);
			
    while (p != NULL) {
	pnew = p->prev;
	hl = p->h;
	LocalUnlock (hl);
	LocalFree (hl);
	p = pnew;
    }
    fflush (MemDebugFile);
#if 0 
Fail2:	GlobalUnlock (hg);
Fail1:	GlobalFree (hg);
#endif
	return;
}
#endif /* MEM_DEBUG */

#else /* SEGHEAP */

/* Copyright (C) Stephen Chung, 1991-1992.  All rights reserved. */


#define MAGIC           0x42022667
#define MAGIC2		0x56743296

typedef struct MemoryStruct {
    long int		magic;
    void far		*page;
    WORD		id;
    MemSize		size;
    BOOL		allocated;
    struct MemoryStruct far *next, far *prev;
    long int		magic2;
} MEMHEADER;

typedef struct PageHeaderStruct {
    long int		magic;
    HANDLE		handle;
    WORD		id;
    MemSize		size;
    MemSize		used;
    MemSize		overhead;
    MEMHEADER far	*data, far *empty;
    struct PageHeaderStruct far *next, far *prev;
    long int		magic2;
} MEMPAGEHEADER;

typedef struct {
    MEMPAGEHEADER far *pages;
    int nr_pages;
} MAINMEMHEADER;

#define PAGESIZE        (6 * 1024)
#define USEABLESIZE     (PAGESIZE - sizeof(MEMPAGEHEADER) - sizeof(MEMHEADER))


LOCAL MAINMEMHEADER	MemHeader = { NULL, 0 };
LOCAL WORD		MemID = 0;		/* Keep track of ID. */
LOCAL WORD		PageID = 0;
#ifdef MEM_DEBUG
LOCAL unsigned long	MemInUse = 0;		/* Total bytes in use. */
LOCAL unsigned long	MemInUseMax = 0;	/* max in use at one time. */
LOCAL unsigned long     PageMemInUse = 0;
LOCAL unsigned long	PageMemInUseMax = 0;
#endif /* MEM_DEBUG */



static MEMPAGEHEADER far *
AddPage(MemSize n)
{
    void far *cp;
    MEMHEADER far *mp;
    MEMPAGEHEADER far *p;
    HANDLE handle = NULL;

    handle = GlobalAlloc(GHND, n);
    if (handle == NULL) {
#ifdef MEM_DEBUG
	if (MemDoDebug >= 1) 
	    fprintf (MemDebugFile, "Out of memory: allocating %d bytes", n);
#endif
        return (NULL);
    }

    if (MemHeader.pages == NULL || MemHeader.nr_pages <= 0) {
        p = MemHeader.pages = (MEMPAGEHEADER far *) GlobalLock(handle);
        p->prev = NULL;
    } else {
        for (p = MemHeader.pages; p->next != NULL; p = p->next);
        p->next = (MEMPAGEHEADER far *) GlobalLock(handle);
        p->next->prev = p;
        p = p->next;
    }

    p->magic = MAGIC;
    p->handle = handle;
    p->next = NULL;
    p->id = PageID++;
    p->size = n;
    p->used = 0;
    p->overhead = sizeof(MEMPAGEHEADER) + sizeof(MEMHEADER);
    p->magic2 = MAGIC2;

    cp = ((char far *) p) + sizeof(MEMPAGEHEADER);
    mp = (MEMHEADER far *) cp;

    p->data = p->empty = mp;

    mp->magic = 0L;
    mp->magic2 = 0L;
    mp->allocated = FALSE;
    mp->page = p;
    mp->size = p->size - p->overhead;
    mp->next = mp->prev = NULL;

    MemHeader.nr_pages++;

#ifdef MEM_DEBUG
    if (MemDoDebug) {
	fprintf (MemDebugFile, "PageAlloc: addr(%lx) id(%u) size(%ld) global(%d)\n",
		p, p->id, (long)n, 1);
	fflush (MemDebugFile);
    }
    PageMemInUse += n;
    if (PageMemInUse > PageMemInUseMax)
	PageMemInUseMax = PageMemInUse;
#endif /* MEM_DEBUG */
    

    return (p);
}



static void 
DeletePage (MEMPAGEHEADER far *p)
{
#ifdef MEM_DEBUG    
    /* Deubgging info... */
    if (MemDoDebug) {
	if (PageMemInUse == PageMemInUseMax) 
	   fprintf (MemDebugFile, "Page usage is up to %lu\n", PageMemInUseMax);
    }
    PageMemInUse -= p->size;
    if (MemDoDebug) {
	fprintf (MemDebugFile, "PageFree: addr(%lx) id(%u)\n", 
		p, p->id);
	fflush (MemDebugFile);
    }
#endif /* MEM_DEBUG */


    if (p->next == NULL && p->prev == NULL) {
        MemHeader.pages = NULL;
        MemHeader.nr_pages = 0;
	GlobalUnlock (p->handle);
        GlobalFree (p->handle);
    } else {
        if (p == MemHeader.pages) MemHeader.pages = p->next;
        MemHeader.nr_pages--;

        if (p->prev != NULL) p->prev->next = p->next;
        if (p->next != NULL) p->next->prev = p->prev;

	GlobalUnlock (p->handle);
        GlobalFree (p->handle);
    }
}


/* 
 * Segmented heap memory allocation. 
 */

MemPtr
_MemAlloc (MemSize n, char __far * file, int line)
{
    MEMPAGEHEADER far *p;
    MEMHEADER far *mp;
    char far *cp;

    if (n >= 65535) {
	assert (n < 65535);
        return (NULL);
    }

    /* Larger than page size? */

    if (n > USEABLESIZE) {
	p = AddPage(n + sizeof(MEMPAGEHEADER) + sizeof(MEMHEADER));
	if (p == NULL)
	    return (NULL);

        mp = p->data;
        mp->magic = MAGIC;
	mp->magic2 = MAGIC2;
	mp->id = MemID++;
        mp->allocated = TRUE;
	

        p->used = n;
        p->empty = NULL;

        cp = ((char far *) mp) + sizeof(MEMHEADER);
#ifdef MEM_DEBUG
	if (MemDoDebug) {
	    fprintf (MemDebugFile, "MemAlloc: addr(%lx) id(%u) size(%ld) global(%d)\n",
		    cp, mp->id, (long)n, 0);
	    fflush (MemDebugFile);
	}
	MemInUse += n;
	if (MemInUse > MemInUseMax)
	    MemInUseMax = MemInUse;
#endif /* MEM_DEBUG */
        return ((MemPtr) cp);
    }


    /* Search for the hole */

    for (p = MemHeader.pages; p != NULL; p = p->next) {
        /* Scan the chains */
        if (p->size - p->used - p->overhead <= 0) continue;
		if (p->empty == NULL) continue;

        for (mp = p->empty; mp != NULL; mp = mp->next) {
            if (!mp->allocated && mp->size >= n) break;
        }

        if (mp != NULL) break;
    }

    /* New page needed? */

    if (p == NULL) {
        p = AddPage(PAGESIZE);
	if (p == NULL)
	    return (NULL);
	mp = p->data;
    }

    /* Do we need to break it up? */

    if (mp->size - n > sizeof(MEMHEADER)) {
        MEMHEADER far *mp2;

        cp = ((char far *) mp) + n + sizeof(MEMHEADER);
        mp2 = (MEMHEADER far *) cp;

        mp2->magic = 0L;
	mp2->magic2 = 0L;
        mp2->allocated = FALSE;
        mp2->page = p;
        mp2->size = mp->size - n - sizeof(MEMHEADER);

        mp2->next = mp->next;
        mp2->prev = mp;
        if (mp->next != NULL) mp->next->prev = mp2;
        mp->next = mp2;


        p->overhead += sizeof(MEMHEADER);

        mp->size = n;
    }

    mp->magic = MAGIC;
    mp->magic2 = MAGIC2;
    mp->allocated = TRUE;
    mp->id = MemID++;

    p->used += n;
    cp = ((char far *) mp) + sizeof(MEMHEADER);


    /* Debugging info... */
#ifdef MEM_DEBUG
    if (MemDoDebug) {
	fprintf (MemDebugFile, "MemAlloc: addr(%lx) id(%u) size(%ld) global(%d)\n",
		cp, mp->id, (long)n, 0);
	fflush (MemDebugFile);
    }
    MemInUse += n;
    if (MemInUse > MemInUseMax)
	MemInUseMax = MemInUse;
#endif /* MEM_DEBUG */
    
    
    
    
    /* Search for the next empty hole */

    for (; mp != NULL; mp = mp->next) {
        if (!mp->allocated && mp->size > 0) break;
    }

    p->empty = mp;

    return ((MemPtr) cp);
}



/*
 * Segmented heap memory free.
 */
int
_MemFree (MemPtr vp, char __far *file, int line)
{
    MEMPAGEHEADER far *p;
    MEMHEADER far *mp, far *mp2;
    char far *cp;
    
    if (vp == NULL)
        return (0);
    

    cp = ((char far *) vp) - sizeof(MEMHEADER);
    mp = (MEMHEADER far *) cp;

    if (mp->magic != MAGIC || mp->magic2 != MAGIC2|| !mp->allocated) {
	assert (mp->magic == MAGIC);
	assert (mp->magic2 == MAGIC2);
	assert (mp->allocated);
	return (-1);
    }
    
#ifdef MEM_DEBUG    
    /* Deubgging info... */
    if (MemDoDebug) {
	if (MemInUse == MemInUseMax) 
	   fprintf (MemDebugFile, "Memory usage is up to %lu\n", MemInUseMax);
    }
    MemInUse -= mp->size;
    if (MemDoDebug) {
	fprintf (MemDebugFile, "MemFree: addr(%lx) id(%u)\n", vp, mp->id);
	fflush (MemDebugFile);
    }
#endif /* MEM_DEBUG */
    

    p = (MEMPAGEHEADER far *) mp->page;
    p->used -= mp->size;

    mp->magic = 0L;
    mp->magic2 = 0L;
    mp->allocated = FALSE;

    /* Merge? */

    mp2 = mp->prev;

    if (mp2 != NULL && !mp2->allocated) {
        mp2->next = mp->next;
        if (mp->next != NULL) mp->next->prev = mp2;
        mp2->size += mp->size + sizeof(MEMHEADER);

        p->overhead -= sizeof(MEMHEADER);

        mp = mp2;
    }

    mp2 = mp->next;

    if (mp2 != NULL && !mp2->allocated) {
        mp->next = mp2->next;
        if (mp2->next != NULL) 
	    mp2->next->prev = mp;

        mp->size += mp2->size + sizeof(MEMHEADER);

	p->overhead -= sizeof(MEMHEADER);
    }

    if (mp->prev == NULL && mp->next == NULL) {
        DeletePage(p);
    } else {
        if (p->empty == NULL || mp < p->empty) p->empty = mp;
    }
    return (0);
}



MemPtr
_MemRealloc (MemPtr p, MemSize n, char __far *file, int line)
{
    MEMHEADER far *mp;
    char far *cp;

    if (p != NULL) {
	/* Block already large enough? */
	cp = ((char far *) p) - sizeof(MEMHEADER);
	mp = (MEMHEADER far *) cp;

	if (mp->magic != MAGIC || mp->magic2 != MAGIC2) {
	    assert (mp->magic == MAGIC);
	    assert (mp->magic2 == MAGIC2);
	    return (p);
	}

	if (mp->size >= n) return (p);      /* No need to do anything */
    }
    /* Else swap to another block */

    cp = MemAlloc (n);
    if (cp == NULL)
	return (NULL);

    if (p != NULL) {
	_fmemcpy(cp, p, (size_t)((mp->size >= n) ? n : mp->size));
	MemFree (p);
    }

    return ((void far *) cp);
}



MemSize
MemBlkSize (MemPtr p)
{
    MEMHEADER far *mp;
    char far *cp;

    if (p == NULL) return (0);
    cp = ((char far *) p) - sizeof(MEMHEADER);

    mp = (MEMHEADER far *) cp;

    if (mp->magic != MAGIC || mp->magic2 != MAGIC2) {
	assert (mp->magic == MAGIC);
	assert (mp->magic2 == MAGIC2);
	return (0);
    }

    return (mp->size);
}


#if 0
MemPtr
MemDup (void far *p)
{
    unsigned int len;
    void far *p1;

    len = MgetBlkSize (p);
    p1 = MemAlloc (len);
    if (p1 != NULL)
	_fmemcpy(p1, p, len);

    return (p1);
}


void 
MemoryStatistics (long int *allocated, long int *used, long int *overhead)
{
    MEMPAGEHEADER far *p;

    *allocated = *used = *overhead = 0L;

    for (p = MemHeader.pages; p != NULL; p = p->next) {
        *allocated += p->size;
        *used += p->used;
        *overhead += p->overhead;
    }
}
#endif


void 
MemFreeAll (void)
{
    MEMPAGEHEADER far *p, far *p1;

    for (p = MemHeader.pages; p != NULL; ) {
        p1 = p->next;
	GlobalUnlock (p->handle);
        GlobalFree (p->handle);
        p = p1;
    }

    MemHeader.pages = NULL;
    MemHeader.nr_pages = 0;
}


#ifdef MEM_DEBUG

/* For debugging purposes...  not very pretty */

void PrintMemoryChains(void)
{
    MEMPAGEHEADER far *p;
	MEMHEADER far *mp;
	char far *cp;
    char buffer[100];

	/* Block already large enough? */


    for (p = MemHeader.pages; p != NULL; p = p->next) {
        for (mp = p->data; mp != NULL; mp = mp->next) {
            fprintf (MemDebugFile, "%Fp | %u | %s", mp, mp->size, mp->allocated ? "Alloc" : "Free");
        }
    }
}

#endif /* DEBUG */

#endif /* ifdef SEGHEAP */



void 
AssertFail	(char *str, char *file, int line, int msgbox)
{
    /* static to avoid risk of stack overflow */
    static int	inAssert	= 0;
    static int	doBreak		= 1;
    char	*	filename;
    int			ret;



    /* for now, strip off path from filename */
    filename = _fstrrchr(file, '\\');
    if (filename)
	    filename++;
    else
	    filename = file;

    wsprintf(TempBuf, "Assert(%s) failed!  %s:%d\n", 
			    str, filename, line);

    inAssert++;


retry:

    /*	Unfortunately, there are certain times when attempting to
     *	display a message box will cause the system to crash (e.g.,
     *	when handling certain messages in a WndProc).
     *
     *	Message box was previously TaskModal, but this didn't work
     *	well because the client AIM could keep sending requests.
     *	SystemModal shuts the whole system down but at least it
     *	guarantees some degree of consistency, and makes debugging
     *	a bit easier.
     */
    ret = MessageBox (NULL, TempBuf, NULL, 
				    MB_ABORTRETRYIGNORE | MB_SYSTEMMODAL );


    if (ret == IDABORT) {
	    ret = MessageBox(NULL, 
			    "AbortIng may not properly free resources.  Are you sure?",
			    "Assertion Abort",
			    MB_YESNO | MB_TASKMODAL | MB_ICONSTOP);

	    if (ret == IDYES) {
		    /*
		     *	Cause a GPF in case DrWatson is running
		     */
		    char *p = NULL;
		    *p = 1;
	    }
	    else 
		    goto retry;
    }

    /* retry is not (and will never be) hooked up, but it's
     * easier to use the standard dialog box than create
     * our own.  if retry is selected, just report the
     * error again.
     */
    if (ret == IDRETRY)
	    goto retry;
    inAssert--;
}
    if (n >= 65535) {
	assert (n < 65535);
        return (NULL);
    }

    /* Larger than page size? */

    if (n > USEABLESIZE) {
	p = AddPage(n + sizeof(MEMPAGEHEADER) + sizeof(MEMHEADER));
	if (p == NULL)
	    return (NULL);

        mp = p->data;
        mp->magic = MAGIC;
	mp->magic2 = MAGIC2;
	mp->id = MemID++;
        mp->allocated = DarkNET-1.08/pico.BBS/os_win.c                                                                         644   21270   21270        34164  5672463053  11114                                                                                                                                                                                                                                                                                                                                                                      #line 2 "os_win.c"		/* So compiler knows original name of this file.*/
/*
 * $Id: os_win.c,v 4.8 1994/09/27 15:59:37 mikes Exp $
 *
 * Program:	Operating system dependent routines - MS Windows 3.1
 *
 *
 * Tom Unger
 * Networks and Distributed Computing
 * Computing and Communications
 * University of Washington
 * Administration Builiding, AG-44
 * Seattle, Washington, 98195, USA
 * Internet: mikes@cac.washington.edu
 *
 * Please address all bugs and comments to "pine-bugs@cac.washington.edu"
 *
 * Copyright 1991-1994  University of Washington
 *
 *  Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee to the University of
 * Washington is hereby granted, provided that the above copyright notice
 * appears in all copies and that both the above copyright notice and this
 * permission notice appear in supporting documentation, and that the name
 * of the University of Washington not be used in advertising or publicity
 * pertaining to distribution of the software without specific, written
 * prior permission.  This software is made available "as is", and
 * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
 * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
 * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
 * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 * Pine and Pico are trademarks of the University of Washington.
 * No commercial use of these trademarks may be made without prior
 * written permission of the University of Washington.
 *
 *
 * Notes:
 *      - mouse support added (mss, 921215)
 *
 *  Portions of this code derived from MicroEMACS 3.10:
 *
 *	MSDOS.C:	Operating specific I/O and Spawning functions
 *			under the MS/PCDOS operating system
 *			for MicroEMACS 3.10
 *			(C)opyright 1988 by Daniel M. Lawrence
 *
 */

/*#include	<windows.h>*/

#include 	<stdio.h>
#include	<errno.h>
#include	<signal.h>
#include	<setjmp.h>
#include	<time.h>
#include	<fcntl.h>
/*#include	<io.h>*/
/*#include	<bios.h>*/

#include	"osdep.h"
#include	"estruct.h"
#include	"efunc.h"
#include        "edef.h"
#include        "pico.h"
#include	"dos_gen.h"

#ifdef	MOUSE

#define MOUSE_BUTTONS		3
					 
#endif	/* MOUSE */

/*
 * Internal functions...
 */
static int	MapMSKEYtoPK (int c);
static int	ProcessMouse(MEvent *, unsigned int *);
static void	invert_label(int, MENUITEM *);
int		ttopen ();
int		ttclose ();


/*
 * Include generic DOS/Windows routines
 */
#include	"dos_gen.c"


#define	MARGIN			8	/* size of minimim margin and	*/
#define	SCRSIZ			64	/* scroll size for extended lines */



/*
 * Standard terminal interface dispatch table. Fields point to functions
 * that operate the terminal.  All these functions live in mswin.c, but
 * this structure is defined here because it is specific to pico.
 */
TERM    term    = {
        0,
        0,
	MARGIN,
	SCRSIZ,
        ttopen,
        ttclose,
        mswin_getc,
	mswin_putc,
        mswin_flush,
        mswin_move,
        mswin_eeol,
        mswin_eeop,
        mswin_beep,
	mswin_rev
};



int ttresize (row, col)
{
    resize_pico (row-1, col);
    return (0);
}



/*
 * This function is called once to set up the terminal device streams.
 */
int
ttopen()
{
    int rows, columns;

    
    mswin_getscreensize (&rows, &columns);
    term.t_nrow = rows - 1;
    term.t_ncol = columns;
    term.t_scrsiz = (columns * 2) / 3;
    
    /*
     * Do we implement optimized character insertion and deletion?
     * o_insert() and o_delete()
     */
    inschar  = delchar = FALSE;
    revexist = TRUE;
    
    mswin_setresizecallback (ttresize);
    
    

#if	MOUSE
    init_mouse();
#else	/* !MOUSE */
    mexist = 0;
#endif	/* MOUSE */
    return(1);
}


#ifdef	MOUSE
/* 
 * init_mouse - check for and initialize mouse driver...
 */
int
init_mouse()
{
    nbuttons = MOUSE_BUTTONS;
    return (mexist = TRUE);		/* Mouse always exists under windows */
}


/*
 * mouseon - call made available for programs calling pico to turn ON the
 *           mouse cursor.
 */
void
mouseon()
{
}


/*
 * mouseoff - call made available for programs calling pico to turn OFF the
 *           mouse cursor.
 */
void
mouseoff()
{
}
#endif



/*
 * This function gets called just before we go back home to the command
 * interpreter.
 */
int
ttclose()
{
    mswin_clearresizecallback (ttresize);
    return(1);
}



/*
 * Flush terminal buffer. Does real work where the terminal output is buffered
 * up. A no-operation on systems where byte at a time terminal I/O is done.
 */
int
ttflush()
{
    return(1);
}



/*
 * Read in a key.
 * Do the standard keyboard preprocessing. Convert the keys to the internal
 * character set.  Resolves escape sequences and returns no-op if global
 * timeout value exceeded.
 */
int
GetKey ()
{
    int			ch = 0;
    unsigned int	lch;
    long		timein;
    int			controlKey;
    MEvent		mouse;
    
    
    controlKey = FALSE;			/* xxx Don't know how to tell. */
    ch = NODATA;

    
    timein = time(0L);


    /*
     * Main character processing loop.
     */
    while((ch = mswin_getc ()) == MSWIN_KEY_NODATA) {

#if MOUSE
	/* Check Mouse.  If we get a mouse event, convert to char
	 * event and return that. */
	if (checkmouse (&ch)) {
	    curwp->w_flag |= WFHARD;
	    return (ch);
	}
#endif /* MOUSE */


	/* Check Timeout. */
	if(time(0L) >= timein+timeout) 
	    return(NODATA);
    }

    
    return (MapMSKEYtoPK (ch));
}



static int
MapMSKEYtoPK (int c)
{
    switch (c) {
	case MSWIN_KEY_UP:		return (K_PAD_UP);
	case MSWIN_KEY_DOWN:		return (K_PAD_DOWN);
	case MSWIN_KEY_RIGHT:		return (K_PAD_RIGHT);
	case MSWIN_KEY_LEFT:		return (K_PAD_LEFT);
	case MSWIN_KEY_PREVPAGE:	return (K_PAD_PREVPAGE);
	case MSWIN_KEY_NEXTPAGE:	return (K_PAD_NEXTPAGE);
	case MSWIN_KEY_HOME:		return (K_PAD_HOME);
	case MSWIN_KEY_END:		return (K_PAD_END);
	case MSWIN_KEY_DELETE:		return (K_PAD_DELETE);
	case MSWIN_KEY_F1:		return (F1);
	case MSWIN_KEY_F2:		return (F2);
	case MSWIN_KEY_F3:		return (F3);
	case MSWIN_KEY_F4:		return (F4);
	case MSWIN_KEY_F5:		return (F5);
	case MSWIN_KEY_F6:		return (F6);
	case MSWIN_KEY_F7:		return (F7);
	case MSWIN_KEY_F8:		return (F8);
	case MSWIN_KEY_F9:		return (F9);
	case MSWIN_KEY_F10:		return (F10);
	case MSWIN_KEY_F11:		return (F11);
	case MSWIN_KEY_F12:		return (F12);
	case MSWIN_KEY_NODATA:		return (NODATA);
    }
    
    /* Control keys. */
    if (c < ' ') 
	return (CTRL | (c + '@'));
    
    /* Normal keys. */
    return (c);
}





#if	MOUSE
/* 
 * checkmouse - Check mouse and return maped command.
 *
 *	EXPORTED to pico.
 */
int	
checkmouse (unsigned int *ch)
{
    static int	oindex;		/* Index of previous mouse down. */
    int		k;		/* current bit/button of mouse */
    int		mcol;		/* current mouse column */
    int		mrow;		/* current mouse row */
    int		down;		/* TRUE when mouse down event. */
    int		rv = 0;		/* TRUE when we have something to return. */
    MEvent      mouse;

    
    
    *ch = 0;
    
    /* Mouse installed? */
    if (!mexist)
	return (FALSE);

    if (!WinGetMEvent (&mouse)) 
	return (FALSE);


    /* Location of mouse event. */
    mcol = mouse.nColumn;
    mrow = mouse.nRow;


    /* Only pay attation to button 1. */
    if (mouse.button == 1) {
	int i = 0;

	/* Mouse down or up? */
	down = FALSE;
	if (mouse.event == MEVENT_MOUSEDOWN) {	/* button down */
	    down = TRUE;
	    oindex = -1;	/* No Previous mouse down. */
        }

	
	/* In special screen region? */
	if(mfunc.action && M_ACTIVE(mrow, mcol, &mfunc)){
	    unsigned long r;

	    r = (*mfunc.action)(down, mrow, mcol);
	    if (r & 0xffff){
		*ch = (unsigned) ((r>>16) & 0xffff);
		rv  = TRUE;
	    }
	}
	else{
		
	    /* In any of the menuitems? */
	    while(1){	/* see if we understand event */
		if(i >= 12){
		    i = -1;	/* Not Found. */
		    break;
		}

		if(M_ACTIVE(mrow, mcol, &menuitems[i]))
		    break;	/* Found. */

		i++;		/* Next. */
	    }

	    /* Now, was that a mouse down or mouse up? */
	    if (down) {				/* button down */
		oindex = i;			/* remember where */
		if(i != -1)			/* invert label */
		    invert_label (1, &menuitems[i]);
	    }
	    else {				/* button up */
		if (oindex != -1) {		/* If up in menu item. */
		    if (i == oindex){		/* And same item down in. */
			*ch = menuitems[i].val; /* Return menu character. */
			rv = 1;
		    }
		}
	    }
	}

	/* If this is mouse up AND there was a mouse down in a menu item
	 * then uninvert that menu item */
	if(!down && oindex != -1)
	  invert_label(0, &menuitems[oindex]);	/* restore label */
    }
    return(rv);
}


/*
 * invert_label - highlight the label of the given menu item.
 */
static void
invert_label(state, m)
int state;
MENUITEM *m;
{
    int			i, j, r, c, p;
    char		*lp;
    int			old_state;
	int			wasShown;

    if(m->val == mnoop)
      return;

  
	mswin_getpos (&r, &c);			/* get cursor position */
	wasShown = mswin_showcursor (0);
    old_state = mswin_getrevstate ();
    (*term.t_move)(m->tl.r, m->tl.c);
    (*term.t_rev)(state);

	for(i = m->tl.r; i <= m->br.r; i++) {
      for(j = m->tl.c; j <= m->br.c; j++) {
        if(i == m->lbl.r && j == m->lbl.c){	/* show label?? */
	      lp = m->label;
	      while(*lp && j++ < m->br.c)
	        (*term.t_putchar)(*lp++);

	      continue;
	    }
	    else
	      (*term.t_putchar)(' ');
      }
    }

    (*term.t_rev)(old_state);
	mswin_move (r, c);
	mswin_showcursor (wasShown);
}
#endif	/* MOUSE */



/*
 * alt_editor - fork off an alternate editor for mail message composition
 *
 */
int
alt_editor(int f, int n)
{
    char   eb[NLINE];				/* buf holding edit command */
    char   *fn;					/* tmp holder for file name */
    char   *writetmp();
    int	   status;
    int	   done;
    int	   rc;


    if(Pmaster == NULL)
      return(-1);

    if(gmode&MDSCUR){
	emlwrite("Alternate editor not available in restricted mode", NULL);
	return(-1);
    }

    if(Pmaster->alt_ed == NULL){
	if(!(gmode&MDADVN)){
	    emlwrite("\007Unknown Command",NULL);
	    return(-1);
	}
	
	/* Guess which editor they want. */
	if(getenv("EDITOR"))
	  strcpy(eb, (char *)getenv("EDITOR"));
	else
	  *eb = '\0';
  
	done = FALSE;
	while(!done){
	    rc = mlreplyd("Which alternate editor ? ",eb,NLINE,QDEFLT,NULL);

	    switch(rc){
	      case ABORT:
		return(-1);
	      case HELPCH:
		emlwrite("no alternate editor help yet", NULL);

/* take sleep and break out after there's help */
		sleep(3);
		break;
	      case (CTRL|'L'):
		sgarbf = TRUE;
		update();
		break;
	      case TRUE:
	      case FALSE:			/* does editor exist ? */
		if(*eb == '\0'){		/* leave silently? */
		    mlerase();
		    return(-1);
		}

		done++;
		break;
	      default:
		break;
	    }
	}
    }
    else
      strcpy(eb, Pmaster->alt_ed);

    if((fn=writetmp(0, 1)) == NULL){		/* get temp file */
	emlwrite("Problem writing temp file for alt editor", NULL);
	return(-1);
    }

    strcat(eb, " ");
    strcat(eb, fn);
    
    emlwrite("Waiting for alternate editor to finish...", NULL);
    
    status = mswin_exec_and_wait ("alternate editor", eb);

    switch (status) {

    case 0:
	/*
	 * Success:  replace edited text with new text 
	 */
	curbp->b_flag &= ~BFCHG;	/* make sure old text gets blasted */
	readin(fn, 0);			/* read new text overwriting old */
	unlink(fn);			/* blast temp file */
	curbp->b_flag |= BFCHG;		/* mark dirty for packbuf() */
	ttopen();			/* reset the signals */
	refresh(0, 1);			/* redraw */
	return(0);

	
	/*
	 * Possible errors.
	 */
    case -1:
	/* Failed to map return from WinExec to a HTASK. */
	emlwrite("Problem finding alternet editor task handle.", NULL);
	return (-1);
	
    case -2:
	/* User decided to abandon the alternate editor.*/
	emlwrite("Alternate editor abandoned.", NULL);
	return (-1);

	
	/*
	 * Positive error codes are from WinExec.  The _really_ common
	 * ones get interpreted.
	 */
    case 2:
    case 3:
	emlwrite("Alternate editor %s not found.", eb);
	return (-1);
	
    case 8:
	emlwrite("Not enough memory to run alternate editor.", NULL);
	return (-1);
	
    default:
	emlwrite("Error %d starting alternate editor.",(void *)status);
	return (-1);
    }
    return (-1);
}




/*
 *  bktoshell - suspend and wait to be woken up
 *
 *  NOTE:  Not yet used under WINDOWS.
 */
int
bktoshell()
{
    return (0);
}


/*
 * P_open - run the given command in a sub-shell returning a file pointer
 *	    from which to read the output
 *
 * note:
 *	For OS's other than unix, you will have to rewrite this function.
 *	Hopefully it'll be easy to exec the command into a temporary file, 
 *	and return a file pointer to that opened file or something.
 *
 * xxx Need to figure out how to do this in windows.
 */
FILE *P_open(c)
char *c;
{
    return (NULL);
}


/*
 * P_close - close the given descriptor
 *
 */
P_close(fp)
FILE *fp;
{
}







/*
 * FileBrowse - display contents of given directory dir
 *
 *	    intput:  
 *		     dir points to initial dir to browse.
 *		     fn  initial file name. 
 *		     flags
 *
 *         returns:
 *                   dir points to currently selected directory (without
 *			 trailing seperator character).
 *                   fn  points to currently selected file
 *                   sz  points to size of file if ptr passed was non-NULL
 *
 *                   1 if a file's been selected
 *                   0 if no files seleted
 *                  -1 if there where problems
 */
FileBrowse(dir, fn, sz, flags)
char *dir, *fn, *sz;			/* dir, name and optional size */
int  flags;
{
    struct stat sbuf;
    int			rc;
    char		lfn[NFILEN];
    
    if (flags & FB_SAVE) {
	rc = mswin_savefile (dir, fn, NFILEN);
    }
    else {
	*fn = '\0';				/* No initial file names for 
						 * open. */
	rc = mswin_openfile (dir, fn, NFILEN);
    }
    if (rc == 0) {
	if (sz != NULL) {
	    /* build full path to stat file. */
	    strcpy (lfn, dir);
	    strcat (lfn, S_FILESEP);
	    strcat (lfn, fn);
	    if (stat (fn, &sbuf) < 0) 
		 strcpy (sz, "0");
	    else 
		 strcpy (sz, prettysz (sbuf.st_size));
	}
	return (1);
    }
    return (0);
}



ResizeBrowser ()
{
    return (0);
}
se MSWIN_KEY_F1:		return (F1);
	case MSWIN_KEY_F2:		return (F2);
	case MSWIN_KEY_F3:		return (F3);
	case MSWIN_KEY_F4:		return (F4);
	case MSWIN_KEY_F5:		return (F5);
	case MSWIN_KEY_F6:		return (F6);
	case MSWIN_KEY_F7:		return (F7);
	case MSWIN_KEY_F8:		return (F8);
	case MSWIN_KEY_F9:		return (F9);
	case MSWIN_KEY_F10:		return (F10);
	case MSWIN_KEY_F11:		return (F11);
	case MSWIN_KEY_F12:	DarkNET-1.08/pico.BBS/os_win.h                                                                         644   21270   21270         5547  5672463053  11104                                                                                                                                                                                                                                                                                                                                                                      #line 2 "os_win.h"
/*
 * $Id: os_win.h,v 4.3 1994/09/22 21:59:57 mikes Exp $
 *
 * Program:	Operating system dependent routines - Ultrix 4.1
 *
 *
 * Michael Seibel
 * Networks and Distributed Computing
 * Computing and Communications
 * University of Washington
 * Administration Builiding, AG-44
 * Seattle, Washington, 98195, USA
 * Internet: mikes@cac.washington.edu
 *
 * Please address all bugs and comments to "pine-bugs@cac.washington.edu"
 *
 * Copyright 1991-1994  University of Washington
 *
 *  Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee to the University of
 * Washington is hereby granted, provided that the above copyright notice
 * appears in all copies and that both the above copyright notice and this
 * permission notice appear in supporting documentation, and that the name
 * of the University of Washington not be used in advertising or publicity
 * pertaining to distribution of the software without specific, written
 * prior permission.  This software is made available "as is", and
 * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
 * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
 * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
 * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 * Pine and Pico are trademarks of the University of Washington.
 * No commercial use of these trademarks may be made without prior
 * written permission of the University of Washington.
 *
 */

#ifndef	OSDEP_H
#define	OSDEP_H

#include	<stdlib.h>
#include	<string.h>
#include	<dos.h>
#include	<direct.h>
#include	<search.h>
#undef	CTRL
#include	<ctype.h>
#include	<sys/types.h>
#include	<sys/stat.h>


/* define machine specifics */
#define	IBMPC	1



/*
 * type qsort expects
 */
#define	QSType	void
#define QcompType const void


/*
 * File name separators, char and string
 */
#define	C_FILESEP	'\\'
#define	S_FILESEP	"\\"


/*
 * What and where the tool that checks spelling is located.  If this is
 * undefined, then the spelling checker is not compiled into pico.
 */
#undef	SPELLER


/*
 * Mode passed chmod() to make tmp files exclusively user read/write-able
 */
#define	MODE_READONLY	(S_IREAD | S_IWRITE)


#ifdef	maindef
/*	possible names and paths of help files under different OSs	*/

char *pathname[] = {
	"picorc",
	"pico.hlp",
	"\\usr\\local\\",
	"\\usr\\lib\\",
	""
};

#define	NPNAMES	(sizeof(pathname)/sizeof(char *))

jmp_buf got_hup;

extern struct KBSTREE *kpadseqs = NULL;

#endif

#include "mswin.h"


#endif	/* !OSDEP_H */
                                                                                                                                                         DarkNET-1.08/pico.BBS/mswin.ico                                                                        644   21270   21270         1376  5672463053  11262                                                                                                                                                                                                                                                                                                                                                                                 è     (       @         €                       €  €   €€ €   € € €€  ÀÀÀ €€€   ÿ  ÿ   ÿÿ ÿ   ÿ ÿ ÿÿ  ÿÿÿ wwwwwwwwwwwwwwpwˆˆˆˆˆˆˆˆˆˆˆˆˆ‡wwÿÿÿÿÿÿÿÿÿÿÿÿÿ÷w‡wwwwwwwwwwww‡‡wwwwwwwwwwww‡‡wwwww÷wwwww‡‡wxˆww÷wwˆ‡w‡‡wwˆ‡w÷wxˆww‡‡wwxˆw÷wˆ‡ww‡‡wwwˆ‡÷xˆwww‡‡xˆˆˆˆˆˆˆˆˆˆ‡‡‡wwwwwwwwww‡‡‡|ÌÌÌÌÌÌÌÌÇ‡‡‡|ÌÌÌÌÌÌÌÌÇ‡‡‡|ÌÌÌÌÌÌÌÌÇ‡‡‡|ÌÌÌÌÌÌÌÌÇ‡‡‡|ÌÌÌÌÌÌÌÌÇ‡‡‡|¼ÌËÌ»¼Ë¼Ç‡‡‡|¼ÌËËÌÌ¼ËÇ‡‡‡|»¼ËËÌÌ¼ËÇ‡‡‡|¼ËËËÌÌ¼ËÇ‡‡‡|»¼ËÌ»¼Ë¼Ç‡‡‡|ÌÌÌÌÌÌÌÌÇ‡‡‡|ÌÌÌÌÌÌÌÌÇ‡‡‡|ÌÌÌÌÌÌÌÌÇ‡‡‡wwwwwwwwww‡‡‡ÿÿÿÿÿÿÿÿÿÿ÷‡‡wwwwwwwwwwww‡‡wwwwwwwwwwww‡ˆˆˆˆˆˆˆˆˆˆˆˆˆ‡wÿÿÿÿÿÿÿÿÿÿÿÿÿ÷wwwwwwwwwwwwwwwp€                                                                                                                          €  ‡wwxˆw÷wˆ‡ww‡‡wwwˆ‡÷xˆwww‡‡xˆˆˆˆˆˆˆˆˆˆ‡‡‡wwwwwwwwww‡‡‡|ÌÌÌÌÌÌÌÌÇ‡‡‡|ÌÌÌÌÌÌÌÌÇ‡‡‡|ÌÌÌÌÌÌÌÌÇ‡‡‡|ÌÌÌÌÌÌÌÌÇ‡‡‡|ÌÌÌÌÌÌÌÌÇ‡‡‡|¼ÌËÌ»¼Ë¼Ç‡‡‡|¼ÌËËÌÌ¼ËÇ‡‡‡|»¼ËËÌÌ¼ËÇ‡‡‡|¼ËËËÌÌ¼ËÇ‡‡‡|»¼ËÌ»¼Ë¼Ç‡‡‡|ÌÌÌÌÌÌÌÌÇ‡‡‡|ÌÌÌÌÌÌÌÌÇ‡‡‡DarkNET-1.08/pico.BBS/mswin.rc                                                                         644   21270   21270         6326  5672463053  11114                                                                                                                                                                                                                                                                                                                                                                      //Microsoft App Studio generated resource script.
//
#include "resource.h"

#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#define APSTUDIO_HIDDEN_SYMBOLS
#include "windows.h"
#undef APSTUDIO_HIDDEN_SYMBOLS


/////////////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS


//////////////////////////////////////////////////////////////////////////////
//
// Icon
//

PINEICON                ICON    DISCARDABLE     "MSWIN.ICO"

//////////////////////////////////////////////////////////////////////////////
//
// Bitmap
//

PINEBITMAP              BITMAP  MOVEABLE PURE   "MSWIN.BMP"

//////////////////////////////////////////////////////////////////////////////
//
// Menu
//

PINEMENU MENU DISCARDABLE 
BEGIN
    POPUP "&File"
    BEGIN
        MENUITEM "E&xit",                       IDM_FILE_EXIT
    END
    POPUP "&Edit"
    BEGIN
        MENUITEM "Cu&t",                        IDM_EDIT_CUT
        MENUITEM "&Copy",                       IDM_EDIT_COPY
        MENUITEM "Copy &Append",                IDM_EDIT_COPY_APPEND
        MENUITEM "&Paste",                      IDM_EDIT_PASTE
        MENUITEM "Cance&l Paste!",              IDM_EDIT_CANCEL_PASTE
    END
    POPUP "&Options"
    BEGIN
        MENUITEM "Set &Font",                   IDM_SETFONT
    END
    MENUITEM "A&bout",                      IDM_ABOUT
END


//////////////////////////////////////////////////////////////////////////////
//
// Dialog
//

ABOUTDLGBOX DIALOG DISCARDABLE  10, 25, 220, 115
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "PC-Pico"
FONT 8, "Helv"
BEGIN
    ICON            PINEICON,IDD_ABOUTICON,10,5,18,20
    CTEXT           "PC-Pico for Windows\nversion %d.%02d\nBETA (%s)",
                    IDD_VERSION,46,8,120,26,SS_NOPREFIX | NOT WS_GROUP
    LTEXT           "",IDD_BYLINE,45,40,172,56,SS_NOPREFIX | NOT WS_GROUP
    DEFPUSHBUTTON   "OK",IDD_OK,177,8,40,14
END

#ifdef APSTUDIO_INVOKED
//////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//

0X00020000L TEXTINCLUDE DISCARDABLE 
BEGIN
    "resource.h\0"
END

2 TEXTINCLUDE DISCARDABLE 
BEGIN
    "#define APSTUDIO_HIDDEN_SYMBOLS\r\n"
    "#include ""windows.h""\r\n"
    "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n"
    "\r\n"
    "\0"
END

3 TEXTINCLUDE DISCARDABLE 
BEGIN
    "\r\n"
    "\0"
END

1 TEXTINCLUDE DISCARDABLE 
BEGIN
    "resource.h\0"
END

/////////////////////////////////////////////////////////////////////////////////////
#endif    // APSTUDIO_INVOKED


//////////////////////////////////////////////////////////////////////////////
//
// String Table
//

STRINGTABLE DISCARDABLE 
BEGIN
    IDS_BYLINE              "PICO is a product of the University of Washington,\nOffice of Computing & Communications.\n\nCopyright 1989-1994 University of Washington."
    IDS_APPNAME             "PC-Pico"
END


#ifndef APSTUDIO_INVOKED
////////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//


/////////////////////////////////////////////////////////////////////////////////////
#endif    // not APSTUDIO_INVOKED

                                                                                                                                                                                                                                                                                                          DarkNET-1.08/pico.BBS/mswin.def                                                                        644   21270   21270          404  5672463053  11215                                                                                                                                                                                                                                                                                                                                                                      NAME         PICO
EXETYPE      WINDOWS
DESCRIPTION  'Pico for Windows (Character)'
STUB         'winstub.exe'

CODE         PRELOAD DISCARDABLE SHARED
DATA         PRELOAD MULTIPLE 

HEAPSIZE     4096

EXPORTS
   PWNDPROC         @1
   ABOUTDLGPROC	      @2


                                                                                                                                                                                                                                                            DarkNET-1.08/pico.BBS/os_vms.c                                                                         644   21270   21270        73202  5672463053  11120                                                                                                                                                                                                                                                                                                                                                                      #if     !defined(lint) && !defined(DOS)
static char rcsid[] = "$Id: os_vms.c,v 1.2 1994/06/27 18:20:28 dlm Exp $";
#endif
/*
 * Program:     Operating system dependent routines - VMS 5.n
 *
 *
 * Yehavi Bourvine
 * Hebrew University of Jeruselem
 * +972-2-585684
 * YEHAVI@vms.huji.ac.il
 *
 * Please address all bugs and comments to "pine-bugs@cac.washington.edu"
 *
 * Copyright 1991-1994  University of Washington
 *
 *  Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee to the University of
 * Washington is hereby granted, provided that the above copyright notice
 * appears in all copies and that both the above copyright notice and this
 * permission notice appear in supporting documentation, and that the name
 * of the University of Washington not be used in advertising or publicity
 * pertaining to distribution of the software without specific, written
 * prior permission.  This software is made available "as is", and
 * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
 * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
 * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
 * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 * Pine and Pico are trademarks of the University of Washington.
 * No commercial use of these trademarks may be made without prior
 * written permission of the University of Washington.
 *
 *
 * Notes:
 *
 *
 */

#include 	<stdio.h>
#include	<errno.h>
#include	<setjmp.h>
#include	<time.h>
#include	"osdep.h"
#include        "pico.h"
#include	"estruct.h"
#include        "edef.h"
#include        "efunc.h"
#ifdef __ALPHA
#include	<fcntl.h>
#endif
#include	<file.h>
#include	<types.h>
#include	<time.h>

#include <iodef.h>
#include <ttdef.h>
#include <tt2def.h>
#include <lib$routines.h>
#include <descrip.h>

/* Output channel and buffers */
static short	TerminalChan;
#define	MAXBUF	1024		/* Save up to 1024 characters before sending them */
unsigned char	OutputBuffer[MAXBUF + 1];
int	OutputBufferCounter;

/* For setting and resting the PASTHRU flag: */
struct	{
	unsigned char	class, type;
	unsigned short	width;
	unsigned long	BasicChar,
			ExtendChar;
	} TerminalChar;


struct KBSTREE *kpadseqs = NULL;


#define	SIGTYPE	void

struct DESC {		/* String descriptor */
	short	length, type;
	char	*address;
	} ;

    int      kbseq();
    SIGTYPE  do_hup_signal();
    SIGTYPE  rtfrmshell();
#ifdef	TIOCGWINSZ
    SIGTYPE  winch_handler();
#endif


/*
 * for alt_editor arg[] building
 */
#define	MAXARGS	10

/*
 * ttopen - this function is called once to set up the terminal device 
 *          streams.  if called as pine composer, don't mess with
 *          tty modes, but set signal handlers.
 */
ttopen()
{
	long	status;
	struct DESC TerminalDesc;
	char	TerminalName[] = "SYS$OUTPUT:";

	TerminalDesc.address = TerminalName; TerminalDesc.type = 0;
	TerminalDesc.length = strlen(TerminalName);

	status = sys$assign(&TerminalDesc, &TerminalChan, (int)(0), (int)(0));
	if((status & 0x1) == 0) {
		printf("Can't assign channel to terminal\n");
		exit(status);
	}

    signal(SIGHUP,  do_hup_signal);	/* deal with SIGHUP */
    signal(SIGTERM, do_hup_signal);	/* deal with SIGTERM */
#ifdef	SIGTSTP
    signal(SIGTSTP, SIG_DFL);
#endif

/* Some default values since we do not have TERMCAP: */
	eolexist = FALSE;
	revexist = TRUE;
	delchar = FALSE;
	inschar = FALSE;
      scrollexist = TRUE;

	init_kpnames();

	OutputBufferCounter = 0;	/* Output buffer is empty */

/* Set the PASTHRU bit */
	status = sys$qiow((int)(0), TerminalChan, (short)(IO$_SENSEMODE),
			NULL, (int)(0), (int)(0),
			&TerminalChar, sizeof(TerminalChar),
			(int)(0), (int)(0), (int)(0), (int)(0));
	if((status & 0x1) == 0) {
		printf("Can't read for set terminal to /PASTHRU\n");
		exit(status);
	}

	TerminalChar.ExtendChar |= TT2$M_PASTHRU;
	status = sys$qiow((int)(0), TerminalChan, (short)(IO$_SETMODE),
			NULL, (int)(0), (int)(0),
			&TerminalChar, sizeof(TerminalChar),
			(int)(0), (int)(0), (int)(0), (int)(0));
	if((status & 0x1) == 0) {
		printf("Can't set terminal to /PASTHRU\n");
		exit(status);
	}

    ttgetwinsz();
    return(1);
}



/*
 * ttclose - this function gets called just before we go back home to 
 *           the command interpreter.  If called as pine composer, don't
 *           worry about modes, but set signals to default, pine will 
 *           rewire things as needed.
 */
ttclose()
{
	int	status;

	ttflush();

/* Clear the PASTHRU flag */
	TerminalChar.ExtendChar &= ~TT2$M_PASTHRU;
	status = sys$qiow((int)(0), TerminalChan, (short)(IO$_SETMODE),
			NULL, (int)(0), (int)(0),
			&TerminalChar, sizeof(TerminalChar),
			(int)(0), (int)(0), (int)(0), (int)(0));
	if((status & 0x1) == 0) {
		printf("Can't set terminal to /NOPASTHRU\n");
		exit(status);
	}
	sys$dassgn(TerminalChan);

    return(1);
}


/*
 * ttspeed - return TRUE if tty line speed < 9600 else return FALSE
 */
ttisslow()
{
	return(TRUE);
}


/*
 * ttgetwinsz - set global rows and columns values and return
 */
ttgetwinsz()
{
#define TT_STRING_SIZE 20
       char string[TT_STRING_SIZE] ;   /* string for holding tt:'s dev name */
       int rows, col ;                 /* row / column vars */
       unsigned long status ;          /* status return var */
       unsigned long terminal_item = 797 ; /* JPI$_TERMINAL */
       unsigned long tt_page_item = 170 ;  /* DVI$_TT_PAGE */
       unsigned long devbufsz_item = 8 ;   /* DVI$_DEVBUFSIZ */
       struct dsc$descriptor_vs tt_sdesc =
                               {TT_STRING_SIZE,/* max string size */
                               DSC$K_DTYPE_VT, /* descriptor type */
                               DSC$K_CLASS_VS, /* descriptor class = var str */
                               string} ;       /* pointer to var string */


/* Set the defaults */
          term.t_nrow = 23;
          term.t_ncol = 80;

               /* Get our terminal's device name */
       status = lib$getjpi(&terminal_item,NULL,NULL,NULL,&tt_sdesc,NULL) ;
       if ((status&1) == 1)
          {
               /* Get our terminal's page size */
          status = lib$getdvi(&tt_page_item,NULL,&tt_sdesc,&rows,NULL,NULL) ;
               /* Get our terminal's page width */
	  if((status & 0x1) == 1) {
	          status = lib$getdvi(&devbufsz_item,NULL,&tt_sdesc,&col,NULL,NULL) ;
		if((status & 0x1) == 1) {
	               /* Set the globals for rows and columns */
		          term.t_nrow = rows-1 ;
		          term.t_ncol = col ;
			}
		}
          }
       else
          printf("Can't find process's terminal -- using defaults.\n") ;
}

/*
 | Physically write a string to the terminal.
 */
write_terminal(string, size)
char	*string;
int	size;
{
	long	status;
	short	iosb[4];

	status = sys$qiow((int)(0), TerminalChan, (short)(IO$_WRITEVBLK),
			iosb, (int)(0), (int)(0),
			string, size, (int)(0), (int)(0), (int)(0), (int)(0));
	if(((status & 0x1) == 0) || ((iosb[0] & 0x1) == 0)) {
		printf("Can't write to terminal; status=%d, iosb=%d\n",
			status, iosb[0]);
		exit(status);
	}
	return 0;	/* Success */
}


/*
 * __ttputc - Write a character to the display. Actually save it in our buffer
 * and write it only if the buffer is becoming full.
 * This function is called by TTPUTC().
 */
__ttputc(c)
{
	OutputBuffer[OutputBufferCounter++] = c;
	if(OutputBufferCounter >= MAXBUF)
		ttflush();
	return c;
}

/*
 * ttputc - Write a character to the display. Actually save it in our buffer
 * and write it only if the buffer is becoming full.
 */
#undef ttputc
ttputc(c)
{
	return(__ttputc(c));
}


/*
 * ttflush - Flush our buffer to the terminal.
 */
ttflush()
{
	if(OutputBufferCounter > 0) {
		write_terminal(OutputBuffer, OutputBufferCounter);
		OutputBufferCounter = 0;
	}
}


/*
 * ttgetc - Read a character from the terminal, performing no editing 
 *          and doing no echo at all.
 */
ttgetc()
{
	unsigned char c;
	int i;
	long	status;
	unsigned long Terminator[4] = { -1, -1, -1, -1};
	struct DESC	TerminatorDesc = { sizeof(Terminator), 0, Terminator };
	short	iosb[4];

	status = sys$qiow((int)(0), TerminalChan,
		(short)(IO$_READLBLK | IO$M_NOFORMAT | IO$M_NOFILTR | IO$M_NOECHO | IO$M_TRMNOECHO),
			iosb, (int)(0), (int)(0),
			&c, 1, (int)(0), &TerminatorDesc, (int)(0), (int)(0));
	if(((status & 0x1) == 0) || ((iosb[0] & 0x1) == 0)) {
		printf("Can't read from terminal; status=%d, iosb=%d\n",
			status, iosb[0]);
		exit(status);
	}

	c &= 0xff;
	if(c == 155) c = 27;	/* Convert 8th bit escape to 7bit one */
	return((int)(c));
}


/*
 * GetKey - Read in a key.
 * Do the standard keyboard preprocessing. Convert the keys to the internal
 * character set.  Resolves escape sequences and returns no-op if global
 * timeout value exceeded.
 */
GetKey()
{
    int    c;

/*~~~ HUJI/VMS - No timeout is supported on VMS to make it simple... */
    if ((c = (*term.t_getchar)()) == METACH) { /* Apply M- prefix      */
	int status;
	    
	/*
	 * this code should intercept special keypad keys
	 */
	switch(status = kbseq(&c)){
	  case 0 : 	/* no dice */
	    return(c);
	  case  K_PAD_UP		:
	  case  K_PAD_DOWN		:
	  case  K_PAD_RIGHT		:
	  case  K_PAD_LEFT		:
	  case  K_PAD_PREVPAGE	:
	  case  K_PAD_NEXTPAGE	:
	  case  K_PAD_HOME		:
	    return(status);
	  case F1  :
	  case F2  :
	  case F3  :
	  case F4  :
	  case F5  :
	  case F6  :
	  case F7  :
	  case F8  :
	  case F9  :
	  case F10 :
	  case F11 :
	  case F12 :
	    return(status);
	  case BADESC :
	    if(c == '\033'){
		c = (*term.t_getchar)();
		if(myislower(c))	/* canonicalize c */
		  c = toupper(c);

		return((myisalpha(c) || c == '@' || (c >= '[' && c <= '_'))
		       ? (CTRL | c) : c);
	    }

	  default :				/* punt the whole thing	*/
	    (*term.t_beep)();
	    break;
	}
    }

    if (c>=0x00 && c<=0x1F)                 /* C0 control -> C-     */
      c = CTRL | (c+'@');
    return (c);

}



/* 
 * kbseq - looks at an escape sequence coming from the keyboard and 
 *         compares it to a trie of known keyboard escape sequences, and
 *         performs the function bound to the escape sequence.
 * 
 *         returns: BADESC, the escaped function, or 0 if not found.
 */
kbseq(c)
int	*c;
{
    register char	b;
    register int	first = 1;
    register struct	KBSTREE	*current = kpadseqs;

    if(kpadseqs == NULL)			/* bag it */
      return(BADESC);

    while(1){
	*c = b = (*term.t_getchar)();
	while(current->value != b){
	    if(current->left == NULL){		/* NO MATCH */
		if(first)
		  return(BADESC);
		else
		  return(0);
	    }
	    current = current->left;
	}

	if(current->down == NULL)		/* match!!!*/
	  return(current->func);
	else
	  current = current->down;

	first = 0;
    }
}



/*
 * alt_editor - Use normal SYSTEM() and not fork.
 */
alt_editor(f, n)
{
    char   eb[NLINE];				/* buf holding edit command */
    char   *fn;					/* tmp holder for file name */
    char   *cp;
    long   l;
    int    i, pid, done = 0;

    if(Pmaster == NULL)
      return;

    if(gmode&MDSCUR){
	emlwrite("Alternate editor not available in restricted mode", NULL);
	return;
    }

    if(Pmaster->alt_ed == NULL){
	if(!(gmode&MDADVN)){
	    emlwrite("\007Unknown Command",NULL);
	    return;
	}

	if(getenv("EDITOR"))
	  strcpy(eb, (char *)getenv("EDITOR"));
	else
	  *eb = '\0';

	while(!done){
	    pid = mlreplyd("Which alternate editor ? ", eb, NLINE, QDEFLT);

	    switch(pid){
	      case ABORT:
		return(-1);
	      case HELPCH:
		emlwrite("no alternate editor help yet", NULL);

/* take sleep and break out after there's help */
		sleep(3);
		break;
	      case (CTRL|'L'):
		sgarbf = TRUE;
		update();
		break;
	      case TRUE:
	      case FALSE:			/* does editor exist ? */
		if(*eb == '\0'){		/* leave silently? */
		    mlerase();
		    return(-1);
		}

		done++;
		break;
	      default:
		break;
	    }
	}
    }
    else
      strcpy(eb, Pmaster->alt_ed);

    if((fn=writetmp(0, 1)) == NULL){		/* get temp file */
	emlwrite("Problem writing temp file for alt editor", NULL);
	return(-1);
    }

    strcat(eb, " ");

/* fn is /SYS$SCRATCH/filename;  Modify it to suit DCL style... */
    if((cp = strrchr(fn, '/')) != NULL) {
	strcat(eb, "SYS$SCRATCH:"); strcat(eb, &cp[1]);
    } else strcat(eb, fn);

    cp = eb;

    if(Pmaster)
      (*Pmaster->raw_io)(0);			/* turn OFF raw mode */

	system(eb);
    if(Pmaster)
      (*Pmaster->raw_io)(1);		/* turn ON raw mode */

    /*
     * replace edited text with new text 
     */
    curbp->b_flag &= ~BFCHG;		/* make sure old text gets blasted */
    readin(fn, 0);			/* read new text overwriting old */
    unlink(fn);				/* blast temp file */
    curbp->b_flag |= BFCHG;		/* mark dirty for packbuf() */
    ttopen();				/* reset the signals */
    refresh(0, 1);			/* redraw */
}



/*
 *  bktoshell - suspend and wait to be woken up
 */
bktoshell()		/* suspend MicroEMACS and wait to wake up */
{
	emlwrite("\007Unknown command (in BktoShell): ^Z", NULL);
	return;
}


/* 
 * rtfrmshell - back from shell, fix modes and return
 */
SIGTYPE
rtfrmshell()
{
}


/*
 * do_hup_signal - jump back in the stack to where we can handle this
 */
SIGTYPE
do_hup_signal()
{
    if(Pmaster){
	extern jmp_buf finstate;

	signal(SIGHUP, SIG_IGN); 		/* don't bother us. */
	signal(SIGTERM, SIG_IGN);
	longjmp(finstate, COMP_GOTHUP);
    }
    else{
	/*
	 * if we've been interrupted and the buffer is changed,
	 * save it...
	 */
	if(anycb() == TRUE){			/* time to save */
	    if(curbp->b_fname[0] == '\0'){	/* name it */
		strcpy(curbp->b_fname, "pico.save");
	    }
	    else{
		strcat(curbp->b_fname, ".save");
	    }
	    writeout(curbp->b_fname);
	}
	vttidy();
	exit(1);
    }
}


unlink(fn)
char	*fn;
{
	delete(fn);
}

/*
 * big bitmap of ASCII characters allowed in a file name
 * (needs reworking for other char sets)
 */
unsigned char okinfname[32] = {
      0,    0, 			/* ^@ - ^G, ^H - ^O  */
      0,    0,			/* ^P - ^W, ^X - ^_  */
      0xff, 0xff,		/* SP - ' ,  ( - /   */
      0xff, 0xff,		/*  0 - 7 ,  8 - ?   */
      0xff, 0xff,		/*  @ - G ,  H - O   */
      0xff, 0xff,		/*  P - W ,  X - _   */
      0xff, 0xff,		/*  ` - g ,  h - o   */
      0xff, 0xff,		/*  p - w ,  x - DEL */
      0,    0, 			/*  > DEL   */
      0,    0,			/*  > DEL   */
      0,    0, 			/*  > DEL   */
      0,    0, 			/*  > DEL   */
      0,    0 			/*  > DEL   */
};


/*
 * fallowc - returns TRUE if c is allowable in filenames, FALSE otw
 */
fallowc(c)
char c;
{
    return(okinfname[c>>3] & 0x80>>(c&7));
}


/*
 * fexist - returns TRUE if the file exists with mode passed in m, 
 *          FALSE otherwise.  By side effect returns length of file in l
 */
fexist(file, m, l)
char *file;
char *m;					/* files mode: r, w or rw */
long *l;
{
    struct stat	sbuf;

    if(l)
      *l = 0L;

    if(stat(file, &sbuf) < 0){
	switch(errno){
	  case ENOENT :				/* File not found */
	    return(FIOFNF);
#ifdef	ENAMETOOLONG
	  case ENAMETOOLONG :			/* Name is too long */
	    return(FIOLNG);
#endif
	  default:				/* Some other error */
	    return(FIOERR);
	}
    }

    if(l)
      *l = sbuf.st_size;

    if((sbuf.st_mode&S_IFMT) == S_IFDIR)
      return(FIODIR);

    if(m[0] == 'r')				/* read access? */
      return((S_IREAD&sbuf.st_mode) ? FIOSUC : FIONRD);
    else if(m[0] == 'w')			/* write access? */
      return((S_IWRITE&sbuf.st_mode) ? FIOSUC : FIONWT);
    else if(m[0] == 'x')			/* execute access? */
      return((S_IEXEC&sbuf.st_mode) ? FIOSUC : FIONEX);
    return(FIOERR);				/* what? */
}


/*
 * isdir - returns true if fn is a readable directory, false otherwise
 *         silent on errors (we'll let someone else notice the problem;)).
 */
isdir(fn, l)
char *fn;
long *l;
{
    struct stat sbuf;

    if(l)
      *l = 0;

    if(stat(fn, &sbuf) < 0)
      return(0);

    if(l)
      *l = sbuf.st_size;
    return((sbuf.st_mode&S_IFMT) == S_IFDIR);
}



/*
 * gethomedir - returns the users home directory
 *              Note: home is malloc'd for life of pico
 */
char *
gethomedir(l)
int *l;
{
    static char *home = NULL;
    static short hlen = 0;
    char   s[1024];

    if(home == NULL){
	strcpy(s, getenv("HOME"));
	hlen = strlen(s);
	if((home=(char *)malloc((strlen(s) + 1) * sizeof(char))) == NULL){
	    emlwrite("Problem allocating space for home dir", NULL);
	    return(0);
	}
	strcpy(home, s);
    }

    if(l)
      *l = hlen;

    return(home);
}


/*
 * homeless - returns true if given file does not reside in the current
 *            user's home directory tree. 
 */
homeless(f)
char *f;
{
    char *home;
    int   len;

    home = gethomedir(&len);
    return(strncmp(home, f, len));
}



/*
 * errstr - return system error string corresponding to given errno
 *          Note: strerror() is not provided on all systems, so it's 
 *          done here once and for all.
 */
char *
errstr(err)
int err;
{
    extern char *sys_errlist[];
    extern int  sys_nerr;

    return((err >= 0 && err < sys_nerr) ? sys_errlist[err] : NULL);
}



/*
 * getfnames - return all file names in the given directory in a single 
 *             malloc'd string.  n contains the number of names
 */
char *
getfnames(dn, n)
char *dn;
int  *n;
{
	char	*ddn;		/* Don't ruin the original */
	int	context = 0;	/* Used in LIB$FIND_FILE */
	struct	DESC	file_mask, file_name;
	int	status;
	char	*p, *OutputPointer;
	char	*RetFiles = malloc(8192);	/* Hopefully it will be enough... */
	char	FileName[256];	/* Temporary place */

	*n = 0;		/* Init - no files yet */
	if(RetFiles == NULL) return;
	*(OutputPointer = RetFiles) = '\0';

/* For all directory names append *.* for the finction to succeed */
	strcpy(ddn, dn);	/* Don't ruin it */
	strcat(ddn, "*.*");

	file_mask.length = strlen(ddn); file_mask.address = ddn;
	file_mask.type = 0;

	for(;;) {
		file_name.address = FileName; file_name.length = sizeof(FileName) - 1;
		file_name.type = 0;

		status = LIB$FIND_FILE(&file_mask, &file_name, &context);
		if((status & 0x1) == 0) {
			if(context != 0)
				LIB$FIND_FILE_END(&context);
			context = 0;	/* Init for next search */
			return RetFiles;
		}

/* File found - Remove the leading directory name and the trailing spaces */
		if((p = strchr(FileName, ' ')) != NULL) *p = '\0';
		if((p = strrchr(FileName, ']')) != NULL) p++;
		else					p = FileName;
		while((*OutputPointer++ = *p++) != '\0');
		*n += 1;
	}
}


/*
 * fioperr - given the error number and file name, display error
 */
void
fioperr(e, f)
int  e;
char *f;
{
    switch(e){
      case FIOFNF:				/* File not found */
	emlwrite("\007File \"%s\" not found", f);
	break;
      case FIOEOF:				/* end of file */
	emlwrite("\007End of file \"%s\" reached", f);
	break;
      case FIOLNG:				/* name too long */
	emlwrite("\007File name \"%s\" too long", f);
	break;
      case FIODIR:				/* file is a directory */
	emlwrite("\007File \"%s\" is a directory", f);
	break;
      case FIONWT:
	emlwrite("\007Write permission denied: %s", f);
	break;
      case FIONRD:
	emlwrite("\007Read permission denied: %s", f);
	break;
      case FIONEX:
	emlwrite("\007Execute permission denied: %s", f);
	break;
      default:
	emlwrite("\007File I/O error: %s", f);
    }
}



/*
 * pfnexpand - pico's function to expand the given file name if there is 
 *	       a leading '~'
 */
char *pfnexpand(fn, len)
char *fn;
int  len;
{
    char	*pw;
    register char *x, *y, *z;
    char name[256];
    
    if(*fn == '~') {
        for(x = fn+1, y = name; *x != '/' && *x != '\0'; *y++ = *x++);
        *y = '\0';
        if(x == fn + 1) 
          pw = getenv("HOME");
        else
          pw = NULL;
        if(pw == NULL)
          return(NULL);

	/* make room for expanded path */
	for(z=x+strlen(x),y=fn+strlen(x)+strlen(pw);
	    z >= x;
	    *y-- = *z--);
	/* and insert the expanded address */
	for(x=fn,y=pw; *y != '\0'; *x++ = *y++);
    }
    return(fn);
}



/*
 * fixpath - do nothing...
 */
fixpath(name, len)
char *name;
int  len;
{
}


/*
 * compresspath - given a base path and an additional directory, collapse
 *                ".." and "." elements and return absolute path (appending
 *                base if necessary).  
 *
 *                returns  1 if OK, 
 *                         0 if there's a problem
 *                         new path, by side effect, if things went OK
 */
compresspath(base, path, len)
char *base, *path;
int  len;
{
    register int i;
    int  depth = 0;
    char *p;
    char *stack[32];
    char s[1024];

#define PUSHD(X)  (stack[depth++] = X)
#define POPD()    ((depth > 0) ? stack[--depth] : "")

    if(*path == '~'){
	fixpath(path, len);
	strcpy(s, path);
    }
    else if(*path != C_FILESEP)
      sprintf(s, "%s%c%s", base, C_FILESEP, path);
    else
      strcpy(s, path);

    p = s;
    for(i=0; s[i] != '\0'; i++){		/* pass thru path name */
	if(s[i] == '/'){
	    if(p != s)
	      PUSHD(p);				/* push dir entry */
	    p = &s[i+1];			/* advance p */
	    s[i] = '\0';			/* cap old p off */
	    continue;
	}

	if(s[i] == '.'){			/* special cases! */
	    if(s[i+1] == '.'			/* parent */
	       && (s[i+2] == '/' || s[i+2] == '\0')){
		if(!strcmp(POPD(),""))		/* bad news! */
		  return(0);

		i += 2;
		p = (s[i] == '\0') ? "" : &s[i+1];
	    }
	    else if(s[i+1] == '/' || s[i+1] == '\0'){		/* no op */
		i++;
		p = (s[i] == '\0') ? "" : &s[i+1];
	    }
	}
    }

    if(*p != '\0')
      PUSHD(p);					/* get last element */

    path[0] = '\0';
    for(i = 0; i < depth; i++){
	strcat(path, S_FILESEP);
	strcat(path, stack[i]);
    }

    return(1);					/* everything's ok */
}


/*
 * tmpname - return a temporary file name in the given buffer
 */
void
tmpname(name)
char *name;
{
    sprintf(name, "/SYS$SCRATCH/pico.%d", getpid());	/* tmp file name */
}


/*
 * Take a file name, and from it
 * fabricate a buffer name. This routine knows
 * about the syntax of file names on the target system.
 * I suppose that this information could be put in
 * a better place than a line of code.
 */
void
makename(bname, fname)
char    bname[];
char    fname[];
{
    register char   *cp1;
    register char   *cp2;

    cp1 = &fname[0];
    while (*cp1 != 0)
      ++cp1;

    while (cp1!=&fname[0] && cp1[-1]!='/')
      --cp1;

    cp2 = &bname[0];
    while (cp2!=&bname[NBUFN-1] && *cp1!=0 && *cp1!=';')
      *cp2++ = *cp1++;

    *cp2 = 0;
}


/*
 * copy - copy contents of file 'a' into a file named 'b'.  Return error
 *        if either isn't accessible or is a directory
 */
copy(a, b)
char *a, *b;
{
    int    in, out, n, rv = 0;
    char   *cb;
    struct stat tsb, fsb;
    extern int  errno;

    if(stat(a, &fsb) < 0){		/* get source file info */
	emlwrite("Can't Copy: %s", errstr(errno));
	return(-1);
    }

    if(!(fsb.st_mode&S_IREAD)){		/* can we read it? */
	emlwrite("\007Read permission denied: %s", a);
	return(-1);
    }

    if((fsb.st_mode&S_IFMT) == S_IFDIR){ /* is it a directory? */
	emlwrite("\007Can't copy: %s is a directory", a);
	return(-1);
    }

    if(stat(b, &tsb) < 0){		/* get dest file's mode */
	switch(errno){
	  case ENOENT:
	    break;			/* these are OK */
	  default:
	    emlwrite("\007Can't Copy: %s", errstr(errno));
	    return(-1);
	}
    }
    else{
	if(!(tsb.st_mode&S_IWRITE)){	/* can we write it? */
	    emlwrite("\007Write permission denied: %s", b);
	    return(-1);
	}

	if((tsb.st_mode&S_IFMT) == S_IFDIR){	/* is it directory? */
	    emlwrite("\007Can't copy: %s is a directory", b);
	    return(-1);
	}

	if(fsb.st_dev == tsb.st_dev && fsb.st_ino == tsb.st_ino){
	    emlwrite("\007Identical files.  File not copied", NULL);
	    return(-1);
	}
    }

    if((in = open(a, O_RDONLY)) < 0){
	emlwrite("Copy Failed: %s", errstr(errno));
	return(-1);
    }

    if((out=creat(b, fsb.st_mode&0xfff)) < 0){
	emlwrite("Can't Copy: %s", errstr(errno));
	close(in);
	return(-1);
    }

    if((cb = (char *)malloc(NLINE*sizeof(char))) == NULL){
	emlwrite("Can't allocate space for copy buffer!", NULL);
	close(in);
	close(out);
	return(-1);
    }

    while(1){				/* do the copy */
	if((n = read(in, cb, NLINE)) < 0){
	    emlwrite("Can't Read Copy: %s", errstr(errno));
	    rv = -1;
	    break;			/* get out now */
	}

	if(n == 0)			/* done! */
	  break;

	if(write(out, cb, n) != n){
	    emlwrite("Can't Write Copy: %s", errstr(errno));
	    rv = -1;
	    break;
	}
    }

    free(cb);
    close(in);
    close(out);
    return(rv);
}


/*
 * Open a file for writing. Return TRUE if all is well, and FALSE on error
 * (cannot create).
 */
ffwopen(fn)
char    *fn;
{
    extern FILE *ffp;

    if ((ffp=fopen(fn, "w")) == NULL) {
        emlwrite("Cannot open file for writing", NULL);
        return (FIOERR);
    }

    return (FIOSUC);
}


/*
 * Close a file. Should look at the status in all systems.
 */
ffclose()
{
    extern FILE *ffp;

    if (fclose(ffp) != FALSE) {
        emlwrite("Error closing file", NULL);
        return(FIOERR);
    }

    return(FIOSUC);
}


/*
 * P_open - run the given command in a sub-shell returning a file pointer
 *	    from which to read the output
 *
 * note:
 *	For OS's other than unix, you will have to rewrite this function.
 *	Hopefully it'll be easy to exec the command into a temporary file, 
 *	and return a file pointer to that opened file or something.
 */
FILE *P_open(s)
char *s;
{
	printf("Popen not supported on VMS yet.\n");
	return NULL;
}



/*
 * P_close - close the given descriptor
 *
 */
P_close(fp)
FILE *fp;
{
    return;
}



/*
 * worthit - generic sort of test to roughly gage usefulness of using 
 *           optimized scrolling.
 *
 * note:
 *	returns the line on the screen, l, that the dot is currently on
 */
worthit(l)
int *l;
{
    int i;			/* l is current line */
    unsigned below;		/* below is avg # of ch/line under . */

    *l = doton(&i, &below);
    below = (i > 0) ? below/(unsigned)i : 0;

    return(below > 3);
}



/*
 * pico_new_mail - just checks mtime and atime of mail file and notifies user 
 *	           if it's possible that they have new mail.
 */
pico_new_mail()
{
    int ret = 0;
    static time_t lastchk = 0;
    struct stat sbuf;
    char   inbox[256], *p;

	sprintf(inbox,"SYS$LOGIN:MAIL.MAI");

    if(stat(inbox, &sbuf) == 0){
	ret = sbuf.st_atime <= sbuf.st_mtime &&
	  (lastchk < sbuf.st_mtime && lastchk < sbuf.st_atime);
	lastchk = sbuf.st_mtime;
	return(ret);
    }
    else
      return(ret);
}



/*
 * time_to_check - checks the current time against the last time called 
 *                 and returns true if the elapsed time is > timeout
 */
time_to_check()
{
    static time_t lasttime = 0L;

    if(!timeout)
      return(FALSE);

    if(time((long *) 0) - lasttime > (time_t)timeout){
	lasttime = time((long *) 0);
	return(TRUE);
    }
    else
      return(FALSE);
}


/*
 * sstrcasecmp - compare two pointers to strings case independently
 */
sstrcasecmp(s1, s2)
QcompType *s1, *s2;
{
    register char *a, *b;

    a = *(char **)s1;
    b = *(char **)s2;
    while(toupper(*a) == toupper(*b++))
	if(*a++ == '\0')
	  return(0);

    return(toupper(*a) - toupper(*--b));
}


#ifdef	TIOCGWINSZ
/*
 * winch_handler - handle window change signal
 */
SIGTYPE winch_handler()
{
    struct winsize win;
    extern int resize_pico();

    signal(SIGWINCH, winch_handler);

    if (ioctl(0, TIOCGWINSZ, &win) == 0) {
	if (win.ws_col && win.ws_row)
	  resize_pico(win.ws_row - 1, win.ws_col);
    }
}
#endif	/* TIOCGWINSZ */


/* Copied from TCAP */
hide_cur()
{
write_terminal("\033[?25l", 6);
}
show_cur()
{
write_terminal("\033[?25h", 6);
}

o_insert()
{
	return 0;
}

o_delete()
{
	return 0;
}


init_kpnames()
{
	kpinsert("OP",F1);
	kpinsert("OQ",F2);
	kpinsert("OR",F3);
	kpinsert("OS",F4);
	kpinsert("Op",F5);
	kpinsert("Oq",F6);
	kpinsert("Or",F7);
	kpinsert("Os",F8);
	kpinsert("Ot",F9);
	kpinsert("Ou",F10);
	kpinsert("Ov",F11);
	kpinsert("Ow",F12);

	/*
	 * special keypad functions
	 */
	kpinsert("[4J",K_PAD_PREVPAGE);
	kpinsert("[3J",K_PAD_NEXTPAGE);
	kpinsert("[2J",K_PAD_HOME);
	kpinsert("[N",K_PAD_END);

	/* 
	 * ANSI mode.
	 */
	kpinsert("[=a",F1);
	kpinsert("[=b",F2);
	kpinsert("[=c",F3);
	kpinsert("[=d",F4);
	kpinsert("[=e",F5);
	kpinsert("[=f",F6);
	kpinsert("[=g",F7);
	kpinsert("[=h",F8);
	kpinsert("[=i",F9);
	kpinsert("[=j",F10);
	kpinsert("[=k",F11);
	kpinsert("[=l",F12);

    kpinsert("OA",K_PAD_UP);	/* DEC vt100, ANSI and cursor key mode. */
    kpinsert("OB",K_PAD_DOWN);
    kpinsert("OD",K_PAD_LEFT);
    kpinsert("OC",K_PAD_RIGHT);

    kpinsert("[A",K_PAD_UP);	/* DEC vt100, ANSI, cursor key mode reset. */
    kpinsert("[B",K_PAD_DOWN);
    kpinsert("[D",K_PAD_LEFT);
    kpinsert("[C",K_PAD_RIGHT);

    kpinsert("A",K_PAD_UP);	/* DEC vt52 mode. */
    kpinsert("B",K_PAD_DOWN);
    kpinsert("D",K_PAD_LEFT);
    kpinsert("C",K_PAD_RIGHT);

    kpinsert("[215z",K_PAD_UP); /* Sun Console sequences. */
    kpinsert("[221z",K_PAD_DOWN);
    kpinsert("[217z",K_PAD_LEFT);
    kpinsert("[219z",K_PAD_RIGHT);
}


#define	newnode()	(struct KBSTREE *)malloc(sizeof(struct KBSTREE))
/*
 * kbinsert - insert a keystroke escape sequence into the global search
 *	      structure.
 */
kpinsert(kstr, kval)
char	*kstr;
int	kval;
{
    register	char	*buf;
    register	struct KBSTREE *temp;
    register	struct KBSTREE *trail;

    if(kstr == NULL)
      return;

    temp = trail = kpadseqs;
    if(kstr[0] == '\033')
      buf = kstr+1;			/* can the ^[ character */ 
    else
      buf = kstr;

    for(;;) {
	if(temp == NULL){
	    temp = newnode();
	    temp->value = *buf;
	    temp->func = 0;
	    temp->left = NULL;
	    temp->down = NULL;
	    if(kpadseqs == NULL)
	      kpadseqs = temp;
	    else
	      trail->down = temp;
	}
	else{				/* first entry */
	    while((temp != NULL) && (temp->value != *buf)){
		trail = temp;
		temp = temp->left;
	    }

	    if(temp == NULL){   /* add new val */
		temp = newnode();
		temp->value = *buf;
		temp->func = 0;
		temp->left = NULL;
		temp->down = NULL;
		trail->left = temp;
	    }
	}

	if (*(++buf) == '\0'){
	    break;
	}
	else{
	    trail = temp;
	    temp = temp->down;
	}
    }
    
    if(temp != NULL)
      temp->func = kval;
}
 I suppose that this information could be put in
 * a better place than a line of code.
 */
void
makename(bname, fname)
char    bname[];
char    fname[];
{
    register char   *cp1;
    register char   *cp2;

    cp1 = &fname[0];
    while (*cp1 != 0)
      ++cp1;

    while (cp1!=&fname[0] && cp1[-1]!='/')
      --cp1;

    cp2 = &bname[0];
    while (cp2!=&bname[NBUFN-1] && *cpDarkNET-1.08/pico.BBS/mswin.bmp                                                                        644   21270   21270         4166  5672463053  11266                                                                                                                                                                                                                                                                                                                                                                      BMv      v   (   @   @                                 €  €   €€ €   € € €€  ÀÀÀ €€€   ÿ  ÿ   ÿÿ ÿ   ÿ ÿ ÿÿ  ÿÿÿ wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwxˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ‡wwwwwwxˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ‡wwwwwwÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷wwwwwwÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷wwwwwø‡wwwwwwwwwwwwwwwwwwwwwwwø‡wwwø‡wwwwwwwwwwwwwwwwwwwwwwwø‡wwwø‡wwwwwwwwwwwwwwwwwwwwwwwø‡wwwø‡wwwwwwwwwwwwwwwwwwwwwwwø‡wwwø‡wwwwwwwwwwÿ÷wwwwwwwwwwø‡wwwø‡wwwwwwwwwwÿ÷wwwwwwwwwwø‡wwwø‡wwwˆˆˆwwwwÿ÷wwwwˆˆˆwwwø‡wwwø‡wwwˆˆˆwwwwÿ÷wwwwˆˆˆwwwø‡wwwø‡wwwwˆˆˆwwwÿ÷wwwˆˆˆwwwwø‡wwwø‡wwwwˆˆˆwwwÿ÷wwwˆˆˆwwwwø‡wwwø‡wwwwwˆˆ‡wwÿ÷wwˆˆˆwwwwwø‡wwwø‡wwwwwˆˆ‡wwÿ÷wwˆˆˆwwwwwø‡wwwø‡wwwwwwˆˆ‡wÿ÷wxˆˆwwwwwwø‡wwwø‡wwwwwwˆˆ‡wÿ÷wxˆˆwwwwwwø‡wwwø‡wˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆwø‡wwwø‡wˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆwø‡wwwø‡wÿwwwwwwwwwwwwwwwwwwwˆwø‡wwwø‡wÿwwwwwwwwwwwwwwwwwwwˆwø‡wwwø‡wÿwÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌwˆwø‡wwwø‡wÿwÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌwˆwø‡wwwø‡wÿwÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌwˆwø‡wwwø‡wÿwÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌwˆwø‡wwwø‡wÿwÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌwˆwø‡wwwø‡wÿwÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌwˆwø‡wwwø‡wÿwÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌwˆwø‡wwwø‡wÿwÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌwˆwø‡wwwø‡wÿwÌË¼ÌÌÌ»ÌË»»ÌÌ»»¼Ìwˆwø‡wwwø‡wÿwÌË¼ÌÌÌ»Ì»»»¼Ë»»»Ìwˆwø‡wwwø‡wÿwÌË¼ÌÌÌ»Ì»ÌË¼Ë¼Ì»Ìwˆwø‡wwwø‡wÿwÌË¼ÌÌÌ»Ì»ÌÌÌË¼Ì»Ìwˆwø‡wwwø‡wÿwÌË»»¼Ì»Ì»ÌÌÌË¼Ì»Ìwˆwø‡wwwø‡wÿwÌË¼Ì»Ì»Ì»ÌÌÌË¼Ì»Ìwˆwø‡wwwø‡wÿwÌË¼Ì»Ì»Ì»ÌË¼Ë¼Ì»Ìwˆwø‡wwwø‡wÿwÌË»»»Ì»Ì»»»¼Ë»»»Ìwˆwø‡wwwø‡wÿwÌË»»¼Ì»ÌË»»ÌÌ»»¼Ìwˆwø‡wwwø‡wÿwÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌwˆwø‡wwwø‡wÿwÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌwˆwø‡wwwø‡wÿwÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌwˆwø‡wwwø‡wÿwÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌwˆwø‡wwwø‡wÿwÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌwˆwø‡wwwø‡wÿwÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌwˆwø‡wwwø‡wÿwÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌwˆwø‡wwwø‡wÿwÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌwˆwø‡wwwø‡wÿwwwwwwwwwwwwwwwwwwwˆwø‡wwwø‡wÿwwwwwwwwwwwwwwwwwwwˆwø‡wwwø‡wÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿwø‡wwwø‡wÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿwø‡wwwø‡wwwwwwwwwwwwwwwwwwwwwwwø‡wwwø‡wwwwwwwwwwwwwwwwwwwwwwwø‡wwwø‡wwwwwwwwwwwwwwwwwwwwwwwø‡wwwø‡wwwwwwwwwwwwwwwwwwwwwwwø‡wwwøˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆø‡wwwwøˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆø‡wwwwÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷wwwwwwÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww                                                                                                                                                                                                                                                                                                                                                                                                          DarkNET-1.08/pico.BBS/mswinver.c                                                                       644   21270   21270         1744  5672463053  11446                                                                                                                                                                                                                                                                                                                                                                      /*
 * Pico Versions:
 *
 * 1.0.16	Looks for 'mailcap' in the pine home directory.
 *		Slightly more informative error messages when failed to exec
 *		viewer.
 *		Changed the name to PC-Pine and PC-Pico (for Windows).
 *		Tells the user to delete the temp image file.
 * 1.0.17	Added Cut, Copy, and Paste.
 *		Several changes in pine.
 *		Fixed bug with reallocating a NULL block.
 * 1.0.18	Added "Cancel Paste!"
 * 2.4.1	Aligned with pico version numbers.
 * 2.4.2	Support for copy of whole text from pine's text viewer, and
 *		limited amount of text that will be pasted during text
 *		input prompts.
 * 2.4.3	Added printing capability.
 *
 */


#define VER_MAJOR 2
#define VER_MINOR 5
extern char datestamp[];


/*
 * Return major version number...
 */
int
mswin_majorver()
{
    return(VER_MAJOR);
}


/*
 * Return minor version number...
 */
int
mswin_minorver()
{
    return(VER_MINOR);
}


/*
 * Return compilation number...
 */
char *
mswin_compilation_date()
{
    return(datestamp);
}
f whole text from pine's texDarkNET-1.08/pico.BBS/os_vms.h                                                                         644   21270   21270         5553  5672463053  11111                                                                                                                                                                                                                                                                                                                                                                      /*
 * $Id: os_vms.h,v 1.3 1994/09/22 21:59:53 mikes Exp $
 *
 * Program:	Operating system dependent routines - VMS 5.n
 *
 *
 * Yehavi Bourvine
 * Hebrew University of Jeruselem
 * +972-2-585684
 * YEHAVI@vms.huji.ac.il
 *
 * Please address all bugs and comments to "pine-bugs@cac.washington.edu"
 *
 * Copyright 1991-1994  University of Washington
 *
 *  Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee to the University of
 * Washington is hereby granted, provided that the above copyright notice
 * appears in all copies and that both the above copyright notice and this
 * permission notice appear in supporting documentation, and that the name
 * of the University of Washington not be used in advertising or publicity
 * pertaining to distribution of the software without specific, written
 * prior permission.  This software is made available "as is", and
 * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
 * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
 * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
 * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 * Pine and Pico are trademarks of the University of Washington.
 * No commercial use of these trademarks may be made without prior
 * written permission of the University of Washington.
 *
 */

#ifndef	OSDEP_H
#define	OSDEP_H

#include	<string.h>

#undef	CTRL
#include	<signal.h>

#include	<ctype.h>
#include	<types.h>

#include	<stat.h>

/*
 * type qsort() expects
 */
#define	QSType	  int
#define QcompType void

/*
 * File name separator, as a char and string
 */
#define	C_FILESEP	'/'
#define	S_FILESEP	""

/*
 * Place where mail gets delivered (for pico's new mail checking)
 */
#define	MAILDIR		"SYS$LOGIN:"


/*
 * What and where the tool that checks spelling is located.  If this is
 * undefined, then the spelling checker is not compiled into pico.
 */
#define SPELLER         "$ SPELL"

/* memcpy() is no good for overlapping blocks.  If that's a problem, use
 * the memmove() in ../c-client
 */
#define bcopy(a,b,s) memmove (b, a, s)

struct  KBSTREE {
	char	value;
        int     func;              /* Routine to handle it         */
	struct	KBSTREE *down; 
	struct	KBSTREE	*left;
};
extern struct KBSTREE *kpadseqs;
extern int kbseq();


extern char *getcwd(char *, int);

#ifdef ANSI_DRIVER
#define	NROW	24
#define	NCOL	80
#endif

#define ttputc __ttputc

/*
 * Mode passed chmod() to make tmp files exclusively user read/write-able
 */
#define	MODE_READONLY	(0600)

#endif	/* OSDEP_H */
                                                                                                                                                     DarkNET-1.08/pico.BBS/dos_gen.c                                                                        644   21270   21270        41135  5672463053  11230                                                                                                                                                                                                                                                                                                                                                                      /*
 * $Id: dos_gen.c,v 4.3 1994/09/27 16:20:33 mikes Exp $
 *
 * Program:	Operating system dependent routines - MS DOS Generic
 *
 *
 * Michael Seibel
 * Networks and Distributed Computing
 * Computing and Communications
 * University of Washington
 * Administration Builiding, AG-44
 * Seattle, Washington, 98195, USA
 * Internet: mikes@cac.washington.edu
 *
 * Please address all bugs and comments to "pine-bugs@cac.washington.edu"
 *
 * Copyright 1991-1994  University of Washington
 *
 *  Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee to the University of
 * Washington is hereby granted, provided that the above copyright notice
 * appears in all copies and that both the above copyright notice and this
 * permission notice appear in supporting documentation, and that the name
 * of the University of Washington not be used in advertising or publicity
 * pertaining to distribution of the software without specific, written
 * prior permission.  This software is made available "as is", and
 * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
 * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
 * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
 * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 * Pine and Pico are trademarks of the University of Washington.
 * No commercial use of these trademarks may be made without prior
 * written permission of the University of Washington.
 *
 *
 * Notes:
 *     - This file should contain the cross section of functions useful
 *       in both DOS and Windows ports of pico.
 *
 */


/*
 * Useful definitions...
 */
static int mexist = 0;		/* is the mouse driver installed? */
static int nbuttons;		/* number of buttons on the mouse */
static unsigned mnoop;
static unsigned char okinfname[32] = {
      0,    0, 			/* ^@ - ^G, ^H - ^O  */
      0,    0,			/* ^P - ^W, ^X - ^_  */
      0,    0x17,		/* SP - ' ,  ( - /   */
      0xff, 0xe0,		/*  0 - 7 ,  8 - ?   */
      0x7f, 0xff,		/*  @ - G ,  H - O   */
      0xff, 0xe9,		/*  P - W ,  X - _   */
      0x7f, 0xff,		/*  ` - g ,  h - o   */
      0xff, 0xf6,		/*  p - w ,  x - DEL */
      0,    0, 			/*  > DEL   */
      0,    0,			/*  > DEL   */
      0,    0, 			/*  > DEL   */
      0,    0, 			/*  > DEL   */
      0,    0 			/*  > DEL   */
};


#if	MOUSE

/*
 * register_mfunc - register the given function to get called
 * 		    on mouse events in the given display region
 */
register_mfunc(f, tlr, tlc, brr, brc)
unsigned long (*f)(int, int, int);
int      tlr, tlc, brr, brc;
{
    if(!mexist)
      return(FALSE);

    mfunc.action = f;
    mfunc.tl.r   = tlr;
    mfunc.br.r   = brr;
    mfunc.tl.c   = tlc;
    mfunc.br.c   = brc;
    mfunc.lbl.c  = mfunc.lbl.r = 0;
    mfunc.label  = "";
    return(TRUE);
}


/*
 * clear_mfunc - clear any previously set mouse function
 */
void
clear_mfunc()
{
    mfunc.action = NULL;
}


/*
 * register_key - register the given keystroke to accept mouse events
 */
void
register_key(i, rval, label, row, col, len)
int       i;
unsigned  rval;
char     *label;
int       row, col, len;
{
    if(i > 11)
      return;

    menuitems[i].val   = rval;
    menuitems[i].tl.r  = menuitems[i].br.r = row;
    menuitems[i].tl.c  = col;
    menuitems[i].br.c  = col + len;
    menuitems[i].lbl.r = menuitems[i].tl.r;
    menuitems[i].lbl.c = menuitems[i].tl.c;
    menuitems[i].label = label;
}


/*
 * pico_mouse - general handler for mouse events in the pico's
 *              text region.
 */
unsigned long
pico_mouse(down, row, col)
int down, row, col;
{
    static   int ldown = 0, lrow = 0, lcol = 0, double_click = 0;
    static   clock_t lastcalled = 0;
    unsigned long rv = FALSE;
    unsigned c;

    if(down){
	if(lrow == row && lcol == col){		/* same event!! */
	    if(clock() < (lastcalled + (clock_t)(CLOCKS_PER_SEC/2)))
	      double_click++;
	}

	lrow       = row;
	lcol       = col;
	lastcalled = clock();
    }
    else if(lrow == row && lcol == col){
	LINE *lp = curwp->w_linep;
	int    i;

	i = lrow - ((Pmaster) ? ComposerTopLine : 2);
	while(i-- && lp != curbp->b_linep)
	  lp = lforw(lp);

        curgoal = col;
	curwp->w_dotp = lp;
	curwp->w_doto = getgoal(lp);
	curwp->w_flag |= WFMOVE;

	if(double_click)
	  setmark(0, 1);

	double_click = 0;
	rv = NODATA;
	rv = (rv<<16)|TRUE;
    }
    return(rv);
}
#endif	/* MOUSE */


/*
 * fallowc - returns TRUE if c is allowable in filenames, FALSE otw
 */
fallowc(c)
int c;
{
    return(okinfname[c>>3] & 0x80>>(c&7));
}


/*
 * fexist - returns TRUE if the file exists, FALSE otherwise
 */
fexist(file, m, l)
char *file, *m;
long *l;
{
    struct stat	sbuf;

    if(l != NULL)
      *l = 0L;

    if(stat(file, &sbuf) < 0){
	if(ENOENT)				/* File not found */
	  return(FIOFNF);
	else
	  return(FIOERR);
    }

    if(l != NULL)
      *l = sbuf.st_size;

    if(sbuf.st_mode & S_IFDIR)
      return(FIODIR);

    if(m[0] == 'r')				/* read access? */
      return((S_IREAD & sbuf.st_mode) ? FIOSUC : FIONRD);
    else if(m[0] == 'w')			/* write access? */
      return((S_IWRITE & sbuf.st_mode) ? FIOSUC : FIONWT);
    else if(m[0] == 'x')			/* execute access? */
      return((S_IEXEC & sbuf.st_mode) ? FIOSUC : FIONEX);
    return(FIOERR);				/* what? */
}


/*
 * isdir - returns true if fn is a readable directory, false otherwise
 *         silent on errors (we'll let someone else notice the problem;)).
 */
isdir(fn, l)
char *fn;
long *l;
{
    struct stat sbuf;

    if(l)
      *l = 0;

    if(stat(fn, &sbuf) < 0)
      return(0);

    if(l)
      *l = sbuf.st_size;

    return(sbuf.st_mode & S_IFDIR);
}


/*
 * gethomedir - returns the users home directory
 *              Note: home is malloc'd for life of pico
 */
char *gethomedir(l)
int *l;
{
    static char *home = NULL;
    static short hlen = 0;

    if(home == NULL){
	char buf[NLINE];
	sprintf(buf, "%c:\\", _getdrive() + 'A' - 1);
	hlen = strlen(buf);
	if((home=(char *)malloc(((size_t)hlen + 1) * sizeof(char))) == NULL){
	    emlwrite("Problem allocating space for home dir", NULL);
	    return(0);
	}
	strcpy(home, buf);
    }

    if(l)
      *l = hlen;

    return(home);
}


/*
 * homeless - returns true if given file does not reside in the current
 *            user's home directory tree. 
 */
homeless(f)
char *f;
{
    char *home;
    int   len;

    home = gethomedir(&len);
    return(strncmp(home, f, len));
}


/*
 * errstr - return system error string corresponding to given errno
 *          Note: strerror() is not provided on all systems, so it's 
 *          done here once and for all.
 */
char *errstr(err)
int err;
{
    return((err >= 0 && err < sys_nerr) ? sys_errlist[err] : NULL);
}


/*
 * getfnames - return all file names in the given directory in a single 
 *             malloc'd string.  n contains the number of names
 */
char *getfnames(dn, n)
char *dn;
int  *n;
{
    int status;
    long l;
    char *names, *np, *p;
    char buf[NLINE];
    struct stat sbuf;
    struct find_t dbuf;					/* opened directory */

    *n = 0;

    if(stat(dn, &sbuf) < 0){
	sprintf(buf, "\007Dir \"%s\": %s", dn, strerror(errno));
	emlwrite(buf, NULL);
	return(NULL);
    } 
    else{
	l = sbuf.st_size;
	if(!(sbuf.st_mode & S_IFDIR)){
	    emlwrite("\007Not a directory: \"%s\"", dn);
	    return(NULL);
	}
    }

    if((names=(char *)malloc(sizeof(char)*3072)) == NULL){
	emlwrite("\007Can't malloc space for file names", NULL);
	return(NULL);
    }
    np = names;

    strcpy(buf, dn);
    if(dn[strlen(dn)-1] == '\\')
      strcat(buf, "*.*");
    else
      strcat(buf, "\\*.*");

    if(_dos_findfirst(buf, _A_NORMAL|_A_SUBDIR, &dbuf) != 0){
	emlwrite("Can't find first file in \"%s\"", dn);
	free((char *) names);
	return(NULL);
    }

    do{
	(*n)++;
	p = dbuf.name;
	while((*np++ = *p++) != '\0')
	  ;
    }
    while(_dos_findnext(&dbuf) == 0);

    return(names);
}


/*
 * fioperr - given the error number and file name, display error
 */
void
fioperr(e, f)
int  e;
char *f;
{
    switch(e){
      case FIOFNF:				/* File not found */
	emlwrite("\007File \"%s\" not found", f);
	break;
      case FIOEOF:				/* end of file */
	emlwrite("\007End of file \"%s\" reached", f);
	break;
      case FIOLNG:				/* name too long */
	emlwrite("\007File name \"%s\" too long", f);
	break;
      case FIODIR:				/* file is a directory */
	emlwrite("\007File \"%s\" is a directory", f);
	break;
      case FIONWT:
	emlwrite("\007Write permission denied: %s", f);
	break;
      case FIONRD:
	emlwrite("\007Read permission denied: %s", f);
	break;
      case FIONEX:
	emlwrite("\007Execute permission denied: %s", f);
	break;
      default:
	emlwrite("\007File I/O error: %s", f);
    }
}


/*
 * pfnexpand - pico's function to expand the given file name if there is 
 *	       a leading '~'
 */
char *pfnexpand(fn, len)
char *fn;
int  len;
{
    return(fn);
}


/*
 * fixpath - make the given pathname into an absolute path
 */
fixpath(name, len)
char *name;
int  len;
{
    char file[_MAX_PATH];
    int  dr;

    if(!len)
      return(0);
    
    /* return the full path of given file */
    if(myisalpha(name[0]) && name[1] == ':'){	/* have drive spec? */
	if(name[2] != '\\'){			/* including path? */
	    dr = toupper(name[0]) - 'A' + 1;
	    if(_getdcwd(dr, file, _MAX_PATH) != NULL){
		if(file[strlen(file)-1] != '\\')
		  strcat(file, "\\");

		strcat(file, &name[2]);		/* add file name */
	    }
	    else
	      return(0);
	}
	else
	  return(1);		/* fully qualified with drive and path! */
    }
    else if(name[0] == '\\') {			/* no drive spec! */
	sprintf(file, "%c:%s", _getdrive()+'A'-1, name);
    }
    else{
	if(Pmaster && !gmode&MDCURDIR)		/* home dir relative */
	  strcpy(file, gethomedir(NULL));
	else if(!_getcwd(file, _MAX_PATH))	/* no qualification */
	  return(0);

	if(*name){				/* if name, append it */
	    strcat(file, "\\");
	    strcat(file, name);
	}
    }

    strncpy(name, file, len);			/* copy back to real buffer */
    name[len-1] = '\0';				/* tie off just in case */
    return(1);
}


/*
 * compresspath - given a base path and an additional directory, collapse
 *                ".." and "." elements and return absolute path (appending
 *                base if necessary).  
 *
 *                returns  1 if OK, 
 *                         0 if there's a problem
 *                         new path, by side effect, if things went OK
 */
compresspath(base, path, len)
char *base, *path;
int  len;
{
    register int i;
    int  depth = 0;
    char *p;
    char *stack[32];
    char  pathbuf[NLINE];

#define PUSHD(X)  (stack[depth++] = X)
#define POPD()    ((depth > 0) ? stack[--depth] : "")

    strcpy(pathbuf, path);
    fixpath(pathbuf, len);

    p = pathbuf;
    for(i=0; pathbuf[i] != '\0'; i++){		/* pass thru path name */
	if(pathbuf[i] == C_FILESEP){
	    if(p != pathbuf)
	      PUSHD(p);				/* push dir entry */
	    p = &pathbuf[i+1];			/* advance p */
	    pathbuf[i] = '\0';			/* cap old p off */
	    continue;
	}

	if(pathbuf[i] == '.'){			/* special cases! */
	    if(pathbuf[i+1] == '.'			/* parent */
	       && (pathbuf[i+2] == C_FILESEP || pathbuf[i+2] == '\0')){
		if(!strcmp(POPD(),""))		/* bad news! */
		  return(0);

		i += 2;
		p = (pathbuf[i] == '\0') ? "" : &pathbuf[i+1];
	    }
	    else if(pathbuf[i+1] == C_FILESEP || pathbuf[i+1] == '\0'){
		i++;
		p = (pathbuf[i] == '\0') ? "" : &pathbuf[i+1];
	    }
	}
    }

    if(*p != '\0')
      PUSHD(p);					/* get last element */

    path[0] = '\0';
    for(i = 0; i < depth; i++){
	strcat(path, S_FILESEP);
	strcat(path, stack[i]);
    }

    return(1);					/* everything's ok */
}


/*
 * tmpname - return a temporary file name in the given buffer
 */
void
tmpname(name)
char *name;
{
    sprintf(name, tmpnam(NULL));	/* tmp file name */
    strcat(name, ".txt");
}


/*
 * Take a file name, and from it
 * fabricate a buffer name. This routine knows
 * about the syntax of file names on the target system.
 * I suppose that this information could be put in
 * a better place than a line of code.
 */
void
makename(bname, fname)
char    bname[];
char    fname[];
{
        register char   *cp1;
        register char   *cp2;

        cp1 = &fname[0];
        while (*cp1 != 0)
                ++cp1;

        while (cp1!=&fname[0] && cp1[-1]!='\\')
                --cp1;
        cp2 = &bname[0];
        while (cp2!=&bname[NBUFN-1] && *cp1!=0 && *cp1!=';')
                *cp2++ = *cp1++;
        *cp2 = 0;
}


/*
 * copy - copy contents of file 'a' into a file named 'b'.  Return error
 *        if either isn't accessible or is a directory
 */
copy(a, b)
char *a, *b;
{
    int    in, out, n, rv = 0;
    char   *cb;
    struct stat tsb, fsb;

    if(stat(a, &fsb) < 0){		/* get source file info */
	emlwrite("Can't Copy: %s", errstr(errno));
	return(-1);
    }

    if(!(fsb.st_mode&S_IREAD)){		/* can we read it? */
	emlwrite("\007Read permission denied: %s", a);
	return(-1);
    }

    if((fsb.st_mode&S_IFMT) == S_IFDIR){ /* is it a directory? */
	emlwrite("\007Can't copy: %s is a directory", a);
	return(-1);
    }

    if(stat(b, &tsb) < 0){		/* get dest file's mode */
	switch(errno){
	  case ENOENT:
	    break;			/* these are OK */
	  default:
	    emlwrite("\007Can't Copy: %s", errstr(errno));
	    return(-1);
	}
    }
    else{
	if(!(tsb.st_mode&S_IWRITE)){	/* can we write it? */
	    emlwrite("\007Write permission denied: %s", b);
	    return(-1);
	}

	if((tsb.st_mode&S_IFMT) == S_IFDIR){	/* is it directory? */
	    emlwrite("\007Can't copy: %s is a directory", b);
	    return(-1);
	}

	if(fsb.st_dev == tsb.st_dev && fsb.st_ino == tsb.st_ino){
	    emlwrite("\007Identical files.  File not copied", NULL);
	    return(-1);
	}
    }

    if((in = open(a, _O_RDONLY)) < 0){
	emlwrite("Copy Failed: %s", errstr(errno));
	return(-1);
    }

    if((out=creat(b, fsb.st_mode&0xfff)) < 0){
	emlwrite("Can't Copy: %s", errstr(errno));
	close(in);
	return(-1);
    }

    if((cb = (char *)malloc(NLINE*sizeof(char))) == NULL){
	emlwrite("Can't allocate space for copy buffer!", NULL);
	close(in);
	close(out);
	return(-1);
    }

    while(1){				/* do the copy */
	if((n = read(in, cb, NLINE)) < 0){
	    emlwrite("Can't Read Copy: %s", errstr(errno));
	    rv = -1;
	    break;			/* get out now */
	}

	if(n == 0)			/* done! */
	  break;

	if(write(out, cb, n) != n){
	    emlwrite("Can't Write Copy: %s", errstr(errno));
	    rv = -1;
	    break;
	}
    }

    free(cb);
    close(in);
    close(out);
    return(rv);
}


/*
 * Open a file for writing. Return TRUE if all is well, and FALSE on error
 * (cannot create).
 */
ffwopen(fn)
char    *fn;
{
    extern FILE *ffp;

    if ((ffp=fopen(fn, "w")) == NULL) {
        emlwrite("Cannot open file for writing", NULL);
        return (FIOERR);
    }

    return (FIOSUC);
}


/*
 * Close a file. Should look at the status in all systems.
 */
ffclose()
{
    extern FILE *ffp;

    if (fclose(ffp) != FALSE) {
        emlwrite("Error closing file", NULL);
        return(FIOERR);
    }

    return(FIOSUC);
}


/*
 * worthit - generic sort of test to roughly gage usefulness of using 
 *           optimized scrolling.
 *
 * note:
 *	returns the line on the screen, l, that the dot is currently on
 */
worthit(l)
int *l;
{
    int i;			/* l is current line */
    unsigned below;		/* below is avg # of ch/line under . */

    *l = doton(&i, &below);
    below = (i > 0) ? below/(unsigned)i : 0;

    return(below > 3);
}


/*
 * o_insert - optimize screen insert of char c
 */
o_insert(c)
char c;
{
    return(0);
}


/*
 * o_delete - optimized character deletion
 */
o_delete()
{
    return(0);
}


/*
 * pico_new_mail - just checks mtime and atime of mail file and notifies user 
 *	           if it's possible that they have new mail.
 */
pico_new_mail()
{
    return(0);
}



/*
 * time_to_check - checks the current time against the last time called 
 *                 and returns true if the elapsed time is > timeout
 */
time_to_check()
{
    static time_t lasttime = 0L;

    if(!timeout)
      return(FALSE);

    if(time((long *) 0) - lasttime > (time_t)timeout){
	lasttime = time((long *) 0);
	return(TRUE);
    }
    else
      return(FALSE);
}


/*
 * sstrcasecmp - compare two pointers to strings case independently
 */
sstrcasecmp(s1, s2)
QcompType *s1, *s2;
{
    return(stricmp(*(char **)s1, *(char **)s2));
}


/*
 * sleep the given number of microseconds
 */
ssleep(s)
    clock_t s;
{
    s += clock();
    while(s > clock())
      ;
}


/*
 * sleep the given number of seconds
 */
sleep(t)
    int t;
{
    time_t out = (time_t)t + time((long *) 0);
    while(out > time((long *) 0))
      ;
}
07Write permission denied: %s", f);
	break;
      case FIONRD:
	emlwrite("\007Read permission denied: %s", f);
	break;
      case FIONEX:
	emlwrite("\007Execute permission denied: %s", f);
	break;
      default:
	emlwrite("\007File I/O error: %s", f);
    }
}


/*
 * pfnexpand - pico's function to expand the given file name if there is 
 *	       a leading '~'
 */
char *pfnexpand(fn, len)
char *fn;
int  len;
{
    rDarkNET-1.08/pico.BBS/dos_gen.h                                                                        644   21270   21270         5365  5672463053  11222                                                                                                                                                                                                                                                                                                                                                                      /*
 * $Id: dos_gen.h,v 4.1 1994/04/04 20:36:54 mikes Exp $
 *
 * Program:	Operating system dependent header - MS DOS Generic
 *
 *
 * Michael Seibel
 * Networks and Distributed Computing
 * Computing and Communications
 * University of Washington
 * Administration Builiding, AG-44
 * Seattle, Washington, 98195, USA
 * Internet: mikes@cac.washington.edu
 *
 * Please address all bugs and comments to "pine-bugs@cac.washington.edu"
 *
 * Copyright 1991-1994  University of Washington
 *
 *  Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee to the University of
 * Washington is hereby granted, provided that the above copyright notice
 * appears in all copies and that both the above copyright notice and this
 * permission notice appear in supporting documentation, and that the name
 * of the University of Washington not be used in advertising or publicity
 * pertaining to distribution of the software without specific, written
 * prior permission.  This software is made available "as is", and
 * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
 * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
 * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
 * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 * Pine and Pico are trademarks of the University of Washington.
 * No commercial use of these trademarks may be made without prior
 * written permission of the University of Washington.
 *
 *
 * Notes:
 *     - This file should contain the cross section of functions useful
 *       in both DOS and Windows ports of pico.
 *
 */

#ifdef	MOUSE

typedef struct point {
    unsigned	r:8;		/* row value				*/
    unsigned	c:8;		/* column value				*/
} POINT;


typedef struct menuitem {
    unsigned	val;		/* return value				*/
    unsigned long (*action)();	/* action to perform			*/
    POINT	tl;		/* top-left corner of active area	*/
    POINT	br;		/* bottom-right corner of active area	*/
    POINT	lbl;		/* where the label starts		*/
    char	*label;
} MENUITEM;


MENUITEM menuitems[12];		/* key labels and functions */
MENUITEM mfunc;			/* single generic function  */


/* Test if mouse position (R, C) is in menu item (X) */
#define	M_ACTIVE(R, C, X)	(((R) >= (X)->tl.r && (R) <= (X)->br.r) \
				 && ((C) >= (X)->tl.c && (C) < (X)->br.c))
#endif	/* MOUSE */

#ifdef TURBOC
/*
 * big stack for turbo C
 */
extern	unsigned	_stklen = 16384;
#endif
yright notice and this
 * permission notice appear in supporting documentation, and that the name
 * of the University of Washington not be used in advertising or publicity
 * pertaining to distribution of the software without specific, written
 * prior permission.  DarkNET-1.08/pico.BBS/mswin.h                                                                          644   21270   21270        15544  5672463053  10761                                                                                                                                                                                                                                                                                                                                                                      #line 2 "mswin.h"
/*
 *
 * Program:	Operating system dependent routines - Microsoft Windows 3.1
 *
 *
 * Thomas Unger
 * Networks and Distributed Computing
 * Computing and Communications
 * University of Washington
 * Administration Builiding, AG-44
 * Seattle, Washington, 98195, USA
 * Internet: tunger@cac.washington.edu
 *
 * Please address all bugs and comments to "pine-bugs@cac.washington.edu"
 *
 * Copyright 1991-1994  University of Washington
 *
 *  Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee to the University of
 * Washington is hereby granted, provided that the above copyright notice
 * appears in all copies and that both the above copyright notice and this
 * permission notice appear in supporting documentation, and that the name
 * of the University of Washington not be used in advertising or publicity
 * pertaining to distribution of the software without specific, written
 * prior permission.  This software is made available "as is", and
 * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
 * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
 * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
 * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 * Pine and Pico are trademarks of the University of Washington.
 * No commercial use of these trademarks may be made without prior
 * written permission of the University of Washington.
 *
 */


#undef OWNRECT

/*
 * Equivalent to a windows handle.
 */
typedef unsigned int	WINHAND;

/*
 * Mouse input events. 
 */
typedef struct {
	int		event;
	int		button;
	int		nRow;
	int		nColumn;
	unsigned long	flags;
} MEvent;


/*
 * Type of function expected by mswin_allowcopy and mswin_allowcopycut
 * and used in EditDoCopyData
 */
typedef	int (*getc_t)(int pos);


#define MEVENT_NONE		0x0000
#define MEVENT_MOUSEUP		0x0001
#define MEVENT_MOUSEDOWN	0x0002
#define MEVENT_ANY		0x0003

#define MEVENT_KEY_LBUTTON	0x0001		/* = MK_LBUTTON */
#define MEVENT_KEY_MBUTTON	0x0010		/* = MK_MBUTTON */
#define MEVENT_KEY_RBUTTON	0x0002		/* = MK_RBUTTON */
#define MEVENT_KEY_SHIFT	0x0004		/* = MK_SHIFT */
#define MEVENT_KEY_CONTROL	0x0008		/* = MK_CONTROL */


#define MSWIN_RANGE_START	0x7001
#define MSWIN_KEY_UP		0x7001
#define MSWIN_KEY_DOWN		0x7002
#define MSWIN_KEY_RIGHT		0x7003
#define MSWIN_KEY_LEFT		0x7004
#define MSWIN_KEY_PREVPAGE	0x7005
#define MSWIN_KEY_NEXTPAGE	0x7006
#define MSWIN_KEY_HOME		0x7007
#define MSWIN_KEY_END		0x7008
#define MSWIN_KEY_DELETE	0x7009
#define MSWIN_KEY_F1		0x700a
#define MSWIN_KEY_F2		0x700b
#define MSWIN_KEY_F3		0x700c
#define MSWIN_KEY_F4		0x700d
#define MSWIN_KEY_F5		0x700e
#define MSWIN_KEY_F6		0x700f
#define MSWIN_KEY_F7		0x7010
#define MSWIN_KEY_F8		0x7011
#define MSWIN_KEY_F9		0x7012
#define MSWIN_KEY_F10		0x7013
#define MSWIN_KEY_F11		0x7014
#define MSWIN_KEY_F12		0x7015
#define MSWIN_KEY_NODATA	0x7016
#define MSWIN_RANGE_END		0x7016

#define	MSWIN_PASTE_DISABLE	0
#define	MSWIN_PASTE_FULL	1
#define	MSWIN_PASTE_LINE	2

#define MSWIN_EXIT_DISABLE	0	/* disable the File/Exit menu. */
#define MSWIN_EXIT_DENY		1	/* Enable the menu, but deny exit.*/
#define MSWIN_EXIT_SENDCHAR	2	/* Enable the menu and exit by
					 * sending a character to the app.*/




/*
 * functions from mswin.c
 */

#define assert(x)	if (!(x)) AssertFail (#x, __FILE__, __LINE__, 1);
void			AssertFail	(char *str, char *file, int line, int msgbox);


int		WinGetMEvent (MEvent * pMouse);
void		WinIdle (void);
int		mswin_setdebug (int debug, FILE *debugfile);
int		mswin_setresizecallback (int (*cb)());
int		mswin_clearresizecallback (int (*cb)());
int		mswin_sethelptext (char *pHelpText);
int		mswin_setclosetext (char *pCloseText);
int		mswin_setwindow (char *fontName, char *fontSize, 
			char *fontStyle, char *windowPosition);
int		mswin_getwindow (char *fontName, char *fontSize, 
			char *fontStyle, char *windowPosition);
int		mswin_charavail (void);
int		mswin_getc (void);
int		mswin_getc_fast (void);
int		mswin_open (void);
int		mswin_close (void);
int		mswin_showcursor (int show);
int		mswin_move (int row, int column);
int		mswin_getpos (int *row, int *column);
int		mswin_getscreensize (int *row, int *column);
int		mswin_putblock (char *str, int strLen);
int		mswin_puts (char *str);
int		mswin_putc (int c);
int		mswin_outc (char c);
int		mswin_delchar (void);
int		mswin_inschar (int c);
int		mswin_rev (int state);
int		mswin_getrevstate (void);
int		mswin_eeol (void);
int		mswin_eeop (void);
int		mswin_beep (void);
int		mswin_pause (int);
int		mswin_flush (void);
int		mswin_allowpaste (int);
int		mswin_allowcopycut (getc_t);
int		mswin_allowcopy (getc_t);
int		mswin_allowexit (int allow, char *denyReason, int quitCmd);
WINHAND		mswin_inst2task (WINHAND hInst);
int		mswin_exec_and_wait (char *whatsit, char *command);
int		mswin_ontask_del (WINHAND hTask, char *path);
int		mswin_print_ready (char *docDesc);
int		mswin_print_done (void);
char *		mswin_print_error (int errorcode);
int		mswin_print_char (int c);
int		mswin_print_text (char *text);
int		mswin_savefile (char *dir, char *fName, int nMaxFName);
int		mswin_openfile (char *dir, char *fName, int nMaxFName);
int		pico_nfcolor(char *);
int		pico_nbcolor(char *);
int		pico_rfcolor(char *);
int		pico_rbcolor(char *);
int		mswin_fflush (FILE *f);
int		mswin_majorver();
int		mswin_minorver();
char	       *mswin_compilation_date();


/*
 * Memory management stuff, also from mswin.c
 */
typedef unsigned long		MemSize;
typedef void __far	      *	MemPtr;

#define MemAlloc(s)		_MemAlloc (s, __FILE__, __LINE__)
#define malloc(s)		_MemAlloc (s, __FILE__, __LINE__)
#define MemFree(b)		_MemFree (b, __FILE__, __LINE__)
#define free(b)			_MemFree (b, __FILE__, __LINE__)
#define MemRealloc(b,s)		_MemRealloc (b, s, __FILE__, __LINE__)
#define realloc(b,s)		_MemRealloc (b, s, __FILE__, __LINE__)
#define MEM_BLOCK_SIZE_MAX	0xff00

void		MemDebug (int debug, FILE *debugFile);
void __far *	_MemAlloc (MemSize size, char __far * file, int line);
int		_MemFree (void __far *block, char __far *file, int line);
void __far *	_MemRealloc (void __far *block, MemSize size, 
					char __far * file, int line);
MemSize		MemBlkSize (MemPtr block);


/*
 * Signals that are not defined by MS C
 */
#define SIGINT      2   /* Ctrl-C sequence */
#define SIGILL      4   /* illegal instruction - invalid function image */
#define SIGSEGV     11  /* segment violation */
#define SIGTERM     15  /* Software termination signal from kill */
#define SIGABRT     22  /* abnormal termination triggered by abort call */
#define SIGWINCH    28	/* Change in window size. */


#define fflush	mswin_fflush

nd comments to "pine-bugs@cac.washington.edu"
 *
 * Copyright 1991-1994  University of Washington
 *
 *  Permission to use, copy, modify, and distribute thiDarkNET-1.08/pico.BBS/blddate.c                                                                        644   21270   21270         1265  5672463054  11172                                                                                                                                                                                                                                                                                                                                                                      #include <stdio.h>
#include <time.h>

main(argc, argv)
    int    argc;
    char **argv;
{
    struct tm *t;
    time_t     ltime;

    time(&ltime);
    t = localtime(&ltime);
    printf("char datestamp[]=\"%02d-%s-%d\";\n", t->tm_mday, 
	    (t->tm_mon == 0) ? "Jan" : 
	     (t->tm_mon == 1) ? "Feb" : 
	      (t->tm_mon == 2) ? "Mar" : 
	       (t->tm_mon == 3) ? "Apr" : 
		(t->tm_mon == 4) ? "May" : 
		 (t->tm_mon == 5) ? "Jun" : 
		  (t->tm_mon == 6) ? "Jul" : 
		   (t->tm_mon == 7) ? "Aug" : 
		    (t->tm_mon == 8) ? "Sep" : 
		     (t->tm_mon == 9) ? "Oct" : 
		      (t->tm_mon == 10) ? "Nov" : 
		       (t->tm_mon == 11) ? "Dec" : "UKN",
	    1900 + t->tm_year);
    exit(0);
}
                                                                                                                                                                                                                                                                                                                                           DarkNET-1.08/pico.BBS/pine-win.lnk                                                                     644   21270   21270          127  5672463054  11637                                                                                                                                                                                                                                                                                                                                                                      bdate+mswinver+main
pico
pico
libpico+libw+toolhelp+llibcew+oldnames+commdlg
mswin.def
                                                                                                                                                                                                                                                                                                                                                                                                                                         DarkNET-1.08/pico.BBS/Makefile                                                                         644   21270   21270         5720  6044626572  11067                                                                                                                                                                                                                                                                                                                                                                      # $Id: makefile.lnx,v 1.3 1994/10/11 21:56:50 mikes Exp $
#
#   Michael Seibel
#   Networks and Distributed Computing
#   Computing and Communications
#   University of Washington
#   Administration Builiding, AG-44
#   Seattle, Washington, 98195, USA
#   Internet: mikes@cac.washington.edu
#
#   Please address all bugs and comments to "pine-bugs@cac.washington.edu"
#
#   Copyright 1991-1994  University of Washington
#
#    Permission to use, copy, modify, and distribute this software and its
#   documentation for any purpose and without fee to the University of
#   Washington is hereby granted, provided that the above copyright notice
#   appears in all copies and that both the above copyright notice and this
#   permission notice appear in supporting documentation, and that the name
#   of the University of Washington not be used in advertising or publicity
#   pertaining to distribution of the software without specific, written
#   prior permission.  This software is made available "as is", and
#   THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
#   WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
#   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
#   NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
#   INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
#   LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
#   (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
#   WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#  
#   Pine and Pico are trademarks of the University of Washington.
#   No commercial use of these trademarks may be made without prior
#   written permission of the University of Washington.
#

#
# Makefile for Linux of the PINE composer library and 
# stand-alone editor pico.
#
CC		= cc

#includes symbol for debugging
#DASHO=		-g
#for normal build
DASHO=		-O2 

CFLAGS=	 	-Dbsd -DPOSIX -DJOB_CONTROL

# switches for library building
LIBCMD=		ar
LIBARGS=	ru
RANLIB=		ranlib

LIBS=		-ltermcap

OFILES=		attach.o ansi.o basic.o bind.o browse.o buffer.o \
		composer.o display.o file.o fileio.o line.o osdep.o \
		pico.o random.o region.o search.o spell.o tcap.o \
		window.o word.o hangul.o

CFILES=		attach.c ansi.c basic.c bind.c browse.c buffer.c \
		composer.c display.c file.c fileio.c line.c osdep.c \
		pico.c random.c region.c search.c spell.c tcap.c \
		window.c word.c hangul.c

HFILES=		estruct.h edef.h efunc.h ebind.h pico.h


#
# dependencies for the Unix versions of pico and libpico.a
#
all:		pico

osdep.c:	os_unix.c
		rm -f osdep.c
		cp os_unix.c osdep.c

osdep.h:	os_unix.h
		rm -f osdep.h
		cp os_unix.h osdep.h

libpico.a:	osdep.c osdep.h $(OFILES)
		$(LIBCMD) $(LIBARGS) libpico.a $(OFILES)
		$(RANLIB) libpico.a

pico:		main.c libpico.a
		$(CC) $(CFLAGS) main.c libpico.a $(LIBS) -o pico

.c.o:		; $(CC) -c $(CFLAGS) $(DASHO) $*.c

$(OFILES):	$(HFILES)

clean:
		rm -f *.a *.o *~ osdep.c osdep.h
                                                DarkNET-1.08/pico.BBS/makefiles/                                                                       755   21270   21270            0  5672463056  11300                                                                                                                                                                                                                                                                                                                                                                      DarkNET-1.08/pico.BBS/makefiles/makefile.3b1                                                           644   21270   21270         6171  5672463054  13454                                                                                                                                                                                                                                                                                                                                                                      ## $Id: makefile.3b1,v 1.2 1994/02/25 18:36:33 hubert Exp $
#
#   Michael Seibel
#   Networks and Distributed Computing
#   Computing and Communications
#   University of Washington
#   Administration Builiding, AG-44
#   Seattle, Washington, 98195, USA
#   Internet: mikes@cac.washington.edu
#
#   Please address all bugs and comments to "pine-bugs@cac.washington.edu"
#
#   Copyright 1991-1994  University of Washington
#
#    Permission to use, copy, modify, and distribute this software and its
#   documentation for any purpose and without fee to the University of
#   Washington is hereby granted, provided that the above copyright notice
#   appears in all copies and that both the above copyright notice and this
#   permission notice appear in supporting documentation, and that the name
#   of the University of Washington not be used in advertising or publicity
#   pertaining to distribution of the software without specific, written
#   prior permission.  This software is made available "as is", and
#   THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
#   WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
#   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
#   NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
#   INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
#   LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
#   (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
#   WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
#   Pine and Pico are trademarks of the University of Washington.
#   No commercial use of these trademarks may be made without prior
#   written permission of the University of Washington.
#

#
# Makefile for Convergent Technologies made for AT&T 3b1 and 7300 computers.
# version of the PINE composer library and stand-alone editor pico.
# Port Contributor: Robert Lewis <robertle@sco.com>
#

include $(MAKEINC)/Makepre.h

#includes symbol info for debugging 
#DASHO=		-g
#for normal build
#DASHO=		-O

CFLAGS=		-Dct

# switches for library building
LIBCMD=		ar
LIBARGS=	ru
RANLIB=		:

LIBS=		-ltermcap

OFILES=		attach.o ansi.o basic.o bind.o browse.o buffer.o \
		composer.o display.o file.o fileio.o line.o osdep.o \
		pico.o random.o region.o search.o spell.o tcap.o \
		window.o word.o

CFILES=		attach.c ansi.c basic.c bind.c browse.c buffer.c \
		composer.c display.c file.c fileio.c line.c osdep.c \
		pico.c random.c region.c search.c spell.c tcap.c \
		window.c word.c

HFILES=		estruct.h edef.h efunc.h ebind.h pico.h osdep.h


#
# dependencies for the Unix versions of pico and libpico.a
#
all:		pico

osdep.c:	os_unix.c
		rm -f osdep.c
		cp os_unix.c osdep.c

osdep.h:	os_unix.h
		rm -f osdep.h
		cp os_unix.h osdep.h

libpico.a:	osdep.c osdep.h $(OFILES)
		$(LIBCMD) $(LIBARGS) libpico.a $(OFILES)
		$(RANLIB) libpico.a

pico:		main.c libpico.a
		$(LD) $(LDFLAGS) -s libpico.a $(SHAREDLIB) -o pico
#		$(CC) $(CFLAGS) main.c libpico.a $(LIBS) $(SHAREDLIB) -o pico

.c.o:		; $(CC) -c $(CFLAGS) $(DASHO) $*.c

$(OFILES):	$(HFILES)

clean:
		rm -f *.a *.o *~ osdep.c osdep.h
                                                                                                                                                                                                                                                                                                                                                                                                       DarkNET-1.08/pico.BBS/makefiles/makefile.a32                                                           644   21270   21270         6002  5672463054  13445                                                                                                                                                                                                                                                                                                                                                                      # $Id: makefile.a32,v 4.4 1994/02/25 18:36:33 hubert Exp $
#
#   Michael Seibel
#   Networks and Distributed Computing
#   Computing and Communications
#   University of Washington
#   Administration Builiding, AG-44
#   Seattle, Washington, 98195, USA
#   Internet: mikes@cac.washington.edu
#
#   Please address all bugs and comments to "pine-bugs@cac.washington.edu"
#
#   Copyright 1991-1994  University of Washington
#
#    Permission to use, copy, modify, and distribute this software and its
#   documentation for any purpose and without fee to the University of
#   Washington is hereby granted, provided that the above copyright notice
#   appears in all copies and that both the above copyright notice and this
#   permission notice appear in supporting documentation, and that the name
#   of the University of Washington not be used in advertising or publicity
#   pertaining to distribution of the software without specific, written
#   prior permission.  This software is made available "as is", and
#   THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
#   WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
#   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
#   NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
#   INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
#   LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
#   (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
#   WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#  
#   Pine and Pico are trademarks of the University of Washington.
#   No commercial use of these trademarks may be made without prior
#   written permission of the University of Washington.
#

#
# Makefile for IBM AIX on RS6000 version of the PINE composer library and 
# stand-alone editor pico.
#

#includes symbol for debugging
DASHO=		-g
#includes symbol for debugging
#DASHO=		-O

CC=		cc
CFLAGS=		-D_ALL_SOURCE -Da32 -DJOB_CONTROL -DPOSIX
#CFLAGS=		-g -I/usr/include -Da32

# switches for library building
LIBCMD=		ar
LIBARGS=	ru
RANLIB=		:

LIBS=		-lcurses -lc

OFILES=		ansi.o attach.o basic.o bind.o browse.o buffer.o \
		composer.o display.o file.o fileio.o line.o osdep.o \
		pico.o random.o region.o search.o spell.o tcap.o window.o word.o

CFILES=		ansi.c attach.c basic.c bind.c browse.c buffer.c \
		composer.c display.c file.c fileio.c line.c osdep.c \
		pico.c random.c region.c search.c spell.c tcap.c window.c word.c

HFILES=		estruct.h edef.h efunc.h ebind.h pico.h


#
# dependencies for the Unix versions of pico and libpico.a
#
all:		pico

osdep.c:	os_unix.c
		rm -f osdep.c
		cp os_unix.c osdep.c

osdep.h:	os_unix.h
		rm -f osdep.h
		cp os_unix.h osdep.h

libpico.a:	osdep.c osdep.h $(OFILES)
		$(LIBCMD) $(LIBARGS) libpico.a $(OFILES)
		$(RANLIB) libpico.a

pico:		main.c libpico.a
		$(CC) $(CFLAGS) main.c libpico.a $(LIBS) -o pico

.c.o:		; $(CC) -c $(CFLAGS) $(DASHO) $*.c

$(OFILES):	$(HFILES)

clean:
		rm -f *.a *.o *~ osdep.c osdep.h
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              DarkNET-1.08/pico.BBS/makefiles/makefile.aix                                                           644   21270   21270         5704  5672463054  13651                                                                                                                                                                                                                                                                                                                                                                      # $Id: makefile.aix,v 4.3 1994/02/25 18:36:33 hubert Exp $
#
#   Michael Seibel
#   Networks and Distributed Computing
#   Computing and Communications
#   University of Washington
#   Administration Builiding, AG-44
#   Seattle, Washington, 98195, USA
#   Internet: mikes@cac.washington.edu
#
#   Please address all bugs and comments to "pine-bugs@cac.washington.edu"
#
#   Copyright 1991-1994  University of Washington
#
#    Permission to use, copy, modify, and distribute this software and its
#   documentation for any purpose and without fee to the University of
#   Washington is hereby granted, provided that the above copyright notice
#   appears in all copies and that both the above copyright notice and this
#   permission notice appear in supporting documentation, and that the name
#   of the University of Washington not be used in advertising or publicity
#   pertaining to distribution of the software without specific, written
#   prior permission.  This software is made available "as is", and
#   THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
#   WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
#   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
#   NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
#   INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
#   LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
#   (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
#   WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#  
#   Pine and Pico are trademarks of the University of Washington.
#   No commercial use of these trademarks may be made without prior
#   written permission of the University of Washington.
#

#
# Makefile for AIX on 3090 version of the PINE composer library and 
# stand-alone editor pico.
#

DASHO=		

#includes symbol info for debugging 
CFLAGS=		-g -I/usr/include -Daix

#for the normal library
#CFLAGS=	-O -I/usr/include -Daix

# switches for library building
LIBCMD=ar
LIBARGS=ru

LIBS=		-ltermcap -lc

OFILES=		ansi.o attach.o basic.o bind.o browse.o buffer.o \
		composer.o display.o file.o fileio.o line.o osdep.o \
		pico.o random.o  region.o search.o spell.o tcap.o window.o word.o

CFILES=		ansi.c attach.o basic.c bind.c browse.o buffer.c \
		composer.c display.c file.c fileio.c line.c osdep.c \
		pico.c random.c region.c search.c spell.c tcap.c window.c word.c

HFILES=		estruct.h edef.h efunc.h ebind.h pico.h


#
# dependencies for the Unix versions of pico and libpico.a
#
all:		pico

osdep.c:	os_unix.c
		rm -f osdep.c
		cp os_unix.c osdep.c

osdep.h:	os_unix.h
		rm -f osdep.h
		cp os_unix.h osdep.h

libpico.a:	osdep.c osdep.h $(OFILES)
		$(LIBCMD) $(LIBARGS) libpico.a $(OFILES)
		ranlib libpico.a

pico:		main.c libpico.a
		$(CC) $(CFLAGS) main.c libpico.a $(LIBS) -o pico

.c.o:		; $(CC) -c $(CFLAGS) $(DASHO) $*.c

$(OFILES):	$(HFILES)

clean:
		rm -f *.a *.o *~ osdep.c osdep.h
                                                            DarkNET-1.08/pico.BBS/makefiles/makefile.att                                                           644   21270   21270         5772  5672463054  13665                                                                                                                                                                                                                                                                                                                                                                      ## $Id: makefile.att,v 4.1 1994/02/25 18:36:33 hubert Exp $
#
#   Michael Seibel
#   Networks and Distributed Computing
#   Computing and Communications
#   University of Washington
#   Administration Builiding, AG-44
#   Seattle, Washington, 98195, USA
#   Internet: mikes@cac.washington.edu
#
#   Please address all bugs and comments to "pine-bugs@cac.washington.edu"
#
#   Copyright 1991-1994  University of Washington
#
#    Permission to use, copy, modify, and distribute this software and its
#   documentation for any purpose and without fee to the University of
#   Washington is hereby granted, provided that the above copyright notice
#   appears in all copies and that both the above copyright notice and this
#   permission notice appear in supporting documentation, and that the name
#   of the University of Washington not be used in advertising or publicity
#   pertaining to distribution of the software without specific, written
#   prior permission.  This software is made available "as is", and
#   THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
#   WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
#   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
#   NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
#   INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
#   LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
#   (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
#   WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
#   Pine and Pico are trademarks of the University of Washington.
#   No commercial use of these trademarks may be made without prior
#   written permission of the University of Washington.
#

#
# Makefile for Ultrix 4.1 version of the PINE composer library and 
# stand-alone editor pico.
# Port Contributor: Robert Lewis <robertle@sco.com>
#

#includes symbol info for debugging 
#DASHO=		-g
#for normal build
#DASHO=		-O

CFLAGS=		-Dsv3

# switches for library building
LIBCMD=		ar
LIBARGS=	ru
RANLIB=		:

LIBS=		-ltermcap -lc -lc_s

OFILES=		attach.o ansi.o basic.o bind.o browse.o buffer.o \
		composer.o display.o file.o fileio.o line.o osdep.o \
		pico.o random.o region.o search.o spell.o tcap.o \
		window.o word.o

CFILES=		attach.c ansi.c basic.c bind.c browse.c buffer.c \
		composer.c display.c file.c fileio.c line.c osdep.c \
		pico.c random.c region.c search.c spell.c tcap.c \
		window.c word.c

HFILES=		estruct.h edef.h efunc.h ebind.h pico.h osdep.h


#
# dependencies for the Unix versions of pico and libpico.a
#
all:		pico

osdep.c:	os_unix.c
		rm -f osdep.c
		cp os_unix.c osdep.c

osdep.h:	os_unix.h
		rm -f osdep.h
		cp os_unix.h osdep.h

libpico.a:	osdep.c osdep.h $(OFILES)
		$(LIBCMD) $(LIBARGS) libpico.a $(OFILES)
		$(RANLIB) libpico.a

pico:		main.c libpico.a
		$(CC) $(DASHO) $(CFLAGS) main.c libpico.a $(LIBS) -o pico

.c.o:		; $(CC) -c $(CFLAGS) $(DASHO) $*.c

$(OFILES):	$(HFILES)

clean:
		rm -f *.a *.o *~ osdep.c osdep.h
      DarkNET-1.08/pico.BBS/makefiles/makefile.aux                                                           644   21270   21270         5755  5672463054  13673                                                                                                                                                                                                                                                                                                                                                                      # $Id: makefile.aux,v 4.2 1994/02/25 18:36:33 hubert Exp $
#
#   Michael Seibel
#   Networks and Distributed Computing
#   Computing and Communications
#   University of Washington
#   Administration Builiding, AG-44
#   Seattle, Washington, 98195, USA
#   Internet: mikes@cac.washington.edu
#
#   Please address all bugs and comments to "pine-bugs@cac.washington.edu"
#
#   Copyright 1991-1994  University of Washington
#
#    Permission to use, copy, modify, and distribute this software and its
#   documentation for any purpose and without fee to the University of
#   Washington is hereby granted, provided that the above copyright notice
#   appears in all copies and that both the above copyright notice and this
#   permission notice appear in supporting documentation, and that the name
#   of the University of Washington not be used in advertising or publicity
#   pertaining to distribution of the software without specific, written
#   prior permission.  This software is made available "as is", and
#   THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
#   WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
#   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
#   NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
#   INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
#   LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
#   (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
#   WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#  
#   Pine and Pico are trademarks of the University of Washington.
#   No commercial use of these trademarks may be made without prior
#   written permission of the University of Washington.
#

#
# Makefile for A/UX 3.0 version of the PINE composer library and 
# stand-alone editor pico.
#

#includes symbol info for debugging 
DASHO=		-g
#for normal build
#DASHO=		-O

CFLAGS=		-DAUX -DJOB_CONTROL -D_POSIX_SOURCE -DPOSIX

# switches for library building
LIBCMD=		ar
LIBARGS=	-ru
RANLIB=		/bin/true

LIBS=		-ltermcap -lposix

OFILES=		attach.o ansi.o basic.o bind.o browse.o buffer.o \
		composer.o display.o \
		file.o fileio.o line.o osdep.o \
		pico.o random.o region.o search.o \
		spell.o tcap.o window.o word.o

CFILES=		attach.c ansi.c basic.c bind.c browse.c buffer.c \
		composer.c display.c file.c fileio.c line.c osdep.c \
		pico.c random.c region.c search.c spell.c tcap.c \
		window.c word.c

HFILES=		estruct.h edef.h efunc.h ebind.h pico.h osdep.h


#
# dependencies for the Unix versions of pico and libpico.a
#
all:		pico

osdep.c:	os_unix.c
		rm -f osdep.c
		cp os_unix.c osdep.c

osdep.h:	os_unix.h
		rm -f osdep.h
		cp os_unix.h osdep.h

libpico.a:	osdep.c osdep.h $(OFILES)
		$(LIBCMD) $(LIBARGS) libpico.a $(OFILES)
		$(RANLIB) libpico.a

pico:		main.c libpico.a
		$(CC) $(CFLAGS) main.c libpico.a $(LIBS) -o pico

.c.o:		; $(CC) -c $(CFLAGS) $(DASHO) $*.c

$(OFILES):	$(HFILES)

clean:
		rm -f *.a *.o *~ osdep.c osdep.h

TY, ARISING OUT OF DarkNET-1.08/pico.BBS/makefiles/makefile.bsd                                                           644   21270   21270         5672  5672463054  13644                                                                                                                                                                                                                                                                                                                                                                      # $Id: makefile.bsd,v 4.3 1994/02/25 18:36:33 hubert Exp $
#
#   Michael Seibel
#   Networks and Distributed Computing
#   Computing and Communications
#   University of Washington
#   Administration Builiding, AG-44
#   Seattle, Washington, 98195, USA
#   Internet: mikes@cac.washington.edu
#
#   Please address all bugs and comments to "pine-bugs@cac.washington.edu"
#
#   Copyright 1991-1994  University of Washington
#
#    Permission to use, copy, modify, and distribute this software and its
#   documentation for any purpose and without fee to the University of
#   Washington is hereby granted, provided that the above copyright notice
#   appears in all copies and that both the above copyright notice and this
#   permission notice appear in supporting documentation, and that the name
#   of the University of Washington not be used in advertising or publicity
#   pertaining to distribution of the software without specific, written
#   prior permission.  This software is made available "as is", and
#   THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
#   WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
#   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
#   NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
#   INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
#   LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
#   (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
#   WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#  
#   Pine and Pico are trademarks of the University of Washington.
#   No commercial use of these trademarks may be made without prior
#   written permission of the University of Washington.
#

#
# Makefile for Berkeley UNIX (4.3bsd) of the PINE composer library and 
# stand-alone editor pico.
#

#includes symbol for debugging
DASHO=		-g
#for normal build
#DASHO=		-O


CFLAGS=		-Dbsd -DJOB_CONTROL


# switches for library building
LIBCMD=		ar
LIBARGS=	ru
RANLIB=		ranlib

LIBS=		-ltermcap -lc

OFILES=		attach.o ansi.o basic.o bind.o browse.o buffer.o \
		composer.o display.o file.o fileio.o line.o osdep.o \
		pico.o random.o region.o search.o spell.o tcap.o window.o word.o

CFILES=		attach.c ansi.c basic.c bind.c browse.c buffer.c \
		composer.c display.c file.c fileio.c line.c osdep.c \
		pico.c random.c region.c search.c spell.c tcap.c window.c word.c

HFILES=		estruct.h edef.h efunc.h ebind.h pico.h


#
# dependencies for the Unix versions of pico and libpico.a
#
all:		pico

osdep.c:	os_unix.c
		rm -f osdep.c
		cp os_unix.c osdep.c

osdep.h:	os_unix.h
		rm -f osdep.h
		cp os_unix.h osdep.h

libpico.a:	osdep.c osdep.h $(OFILES)
		$(LIBCMD) $(LIBARGS) libpico.a $(OFILES)
		$(RANLIB) libpico.a

pico:		main.c libpico.a
		$(CC) $(CFLAGS) main.c libpico.a $(LIBS) -o pico

.c.o:		; $(CC) -c $(CFLAGS) $(DASHO) $*.c

$(OFILES):	$(HFILES)

clean:
		rm -f *.a *.o *~ osdep.c osdep.h
                                                                      DarkNET-1.08/pico.BBS/makefiles/makefile.bsi                                                           644   21270   21270         5733  5672463054  13647                                                                                                                                                                                                                                                                                                                                                                      # $Id: makefile.bsi,v 1.2 1994/02/25 18:36:33 hubert Exp $
#
#   Michael Seibel
#   Networks and Distributed Computing
#   Computing and Communications
#   University of Washington
#   Administration Builiding, AG-44
#   Seattle, Washington, 98195, USA
#   Internet: mikes@cac.washington.edu
#
#   Please address all bugs and comments to "pine-bugs@cac.washington.edu"
#
#   Copyright 1991-1994  University of Washington
#
#    Permission to use, copy, modify, and distribute this software and its
#   documentation for any purpose and without fee to the University of
#   Washington is hereby granted, provided that the above copyright notice
#   appears in all copies and that both the above copyright notice and this
#   permission notice appear in supporting documentation, and that the name
#   of the University of Washington not be used in advertising or publicity
#   pertaining to distribution of the software without specific, written
#   prior permission.  This software is made available "as is", and
#   THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
#   WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
#   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
#   NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
#   INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
#   LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
#   (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
#   WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#  
#   Pine and Pico are trademarks of the University of Washington.
#   No commercial use of these trademarks may be made without prior
#   written permission of the University of Washington.
#

#
# Makefile for BSD/386 Gamma 4.1 version of the PINE composer library and 
# stand-alone editor pico.
#

#includes symbol info for debugging 
DASHO=		-g
#for normal build
#DASHO=		-O

CFLAGS=		-DBSDI -DJOB_CONTROL -DANSI

# switches for library building
LIBCMD=		ar
LIBARGS=	ru
RANLIB=		ranlib

LIBS=		-ltermcap

OFILES=		attach.o ansi.o basic.o bind.o browse.o buffer.o \
		composer.o display.o file.o fileio.o line.o osdep.o \
		pico.o random.o region.o search.o spell.o tcap.o window.o word.o

CFILES=		attach.c ansi.c basic.c bind.c browse.c buffer.c \
		composer.c display.c file.c fileio.c line.c osdep.c \
		pico.c random.c region.c search.c spell.c tcap.c window.c word.c

HFILES=		estruct.h edef.h efunc.h ebind.h pico.h osdep.h


#
# dependencies for the Unix versions of pico and libpico.a
#
all:		pico

osdep.c:	os_unix.c
		rm -f osdep.c
		cp os_unix.c osdep.c

osdep.h:	os_unix.h
		rm -f osdep.h
		cp os_unix.h osdep.h

libpico.a:	osdep.c osdep.h $(OFILES)
		$(LIBCMD) $(LIBARGS) libpico.a $(OFILES)
		$(RANLIB) libpico.a

pico:		main.c libpico.a
		$(CC) $(CFLAGS) $(DASHO) main.c libpico.a $(LIBS) -o pico

.c.o:		; $(CC) -c $(CFLAGS) $(DASHO) $*.c

$(OFILES):	$(HFILES)

clean:
		rm -f pico *.a *.o *~ osdep.c osdep.h
 this software and its
#   documentatDarkNET-1.08/pico.BBS/makefiles/makefile.cvx                                                           644   21270   21270         5716  5672463054  13673                                                                                                                                                                                                                                                                                                                                                                      # $Id: makefile.cvx,v 1.4 1994/02/25 18:36:33 hubert Exp $
#
#   Michael Seibel
#   Networks and Distributed Computing
#   Computing and Communications
#   University of Washington
#   Administration Builiding, AG-44
#   Seattle, Washington, 98195, USA
#   Internet: mikes@cac.washington.edu
#
#   Please address all bugs and comments to "pine-bugs@cac.washington.edu"
#
#   Copyright 1991-1994  University of Washington
#
#    Permission to use, copy, modify, and distribute this software and its
#   documentation for any purpose and without fee to the University of
#   Washington is hereby granted, provided that the above copyright notice
#   appears in all copies and that both the above copyright notice and this
#   permission notice appear in supporting documentation, and that the name
#   of the University of Washington not be used in advertising or publicity
#   pertaining to distribution of the software without specific, written
#   prior permission.  This software is made available "as is", and
#   THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
#   WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
#   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
#   NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
#   INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
#   LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
#   (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
#   WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#  
#   Pine and Pico are trademarks of the University of Washington.
#   No commercial use of these trademarks may be made without prior
#   written permission of the University of Washington.
#

#
# Makefile for Convex version of the PINE composer library and 
# stand-alone editor pico.
#

#includes symbol for debugging
DASHO=		-cxdb
#for normal build
#DASHO=		-O


CFLAGS=		-Dcvx -DPOSIX -DJOB_CONTROL


# switches for library building
LIBCMD=		ar
LIBARGS=	ru
RANLIB=		ranlib

LIBS=		-ltermcap -lc

OFILES=		attach.o ansi.o basic.o bind.o browse.o buffer.o \
		composer.o display.o file.o fileio.o line.o osdep.o \
		pico.o random.o region.o search.o spell.o tcap.o window.o word.o

CFILES=		attach.c ansi.c basic.c bind.c browse.c buffer.c \
		composer.c display.c file.c fileio.c line.c osdep.c \
		pico.c random.c region.c search.c spell.c tcap.c window.c word.c

HFILES=		estruct.h edef.h efunc.h ebind.h pico.h


#
# dependencies for the Unix versions of pico and libpico.a
#
all:		pico

osdep.c:	os_unix.c
		rm -f osdep.c
		cp os_unix.c osdep.c

osdep.h:	os_unix.h
		rm -f osdep.h
		cp os_unix.h osdep.h

libpico.a:	osdep.c osdep.h $(OFILES)
		$(LIBCMD) $(LIBARGS) libpico.a $(OFILES)
		$(RANLIB) libpico.a

pico:		main.c libpico.a
		$(CC) $(CFLAGS) $(DASHO) main.c libpico.a $(LIBS) -o pico

.c.o:		; $(CC) -c $(CFLAGS) $(DASHO) $*.c

$(OFILES):	$(HFILES)

clean:
		rm -f *.a *.o *~ osdep.c osdep.h .CXdb/*
                                                  DarkNET-1.08/pico.BBS/makefiles/makefile.d-g                                                           644   21270   21270         6151  5672463054  13534                                                                                                                                                                                                                                                                                                                                                                      # $Id: makefile.d-g,v 1.1 1994/07/22 23:00:34 dlm Exp $
#
#   Michael Seibel
#   Networks and Distributed Computing
#   Computing and Communications
#   University of Washington
#   Administration Builiding, AG-44
#   Seattle, Washington, 98195, USA
#   Internet: mikes@cac.washington.edu
#
#   Please address all bugs and comments to "pine-bugs@cac.washington.edu"
#
#   Copyright 1991-1994  University of Washington
#
#    Permission to use, copy, modify, and distribute this software and its
#   documentation for any purpose and without fee to the University of
#   Washington is hereby granted, provided that the above copyright notice
#   appears in all copies and that both the above copyright notice and this
#   permission notice appear in supporting documentation, and that the name
#   of the University of Washington not be used in advertising or publicity
#   pertaining to distribution of the software without specific, written
#   prior permission.  This software is made available "as is", and
#   THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
#   WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
#   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
#   NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
#   INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
#   LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
#   (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
#   WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#  
#   Pine and Pico are trademarks of the University of Washington.
#   No commercial use of these trademarks may be made without prior
#   written permission of the University of Washington.
#

#
# Makefile for DG/UX version of the PINE composer library and 
# stand-alone editor pico.
#
# [Port courtesy of Jeff Ferguson <jef@zeus.agfx.com>]
#

#for GNU C
#CC= 		gcc
#CFLAGS=	-Dsv4 -DPOSIX -DJOB_CONTROL -ansi

#otherwise
CFLAGS=		-Dsv4 -DPOSIX -DJOB_CONTROL

#includes symbol info for debugging 
#DASHO=		-g
#for normal build
DASHO=		-O


# switches for library building
LIBCMD=		ar
LIBARGS=	ru
RANLIB=		true

LIB=            -lnsl_s -lgen -lcurses # -ltermcap

OFILES=		attach.o ansi.o basic.o bind.o browse.o buffer.o \
		composer.o display.o file.o fileio.o line.o osdep.o \
		pico.o random.o region.o search.o spell.o tinfo.o \
		window.o word.o

CFILES=		attach.c ansi.c basic.c bind.c browse.c buffer.c \
		composer.c display.c file.c fileio.c line.c osdep.c \
		pico.c random.c region.c search.c spell.c tinfo.c \
		window.c word.c

HFILES=		estruct.h edef.h efunc.h ebind.h pico.h


#
# dependencies for the Unix versions of pico and libpico.a
#
all:		pico

osdep.c:	os_unix.c
		rm -f osdep.c
		cp os_unix.c osdep.c

osdep.h:	os_unix.h
		rm -f osdep.h
		cp os_unix.h osdep.h

libpico.a:	$& osdep.c osdep.h $(OFILES)
		$(LIBCMD) $(LIBARGS) libpico.a $(OFILES)
		$(RANLIB) libpico.a

pico:		main.c libpico.a
		$(CC) $(CFLAGS) main.c libpico.a $(LIB) -o pico

.c.o:		; $(CC) -c $(CFLAGS) $(DASHO) $*.c

$(OFILES):	$(HFILES)

clean:
		rm -f *.a *.o *~ osdep.c osdep.h
                                                                                                                                                                                                                                                                                                                                                                                                                       DarkNET-1.08/pico.BBS/makefiles/makefile.dyn                                                           644   21270   21270         5764  5672463054  13670                                                                                                                                                                                                                                                                                                                                                                      # $Id: makefile.dyn,v 4.3 1994/02/25 18:36:33 hubert Exp $
#
#   Michael Seibel
#   Networks and Distributed Computing
#   Computing and Communications
#   University of Washington
#   Administration Builiding, AG-44
#   Seattle, Washington, 98195, USA
#   Internet: mikes@cac.washington.edu
#
#   Please address all bugs and comments to "pine-bugs@cac.washington.edu"
#
#   Copyright 1991-1994  University of Washington
#
#    Permission to use, copy, modify, and distribute this software and its
#   documentation for any purpose and without fee to the University of
#   Washington is hereby granted, provided that the above copyright notice
#   appears in all copies and that both the above copyright notice and this
#   permission notice appear in supporting documentation, and that the name
#   of the University of Washington not be used in advertising or publicity
#   pertaining to distribution of the software without specific, written
#   prior permission.  This software is made available "as is", and
#   THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
#   WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
#   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
#   NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
#   INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
#   LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
#   (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
#   WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#  
#   Pine and Pico are trademarks of the University of Washington.
#   No commercial use of these trademarks may be made without prior
#   written permission of the University of Washington.
#

#
# Makefile for Dynix 3.0 version of the PINE composer library and 
# stand-alone editor pico.
#

#includes symbol info for debugging 
DASHO=		-g
#for normal build
#DASHO=		-O

CFLAGS=		-Ddyn -DJOB_CONTROL

#for the normal library
#CFLAGS=	-O -I/usr/include -Ddyn

# switches for library building
LIBCMD=		ar
LIBARGS=	ru
RANLIB=		ranlib

LIBS=		-ltermcap -lc

OFILES=		attach.o ansi.o basic.o bind.o browse.o buffer.o \
		composer.o display.o file.o fileio.o line.o osdep.o \
		pico.o random.o region.o search.o spell.o tcap.o window.o word.o

CFILES=		attach.c ansi.c basic.c bind.c browse.c buffer.c \
		composer.c display.c file.c fileio.c line.c osdep.c \
		pico.c random.c region.c search.c spell.c tcap.c window.c word.c

HFILES=		estruct.h edef.h efunc.h ebind.h pico.h

#
# dependencies for the Unix versions of pico and libpico.a
#
all:		pico

osdep.c:	os_unix.c
		rm -f osdep.c
		cp os_unix.c osdep.c

osdep.h:	os_unix.h
		rm -f osdep.h
		cp os_unix.h osdep.h

libpico.a: &	osdep.c osdep.h $(OFILES)
		$(LIBCMD) $(LIBARGS) libpico.a $(OFILES)
		$(RANLIB) libpico.a

pico:		main.c libpico.a
		$(CC) $(CFLAGS) main.c libpico.a $(LIBS) -o pico

.c.o:		; $(CC) -c $(CFLAGS) $(DASHO) $*.c

$(OFILES):	$(HFILES)

clean:
		rm -f *.a *.o *~ osdep.c osdep.h
            DarkNET-1.08/pico.BBS/makefiles/makefile.hpp                                                           644   21270   21270         5674  5672463055  13666                                                                                                                                                                                                                                                                                                                                                                      # $Id: makefile.hpp,v 4.4 1994/02/25 18:36:33 hubert Exp $
#
#   Michael Seibel
#   Networks and Distributed Computing
#   Computing and Communications
#   University of Washington
#   Administration Builiding, AG-44
#   Seattle, Washington, 98195, USA
#   Internet: mikes@cac.washington.edu
#
#   Please address all bugs and comments to "pine-bugs@cac.washington.edu"
#
#   Copyright 1991-1994  University of Washington
#
#    Permission to use, copy, modify, and distribute this software and its
#   documentation for any purpose and without fee to the University of
#   Washington is hereby granted, provided that the above copyright notice
#   appears in all copies and that both the above copyright notice and this
#   permission notice appear in supporting documentation, and that the name
#   of the University of Washington not be used in advertising or publicity
#   pertaining to distribution of the software without specific, written
#   prior permission.  This software is made available "as is", and
#   THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
#   WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
#   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
#   NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
#   INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
#   LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
#   (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
#   WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#  
#   Pine and Pico are trademarks of the University of Washington.
#   No commercial use of these trademarks may be made without prior
#   written permission of the University of Washington.
#

#
# Makefile for HP/UX version of the PINE composer library and 
# stand-alone editor pico.
#

#includes symbol info for debugging 
DASHO=		-g
#for normal build
#DASHO=		-O

CFLAGS=	-Dhpp -DPOSIX -DJOB_CONTROL

# switches for library building
LIBCMD=		ar
LIBARGS=	ru
RANLIB=		:

LIBS=		-ltermcap -lV3

OFILES=		attach.o ansi.o basic.o bind.o browse.o buffer.o \
		composer.o display.o file.o fileio.o line.o osdep.o \
		pico.o random.o region.o search.o spell.o tcap.o window.o word.o

CFILES=		attach.c ansi.c basic.c bind.c browse.c buffer.c \
		composer.c display.c file.c fileio.c line.c osdep.c \
		pico.c random.c region.c search.c spell.c tcap.c window.c word.c

HFILES=		estruct.h edef.h efunc.h ebind.h pico.h


#
# dependencies for the Unix versions of pico and libpico.a
#
all:		pico

osdep.c:	os_unix.c
		rm -f osdep.c
		cp os_unix.c osdep.c

osdep.h:	os_unix.h
		rm -f osdep.h
		cp os_unix.h osdep.h

libpico.a:	$& osdep.c osdep.h $(OFILES)
		$(LIBCMD) $(LIBARGS) libpico.a $(OFILES)
		$(RANLIB) libpico.a

pico:		main.c libpico.a
		$(CC) $(CFLAGS) main.c libpico.a $(LIBS) -o pico

.c.o:		; $(CC) -c $(CFLAGS) $(DASHO) $*.c

$(OFILES):	$(HFILES)

clean:
		rm -f *.a *.o *~ osdep.c osdep.h

                                                                    DarkNET-1.08/pico.BBS/makefiles/makefile.isc                                                           644   21270   21270         5776  5672463055  13660                                                                                                                                                                                                                                                                                                                                                                      # $Id: makefile.isc,v 1.5 1994/03/12 00:08:17 dlm Exp $
#
#   Michael Seibel
#   Networks and Distributed Computing
#   Computing and Communications
#   University of Washington
#   Administration Builiding, AG-44
#   Seattle, Washington, 98195, USA
#   Internet: mikes@cac.washington.edu
#
#   Please address all bugs and comments to "pine-bugs@cac.washington.edu"
#
#   Copyright 1991-1994  University of Washington
#
#    Permission to use, copy, modify, and distribute this software and its
#   documentation for any purpose and without fee to the University of
#   Washington is hereby granted, provided that the above copyright notice
#   appears in all copies and that both the above copyright notice and this
#   permission notice appear in supporting documentation, and that the name
#   of the University of Washington not be used in advertising or publicity
#   pertaining to distribution of the software without specific, written
#   prior permission.  This software is made available "as is", and
#   THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
#   WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
#   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
#   NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
#   INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
#   LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
#   (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
#   WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
#   Pine and Pico are trademarks of the University of Washington.
#   No commercial use of these trademarks may be made without prior
#   written permission of the University of Washington.
#

#
# Makefile for ISC UNIX the PINE composer library and 
# stand-alone editor pico.  
# Contributed by Andy Brager <andyb@wndrsvr.la.ca.us>
#

#includes symbol info for debugging 
DASHO=		-g
#for normal build
#DASHO=		-O

CFLAGS=	-I/usr/include -Disc

# switches for library building
LIBCMD=		ar
LIBARGS=	ru
RANLIB=		echo

LIBS=		-ltermcap -lc -lcposix -linet

OFILES=		ansi.o attach.o basic.o bind.o browse.o buffer.o composer.o \
		display.o file.o fileio.o line.o osdep.o pico.o random.o \
		region.o search.o spell.o tcap.o window.o word.o

CFILES=		ansi.c attach.c basic.c bind.c browse.c buffer.c composer.c \
		display.c file.c fileio.c line.c osdep.c pico.c random.c \
		region.c search.c spell.c tcap.c window.c word.c

HFILES=		estruct.h edef.h efunc.h ebind.h pico.h osdep.h

#
# dependencies for the Unix versions of pico and libpico.a
#
all:		pico

osdep.c:	os_unix.c
		rm -f osdep.c
		cp os_unix.c osdep.c

osdep.h:	os_unix.h
		rm -f osdep.h
		cp os_unix.h osdep.h

libpico.a:	osdep.c osdep.h $(OFILES)
		$(LIBCMD) $(LIBARGS) libpico.a $(OFILES)
		$(RANLIB) libpico.a

pico:		main.c libpico.a
		$(CC) $(CFLAGS) $(DASHO) main.c libpico.a $(LIBS) -o pico

.c.o:		; $(CC) -c $(CFLAGS) $(DASHO) $*.c

$(OFILES):	$(HFILES)

clean:
		rm -f *.a *.o *~ osdep.c osdep.h
  DarkNET-1.08/pico.BBS/makefiles/makefile.lnx                                                           644   21270   21270         5674  5672463055  13700                                                                                                                                                                                                                                                                                                                                                                      # $Id: makefile.lnx,v 1.3 1994/10/11 21:56:50 mikes Exp $
#
#   Michael Seibel
#   Networks and Distributed Computing
#   Computing and Communications
#   University of Washington
#   Administration Builiding, AG-44
#   Seattle, Washington, 98195, USA
#   Internet: mikes@cac.washington.edu
#
#   Please address all bugs and comments to "pine-bugs@cac.washington.edu"
#
#   Copyright 1991-1994  University of Washington
#
#    Permission to use, copy, modify, and distribute this software and its
#   documentation for any purpose and without fee to the University of
#   Washington is hereby granted, provided that the above copyright notice
#   appears in all copies and that both the above copyright notice and this
#   permission notice appear in supporting documentation, and that the name
#   of the University of Washington not be used in advertising or publicity
#   pertaining to distribution of the software without specific, written
#   prior permission.  This software is made available "as is", and
#   THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
#   WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
#   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
#   NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
#   INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
#   LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
#   (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
#   WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#  
#   Pine and Pico are trademarks of the University of Washington.
#   No commercial use of these trademarks may be made without prior
#   written permission of the University of Washington.
#

#
# Makefile for Linux of the PINE composer library and 
# stand-alone editor pico.
#

#includes symbol for debugging
DASHO=		-g
#for normal build
#DASHO=		-O2

CFLAGS=	 	-Dbsd -DLINUX -DPOSIX -DJOB_CONTROL

# switches for library building
LIBCMD=		ar
LIBARGS=	ru
RANLIB=		ranlib

LIBS=		-ltermcap

OFILES=		attach.o ansi.o basic.o bind.o browse.o buffer.o \
		composer.o display.o file.o fileio.o line.o osdep.o \
		pico.o random.o region.o search.o spell.o tcap.o \
		window.o word.o

CFILES=		attach.c ansi.c basic.c bind.c browse.c buffer.c \
		composer.c display.c file.c fileio.c line.c osdep.c \
		pico.c random.c region.c search.c spell.c tcap.c \
		window.c word.c

HFILES=		estruct.h edef.h efunc.h ebind.h pico.h


#
# dependencies for the Unix versions of pico and libpico.a
#
all:		pico

osdep.c:	os_unix.c
		rm -f osdep.c
		cp os_unix.c osdep.c

osdep.h:	os_unix.h
		rm -f osdep.h
		cp os_unix.h osdep.h

libpico.a:	osdep.c osdep.h $(OFILES)
		$(LIBCMD) $(LIBARGS) libpico.a $(OFILES)
		$(RANLIB) libpico.a

pico:		main.c libpico.a
		$(CC) $(CFLAGS) main.c libpico.a $(LIBS) -o pico

.c.o:		; $(CC) -c $(CFLAGS) $(DASHO) $*.c

$(OFILES):	$(HFILES)

clean:
		rm -f *.a *.o *~ osdep.c osdep.h
                                                                    DarkNET-1.08/pico.BBS/makefiles/makefile.mct                                                           644   21270   21270         5717  5672463055  13660                                                                                                                                                                                                                                                                                                                                                                      # $Id: makefile.mct,v 4.0 1994/10/07 17:39:00 mikes Exp $
#
#   Michael Seibel
#   Networks and Distributed Computing
#   Computing and Communications
#   University of Washington
#   Administration Builiding, AG-44
#   Seattle, Washington, 98195, USA
#   Internet: mikes@cac.washington.edu
#
#   Please address all bugs and comments to "pine-bugs@cac.washington.edu"
#
#   Copyright 1991-1994  University of Washington
#
#    Permission to use, copy, modify, and distribute this software and its
#   documentation for any purpose and without fee to the University of
#   Washington is hereby granted, provided that the above copyright notice
#   appears in all copies and that both the above copyright notice and this
#   permission notice appear in supporting documentation, and that the name
#   of the University of Washington not be used in advertising or publicity
#   pertaining to distribution of the software without specific, written
#   prior permission.  This software is made available "as is", and
#   THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
#   WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
#   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
#   NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
#   INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
#   LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
#   (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
#   WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#  
#   Pine and Pico are trademarks of the University of Washington.
#   No commercial use of these trademarks may be made without prior
#   written permission of the University of Washington.
#

#
# Makefile for MachTen version of the PINE composer library and 
# stand-alone editor pico.
#

#includes symbol info for debugging 
DASHO=		-g
#for normal build
#DASHO=		-O

CFLAGS=		-Dnxt -DJOB_CONTROL -DANSI

# switches for library building
LIBCMD=		ar
LIBARGS=	ru
RANLIB=		ranlib

LIBS=		-ltermcap

OFILES=		attach.o ansi.o basic.o bind.o browse.o buffer.o \
		composer.o display.o file.o fileio.o line.o osdep.o \
		pico.o random.o region.o search.o spell.o tcap.o window.o word.o

CFILES=		attach.c ansi.c basic.c bind.c browse.c buffer.c \
		composer.c display.c file.c fileio.c line.c osdep.c \
		pico.c random.c region.c search.c spell.c tcap.c window.c word.c

HFILES=		estruct.h edef.h efunc.h ebind.h pico.h osdep.h


#
# dependencies for the Unix versions of pico and libpico.a
#
all:		pico

osdep.c:	os_unix.c
		rm -f osdep.c
		cp os_unix.c osdep.c

osdep.h:	os_unix.h
		rm -f osdep.h
		cp os_unix.h osdep.h

libpico.a:	osdep.c osdep.h $(OFILES)
		$(LIBCMD) $(LIBARGS) libpico.a $(OFILES)
		$(RANLIB) libpico.a

pico:		main.c libpico.a
		$(CC) $(CFLAGS) $(DASHO) main.c libpico.a $(LIBS) -o pico

.c.o:		; $(CC) -c $(CFLAGS) $(DASHO) $*.c

$(OFILES):	$(HFILES)

clean:
		rm -f pico *.a *.o *~ osdep.c osdep.h
NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF ODarkNET-1.08/pico.BBS/makefiles/makefile.msc                                                           644   21270   21270         7116  5672463055  13652                                                                                                                                                                                                                                                                                                                                                                      # $Id: makefile.msc,v 4.8 1994/07/27 04:23:57 mikes Exp $
#
#   Michael Seibel
#   Networks and Distributed Computing
#   Computing and Communications
#   University of Washington
#   Administration Builiding, AG-44
#   Seattle, Washington, 98195, USA
#   Internet: mikes@cac.washington.edu
#
#   Please address all bugs and comments to "pine-bugs@cac.washington.edu"
#
#   Copyright 1991-1994  University of Washington
#
#    Permission to use, copy, modify, and distribute this software and its
#   documentation for any purpose and without fee to the University of
#   Washington is hereby granted, provided that the above copyright notice
#   appears in all copies and that both the above copyright notice and this
#   permission notice appear in supporting documentation, and that the name
#   of the University of Washington not be used in advertising or publicity
#   pertaining to distribution of the software without specific, written
#   prior permission.  This software is made available "as is", and
#   THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
#   WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
#   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
#   NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
#   INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
#   LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
#   (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
#   WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#  
#   Pine and Pico are trademarks of the University of Washington.
#   No commercial use of these trademarks may be made without prior
#   written permission of the University of Washington.
#

#
#
# Makefile for MS-DOS version of the PINE composer library and 
# stand-alone editor pico.
#
# MSC version of makefile
#
CC=cl
RM=del
CP=copy 

#includes mouse support
MOUSE=		-DMOUSE
#includes symbol info for debugging 
DEBUG=			#-Zi -Od

!IF	DEFINED(PCTCP)
NET=	-DPCTCP
!ELSE
NET=
!ENDIF

#in general, no debugging and optimize for size
CFLAGS=	-Os $(DEBUG) -WX -AL -Gt4 -Gy $(NET) -DJOB_CONTROL -DANSI -DDOS $(MOUSE)

# switches for library building
LIBER=lib
LIBARGS=/NOL -+

HFILES=		estruct.h edef.h efunc.h ebind.h pico.h

CFILES=		ansi.c attach.c basic.c bind.c browse.c \
		buffer.c composer.c display.c file.c fileio.c \
		line.c ibmpc.c osdep.c pico.c random.c region.c \
		search.c spell.c window.c word.c

OFILES=		ansi.obj attach.obj basic.obj bind.obj browse.obj \
		buffer.obj composer.obj display.obj file.obj fileio.obj \
		line.obj ibmpc.obj osdep.obj pico.obj random.obj region.obj \
		search.obj spell.obj window.obj word.obj

all:		blddate.exe pico.exe

.c.obj:
	$(CC) -c $(CFLAGS) $*.c
	$(LIBER) libpico $(LIBARGS) $*;

$(OFILES):	$(HFILES)

#
# dependencies for the Unix versions of pico and libpico.a
#
osdep.c:	os_dos.c
		$(RM) osdep.c
		$(CP) os_dos.c osdep.c

osdep.h:	os_dos.h
		$(RM) osdep.h
		$(CP) os_dos.h osdep.h


libpico.lib:	osdep.c osdep.h $(OFILES)
#	del libpico.lib
#	$(LIBER) libpico +ansi+attach+basic+bind+browse;
#	$(LIBER) libpico +buffer+composer+display+file+fileio;
#	$(LIBER) libpico +line+ibmpc+osdep+pico+random+region;
#	$(LIBER) libpico +search+spell+window+word;

blddate.exe:	blddate.c
	$(CC) blddate.c

main.obj: main.c $(HFILES)
	$(CC) /c $(CFLAGS) main.c

pico.exe: libpico.lib main.obj
	link /I /NOI /NOE /stack:32768 main.obj,pico.exe,nul,libpico.lib;
#	link /CO /I /NOI /NOE /stack:32768 main.obj,pico.exe,nul,libpico.lib;

#clean:
#		$(RM) *.lib
#		$(RM) *.obj
#		$(RM) osdep.c
#		$(RM) osdep.h
#
                                                                                                                                                                                                                                                                                                                                                                                                                                                  DarkNET-1.08/pico.BBS/makefiles/makefile.neb                                                           644   21270   21270         5734  5672463055  13640                                                                                                                                                                                                                                                                                                                                                                      # $Id: makefile.neb,v 4.1 1994/10/10 23:25:38 mikes Exp $
#
#   Michael Seibel
#   Networks and Distributed Computing
#   Computing and Communications
#   University of Washington
#   Administration Builiding, AG-44
#   Seattle, Washington, 98195, USA
#   Internet: mikes@cac.washington.edu
#
#   Please address all bugs and comments to "pine-bugs@cac.washington.edu"
#
#   Copyright 1991-1994  University of Washington
#
#    Permission to use, copy, modify, and distribute this software and its
#   documentation for any purpose and without fee to the University of
#   Washington is hereby granted, provided that the above copyright notice
#   appears in all copies and that both the above copyright notice and this
#   permission notice appear in supporting documentation, and that the name
#   of the University of Washington not be used in advertising or publicity
#   pertaining to distribution of the software without specific, written
#   prior permission.  This software is made available "as is", and
#   THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
#   WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
#   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
#   NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
#   INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
#   LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
#   (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
#   WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#  
#   Pine and Pico are trademarks of the University of Washington.
#   No commercial use of these trademarks may be made without prior
#   written permission of the University of Washington.
#

#
# Makefile for NetBSD 0.9B and 1.0A version of the PINE composer library and 
# stand-alone editor pico.
#

#includes symbol info for debugging 
DASHO=		-g
#for normal build
#DASHO=		-O

CFLAGS=		-Dneb -DJOB_CONTROL -DANSI

# switches for library building
LIBCMD=		ar
LIBARGS=	ru
RANLIB=		ranlib

LIBS=		-ltermcap

OFILES=		attach.o ansi.o basic.o bind.o browse.o buffer.o \
		composer.o display.o file.o fileio.o line.o osdep.o \
		pico.o random.o region.o search.o spell.o tcap.o window.o word.o

CFILES=		attach.c ansi.c basic.c bind.c browse.c buffer.c \
		composer.c display.c file.c fileio.c line.c osdep.c \
		pico.c random.c region.c search.c spell.c tcap.c window.c word.c

HFILES=		estruct.h edef.h efunc.h ebind.h pico.h osdep.h


#
# dependencies for the Unix versions of pico and libpico.a
#
all:		pico

osdep.c:	os_unix.c
		rm -f osdep.c
		cp os_unix.c osdep.c

osdep.h:	os_unix.h
		rm -f osdep.h
		cp os_unix.h osdep.h

libpico.a:	osdep.c osdep.h $(OFILES)
		$(LIBCMD) $(LIBARGS) libpico.a $(OFILES)
		$(RANLIB) libpico.a

pico:		main.c libpico.a
		$(CC) $(CFLAGS) $(DASHO) main.c libpico.a $(LIBS) -o pico

.c.o:		; $(CC) -c $(CFLAGS) $(DASHO) $*.c

$(OFILES):	$(HFILES)

clean:
		rm -f pico *.a *.o *~ osdep.c osdep.h
R STRICT LIABILITY, ARISING OUT OF ODarkNET-1.08/pico.BBS/makefiles/makefile.nxt                                                           644   21270   21270         5721  5672463055  13701                                                                                                                                                                                                                                                                                                                                                                      # $Id: makefile.nxt,v 4.3 1994/02/25 18:36:33 hubert Exp $
#
#   Michael Seibel
#   Networks and Distributed Computing
#   Computing and Communications
#   University of Washington
#   Administration Builiding, AG-44
#   Seattle, Washington, 98195, USA
#   Internet: mikes@cac.washington.edu
#
#   Please address all bugs and comments to "pine-bugs@cac.washington.edu"
#
#   Copyright 1991-1994  University of Washington
#
#    Permission to use, copy, modify, and distribute this software and its
#   documentation for any purpose and without fee to the University of
#   Washington is hereby granted, provided that the above copyright notice
#   appears in all copies and that both the above copyright notice and this
#   permission notice appear in supporting documentation, and that the name
#   of the University of Washington not be used in advertising or publicity
#   pertaining to distribution of the software without specific, written
#   prior permission.  This software is made available "as is", and
#   THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
#   WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
#   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
#   NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
#   INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
#   LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
#   (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
#   WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#  
#   Pine and Pico are trademarks of the University of Washington.
#   No commercial use of these trademarks may be made without prior
#   written permission of the University of Washington.
#

#
# Makefile for NeXT 2.1 version of the PINE composer library and 
# stand-alone editor pico.
#

#includes symbol info for debugging 
DASHO=		-g
#for normal build
#DASHO=		-O

CFLAGS=		-Dnxt -DJOB_CONTROL -DANSI

# switches for library building
LIBCMD=		ar
LIBARGS=	ru
RANLIB=		ranlib

LIBS=		-ltermcap

OFILES=		attach.o ansi.o basic.o bind.o browse.o buffer.o \
		composer.o display.o file.o fileio.o line.o osdep.o \
		pico.o random.o region.o search.o spell.o tcap.o window.o word.o

CFILES=		attach.c ansi.c basic.c bind.c browse.c buffer.c \
		composer.c display.c file.c fileio.c line.c osdep.c \
		pico.c random.c region.c search.c spell.c tcap.c window.c word.c

HFILES=		estruct.h edef.h efunc.h ebind.h pico.h osdep.h


#
# dependencies for the Unix versions of pico and libpico.a
#
all:		pico

osdep.c:	os_unix.c
		rm -f osdep.c
		cp os_unix.c osdep.c

osdep.h:	os_unix.h
		rm -f osdep.h
		cp os_unix.h osdep.h

libpico.a:	osdep.c osdep.h $(OFILES)
		$(LIBCMD) $(LIBARGS) libpico.a $(OFILES)
		$(RANLIB) libpico.a

pico:		main.c libpico.a
		$(CC) $(CFLAGS) $(DASHO) main.c libpico.a $(LIBS) -o pico

.c.o:		; $(CC) -c $(CFLAGS) $(DASHO) $*.c

$(OFILES):	$(HFILES)

clean:
		rm -f pico *.a *.o *~ osdep.c osdep.h
                                               DarkNET-1.08/pico.BBS/makefiles/makefile.osf                                                           644   21270   21270         5714  5672463055  13661                                                                                                                                                                                                                                                                                                                                                                      # $Id: makefile.osf,v 1.5 1994/07/28 23:10:45 mikes Exp $
#
#   Michael Seibel
#   Networks and Distributed Computing
#   Computing and Communications
#   University of Washington
#   Administration Builiding, AG-44
#   Seattle, Washington, 98195, USA
#   Internet: mikes@cac.washington.edu
#
#   Please address all bugs and comments to "pine-bugs@cac.washington.edu"
#
#   Copyright 1991-1994  University of Washington
#
#    Permission to use, copy, modify, and distribute this software and its
#   documentation for any purpose and without fee to the University of
#   Washington is hereby granted, provided that the above copyright notice
#   appears in all copies and that both the above copyright notice and this
#   permission notice appear in supporting documentation, and that the name
#   of the University of Washington not be used in advertising or publicity
#   pertaining to distribution of the software without specific, written
#   prior permission.  This software is made available "as is", and
#   THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
#   WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
#   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
#   NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
#   INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
#   LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
#   (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
#   WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#  
#   Pine and Pico are trademarks of the University of Washington.
#   No commercial use of these trademarks may be made without prior
#   written permission of the University of Washington.
#

#
# Makefile for OSF/1 version of the PINE composer library and 
# stand-alone editor pico.
#

#includes symbol for debugging
DASHO=		-g
#for normal build
#DASHO=		-O2 -Olimit 800


CFLAGS=		-Dosf -DJOB_CONTROL -D_BSD


# switches for library building
LIBCMD=		ar
LIBARGS=	ru
RANLIB=		ranlib

LIBS=		-lcurses -lc

OFILES=		attach.o ansi.o basic.o bind.o browse.o buffer.o \
		composer.o display.o file.o fileio.o line.o osdep.o \
		pico.o random.o region.o search.o spell.o tcap.o window.o word.o

CFILES=		attach.c ansi.c basic.c bind.c browse.c buffer.c \
		composer.c display.c file.c fileio.c line.c osdep.c \
		pico.c random.c region.c search.c spell.c tcap.c window.c word.c

HFILES=		estruct.h edef.h efunc.h ebind.h pico.h


#
# dependencies for the Unix versions of pico and libpico.a
#
all:		pico

osdep.c:	os_unix.c
		rm -f osdep.c
		cp os_unix.c osdep.c

osdep.h:	os_unix.h
		rm -f osdep.h
		cp os_unix.h osdep.h

libpico.a:	osdep.c osdep.h $(OFILES)
		$(LIBCMD) $(LIBARGS) libpico.a $(OFILES)
		$(RANLIB) libpico.a

pico:		main.c libpico.a
		$(CC) $(CFLAGS) $(DASHO) main.c libpico.a $(LIBS) -o pico

.c.o:		; $(CC) -c $(CFLAGS) $(DASHO) $*.c

$(OFILES):	$(HFILES)

clean:
		rm -f *.a *.o *~ osdep.c osdep.h
and distribute this software and its
#   documentatiDarkNET-1.08/pico.BBS/makefiles/makefile.pt1                                                           644   21270   21270         6007  5672463055  13572                                                                                                                                                                                                                                                                                                                                                                      # $Id: makefile.pt1,v 1.2 1994/02/25 18:36:33 hubert Exp $
#
#   Michael Seibel
#   Networks and Distributed Computing
#   Computing and Communications
#   University of Washington
#   Administration Builiding, AG-44
#   Seattle, Washington, 98195, USA
#   Internet: mikes@cac.washington.edu
#
#   Please address all bugs and comments to "pine-bugs@cac.washington.edu"
#
#   Copyright 1991-1994  University of Washington
#
#    Permission to use, copy, modify, and distribute this software and its
#   documentation for any purpose and without fee to the University of
#   Washington is hereby granted, provided that the above copyright notice
#   appears in all copies and that both the above copyright notice and this
#   permission notice appear in supporting documentation, and that the name
#   of the University of Washington not be used in advertising or publicity
#   pertaining to distribution of the software without specific, written
#   prior permission.  This software is made available "as is", and
#   THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
#   WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
#   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
#   NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
#   INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
#   LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
#   (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
#   WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#  
#   Pine and Pico are trademarks of the University of Washington.
#   No commercial use of these trademarks may be made without prior
#   written permission of the University of Washington.
#

#
# Makefile for Dynix/PTX version of the PINE composer library and 
# stand-alone editor pico.
#

#includes symbol info for debugging 
DASHO=		-g
#for normal build
#DASHO=		-O

CFLAGS=	-Dptx -DPOSIX -DJOB_CONTROL

# switches for library building
LIBCMD=		ar
LIBARGS=	ru
RANLIB=		true

# DYNIX/ptx 1.3 with TCP 2.1 has strcasecmp in libinet.a.
LIB=		-ltermlib -linet

OFILES=		attach.o ansi.o basic.o bind.o browse.o buffer.o \
		composer.o display.o file.o fileio.o line.o osdep.o \
		pico.o random.o region.o search.o spell.o tinfo.o window.o word.o

CFILES=		attach.c ansi.c basic.c bind.c browse.c buffer.c \
		composer.c display.c file.c fileio.c line.c osdep.c \
		pico.c random.c region.c search.c spell.c tinfo.c window.c word.c

HFILES=		estruct.h edef.h efunc.h ebind.h pico.h


#
# dependencies for the Unix versions of pico and libpico.a
#
all:		pico

osdep.c:	os_unix.c
		rm -f osdep.c
		cp os_unix.c osdep.c

osdep.h:	os_unix.h
		rm -f osdep.h
		cp os_unix.h osdep.h

libpico.a:	$& osdep.c osdep.h $(OFILES)
		$(LIBCMD) $(LIBARGS) libpico.a $(OFILES)
		$(RANLIB) libpico.a

pico:		main.c libpico.a
		$(CC) $(CFLAGS) $(DASHO) main.c libpico.a $(LIB) -o pico

.c.o:		; $(CC) -c $(CFLAGS) $(DASHO) $*.c

$(OFILES):	$(HFILES)

clean:
		rm -f *.a *.o *~ osdep.c osdep.h
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         DarkNET-1.08/pico.BBS/makefiles/makefile.ptx                                                           644   21270   21270         6007  5672463055  13701                                                                                                                                                                                                                                                                                                                                                                      # $Id: makefile.ptx,v 4.3 1994/02/25 18:36:33 hubert Exp $
#
#   Michael Seibel
#   Networks and Distributed Computing
#   Computing and Communications
#   University of Washington
#   Administration Builiding, AG-44
#   Seattle, Washington, 98195, USA
#   Internet: mikes@cac.washington.edu
#
#   Please address all bugs and comments to "pine-bugs@cac.washington.edu"
#
#   Copyright 1991-1994  University of Washington
#
#    Permission to use, copy, modify, and distribute this software and its
#   documentation for any purpose and without fee to the University of
#   Washington is hereby granted, provided that the above copyright notice
#   appears in all copies and that both the above copyright notice and this
#   permission notice appear in supporting documentation, and that the name
#   of the University of Washington not be used in advertising or publicity
#   pertaining to distribution of the software without specific, written
#   prior permission.  This software is made available "as is", and
#   THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
#   WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
#   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
#   NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
#   INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
#   LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
#   (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
#   WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#  
#   Pine and Pico are trademarks of the University of Washington.
#   No commercial use of these trademarks may be made without prior
#   written permission of the University of Washington.
#

#
# Makefile for Dynix/PTX version of the PINE composer library and 
# stand-alone editor pico.
#

#includes symbol info for debugging 
DASHO=		-g
#for normal build
#DASHO=		-O

CFLAGS=	-Dptx -DPOSIX -DJOB_CONTROL

# switches for library building
LIBCMD=		ar
LIBARGS=	ru
RANLIB=		true

# DYNIX/ptx 1.3 with TCP 2.1 has strcasecmp in libinet.a.
LIB=		-ltermlib -linet

OFILES=		attach.o ansi.o basic.o bind.o browse.o buffer.o \
		composer.o display.o file.o fileio.o line.o osdep.o \
		pico.o random.o region.o search.o spell.o tinfo.o window.o word.o

CFILES=		attach.c ansi.c basic.c bind.c browse.c buffer.c \
		composer.c display.c file.c fileio.c line.c osdep.c \
		pico.c random.c region.c search.c spell.c tinfo.c window.c word.c

HFILES=		estruct.h edef.h efunc.h ebind.h pico.h


#
# dependencies for the Unix versions of pico and libpico.a
#
all:		pico

osdep.c:	os_unix.c
		rm -f osdep.c
		cp os_unix.c osdep.c

osdep.h:	os_unix.h
		rm -f osdep.h
		cp os_unix.h osdep.h

libpico.a:	$& osdep.c osdep.h $(OFILES)
		$(LIBCMD) $(LIBARGS) libpico.a $(OFILES)
		$(RANLIB) libpico.a

pico:		main.c libpico.a
		$(CC) $(CFLAGS) $(DASHO) main.c libpico.a $(LIB) -o pico

.c.o:		; $(CC) -c $(CFLAGS) $(DASHO) $*.c

$(OFILES):	$(HFILES)

clean:
		rm -f *.a *.o *~ osdep.c osdep.h
makefile.ptx,v 4.3 1994/02/25 18:36:33 hubert Exp $
#
#   Michael Seibel
#   Networks and Distributed Computing
#   Computing and Communications
#   University of Washington
#   Administration Builiding, AG-44
#   Seattle, Washington, 98195, USA
#   Internet: mikes@cac.washington.edu
#
#   Please address all bugs and comments to "pine-bugs@cac.washington.edu"
#
#   Copyright 1991-1994  University of Washington
#
#    Permission to use, copy, modify, and distribute this software and its
#   documentatDarkNET-1.08/pico.BBS/makefiles/makefile.s40                                                           644   21270   21270         5671  5672463055  13502                                                                                                                                                                                                                                                                                                                                                                      # $Id: makefile.s40,v 4.4 1994/03/15 00:15:29 dlm Exp $
#
#   Michael Seibel
#   Networks and Distributed Computing
#   Computing and Communications
#   University of Washington
#   Administration Builiding, AG-44
#   Seattle, Washington, 98195, USA
#   Internet: mikes@cac.washington.edu
#
#   Please address all bugs and comments to "pine-bugs@cac.washington.edu"
#
#   Copyright 1991-1994  University of Washington
#
#    Permission to use, copy, modify, and distribute this software and its
#   documentation for any purpose and without fee to the University of
#   Washington is hereby granted, provided that the above copyright notice
#   appears in all copies and that both the above copyright notice and this
#   permission notice appear in supporting documentation, and that the name
#   of the University of Washington not be used in advertising or publicity
#   pertaining to distribution of the software without specific, written
#   prior permission.  This software is made available "as is", and
#   THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
#   WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
#   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
#   NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
#   INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
#   LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
#   (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
#   WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#  
#   Pine and Pico are trademarks of the University of Washington.
#   No commercial use of these trademarks may be made without prior
#   written permission of the University of Washington.
#

#
# Makefile for Sun 4.0 version of the PINE composer library and 
# stand-alone editor pico.
#

#includes symbol info for debugging 
DASHO=		-g
#for normal build
#DASHO=		-O

CFLAGS=		-Ds40 -DJOB_CONTROL

# switches for library building
LIBCMD=		ar
LIBARGS=	ru
RANLIB=		ranlib

LIBS=		-ltermcap -lc

OFILES=		attach.o ansi.o basic.o bind.o browse.o buffer.o \
		composer.o display.o file.o fileio.o line.o osdep.o \
		pico.o random.o region.o search.o spell.o tcap.o window.o word.o

CFILES=		attach.c ansi.c basic.c bind.c browse.c buffer.c \
		composer.c display.c file.c fileio.c line.c osdep.c \
		pico.c random.c region.c search.c spell.c tcap.c window.c word.c

HFILES=		estruct.h edef.h efunc.h ebind.h pico.h


#
# dependencies for the Unix versions of pico and libpico.a
#
all:		pico

osdep.c:	os_unix.c
		rm -f osdep.c
		cp os_unix.c osdep.c

osdep.h:	os_unix.h
		rm -f osdep.h
		cp os_unix.h osdep.h

libpico.a:	osdep.c osdep.h $(OFILES)
		$(LIBCMD) $(LIBARGS) libpico.a $(OFILES)
		$(RANLIB) libpico.a

pico:		main.c libpico.a
		$(CC) $(CFLAGS) main.c libpico.a $(LIBS) -o pico

.c.o:		; $(CC) -c $(CFLAGS) $(DASHO) $*.c

$(OFILES):	$(HFILES)

clean:
		rm -f pico *.a *.o *~ osdep.c osdep.h
                                                                       DarkNET-1.08/pico.BBS/makefiles/makefile.sco                                                           644   21270   21270         6017  5672463055  13653                                                                                                                                                                                                                                                                                                                                                                      # $Id: makefile.sco,v 4.3 1994/02/25 18:36:33 hubert Exp $
#
#   Michael Seibel
#   Networks and Distributed Computing
#   Computing and Communications
#   University of Washington
#   Administration Builiding, AG-44
#   Seattle, Washington, 98195, USA
#   Internet: mikes@cac.washington.edu
#
#   Please address all bugs and comments to "pine-bugs@cac.washington.edu"
#
#   Copyright 1991-1994  University of Washington
#
#    Permission to use, copy, modify, and distribute this software and its
#   documentation for any purpose and without fee to the University of
#   Washington is hereby granted, provided that the above copyright notice
#   appears in all copies and that both the above copyright notice and this
#   permission notice appear in supporting documentation, and that the name
#   of the University of Washington not be used in advertising or publicity
#   pertaining to distribution of the software without specific, written
#   prior permission.  This software is made available "as is", and
#   THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
#   WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
#   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
#   NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
#   INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
#   LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
#   (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
#   WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#  
#   Pine and Pico are trademarks of the University of Washington.
#   No commercial use of these trademarks may be made without prior
#   written permission of the University of Washington.
#

#
# Makefile for SCO 3.2vx version of the PINE composer library and 
# stand-alone editor pico.
#
# Port courtesy of Robert Lewis <robertle@sco.COM>, 921217
#

#includes symbol info for debugging 
# DASHO=		-g
#for normal build
#DASHO=		-g

CFLAGS=		-Dsco -DPOSIX -DJOB_CONTROL

# switches for library building
LIBCMD=		ar
LIBARGS=	ru
RANLIB=		ranlib

LIBS=		-ltermcap -lc -lc_s

OFILES=		attach.o ansi.o basic.o bind.o browse.o buffer.o composer.o \
		display.o file.o fileio.o line.o osdep.o pico.o random.o \
		region.o search.o spell.o tcap.o window.o word.o

CFILES=		attach.c ansi.c basic.c bind.c browse.c buffer.c composer.c \
		display.c file.c fileio.c line.c osdep.c pico.c random.c \
		region.c search.c spell.c tcap.c window.c word.c

HFILES=		estruct.h edef.h efunc.h ebind.h pico.h osdep.h


#
# dependencies for the Unix versions of pico and libpico.a
#
all:		pico

osdep.c:	os_unix.c
		rm -f osdep.c
		cp os_unix.c osdep.c

osdep.h:	os_unix.h
		rm -f osdep.h
		cp os_unix.h osdep.h

libpico.a:	osdep.c osdep.h $(OFILES)
		$(LIBCMD) $(LIBARGS) libpico.a $(OFILES)
#		$(RANLIB) libpico.a

pico:		main.c libpico.a
		$(CC) $(CFLAGS) main.c libpico.a $(LIBS) -o pico

.c.o:		; $(CC) -c $(CFLAGS) $(DASHO) $*.c

$(OFILES):	$(HFILES)

clean:
		rm -f *.a *.o *~ osdep.c osdep.h
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 DarkNET-1.08/pico.BBS/makefiles/makefile.sgi                                                           644   21270   21270         6000  5672463055  13641                                                                                                                                                                                                                                                                                                                                                                      # $Id: makefile.sgi,v 4.5 1994/02/25 18:36:33 hubert Exp $
#
#   Michael Seibel
#   Networks and Distributed Computing
#   Computing and Communications
#   University of Washington
#   Administration Builiding, AG-44
#   Seattle, Washington, 98195, USA
#   Internet: mikes@cac.washington.edu
#
#   Please address all bugs and comments to "pine-bugs@cac.washington.edu"
#
#   Copyright 1991-1994  University of Washington
#
#    Permission to use, copy, modify, and distribute this software and its
#   documentation for any purpose and without fee to the University of
#   Washington is hereby granted, provided that the above copyright notice
#   appears in all copies and that both the above copyright notice and this
#   permission notice appear in supporting documentation, and that the name
#   of the University of Washington not be used in advertising or publicity
#   pertaining to distribution of the software without specific, written
#   prior permission.  This software is made available "as is", and
#   THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
#   WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
#   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
#   NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
#   INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
#   LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
#   (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
#   WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#  
#   Pine and Pico are trademarks of the University of Washington.
#   No commercial use of these trademarks may be made without prior
#   written permission of the University of Washington.
#

#
# Makefile for IRIX 4.0.1 version of the PINE composer library and 
# stand-alone editor pico.
#
# Need CFLAGS with -cckr on SGI since cc is now ANSI-cc

#includes symbols for debugging
DASHO=		-g
#for normal build
#DASHO=		-O

CFLAGS=		-cckr -Dsgi -DJOB_CONTROL

# switches for library building
LIBCMD=ar
LIBARGS=ru
RANLIB=/bin/true

LIBS=		-ltermcap -lsun -lc

OFILES=		attach.o ansi.o basic.o bind.o browse.o buffer.o \
		composer.o display.o file.o fileio.o line.o osdep.o \
		pico.o random.o region.o search.o spell.o tinfo.o window.o word.o

CFILES=		attach.c ansi.c basic.c bind.c browse.c buffer.c \
		composer.c display.c file.c fileio.c line.c osdep.c \
		pico.c random.c region.c search.c spell.c tinfo.c window.c word.c

HFILES=		estruct.h edef.h efunc.h ebind.h pico.h osdep.h

#
# dependencies for the Unix versions of pico and libpico.a
#
all:		pico

osdep.c:	os_unix.c
		rm -f osdep.c
		cp os_unix.c osdep.c

osdep.h:	os_unix.h
		rm -f osdep.h
		cp os_unix.h osdep.h

libpico.a:	osdep.c osdep.h $(OFILES)
		$(LIBCMD) $(LIBARGS) libpico.a $(OFILES)
		$(RANLIB) libpico.a

pico:		main.c libpico.a
		$(CC) $(CFLAGS) main.c libpico.a $(LIBS) -o pico

.c.o:		; $(CC) -c $(CFLAGS) $(DASHO) $*.c

$(OFILES):	$(HFILES)

clean:
		rm -f *.a *.o *~ osdep.c osdep.h
DarkNET-1.08/pico.BBS/makefiles/makefile.sol                                                           644   21270   21270         6616  5672463055  13671                                                                                                                                                                                                                                                                                                                                                                      # $Id: makefile.sol,v 4.1 1994/02/25 18:36:33 hubert Exp $
#
#   Michael Seibel
#   Networks and Distributed Computing
#   Computing and Communications
#   University of Washington
#   Administration Builiding, AG-44
#   Seattle, Washington, 98195, USA
#   Internet: mikes@cac.washington.edu
#
#   Please address all bugs and comments to "pine-bugs@cac.washington.edu"
#
#   Copyright 1991-1994  University of Washington
#
#    Permission to use, copy, modify, and distribute this software and its
#   documentation for any purpose and without fee to the University of
#   Washington is hereby granted, provided that the above copyright notice
#   appears in all copies and that both the above copyright notice and this
#   permission notice appear in supporting documentation, and that the name
#   of the University of Washington not be used in advertising or publicity
#   pertaining to distribution of the software without specific, written
#   prior permission.  This software is made available "as is", and
#   THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
#   WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
#   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
#   NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
#   INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
#   LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
#   (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
#   WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#  
#   Pine and Pico are trademarks of the University of Washington.
#   No commercial use of these trademarks may be made without prior
#   written permission of the University of Washington.
#

#
# Makefile for SVR4 version of the PINE composer library and 
# stand-alone editor pico.
#
# [Port courtesy of Marc Unangst <mju@mudos.ann-arbor.mi.us> - mss, 921020]
#

#for GNU C
#CC= 		gcc
# LDCC= /usr/bin/cc
# If you don't have /usr/bin/cc (our Solaris 2.2 doesn't seem to have it,
# it only has /usr/ucb/cc) then change LDCC to the following line and
# give that a try.  This is still using the Solaris compiler but
# leaving out the UCB compatibility includes and libraries.
LDCC= cc5.sol

#CFLAGS=	-Dsv4 -DPOSIX -DJOB_CONTROL -ansi
#otherwise
CFLAGS=		-Dsv4 -DPOSIX -DJOB_CONTROL

#includes symbol info for debugging 
#DASHO=		-g
#for normal build
DASHO=		-O


# switches for library building
LIBCMD=		ar
LIBARGS=	ru
RANLIB=		true

LIB=		-ltermlib

OFILES=		attach.o ansi.o basic.o bind.o browse.o buffer.o \
		composer.o display.o file.o fileio.o line.o osdep.o \
		pico.o random.o region.o search.o spell.o tinfo.o \
		window.o word.o

CFILES=		attach.c ansi.c basic.c bind.c browse.c buffer.c \
		composer.c display.c file.c fileio.c line.c osdep.c \
		pico.c random.c region.c search.c spell.c tinfo.c \
		window.c word.c

HFILES=		estruct.h edef.h efunc.h ebind.h pico.h


#
# dependencies for the Unix versions of pico and libpico.a
#
all:		pico

osdep.c:	os_unix.c
		rm -f osdep.c
		cp os_unix.c osdep.c

osdep.h:	os_unix.h
		rm -f osdep.h
		cp os_unix.h osdep.h

libpico.a:	$& osdep.c osdep.h $(OFILES)
		$(LIBCMD) $(LIBARGS) libpico.a $(OFILES)
		$(RANLIB) libpico.a

pico:		main.c libpico.a
		$(LDCC) $(CFLAGS) main.c libpico.a $(LIB) -o pico

.c.o:		; $(CC) -c $(CFLAGS) $(DASHO) $*.c

$(OFILES):	$(HFILES)

clean:
		rm -f *.a *.o *~ osdep.c osdep.h
                                                                                                                  DarkNET-1.08/pico.BBS/makefiles/makefile.sun                                                           644   21270   21270         5701  5672463055  13673                                                                                                                                                                                                                                                                                                                                                                      # $Id: makefile.sun,v 4.3 1994/02/25 18:36:33 hubert Exp $
#
#   Michael Seibel
#   Networks and Distributed Computing
#   Computing and Communications
#   University of Washington
#   Administration Builiding, AG-44
#   Seattle, Washington, 98195, USA
#   Internet: mikes@cac.washington.edu
#
#   Please address all bugs and comments to "pine-bugs@cac.washington.edu"
#
#   Copyright 1991-1994  University of Washington
#
#    Permission to use, copy, modify, and distribute this software and its
#   documentation for any purpose and without fee to the University of
#   Washington is hereby granted, provided that the above copyright notice
#   appears in all copies and that both the above copyright notice and this
#   permission notice appear in supporting documentation, and that the name
#   of the University of Washington not be used in advertising or publicity
#   pertaining to distribution of the software without specific, written
#   prior permission.  This software is made available "as is", and
#   THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
#   WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
#   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
#   NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
#   INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
#   LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
#   (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
#   WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#  
#   Pine and Pico are trademarks of the University of Washington.
#   No commercial use of these trademarks may be made without prior
#   written permission of the University of Washington.
#

#
# Makefile for Sun 4.0 version of the PINE composer library and 
# stand-alone editor pico.
#

#includes symbol info for debugging 
DASHO=		-g
#for normal build
#DASHO=		-O

CFLAGS=		-Dsun -DJOB_CONTROL -ldl

# switches for library building
LIBCMD=		ar
LIBARGS=	ru
RANLIB=		ranlib

LIBS=		-ltermcap -lc

OFILES=		attach.o ansi.o basic.o bind.o browse.o buffer.o \
		composer.o display.o file.o fileio.o line.o osdep.o \
		pico.o random.o region.o search.o spell.o tcap.o window.o word.o

CFILES=		attach.c ansi.c basic.c bind.c browse.c buffer.c \
		composer.c display.c file.c fileio.c line.c osdep.c \
		pico.c random.c region.c search.c spell.c tcap.c window.c word.c

HFILES=		estruct.h edef.h efunc.h ebind.h pico.h


#
# dependencies for the Unix versions of pico and libpico.a
#
all:		pico

osdep.c:	os_unix.c
		rm -f osdep.c
		cp os_unix.c osdep.c

osdep.h:	os_unix.h
		rm -f osdep.h
		cp os_unix.h osdep.h

libpico.a:	osdep.c osdep.h $(OFILES)
		$(LIBCMD) $(LIBARGS) libpico.a $(OFILES)
		$(RANLIB) libpico.a

pico:		main.c libpico.a
		$(CC) $(CFLAGS) main.c libpico.a $(LIBS) -o pico

.c.o:		; $(CC) -c $(CFLAGS) $(DASHO) $*.c

$(OFILES):	$(HFILES)

clean:
		rm -f pico *.a *.o *~ osdep.c osdep.h
                                                               DarkNET-1.08/pico.BBS/makefiles/makefile.sv4                                                           644   21270   21270         6135  5672463056  13605                                                                                                                                                                                                                                                                                                                                                                      # $Id: makefile.sv4,v 4.5 1994/02/25 18:36:33 hubert Exp $
#
#   Michael Seibel
#   Networks and Distributed Computing
#   Computing and Communications
#   University of Washington
#   Administration Builiding, AG-44
#   Seattle, Washington, 98195, USA
#   Internet: mikes@cac.washington.edu
#
#   Please address all bugs and comments to "pine-bugs@cac.washington.edu"
#
#   Copyright 1991-1994  University of Washington
#
#    Permission to use, copy, modify, and distribute this software and its
#   documentation for any purpose and without fee to the University of
#   Washington is hereby granted, provided that the above copyright notice
#   appears in all copies and that both the above copyright notice and this
#   permission notice appear in supporting documentation, and that the name
#   of the University of Washington not be used in advertising or publicity
#   pertaining to distribution of the software without specific, written
#   prior permission.  This software is made available "as is", and
#   THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
#   WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
#   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
#   NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
#   INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
#   LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
#   (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
#   WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#  
#   Pine and Pico are trademarks of the University of Washington.
#   No commercial use of these trademarks may be made without prior
#   written permission of the University of Washington.
#

#
# Makefile for SVR4 version of the PINE composer library and 
# stand-alone editor pico.
#
# [Port courtesy of Marc Unangst <mju@mudos.ann-arbor.mi.us> - mss, 921020]
#

#for GNU C
#CC= 		gcc
#CFLAGS=	-Dsv4 -DPOSIX -DJOB_CONTROL -ansi

#otherwise
CFLAGS=		-Dsv4 -DPOSIX -DJOB_CONTROL

#includes symbol info for debugging 
#DASHO=		-g
#for normal build
DASHO=		-O


# switches for library building
LIBCMD=		ar
LIBARGS=	ru
RANLIB=		true

LIB=		-ltermlib

OFILES=		attach.o ansi.o basic.o bind.o browse.o buffer.o \
		composer.o display.o file.o fileio.o line.o osdep.o \
		pico.o random.o region.o search.o spell.o tinfo.o \
		window.o word.o

CFILES=		attach.c ansi.c basic.c bind.c browse.c buffer.c \
		composer.c display.c file.c fileio.c line.c osdep.c \
		pico.c random.c region.c search.c spell.c tinfo.c \
		window.c word.c

HFILES=		estruct.h edef.h efunc.h ebind.h pico.h


#
# dependencies for the Unix versions of pico and libpico.a
#
all:		pico

osdep.c:	os_unix.c
		rm -f osdep.c
		cp os_unix.c osdep.c

osdep.h:	os_unix.h
		rm -f osdep.h
		cp os_unix.h osdep.h

libpico.a:	$& osdep.c osdep.h $(OFILES)
		$(LIBCMD) $(LIBARGS) libpico.a $(OFILES)
		$(RANLIB) libpico.a

pico:		main.c libpico.a
		$(CC) $(CFLAGS) main.c libpico.a $(LIB) -o pico

.c.o:		; $(CC) -c $(CFLAGS) $(DASHO) $*.c

$(OFILES):	$(HFILES)

clean:
		rm -f *.a *.o *~ osdep.c osdep.h
                                                                                                                                                                                                                                                                                                                                                                                                                                   DarkNET-1.08/pico.BBS/makefiles/makefile.ult                                                           644   21270   21270         5741  5672463056  13677                                                                                                                                                                                                                                                                                                                                                                      # $Id: makefile.ult,v 4.4 1994/02/25 18:36:33 hubert Exp $
#
#   Michael Seibel
#   Networks and Distributed Computing
#   Computing and Communications
#   University of Washington
#   Administration Builiding, AG-44
#   Seattle, Washington, 98195, USA
#   Internet: mikes@cac.washington.edu
#
#   Please address all bugs and comments to "pine-bugs@cac.washington.edu"
#
#   Copyright 1991-1994  University of Washington
#
#    Permission to use, copy, modify, and distribute this software and its
#   documentation for any purpose and without fee to the University of
#   Washington is hereby granted, provided that the above copyright notice
#   appears in all copies and that both the above copyright notice and this
#   permission notice appear in supporting documentation, and that the name
#   of the University of Washington not be used in advertising or publicity
#   pertaining to distribution of the software without specific, written
#   prior permission.  This software is made available "as is", and
#   THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
#   WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
#   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
#   NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
#   INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
#   LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
#   (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
#   WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#  
#   Pine and Pico are trademarks of the University of Washington.
#   No commercial use of these trademarks may be made without prior
#   written permission of the University of Washington.
#

#
# Makefile for RISC Ultrix 4.1 version of the PINE composer library and 
# stand-alone editor pico.
#

#includes symbol info for debugging 
DASHO=		-g
#for normal build
#DASHO=		-g

CFLAGS=		-Dult -DJOB_CONTROL

# switches for library building
LIBCMD=		ar
LIBARGS=	ru
RANLIB=		ranlib

LIBS=		-ltermcap -lc

OFILES=		attach.o ansi.o basic.o bind.o browse.o buffer.o \
		composer.o display.o \
		file.o fileio.o line.o osdep.o \
		pico.o random.o region.o search.o \
		spell.o tcap.o window.o word.o

CFILES=		attach.c ansi.c basic.c bind.c browse.c buffer.c \
		composer.c display.c file.c fileio.c line.c osdep.c \
		pico.c random.c region.c search.c spell.c tcap.c \
		window.c word.c

HFILES=		estruct.h edef.h efunc.h ebind.h pico.h osdep.h


#
# dependencies for the Unix versions of pico and libpico.a
#
all:		pico

osdep.c:	os_unix.c
		rm -f osdep.c
		cp os_unix.c osdep.c

osdep.h:	os_unix.h
		rm -f osdep.h
		cp os_unix.h osdep.h

libpico.a:	osdep.c osdep.h $(OFILES)
		$(LIBCMD) $(LIBARGS) libpico.a $(OFILES)
		$(RANLIB) libpico.a

pico:		main.c libpico.a
		$(CC) $(CFLAGS) $(DASHO) main.c libpico.a $(LIBS) -o pico

.c.o:		; $(CC) -c $(CFLAGS) $(DASHO) $*.c

$(OFILES):	$(HFILES)

clean:
		rm -f *.a *.o *~ osdep.c osdep.h pico
                               DarkNET-1.08/pico.BBS/makefiles/makefile.vul                                                           644   21270   21270         5733  5672463056  13702                                                                                                                                                                                                                                                                                                                                                                      # $Id: makefile.vul,v 1.2 1994/02/25 18:36:33 hubert Exp $
#
#   Michael Seibel
#   Networks and Distributed Computing
#   Computing and Communications
#   University of Washington
#   Administration Builiding, AG-44
#   Seattle, Washington, 98195, USA
#   Internet: mikes@cac.washington.edu
#
#   Please address all bugs and comments to "pine-bugs@cac.washington.edu"
#
#   Copyright 1991-1994  University of Washington
#
#    Permission to use, copy, modify, and distribute this software and its
#   documentation for any purpose and without fee to the University of
#   Washington is hereby granted, provided that the above copyright notice
#   appears in all copies and that both the above copyright notice and this
#   permission notice appear in supporting documentation, and that the name
#   of the University of Washington not be used in advertising or publicity
#   pertaining to distribution of the software without specific, written
#   prior permission.  This software is made available "as is", and
#   THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
#   WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
#   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
#   NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
#   INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
#   LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
#   (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
#   WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#  
#   Pine and Pico are trademarks of the University of Washington.
#   No commercial use of these trademarks may be made without prior
#   written permission of the University of Washington.
#

#
# Makefile for VAX Ultrix 4.1 version of the PINE composer library and 
# stand-alone editor pico.
#

#includes symbol info for debugging 
DASHO=		-g
#for normal build
#DASHO=		-g

CFLAGS=		-Dult -DJOB_CONTROL

# switches for library building
LIBCMD=		ar
LIBARGS=	ru
RANLIB=		ranlib

LIBS=		-ltermcap -lc

OFILES=		attach.o ansi.o basic.o bind.o browse.o buffer.o \
		composer.o display.o \
		file.o fileio.o line.o osdep.o \
		pico.o random.o region.o search.o \
		spell.o tcap.o window.o word.o

CFILES=		attach.c ansi.c basic.c bind.c browse.c buffer.c \
		composer.c display.c file.c fileio.c line.c osdep.c \
		pico.c random.c region.c search.c spell.c tcap.c \
		window.c word.c

HFILES=		estruct.h edef.h efunc.h ebind.h pico.h osdep.h


#
# dependencies for the Unix versions of pico and libpico.a
#
all:		pico

osdep.c:	os_unix.c
		rm -f osdep.c
		cp os_unix.c osdep.c

osdep.h:	os_unix.h
		rm -f osdep.h
		cp os_unix.h osdep.h

libpico.a:	osdep.c osdep.h $(OFILES)
		$(LIBCMD) $(LIBARGS) libpico.a $(OFILES)
		$(RANLIB) libpico.a

pico:		main.c libpico.a
		$(CC) $(CFLAGS) $(DASHO) main.c libpico.a $(LIBS) -o pico

.c.o:		; $(CC) -c $(CFLAGS) $(DASHO) $*.c

$(OFILES):	$(HFILES)

clean:
		rm -f *.a *.o *~ osdep.c osdep.h
                                     DarkNET-1.08/pico.BBS/makefiles/makefile.win                                                           644   21270   21270         7301  5672463056  13662                                                                                                                                                                                                                                                                                                                                                                      # $Id: makefile.win,v 4.9 1994/09/27 16:21:32 mikes Exp $
#
#   Tom Unger
#   Networks and Distributed Computing
#   Computing and Communications
#   University of Washington
#   Administration Builiding, AG-44
#   Seattle, Washington, 98195, USA
#   Internet: tunger@cac.washington.edu
#
#   Please address all bugs and comments to "pine-bugs@cac.washington.edu"
#
#   Copyright 1991-1994  University of Washington
#
#    Permission to use, copy, modify, and distribute this software and its
#   documentation for any purpose and without fee to the University of
#   Washington is hereby granted, provided that the above copyright notice
#   appears in all copies and that both the above copyright notice and this
#   permission notice appear in supporting documentation, and that the name
#   of the University of Washington not be used in advertising or publicity
#   pertaining to distribution of the software without specific, written
#   prior permission.  This software is made available "as is", and
#   THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
#   WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
#   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
#   NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
#   INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
#   LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
#   (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
#   WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#  
#   Pine and Pico are trademarks of the University of Washington.
#   No commercial use of these trademarks may be made without prior
#   written permission of the University of Washington.
#

#
#
# Makefile for MS-DOS version of the PINE composer library and 
# stand-alone editor pico.
#
# MSC version of makefile
#
CC=cl
RM=del
CP=copy 
RC = rc

#includes mouse support
MOUSE=		-DMOUSE
#includes symbol info for debugging 
CDEBUG=	-Zi -Od
LDEBUG=	/CO


#
CFLAGS=	$(CDEBUG) -nologo -WX -AL -GA -Gt4 -Gy $(NET) -DANSI -DDOS $(MOUSE)

LFLAGS= $(LDEBUG) /NOI /NOD /NOE /ONERROR:NOEXE /stack:32768

RCFLAGS =

# switches for library building
LIBER=lib
LIBARGS=/NOL -+

HFILES=	estruct.h edef.h efunc.h ebind.h pico.h osdep.h mswin.h

CFILES=		attach.c basic.c bind.c \
		buffer.c composer.c display.c file.c fileio.c \
		line.c mswin.c osdep.c pico.c random.c region.c \
		search.c spell.c window.c word.c

OFILES=		attach.obj basic.obj bind.obj \
		buffer.obj composer.obj display.obj file.obj fileio.obj \
		line.obj mswin.obj osdep.obj pico.obj random.obj region.obj \
		search.obj spell.obj window.obj word.obj

all:		blddate.exe pico.exe



.c.obj:
	$(CC) -c $(CFLAGS) $(MAKEDIR)\$*.c
	$(LIBER) libpico $(LIBARGS) $*;

$(OFILES):	$(HFILES)

#
# dependencies for the MS Windows versions of pico and libpico.a
#
osdep.c:	os_win.c dos_gen.h dos_gen.c
		$(RM) osdep.c
		$(CP) os_win.c osdep.c

osdep.h:	os_win.h 
		$(RM) osdep.h
		$(CP) os_win.h osdep.h


libpico.lib:	osdep.c osdep.h $(OFILES)
#	del libpico.lib
#	$(LIBER) libpico +attach+basic+bind;
#	$(LIBER) libpico +buffer+composer+display+file+fileio;
#	$(LIBER) libpico +line+mswin+osdep+pico+random+region;
#	$(LIBER) libpico +search+spell+window+word;


main.obj: main.c $(HFILES)
	$(CC) /c $(CFLAGS) main.c

mswinver.obj:	mswinver.c
	$(CC) /c $(CFLAGS) mswinver.c

mswin.res:  mswin.rc
	$(RC) $(RCFLAGS) -r mswin.rc

blddate.exe: blddate.c
	$(CC) blddate.c

pico.exe:: main.obj libpico.lib mswin.res $(OFILES) mswinver.obj
	blddate > bdate.c
	$(CC) /c $(CFLAGS) bdate.c
	link $(LFLAGS) @pine-win.lnk
	$(RC) -t -k mswin.res pico.exe 

clean:
	$(RM) *.lib
	$(RM) *.obj
	$(RM) mswin.res
	$(RM) osdep.c
	$(RM) osdep.h

                                                                                                                                                                                                                                                                                                                               DarkNET-1.08/pico.BBS/hangul.c                                                                         644   21270   21270         1243  5742633736  11051                                                                                                                                                                                                                                                                                                                                                                      /*
 * Hangul.C for some editor functions.
 *
 * Programmed by Abraxas (Jeong-Hun Moon)
 * Program Date: Oct 14, 1994 (Fri)
 * Programed for.. Hana BBS.
 *
 * Version: 0.1 (Not programmed yet)
 */

#include <stdio.h>
#include "estruct.h"

/*
 * Function:  int isHan(char *string, int index)
 * Return Value:
 *      0 : if string[index] is simple ascii.
 *      1 : if string[index] is 1st char of hangul.
 *      2 : if string[index] is 2nd char of hangul.
 */

int
isHan(str, index)
	CELL	*str;
	int	index;
{
	register int	i = 0, j;
	for(j=0; j <= index; j++) {
		if(!((str[j].c) & 0x80))
			i = 0;		/* clear status */
		else if(i == 1) i = 2;
		else i = 1;
	}
	return i;
}
                                                                                                                                                                                                                                                                                                                                                             DarkNET-1.08/myctype.h                                                                                 644   21270   21270          645  5735706141   7711                                                                                                                                                                                                                                                                                                                                                                      #ifndef MYCTYPE_H
#define MYCTYPE_H
#define myisprint(c) (((unsigned char)(c)>=0xa1&&(unsigned char)(c)<=0xfe)||(isprint(c)))
#define myisspace(c) ((c)==' '||(c)=='\t'||(c)=='\n'||(c)=='\r')
#define myisdigit(c) ((c)>='0'&&(c)<='9')
#define myislower(c) ((c)>='a'&&(c)<='z')
#define ishangul(c) ((unsigned char)(c)>=0xa1&&(unsigned char)(c)<=0xfe)
#define myisalpha(c) (((c)>='a'&&(c)<='z')||((c)>='A'&&(c)<='Z'))
#endif
                                                                                           DarkNET-1.08/c_irc.c                                                                                   644   21270   21270         4710  6044631215   7277                                                                                                                                                                                                                                                                                                                                                                      #include "client.h"
#include <ctype.h>
#include <varargs.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
#include <unistd.h>

#define	IRCPATH		"etc/irc.path"

int ircpid = 0;

static void page_relay()
{
  extern int g_page_pending;
  extern int g_page_need_notify;

  signal(SIGUSR2, SIG_IGN);
  g_page_pending = 1;
  g_page_need_notify = 1;
  if (ircpid)
    kill (ircpid, SIGUSR2);
  signal(SIGUSR2, page_relay);
}

Irc()
{
  CHATID chatid;
  SHORT mode;
  int w, status;
  static char *arglist[] =
        {
        "bin/irc",
        "-c",
        "#ÅÍ",
        "-z",
        NULL,
        NULL,
        "localhost",
        NULL
        };
  FILE *fp;
  char ircpath[PATHLEN+1];

  void (*func)();

  extern int lang;
  extern SHORT my_mode();

  if ((fp = fopen(IRCPATH, "r")) != NULL)
  {
	fgets(ircpath, PATHLEN, fp);
	fclose(fp);
	ircpath[strlen(ircpath)-1] = '\0';
	if (access(ircpath, X_OK) == 0)
	{
	  arglist[0] = ircpath;
	}
  }

  move(2, 0);
  clrtobot();

  if (lang) {
    if (getdata(2,0,"»ç¿ëÇÒ º°¸í: ",chatid,sizeof chatid,DOECHO,1)==-1)
      return FULLUPDATE;
  } else {
    if (getdata(2,0,"Enter chatid: ",chatid,sizeof chatid,DOECHO,1)==-1)
      return FULLUPDATE;
  }

  if (*chatid == '\0') {
    strncpy(chatid, myinfo.userid, CHATID_MAX);
    chatid[CHATID_MAX] = '\0';
  }

  arglist[4] = myinfo.userid;
  arglist[5] = chatid;

  bbs_set_mode (M_IRC);
  mode = my_mode();
  if ((mode & MODE_FLG_NOPAGE) == 0)
    func = signal(SIGUSR2, page_relay);
  else
    func = signal(SIGUSR2, SIG_IGN);

  if ((ircpid = fork()) == 0) {
    extern char *bbsenv[200];
    extern int numbbsenvs;

    if (numbbsenvs == 0)
        bbsenv[0] = NULL;

    signal(SIGUSR2, SIG_IGN);
    execve (arglist[0], arglist, bbsenv);
    fprintf(stderr, "EXECVE FAILED.... (%s)\n", arglist[0]);
    exit (-1);
  } else {
    extern int errno;
    int sig;

    errno = 0;
    while (wait(&status) != ircpid && errno == EINTR)
    {
        if (WIFSIGNALED(status))
        {
          if ((sig = WTERMSIG(status)) == SIGUSR2)
            continue;
	  bbslog(4, "During IRC SIGNAL %d received\n", sig);
          break;
        }
    }
    if (kill(ircpid, 0) == 0)
    {
	kill (ircpid, SIGTERM);
	if (kill(ircpid, 0) == 0)
	    kill (ircpid, SIGKILL);
    }
    signal (SIGUSR2, func);
  }
  /* reset this */
  ircpid = 0;
  add_io(0, 0);
  bbs_set_mode(M_UNDEFINED);
  if (NewPagePending()) {
    chat_show_page_request();
  }      
  return FULLUPDATE;
}
                                                        DarkNET-1.08/c_msg.h                                                                                   644   21270   21270         3060  5743112400   7305                                                                                                                                                                                                                                                                                                                                                                      #define	INFO_MORE		0
#define	INFO_IN_PROGRESS	1
#define	INFO_DONE		2
#define	INFO_CANCELLED		3
#define	INFO_ADDED		4
#define	INFO_DELETING		5
#define	INFO_DELETED		6
#define	INFO_CHANGED		7
#define	INFO_READY_START	8
#define	INFO_DONE_PRESS		9
#define	INFO_UPLOADED		10
#define	INFO_DOWNLOADED		11
#define	INFO_SENT		12
#define	INFO_OVERLIST		13
#define	INFO_BMGR		14
#define	INFO_SENDING_TO		15
#define	INFO_DELETE_RANGE	16
#define	INFO_POSTING		17
#define	INFO_FTP_POSTING	18
#define	INFO_POSTED		19
#define	INFO_REPLY		20
#define	INFO_EDITTED		21
#define	INFO_KICKED		22
#define	INFO_MAIL		23
#define	INFO_MONITOR		24
#define	INFO_TOGGLE		25
#define	INFO_NEVER_LOGGED_IN	26
#define	INFO_NO_PLAN		27
#define	INFO_SAVED		28
#define	INFO_SCANNING		29
#define	INFO_QUIT		30
#define	INFO_NO_BOARD_SELECTED	31

#define	ERR_NOTHING		32
#define	ERR_FAILURE		33
#define	ERR_NO_NAME		34
#define	ERR_EXIST		35
#define	ERR_NOT_EXIST		36
#define	ERR_INVALID_NAME	37
#define	ERR_NOT_SELECTED	38
#define	ERR_CONNECT		39
#define	ERR_PROTOCOL		40
#define	ERR_FILE		41
#define	ERR_ACCT		42
#define	ERR_ADDR		43
#define	ERR_ZERO		44
#define	ERR_SEND_TO		45
#define	ERR_RANGE		46
#define	ERR_PERM		47
#define	ERR_EDIT		48
#define	ERR_NO_LONGER_LOGGED	49
#define	ERR_PAGER_OFF		50
#define	ERR_REFUSED		51
#define	ERR_TMP_PAGER_OFF	52
#define	ERR_RING_AGAIN		53
#define	ERR_NO_LONGER_PAGED	54
#define	ERR_MEM			55
#define	ERR_TERM		56
#define	ERR_EXEC		57

#define	ERR_UNKNOWN		58

#define	N_MSG			59
#define	MAX_MSG_LEN		80

#ifndef TRUE
#define	TRUE			1
#endif

#ifndef FALSE
#define	FALSE			0
#endif
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                DarkNET-1.08/c_msg.c                                                                                   644   21270   21270         6703  6044622363   7320                                                                                                                                                                                                                                                                                                                                                                      #include "c_msg.h"

static char buf[MAX_MSG_LEN+2];
static int last_index = -1;
static int last_lang = -1;

typedef struct {
	char e_msg[MAX_MSG_LEN+1];
	char k_msg[MAX_MSG_LEN+1];
} msg_t;

msg_t msg[N_MSG] = {
	{"--MORE--", "--´õ--" },
	{"In progress...", "±â´Ù¸®¼¼¿ä~..."},
	{"Done!", "´Ù ÇßÀ½!"},
	{"Cancelled!", "Ãë¼ÒÇß¾î¿ä!"},
	{"Added.", "´õÇß½À´Ï´Ù."},
	{"Deleting.", "Áö¿ó´Ï´Ù."},
	{"Deleted.", "Áö¿ü¾î¿ä."},
	{"Changed.", "¹Ù²î¾ú½À´Ï´Ù."},
	{"Press any key to start.", "ÁØºñÇÏ½Ã°í ¾Æ¹«Å°³ª Ä¡½Ã¸é ½ÃÀÛÇÕ´Ï´Ù."},
	{"Done! Press any key.", "³¡³µ½À´Ï´Ù. ¾Æ¹«Å°³ª Ä¡¼¼¿ä."},
	{"File uploaded!", "È­ÀÏÀü¼Û µÇ¾ú½À´Ï´Ù!"},
	{"File downloaded", "È­ÀÏ ´Ù¿î·Îµå µÇ¾ú½À´Ï´Ù."},
	{"Sent!", "º¸³Â½À´Ï´Ù!"},
	{"Edit Talk Override List.", "ÅäÅ© ¿¹¿Ü¸®½ºÆ® ÆíÁý."},
	{"Edit Board Manager List.", "º¸µå °ü¸®ÀÚ ÆíÁý."},
	{"Sending to:", "¼ö½ÅÀÚ:"},
	{"Delete Range:", "»èÁ¦¹üÀ§:"},
	{"Posting..", "±Û ¿Ã¸³´Ï´Ù.."},
	{"FTP Posting (Cntrl-C to cancel)", "FTP Æ÷½ºÆÃ (ÃÖ¼Ò=Cntrl-C)"},
	{"Posted!", "±Û ¿Ã·È½À´Ï´Ù!"},
	{"[RETURN to Re: current title]", "[(¿£ÅÍ)¸é (Re: ¿ø·¡Á¦¸ñ)]"},
	{"File edited", "ÆíÁý ¼º°ø"},
	{"Kicked!", "Ã¡¾î¿ä!"},
	{"(New Mail)", "(ÆíÁö¿Ô¾î¿ä)"},
	{"[Monitor Mode]     Press CTRL-C or CTRL-D to exit", "[¹¹ÇÏ³ª?] Áß´ÜÇÏ½Ã·Á¸é ÄÜÆ®·Ñ-¾¾/ÄÜÆ®·Ñ-µð Ä¡¼¼¿ä"},
	{"Enter the letter/number to toggle, RETURN when done", "¹Ù²Ù°í ½ÍÀº °ÍÀÇ ±ÛÀÚ³ª ¼ýÀÚ¸¦ ³ÖÀ¸¼¼¿ä. ´ÙÇßÀ¸¸é ¸®ÅÏÀ» Ä¡¼¼¿ä"},
	{"Never logged in", "ÇÑ¹øµµ µé¾î ¿ÂÀû ¾ø¾î¿ä"},
	{"No plan", "°èÈ¹ ¾ø³×"},
	{"File saved", "È­ÀÏ °¥¹«¸® µÇ¾ú¾î¿ä"},
	{"Scanning The Unzapped Boards ...", "°¢ º¸µå¿¡ »õ±Û Ã£´Â ÁßÀÔ´Ï´Ù..."},
	{"Quitting...", "±×¸¸ Áß´ÜÇÕ´Ï´Ù..."},
	{"* No Board Selected *", "* º¸µå °í¸¥°Å ¾øÀ½ *"},

	{"Nothing!", "Á¤½ÅÂ÷¸®¼¼¿ä..¾Æ¹«°Íµµ ¾ø¾î¿ä..."},
	{"Failed.", "½ÇÆÐÇß¾î¿ä."},
	{"Must have a name.", "ÀÌ¸§ÀÌ ÀÖ¾î¾ßÁÒ."},
	{"Board already exists.", "ÂêÂê ÇÑ¹ß ´Ê¾ú³×..ÀÌ¹Ì ÀÖ¾î~"},
	{"I don't have that.", "±×·±°Å ¾ø³×¿ä."},
	{"Invalid name", "ÂêÂê..±×°Ç ¸ø¾²³×¿ä.."},
	{"Nothing selected.", "¸ÕÀú °í¸¥°Ô ÀÖ¾î¾ßÁö¿ä..."},
	{"Error connecting!", "¿¬°á ½ÇÆÐ!"},
	{"Protocol error; try another?", "ÇÁ·ÎÅäÄÝ ¿¡·±µ¥¿ä. ´Ù½ÃÇÒ±î¿ä?"},
	{"File error!", "È­ÀÏ ¿¡·¯ÀÔ´Ï´Ù!"},
	{"Cannot get account record.", "¾îÄ«¿îÆ® Á¤º¸¸¦ °¡Á®¿Ã ¼ö°¡ ¾ø³×¿ä."},
	{"Invalid address!", "ÁÖ¼ÒºÒ¸í!"},
	{"Zero length file.", "ÅÖºó°Å °¡Áö°í Àå³­Ä¡³Ä??"},
	{"Mail could not be delivered to:", "ÆíÁö¹è´Þ ¾ÈµÇ³×¿ä."},
	{"Invalid range!", "¹üÀ§ ¶È¹Ù·Î ³Ö¾î!"},
	{"Permission error!", "ÆÛ¹Ì¼Ç ¿¡·¯!"},
	{"Edit failure", "ÆíÁý ½ÇÆÐ"},
	{"User no longer logged in.", "ÀÌ¹Ì ³ª°¬¾î¿ä."},
	{"User's pager is off", "ÆäÀÌÁ® ²¨³ù³×¿ä."},
	{"Refused!", "°ÅÀý ´çÇß¾î¿ä!"},
	{"User cannot be paged at this time", "Áö±ÝÀº À¯Àú°¡ ´ä ¸øÇØ¿ä."},
	{"No answer, Ringing party again", "´ë´äÀÌ ¾ø³×¿ä. ´Ù½Ã ºÎ¸¨´Ï´Ù"},
	{"No longer being paged", "ºÎ¸£´ø »ç¶÷ÀÌ Æ÷±âÇß³ªºÁ¿ä."},
	{"No more memory", "¾Ç!! ¸Þ¸ð¸® ºÎÁ·!"},
	{"Terminal type error!", "ÅÍ¹Ì³¯ Å¸ÀÙ ¿¡·¯!"},
	{"Exec failed!", "½ÇÇàÈ­ÀÏ µ¹¸®´Âµ¥ ½ÇÆÐ Çß¾î¿ä!"},
	{"Unknown error.", "¸ô¶ó..±â³É ¿¡·¯¾ß!"}
};

int c_msg(index, eol)
int index;
int eol;
{
	extern int lang;

	if (index < 0 || index >= N_MSG)
		index = ERR_UNKNOWN;
	if (last_index == -1 || last_index != index ||
		last_lang == -1 || last_lang != lang)
	{
		if (lang)
		{
			if (eol)
				sprintf(buf, "%s\n", msg[index].k_msg);
			else
				strcpy(buf, msg[index].k_msg);
		}
		else
		{
			if (eol)
				sprintf(buf, "%s\n", msg[index].e_msg);
			else
				strcpy(buf, msg[index].e_msg);
		}
		last_index = index;
		last_lang = lang;
	}
	prints(buf);
	return (strlen(buf));
}
                                                             DarkNET-1.08/tools/                                                                                    755   21270   21270            0  6044661525   7134                                                                                                                                                                                                                                                                                                                                                                      DarkNET-1.08/tools/hana.c                                                                              644   21270   21270         5405  5725536461  10305                                                                                                                                                                                                                                                                                                                                                                      #include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <curses.h>

#ifdef linux
#define	sig_t	void
#else
#  ifdef sun
#  define	sig_t	int
#  endif
#endif

#define	BUFSIZE		256
#define	COLMAX		80
#define	ROWMAX		128
#define	TERMCAPBUF	1024
#define	DELEMETER	\
"================================================================================"

static char cmd[] = "/bin/telnet korea.stanford.edu 1992";

int in_curse = 0;

sig_t die ()
{
  if (in_curse)
    {
      clear ();
      nocbreak ();
      echo ();
      endwin ();
    }
  printf ("\n\nHey! You're not supposed to do this!! Get out!\n");
  exit (0);
}

main (ac, av, ev)
     int ac;
     char *av[];
     char *ev[];
{
  FILE *in;
  register int c, count, i, j, DONE, linenum, statusline;
  char line[ROWMAX][COLMAX+1];
  char tbuf[TERMCAPBUF];
  register char *term;

  if ((term = getenv ("TERM")) == NULL)
    {
      perror ("getenv");
      exit (1);
    }
  if (tgetent (tbuf, term) != 1)
    {
      perror ("tgetent");
      exit (1);
    }

  signal (SIGHUP, (sig_t (*)()) die);
  signal (SIGINT, (sig_t (*)()) die);
  signal (SIGQUIT, (sig_t (*)()) die);
  signal (SIGILL, (sig_t (*)()) die);
  signal (SIGTERM, (sig_t (*)()) die);
  signal (SIGSTOP, SIG_IGN);
#ifdef SIGTSTP
  signal (SIGTSTP, SIG_IGN);
#endif
  signal (SIGCONT, (sig_t (*)()) die);

  /* I don't want this error messages from telnet */
  close (2);

  in_curse = 1;
  initscr ();
  noecho ();
  cbreak ();
  mvaddstr(10, 20, "Getting Info. from HanaBB.........");
  refresh();

  if ((in = popen (cmd, "r")) == NULL)
    {
      clear ();
      refresh();
      nocbreak ();
      echo ();
      endwin ();

      printf("popen() failed!\n");
      exit (1);
    }
  for (count = 0; count < ROWMAX && fgets (line[count], COLMAX, in); count++);
  pclose (in);

  linenum = tgetnum ("li");
  linenum--;
  statusline = linenum;
  linenum--;

  move (0, 0);
  clear ();
  for (i = 0, j = 0, DONE = 0; !DONE;)
    {
      if (j < linenum && i < count)
	{
	  mvaddstr (j, 0, line[i]);
	  refresh ();
	  j++;
	  i++;
	  continue;
	}
      mvaddstr(linenum, 0, DELEMETER);
      move (statusline, 0);
      standout();
      addstr("[B/P]");
      standend();
      addstr("-Prev Page / ");
      standout();
      addstr("[Q]");
      standend();
      addstr("-Quit / ");
      standout();
      addstr("[Any]");
      standend();
      addstr(" Key to Continue: ");
      refresh ();
      switch (c = getch ())
	{
	case 'B':
	case 'b':
	case 'P':
	case 'p':
	  if (i > linenum * 2)
	    i -= linenum * 2;
	  else
	    i = 0;
	  break;

	case 'Q':
	case 'q':
	  DONE = 1;
	  break;
	default:
	  if (i == count)
	    DONE = 1;
	  break;
	}
      j = 0;
      clear ();
    }
  clear ();
  refresh();
  nocbreak ();
  echo ();
  endwin ();
  return 0;
}
                                                                                                                                                                                                                                                           DarkNET-1.08/tools/pseudo.c                                                                            644   21270   21270         3543  5731626146  10673                                                                                                                                                                                                                                                                                                                                                                      #include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <curses.h>

#ifdef linux
#define	sig_t	void
#else
# ifdef sun
# define sig_t	int
# endif
#endif

#define	FINGER	"/usr/bin/finger"
#define	TARGET	"h-lee5@uxa.cso.uiuc.edu"
#define	BUFSIZE	256
#define	PATTERN		"slip"

int in_curse = 0;

sig_t
die ()
{
  if (in_curse)
    {
      endwin();
    }
  printf ("\n\nHey! You're not supposed to do this!! Get out!\n");
  exit (0);
}

main ()
{
  FILE *in;
  static char host[BUFSIZE + 1];
  static char cmd[BUFSIZE + 1];
  static char line[BUFSIZE + 1];
  static char result[BUFSIZE + 1];
  register char *ptr1, *ptr2;

  signal (SIGHUP, (sig_t (*)())die);
  signal (SIGINT, (sig_t (*)())die);
  signal (SIGQUIT, (sig_t (*)())die);
  signal (SIGILL, (sig_t (*)())die);
  signal (SIGTERM, (sig_t (*)())die);
  signal (SIGSTOP, (sig_t (*)())die);
#ifdef SIGTSTP
  signal (SIGTSTP, (sig_t (*)())die);
#endif
  signal (SIGCONT, (sig_t (*)())die);

  sprintf (cmd, "%s %s", FINGER, TARGET);

  initscr();
  in_curse = 1;
  clear();
  mvaddstr(5,20, "Getting info. from UIUC.....");
  refresh();

  if ((in = popen (cmd, "r")) == NULL)
    {
      perror ("popen");
      exit (1);
    }
  while (fgets (line, BUFSIZE, in))
    {
      if ((ptr1 = strstr (line, PATTERN)) == (char *) NULL)
	continue;
      ptr2 = (char*)result;
      while (*ptr1 && *ptr1 != ' ')
	ptr1--;
      ptr1++;
      while (*ptr1 && *ptr1 != '.')
	{
	  *ptr2++ = *ptr1++;
	}
      *ptr2 = '\0';
      strcat (result, ".slip.uiuc.edu");
      break;
    }
  pclose (in);

  mvaddstr(7, 20, "The PseudoBBS is at");
  mvaddch(9, 20, '[');
  standout();
  mvaddstr(9, 21, result);
  standend();
  mvaddch(9, 21+strlen(result), ']');
  refresh();

  cbreak();
  mvaddstr(23, 0, "Press Any key to continue..");
  refresh();
  getch();
  nocbreak();

  endwin();
  return 0;
}
                                                                                                                                                             DarkNET-1.08/tools/Makefile                                                                            644   21270   21270          455  6044626644  10650                                                                                                                                                                                                                                                                                                                                                                      CC	=	cc
CFLAGS	=	-g -O2

SRC1	=	hana.c
OBJ1	=	hana.o

SRC2	=	pseudo.c
OBJ2	=	pseudo.o

LIB1	=	-lcurses -ltermcap
LIB2	=	-lcurses -ltermcap

all:	hana pseudo

hana:	$(OBJ1)
	$(CC) -o hana $(OBJ1) $(LIB1)

pseudo:	$(OBJ2)
	$(CC) -o pseudo $(OBJ2) $(LIB2)

clean:
	/bin/rm -f hana pseudo $(OBJ1) $(OBJ2)
                                                                                                                                                                                                                   DarkNET-1.08/chatserv.c                                                                                644   21270   21270       104605  5742346764  10123                                                                                                                                                                                                                                                                                                                                                                      
/*
Eagles Bulletin Board System
Copyright (C) 1994, Ray Rocker, rrrocker@rock.b11.ingr.com
                                rock@seabass.st.usm.edu
                                72673.2105@compuserve.com

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

/*-------------------------------------------------------------------------*/

#include <ctype.h>
#include "server.h"
#include <malloc.h>
#include <errno.h>
#include <signal.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/time.h>

#if !RELIABLE_SELECT_FOR_WRITE
# include <fcntl.h>
#endif

#if USES_SYS_SELECT_H
# include <sys/select.h>
#endif

#if NO_SETPGID
# define setpgid setpgrp
#endif

#ifndef SOMAXCONN
# define SOMAXCONN 5
#endif

#define FLG_CHATOP       0x0100
#define FLG_CHATMGR      0x0200
#define FLG_CHATGUEST    0x0400
#define	FLG_HANGUL	 0x0800
#define FLG_RESTORECLOAK 0x1000

#define RESTRICTED(u)   (users[(u)].flags & FLG_CHATGUEST)
#define OPERATOR(u)     (users[(u)].flags & FLG_CHATOP)
#define MANAGER(u)      (users[(u)].flags & FLG_CHATMGR)
#define	HANGUL(u)	(users[(u)].flags & FLG_HANGUL)

#define ROOM_LOCKED      0x1
#define ROOM_SECRET      0x2

#define LOCKED(r)       (rooms[(r)].flags & ROOM_LOCKED)
#define SECRET(r)       (rooms[(r)].flags & ROOM_SECRET)

#define ROOM_ALL        (-2)

struct chatuser {
  int sockfd;            /* socket to bbs server */
  int utent;             /* utable entry for this user */
  int client_pid;        /* client pid */
  int room;              /* room: -1 means none, 0 means main */
  int flags;             /* FLG_CHATOP, FLG_CHATMGR, FLG_CHATGUEST, etc. */
  NAME userid;           /* real userid */
  NAME chatid;           /* chat id */
  CHATLINE ibuf;         /* buffer for sending/receiving */
  int ibufsize;          /* current size of ibuf */
} *users;

struct chatroom {
  NAME name;             /* name of room; room 0 is "main" */
  short occupants;       /* number of users in room */
  short flags;           /* ROOM_LOCKED, ROOM_SECRET */
  char *invites;         /* Keep track of invites to rooms */
} *rooms;

struct chatcmd {
  char *cmdstr;
  int (*cmdfunc)();
  int exact;
};  

int bbs_max_users;          /* Passed in at exec time as argv[1] */
int sock = -1;              /* the socket for listening */
int nfds;                   /* number of sockets to select on */
int num_conns;              /* current number of connections */
fd_set allfds;              /* fd set for selecting */
struct timeval zerotv;      /* timeval for selecting */
CHATLINE genbuf;            /* general purpose buffer */
CHATLINE hgenbuf;           /* general purpose hangul buffer */

/* These are set up in the chatconfig file. */
NAME mainroom;              /* name of the main room (always exists) */
NAMELIST manager_list;      /* list of chat super-operators */
NAMELIST restricted_list;   /* list of restricted access accounts */

is_valid_chatid(id)
char *id;
{
  int i;
  if (*id == '\0') return 0;

  for (i=0; i<CHATID_MAX && *id; i++, id++)
    if (!myisprint(*id) || *id == '*') return 0;
  return 1;
}

char *
nextword(str)
char **str;
{
  register char *p;

  while (**str == ' ' || **str == '\t') (*str)++;
  p = *str;
  while (**str && **str != ' ' && **str != '\t') (*str)++;
  if (**str) {
    **str = '\0';
    (*str)++;
  }
  return p;
}

chatid_to_indx(chatid)
char *chatid;
{
  register int i;
  for (i=0; i<bbs_max_users; i++) {
    if (users[i].sockfd == -1) continue;
    if (!strcasecmp(chatid, users[i].chatid)) return i;
  }
  return -1;
}

fuzzy_chatid_to_indx(chatid)
char *chatid;
{
  register int i, indx = -1;
  int len = strlen(chatid);
  for (i=0; i<bbs_max_users; i++) {
    if (users[i].sockfd == -1) continue;
    if (!strncasecmp(chatid, users[i].chatid, len)) {
      if (len == strlen(users[i].chatid)) return i;
      if (indx == -1) indx = i; 
      else return -2;
    }
  }
  return indx;
}

roomid_to_indx(roomid)
char *roomid;
{
  register int i;
  for (i=0; i<bbs_max_users; i++) {
    if (i && rooms[i].occupants == 0) continue;
    if (!strcasecmp(roomid, rooms[i].name)) return i;
  }
  return -1;
}

do_send(writefds, str)
fd_set *writefds;
char *str;
{
  register int i;
  int len = strlen(str);
  if (select(nfds, NULL, writefds, NULL, &zerotv) > 0) {
    for (i=0; i<nfds; i++)
      if (FD_ISSET(i, writefds)) send(i, str, len+1, 0);
  }
}          

send_to_room(room, str, hstr)
int room;
char *str;
char *hstr;
{
  int i;
  fd_set writefds;
  fd_set hwritefds;

  FD_ZERO(&writefds);
  if (hstr)
   FD_ZERO(&hwritefds);
  for (i=0; i<bbs_max_users; i++) {
    if (users[i].sockfd == -1) continue;
    if (room == ROOM_ALL || users[i].room == room) {
      if (hstr) {
        if (HANGUL(i))
	  FD_SET(users[i].sockfd, &hwritefds);
        else
          FD_SET(users[i].sockfd, &writefds);
      } else {
        FD_SET(users[i].sockfd, &writefds);
      }
    }
  }
  if (hstr) {
    do_send(&hwritefds, hstr);
  }
  do_send(&writefds, str);
}

send_to_unum(unum, str)
int unum;
char *str;
{
  fd_set writefds;
  FD_ZERO(&writefds);
  FD_SET(users[unum].sockfd, &writefds);
  do_send(&writefds, str);
}  

exit_room(unum, disp, msg)
int unum;
int disp;
char *msg;
{
  int oldrnum = users[unum].room;

  if (oldrnum != -1) {
    if (--rooms[oldrnum].occupants) {
      switch (disp) {
      case EXIT_LOGOUT:
        sprintf(genbuf, "*** %s has left the room", users[unum].chatid);
	sprintf(hgenbuf, "*** %s ¾¾°¡ ³ª°¬½À´Ï´Ù", users[unum].chatid);
        if (msg && *msg) {
          strcat(genbuf, ": ");
          strncat(genbuf, msg, CHATLINE_TEXT_MAX);
          strcat(genbuf, "\n");

          strcat(hgenbuf, ": ");
          strncat(hgenbuf, msg, CHATLINE_TEXT_MAX);
          strcat(hgenbuf, "\n");
        }
 	break;
      case EXIT_LOSTCONN:
        sprintf(genbuf, "*** %s has been disconnected\n", users[unum].chatid);
        sprintf(hgenbuf, "*** %s ¾¾´Â Â©·È³×¿ä\n", users[unum].chatid);
	break;
      case EXIT_KICK:
	sprintf(genbuf, "*** %s has been kicked out\n", users[unum].chatid);
	sprintf(hgenbuf, "*** %s ¾¾´Â ÂÉ²¸³µ¾î¿ä\n", users[unum].chatid);
        break;
      }
      send_to_room(oldrnum, genbuf, hgenbuf);
    }
  }
  users[unum].flags &= ~FLG_CHATOP;
  users[unum].room = -1;
}

enter_room(unum, room, msg)
int unum;
char *room;
char *msg;
{
  char tmp1[32], tmp2[32];
  int rnum = roomid_to_indx(room);
  int op = 0;
  register int i;

  if (rnum == -1) {
    /* new room */
    for (i=1; i<bbs_max_users; i++) {
      if (rooms[i].occupants == 0) {
        rnum = i;
        if (rooms[rnum].invites == NULL) {
          rooms[rnum].invites = (char *)malloc(bbs_max_users);
          if (rooms[rnum].invites == NULL) {
            send_to_unum(unum, "*** Not enough memory\n");
            return 0;
          }
        }
        memset(rooms[rnum].invites, 0, bbs_max_users);
        strncpy(rooms[rnum].name, room, 12);
        rooms[rnum].name[12] = '\0';
        rooms[rnum].flags = 0;
        op++;
        break;
      }
    }
    if (rnum == -1) {
      send_to_unum(unum, "*** No more rooms available\n");
      return 0;
    }
  }
  if (!MANAGER(unum))
    if (LOCKED(rnum) && rooms[rnum].invites[unum] == 0) {
      send_to_unum(unum, "*** Cannot enter locked room without a key\n");
      return 0;
    }

  exit_room(unum, EXIT_LOGOUT, msg);
  users[unum].room = rnum;
  if (op) users[unum].flags |= FLG_CHATOP;
  rooms[rnum].occupants++;
  rooms[rnum].invites[unum] = 0;
  if (HANGUL(unum)) {
    strcpy(tmp1, "Hangul User");
    strcpy(tmp2, "ÇÑ±Û »ç¿ëÀÚ");
  } else {
    strcpy(tmp1, "Eng. User");
    strcpy(tmp2, "¿µ¾î »ç¿ëÀÚ");
  }
  sprintf(genbuf, "*** %s (%s) has entered room '%s'\n", 
          users[unum].chatid, tmp1, rooms[rnum].name);
  sprintf(hgenbuf, "*** %s (%s) ¾¾°¡ '%s' ¹æ¿¡ µé¾î ¿À¼Ì½À´Ï´Ù\n", 
          users[unum].chatid, tmp2, rooms[rnum].name);
  send_to_room(rnum, genbuf, hgenbuf);
  return 0;
}

logout_user(unum)
{
  USERDATA udata;
  int i, sockfd = users[unum].sockfd;
#if DEBUG
  bbslog("Logout on slot %2d, fd %d\n", unum, sockfd);
#endif
  close(sockfd);
  FD_CLR(sockfd, &allfds);

  utable_get_record(users[unum].utent, &udata);
  if (users[unum].flags & FLG_RESTORECLOAK) {
    udata.u.flags |= FLG_CLOAK;
  }
  utable_set_record(users[unum].utent, &udata);

  memset(&users[unum], 0, sizeof(users[unum]));
  users[unum].sockfd = users[unum].utent = users[unum].room = -1;
  for (i=0; i<bbs_max_users; i++) {
    if (rooms[i].invites != NULL) rooms[i].invites[unum] = 0;
  }
  num_conns--;
}

print_user_counts(unum)
{
  int i, c, userc = 0, suserc = 0, roomc = 0;
  for (i=0; i<bbs_max_users; i++) {
    c = rooms[i].occupants;
    if (i > 0 && c > 0) {
      if (!SECRET(i) || MANAGER(unum)) roomc++;
    }
    c = users[i].room;
    if (users[i].sockfd != -1 && c != -1) {
      if (SECRET(c) && !MANAGER(unum)) suserc++;
      else userc++;
    }
  }
  if (HANGUL(unum)) {
    sprintf(hgenbuf, "*** ´Ù¸¥ ÇöÀç  »ç¿ëÀÚ´Â %d ¸íÀÔ´Ï´Ù", userc);
    if (suserc)
      sprintf(hgenbuf+strlen(hgenbuf), " (+ ºñ¹Ð¹æ¿£ %d ¸í)", suserc);
    strcat(hgenbuf, "\n");
    send_to_unum(unum, hgenbuf);
    sprintf(hgenbuf, "*** ´Ù¸¥ º¸ÀÌ´Â ¹æÀº %d °³ ÀÖ¾î¿ä\n", roomc);
    send_to_unum(unum, hgenbuf);
  } else {
    sprintf(genbuf, "*** %d other user(s) present", userc);
    if (suserc)
      sprintf(genbuf+strlen(genbuf), " (+ %d in secret rooms)", suserc);
    strcat(genbuf, "\n");
    send_to_unum(unum, genbuf);
    sprintf(genbuf, "*** %d other visible room(s) in use\n", roomc);
    send_to_unum(unum, genbuf);
  }
  return 0;
}    

login_user(unum, msg)
int unum;
char *msg;
{
  int i, utent, fd = users[unum].sockfd;
  char accessbytes[MAX_CLNTCMDS];
  char *utentstr;
  char *chatid;
  USERDATA udata;
      
  utentstr = nextword(&msg);
  chatid = nextword(&msg);
  utent = atoi(utentstr);
  if (utable_get_record(utent, &udata) != S_OK || udata.u.mode != M_CHAT) {
    send_to_unum(unum, CHAT_LOGIN_BOGUS);
    return -1;
  }
  for (i=0; i<bbs_max_users; i++) {
    if (users[i].sockfd != -1 && users[i].utent == utent) {
      /* Either a "ghost" or a hacker */
      if (kill(users[i].client_pid, 0) == 0) {
        send_to_unum(unum, CHAT_LOGIN_BOGUS);
        return -1;
      }
      else {
	exit_room(i, EXIT_LOSTCONN, (char *)NULL);
	logout_user(i);
      }
    }
  }
  if (strlen(chatid) > CHATID_MAX) chatid[CHATID_MAX] = '\0';
  if (!is_valid_chatid(chatid)) {
    send_to_unum(unum, CHAT_LOGIN_INVALID);
    return 0; /* TODO change to -1 when possible */
  }
  if (chatid_to_indx(chatid) != -1) {
    /* userid in use */
    send_to_unum(unum, CHAT_LOGIN_EXISTS);
    return 0; /* TODO change to -1 when possible */
  }    

  /* Login is ok. Set flags and fill in user record. */
  utable_get_record(utent, &udata);
  if (udata.u.flags & FLG_CLOAK) {
    udata.u.flags &= ~FLG_CLOAK;
    users[unum].flags |= FLG_RESTORECLOAK;
  }  
  if (udata.u.flags & FLG_KOREAN) {
    users[unum].flags |= FLG_HANGUL;
  } else {
    users[unum].flags &= ~FLG_HANGUL;
  }
  utable_set_record(utent, &udata);

  if (is_in_namelist(manager_list, udata.u.userid))
    users[unum].flags |= FLG_CHATMGR;    
  else if (is_in_namelist(restricted_list, udata.u.userid))
    users[unum].flags |= FLG_CHATGUEST;

  users[unum].utent = utent;
  users[unum].client_pid = udata.u.pid;
  strncpy(users[unum].userid, udata.u.userid, NAMELEN);
  strcpy(users[unum].chatid, chatid);
  users[unum].chatid[8] = '\0';
  send_to_unum(unum, CHAT_LOGIN_OK);
  if (HANGUL(unum))
    sprintf(genbuf, "*** ¾î¼­¿À¼¼¿ä, %s\n", users[unum].chatid);
  else
    sprintf(genbuf, "*** Welcome to Chat, %s\n", users[unum].chatid);
  send_to_unum(unum, genbuf);
  print_user_counts(unum);
  enter_room(unum, mainroom, (char *)NULL);
  return 0;  
}  

/*ARGSUSED*/
chat_list_rooms(unum, msg)
int unum;
char *msg;
{
  int i, occupants;

  if (RESTRICTED(unum)) {
    if (HANGUL(unum))
      send_to_unum(unum, "*** ÀÓ¸¶ ³Í ±×°Å ¸øÇØ!\n");
    else
      send_to_unum(unum, "*** You do not have permission to list rooms\n");
    return 0;
  }
  send_to_unum(unum, "***\n");
  if (HANGUL(unum))
    send_to_unum(unum, "*** ¹æ             »ç¿ëÀÚ\n");
  else
    send_to_unum(unum, "*** Room           Users\n");
  send_to_unum(unum, "*** ----           -----\n");
  for (i=0; i<bbs_max_users; i++) {
    occupants = rooms[i].occupants;
    if (occupants > 0) {
      if (!MANAGER(unum))
        if ((rooms[i].flags & ROOM_SECRET) && (users[unum].room != i))
          continue;
      sprintf(genbuf, "*** %-15s %3d", rooms[i].name, occupants);
      if (rooms[i].flags & ROOM_LOCKED) strcat(genbuf, " (LOCKED)");
      if (rooms[i].flags & ROOM_SECRET) strcat(genbuf, " (SECRET)");
      strcat(genbuf, "\n");
      send_to_unum(unum, genbuf);
    }
  }
  return 0;
}

chat_do_user_list(unum, msg, whichroom)
int unum;
char *msg;
int whichroom;
{
  int start, stop, curr = 0;
  int i, rnum, myroom = users[unum].room;
  while (*msg && myisspace(*msg)) msg++;
  start = atoi(msg);
  while (*msg && myisdigit(*msg)) msg++;
  while (*msg && !myisdigit(*msg)) msg++;
  stop = atoi(msg);
  send_to_unum(unum, "***\n");
  if (HANGUL(unum))
    send_to_unum(unum, "*** º°¸í      »ç¿ëÀÚ          ¹æ \n");
  else
    send_to_unum(unum, "*** Nick      Userid          Room\n");
  send_to_unum(unum, "*** ----      ------          ----\n");
  for (i=0; i<bbs_max_users; i++) {
    rnum = users[i].room;
    if (users[i].sockfd != -1 && rnum != -1) {
      if (whichroom != -1 && whichroom != rnum) continue;
      if (myroom != rnum) {
        if (RESTRICTED(unum)) continue;
        if ((rooms[rnum].flags & ROOM_SECRET) && !MANAGER(unum)) continue;
      }
      curr++;
      if (curr < start) continue;
      else if (stop && (curr > stop)) break;
      sprintf(genbuf, "*** %-9s %-15s %s", users[i].chatid, 
              users[i].userid, rooms[rnum].name);
      if (OPERATOR(i)) strcat(genbuf, " (Op)");
      strcat(genbuf, "\n");
      send_to_unum(unum, genbuf);
    }
  }
  return 0;
}

chat_list_by_room(unum, msg)
int unum;
char *msg;
{
  int whichroom;
  char *roomstr;

  roomstr = nextword(&msg);
  if (*roomstr == '\0') whichroom = users[unum].room;
  else { 
    if ((whichroom = roomid_to_indx(roomstr)) == -1) {
      if (HANGUL(unum))
        sprintf(genbuf, "*** ¸¶ ÀÌ·±¹æ ¾ø¾î - '%s'!\n", roomstr);
      else
	sprintf(genbuf, "*** No such room '%s'\n", roomstr);
      send_to_unum(unum, genbuf);
      return 0;
    }    
    if ((rooms[whichroom].flags & ROOM_SECRET) && !MANAGER(unum)) {
      if (HANGUL(unum))
        send_to_unum(unum, "*** ºñ¹Ð¹æ¼± ±×°Å ¾ÈµÅ\n");
      else
        send_to_unum(unum, "*** Cannot list users in secret rooms\n");
      return 0;
    }    
  }
  return (chat_do_user_list(unum, msg, whichroom));
}

chat_list_users(unum, msg)
int unum;
char *msg;
{
  return (chat_do_user_list(unum, msg, -1));
}

chat_map_chatids(unum)
int unum;
{
  int i, c, myroom, rnum;
  myroom = users[unum].room;
  if (HANGUL(unum))
    send_to_unum(unum, 
  "*** º°¸í     »ç¿ëÀÚ         º°¸í     »ç¿ëÀÚ         º°¸í     »ç¿ëÀÚ\n");
  else
    send_to_unum(unum, 
  "*** Chatid   Userid         Chatid   Userid         Chatid   Userid\n");
  send_to_unum(unum,
  "*** ------   ------         ------   ------         ------   ------\n");
  strcpy(genbuf, "***  ");    
  for (i=0, c=0; i<bbs_max_users; i++) {
    rnum = users[i].room;
    if (users[i].sockfd != -1 && rnum != -1) {
      if (myroom != rnum) {
        if (RESTRICTED(unum)) continue;
        if ((rooms[rnum].flags & ROOM_SECRET) && !MANAGER(unum)) continue;
      }
      sprintf(genbuf+(c*24)+4, "%-8s %-12s   \n", 
	      users[i].chatid, users[i].userid);
      if (++c == 3) {
        send_to_unum(unum, genbuf);
	c = 0;
      }
    }
  }
  if (c > 0) send_to_unum(unum, genbuf);
  return 0;    
}

chat_query_chatid(unum, msg)
int unum;
char *msg;
{
  USERDATA udata;
  int recunum;
  char *recipient;

  recipient  = nextword(&msg);
  send_to_unum(unum, "***\n");
  if (*recipient == '\0') {
    /* map all chatids to userids */
    return (chat_map_chatids(unum));
  }
  recunum = fuzzy_chatid_to_indx(recipient);
  if (recunum < 0) {  
    /* no such user, or ambiguous */
    if (HANGUL(unum)) {
      if (recunum == -1)
	sprintf(genbuf, "*** ¶î¶îÇÏ±ä..ÀÌ·± »ç¶÷ ¾ø¾î - '%s'\n", recipient);
      else
	sprintf(genbuf, "*** '%s' ´Â ¾Ö¸Þ¸ðÈ£ÇÏÀÚ³Ê, Á»´õ ÀÚ¼¼È÷", recipient);
    } else {
      if (recunum == -1)
	sprintf(genbuf, "*** No such chatid '%s'\n", recipient);
      else
	sprintf(genbuf, "*** '%s' is ambiguous: try more letters", recipient);
    }
    send_to_unum(unum, genbuf);
    return 0;
  }    
  if (utable_get_record(users[recunum].utent, &udata) != S_OK ||
      strcmp(users[recunum].userid, udata.u.userid) ||
      udata.u.mode != M_CHAT) {
    if (HANGUL(unum))
      sprintf(genbuf, "*** ¾Ñ..ÀÌ·± ºñºñ¾ÆÀÌµð ¾ø´Âµ¥! - '%s'\n",
	users[recunum].userid);
    else
      sprintf(genbuf, "*** Cannot find '%s' in user table!\n",
	users[recunum].userid);
    send_to_unum(unum, genbuf);
    exit_room(recunum, EXIT_LOSTCONN, (char *)NULL);
    logout_user(recunum);        
    return 0;
  }
  sprintf(genbuf, "*** %s is %s (%s)\n", users[recunum].chatid,
          udata.u.userid, udata.u.username);
  send_to_unum(unum, genbuf);
  sprintf(genbuf, "*** Logged in from %s\n", udata.u.fromhost);          
  send_to_unum(unum, genbuf);
  return 0;
}

chat_setroom(unum, msg)
int unum;
char *msg;
{
  char *modestr;
  int rnum;
  int sign = 1;
  int flag;
  char *fstr;

  modestr = nextword(&msg);
  rnum = users[unum].room;
  if (!OPERATOR(unum)) {
    if (HANGUL(unum))
      send_to_unum(unum, "*** ÀÓ¸¶..³Í ¿ÀÆÛ·¹ÀÌÅÍ ¾Æ´ÏÀÚ³Ê\n");
    else
      send_to_unum(unum, "*** You're not operator\n");
    return 0;
  }
  if (*modestr == '+') modestr++;
  else if (*modestr == '-') {
    modestr++;
    sign = 0;
  }
  if (*modestr == '\0') {
    if (HANGUL(unum))
      send_to_unum(unum, "*** ¸ÛÃ»ÇÏ°Ô..¹» ¾îÄÉ ¹Ù²Ù¶õ ¸»¾ß!\n");
    else
      send_to_unum(unum, "*** No flags specified\n");
    return 0;
  }
  while (*modestr) {
    flag = 0;
    switch (*modestr) {
    case 'l': case 'L':
      flag = ROOM_LOCKED;
      fstr = "Locked";
      break;
    case 's': case 'S':
      flag = ROOM_SECRET;
      fstr = "Secret";
      break;
    default:
      if (HANGUL(unum))
        sprintf(genbuf, "*** ±×·± °Ç ¾È´ë - '%c'\n", *modestr);
      else
        sprintf(genbuf, "*** Unknown flag '%c'\n", *modestr);
      send_to_unum(unum, genbuf);
    }
    if (flag && ((rooms[rnum].flags & flag) != sign*flag)) {
      rooms[rnum].flags ^= flag;
      sprintf(genbuf, "*** Mode change by %s to%s%s\n",
              users[unum].chatid, sign ? " " : " NOT ", fstr);
      sprintf(hgenbuf, "*** %s °¡ ¸ðµå¸¦ (%s%s) ·Î ¹Ù²å¾î¿ä\n",
              users[unum].chatid, sign ? " " : " NOT ", fstr);
      send_to_room(rnum, genbuf, hgenbuf);
    }
    modestr++;
  }  
  return 0;  
}  

chat_nick(unum, msg)
int unum;
char *msg;
{
  char *chatid;
  int othernum;

  chatid = nextword(&msg);
  if (!is_valid_chatid(chatid)) {
    if (HANGUL(unum))
      send_to_unum(unum, "*** ±×°Ç º°¸íÀ¸·Î »ç¿ëÇÒ ¼ö ¾ø¾î¿ä\n");
    else
      send_to_unum(unum, "*** Invalid chatid\n");
    return 0;
  }
  if (strlen(chatid) > CHATID_MAX) chatid[CHATID_MAX] = '\0';
  othernum = chatid_to_indx(chatid);
  if (othernum != -1 && othernum != unum) {
    if (HANGUL(unum))
      send_to_unum(unum, "*** ÀÌ¹Ì µý»ç¶÷ÀÌ »ç¿ëÇÏ´Â º°¸íÀÌ¿¡¿ä\n");
    else
      send_to_unum(unum, "*** Chatid is in use\n");
    return 0;
  }    

  sprintf(genbuf, "*** %s is now known as ", users[unum].chatid);
  sprintf(hgenbuf, "*** %s ¾¾´Â ÀÌÁ¦ ", users[unum].chatid);
  strcpy(users[unum].chatid, chatid);
  strcat(genbuf, users[unum].chatid);
  strcat(genbuf, "\n");

  strcat(hgenbuf, users[unum].chatid);
  strcat(hgenbuf, "·Î µÐ°©Çß¾î¿ä\n");

  send_to_room(users[unum].room, genbuf, hgenbuf);

  sprintf(genbuf, "**C %s", users[unum].chatid);
  send_to_unum(unum, genbuf, NULL);
  return 0;
}

chat_private(unum, msg)
int unum;
char *msg;
{
  char *recipient;
  int recunum;

  recipient = nextword(&msg);
  recunum = fuzzy_chatid_to_indx(recipient);
  if (recunum < 0) {  
    /* no such user, or ambiguous */
    if (HANGUL(unum)) {
      if (recunum == -1)
	sprintf(genbuf, "*** ¶î¶îÇÏ±ä..ÀÌ·± »ç¶÷ ¾ø¾î - '%s'\n", recipient);
      else
	sprintf(genbuf, "*** '%s' ´Â ¾Ö¸Þ¸ðÈ£ÇÏÀÚ³Ê, Á»´õ ÀÚ¼¼È÷", recipient);
    } else {
      if (recunum == -1)
	sprintf(genbuf, "*** No such chatid '%s'\n", recipient);
      else
	sprintf(genbuf, "*** '%s' is ambiguous: try more letters", recipient);
    }
/*
    if (recunum == -1) sprintf(genbuf, "*** No such chatid '%s'\n", recipient);
    else sprintf(genbuf, "*** '%s' is ambiguous: try more letters", recipient);
*/
    send_to_unum(unum, genbuf);
    return 0;
  }    
  if (*msg) {
    sprintf(genbuf, "*%s* ", users[unum].chatid);
    strncat(genbuf, msg, CHATLINE_TEXT_MAX);
    strcat(genbuf, "\n");
    send_to_unum(recunum, genbuf);
    sprintf(genbuf, "%s> ", users[recunum].chatid);
    strncat(genbuf, msg, CHATLINE_TEXT_MAX);
    strcat(genbuf, "\n");
    send_to_unum(unum, genbuf);
  }
  return 0;  
}  

put_chatid(unum, str)
int unum;
char *str;
{
  int i;
  char *chatid = users[unum].chatid;
  memset(str, ' ', 10);
  for (i=0; chatid[i]; i++) str[i] = chatid[i];
  str[i] = ':';
  str[10] = '\0';
}

chat_allmsg(unum, msg)
int unum;
char *msg;
{
  if (*msg) {
    put_chatid(unum, genbuf);
    strncat(genbuf, msg, CHATLINE_TEXT_MAX);
    strcat(genbuf, "\n");
    send_to_room(users[unum].room, genbuf, NULL);
  }
  return 0;  
}  

chat_emote(unum, msg)
int unum;
char *msg;
{
  if (*msg) {
    strcpy(genbuf, users[unum].chatid);
    strcat(genbuf, " ");
    strncat(genbuf, msg, CHATLINE_TEXT_MAX);
    strcat(genbuf, "\n");
    send_to_room(users[unum].room, genbuf, NULL);
  }
  return 0;  
}  

chat_join(unum, msg)
int unum;
char *msg;
{
  char *roomid;

  roomid  = nextword(&msg);
  if (RESTRICTED(unum)) {
    send_to_unum(unum, "*** You do not have permission to join other rooms\n");
    return 0;
  }
  if (*roomid == '\0') {
    send_to_unum(unum, "*** You must specify a room\n");
    return 0;
  }
  enter_room(unum, roomid, msg);
  return 0;
}  

chat_kick(unum, msg)
int unum;
char *msg;
{
  char *twit;
  int rnum;
  int recunum;

  twit = nextword(&msg);
  rnum = users[unum].room;
  if (!OPERATOR(unum) && !MANAGER(unum)) {
    send_to_unum(unum, "*** You're not operator\n");
    return 0;
  }
  if ((recunum = chatid_to_indx(twit)) == -1) {
    /* no such user */
    sprintf(genbuf, "*** No such chatid '%s'\n", twit);
    send_to_unum(unum, genbuf);
    return 0;
  }    
  if (rnum != users[recunum].room) {
    sprintf(genbuf, "*** '%s' is not in this room\n", users[recunum].chatid);
    send_to_unum(unum, genbuf);
    return 0;
  }
  exit_room(recunum, EXIT_KICK, (char *)NULL);

  if (rnum == 0) logout_user(recunum);        
  else enter_room(recunum, mainroom, (char *)NULL);    

  return 0;  
}  

chat_makeop(unum, msg)
int unum;
char *msg;
{
  char *newop;
  int rnum;
  int recunum;

  newop = nextword(&msg);
  rnum = users[unum].room;

  if (!OPERATOR(unum)) {
    send_to_unum(unum, "*** You're not operator\n");
    return 0;
  }
  if ((recunum = chatid_to_indx(newop)) == -1) {
    /* no such user */
    sprintf(genbuf, "*** No such chatid '%s'\n", newop);
    send_to_unum(unum, genbuf);
    return 0;
  }    
  if (unum == recunum) {
    sprintf(genbuf, "*** You're already op\n");
    send_to_unum(unum, genbuf);
    return 0;
  }
  if (rnum != users[recunum].room) {
    sprintf(genbuf, "*** '%s' is not in this room\n", users[recunum].chatid);
    send_to_unum(unum, genbuf);
    return 0;
  }
  users[unum].flags &= ~FLG_CHATOP;
  users[recunum].flags |= FLG_CHATOP;
  sprintf(genbuf, "*** %s gave Op to %s\n", users[unum].chatid,
          users[recunum].chatid);
  sprintf(hgenbuf, "*** %s °¡ %s ¸¦ ¹æ´ñ¹æ ½ÃÄÑÁá³×¿ä\n", users[unum].chatid,
          users[recunum].chatid);
  send_to_room(rnum, genbuf, hgenbuf);  
  return 0;  
}  

chat_invite(unum, msg)
int unum;
char *msg;
{
  char *invitee;
  int rnum;
  int recunum;

  invitee = nextword(&msg);
  rnum = users[unum].room;

  if (!OPERATOR(unum)) {
    send_to_unum(unum, "*** You're not operator\n");
    return 0;
  }
  if ((recunum = chatid_to_indx(invitee)) == -1) {
    /* no such user */
    sprintf(genbuf, "*** No such chatid '%s'\n", invitee);
    send_to_unum(unum, genbuf);
    return 0;
  }    
  if (rooms[rnum].invites[recunum] == 1) {
    sprintf(genbuf, "*** %s already has a key\n", users[recunum].chatid);
    send_to_unum(unum, genbuf);
    return 0;
  }
  rooms[rnum].invites[recunum] = 1;
  sprintf(genbuf, "*** %s gave you a key to room '%s'\n", 
          users[unum].chatid, rooms[rnum].name);
  send_to_unum(recunum, genbuf);  
  sprintf(genbuf, "*** Key given to %s\n", users[recunum].chatid);
  send_to_unum(unum, genbuf);
  return 0;  
}  

chat_broadcast(unum, msg)
int unum;
char *msg;
{
  if (!MANAGER(unum)) {
    send_to_unum(unum, "*** You can't do that\n");
    return 0;
  }
  if (*msg == '\0') {
    send_to_unum(unum, "*** No message given\n");
    return 0;
  }
  sprintf(genbuf, "*** Broadcast message from %s:\n", users[unum].chatid);
  send_to_room(ROOM_ALL, genbuf);
  strcpy(genbuf, "*** ");
  strncat(genbuf, msg, CHATLINE_TEXT_MAX);
  send_to_room(ROOM_ALL, genbuf);
  return 0;
}  

chat_goodbye(unum, msg)
int unum;
char *msg;
{
  exit_room(unum, EXIT_LOGOUT, msg);
  return 0;  
}  

static struct chatcmd cmdlist[] = 
{ "exit", chat_goodbye, 0,
  "flags", chat_setroom, 0,
  "¹Ù(²ã)", chat_setroom, 0,
  "nick", chat_nick, 0,
  "º°(¸í)", chat_nick, 0,
  "invite", chat_invite, 0,
  "ÃÊ(´ë)", chat_invite, 0,
  "join", chat_join, 0,
  "³¢(¾î)", chat_join, 0,
  "kick", chat_kick, 0,
  "Â÷", chat_kick, 1,
  "me", chat_emote, 1,
  "³ª", chat_emote, 1,
  "msg", chat_private, 0,
  "¼Ó", chat_private, 1,
  "operator", chat_makeop, 0,
  "ÁÖ(ÀÎ)", chat_makeop, 0,
  "rooms", chat_list_rooms, 0, 
  "¹æ", chat_list_rooms, 1, 
  "whoin", chat_list_by_room, 1,
  "»ç(¶÷)", chat_list_by_room, 0,
  "whois", chat_query_chatid, 1,
  "´©(±¸)", chat_query_chatid, 0,
  "wall", chat_broadcast, 1,
  "¹æ(¼Û)", chat_broadcast, 1,
  "who", chat_list_users, 0,
  "¸ð(µÎ)", chat_list_users, 0,
  NULL, NULL, 0
};

/*
struct chatcmd cmdlist[] =
{ "action", chat_emote, 0,
  "exit", chat_goodbye, 0,
  "flags", chat_setroom, 0,
  "invite", chat_invite, 0,
  "join", chat_join, 0,
  "kick", chat_kick, 0,
  "me", chat_emote, 1,
  "msg", chat_private, 0,
  "nick", chat_nick, 0,
  "operator", chat_makeop, 0,
  "rooms", chat_list_rooms, 0, 
  "whoin", chat_list_by_room, 1,
  "whois", chat_query_chatid, 1,
   wall", chat_broadcast, 1,
  "who", chat_list_users, 0,
  NULL, NULL, 0
};
*/

command_execute(unum)
int unum;
{
  char *msg;
  char *cmd;
  struct chatcmd *cmdrec;
  int match = 1;
  register int i;

  msg = users[unum].ibuf;
#if DEBUG
  bbslog("command_execute: %s\n", msg);
#endif

  /* Validation routine */
  if (users[unum].room == -1) {
    /* MUST give special /! command if not in the room yet */
    if (msg[0] != '/' || msg[1] != '!') return -1;    
    else return (login_user(unum, msg+2));
  }

  /* If not a /-command, it goes to the room. */
  if (msg[0] != '/') {
    chat_allmsg(unum, msg);
    return 0;
  }

  msg++;
  cmd = nextword(&msg);

  /* Look up the command in the chat command table. */
  for (cmdrec = cmdlist; match && cmdrec->cmdstr != NULL; cmdrec++) {
    if (cmdrec->exact) match = strcasecmp(cmd, cmdrec->cmdstr);
    else match = strncasecmp(cmd, cmdrec->cmdstr, strlen(cmd));
    if (match == 0) cmdrec->cmdfunc(unum, msg);
  }

  if (match) {      
    /* invalid input */
    sprintf(genbuf, "*** Unknown command '/%s'\n", cmd);
    send_to_unum(unum, genbuf);
  }

  memset(users[unum].ibuf, 0, sizeof users[unum].ibuf);
  return 0;
}

process_chat_command(unum)
int unum;
{
  register int i;
  int sd, rc, ibufsize;
  CHATLINE recbuf;
  
  sd = users[unum].sockfd;
#if DEBUG
  bbslog("Incoming on fd %d: ", sd);
#endif
  if ((rc = recv(sd, recbuf, sizeof recbuf, 0)) <= 0) {
    /* disconnected */
    exit_room(unum, EXIT_LOSTCONN, (char *)NULL);
    return -1;
  }
  ibufsize = users[unum].ibufsize;
  for (i=0; i<rc; i++) {
    /* if newline is two characters, throw out the first */
    if (recbuf[i] == '\r') continue;

    /* carriage return signals end of line */
    else if (recbuf[i] == '\n') {
      users[unum].ibuf[ibufsize] = '\0';
      if (command_execute(unum) == -1) return -1;
      ibufsize = 0;
    }

    /* add other chars to input buffer unless size limit exceeded */
    else {
      if (ibufsize < CHATLINE_TEXT_MAX)
        users[unum].ibuf[ibufsize++] = recbuf[i];
    }
  }
  users[unum].ibufsize = ibufsize;
  return 0;
}

/*ARGSUSED*/
exit_chatd(rc, str)
int rc;
char *str;
{
  int i;
#if DEBUG
  bbslog("Server exit: %s\n", str);
  close_bbslog();
#endif
  close(sock);
  unlink(PATH_CHATPORT);
  unlink(PATH_CHATPID);
  utable_detach(0);
  if (rc) {
    for (i=0; i<bbs_max_users; i++)
      if (users[i].sockfd != -1) close(users[i].sockfd);
  }
  free(users);
  free(rooms);
  exit(rc);
}

void
sig_catcher(sig)
{
  char msg[80];
  sprintf(msg, "shutting down due to signal %d\n", sig);
  signal(sig, SIG_DFL);
  exit_chatd(1, msg);
}  

_write_daemoninfo(fname, number)
char *fname;
unsigned short number;
{
  FILE *fp;
  if ((fp = fopen(fname, "w")) == NULL) {
    fprintf(stderr, "cannot open %s\n", fname);
    perror("fopen");
    exit_chatd(1, "cannot write chatport or chatpid file");
  }
  fprintf(fp, "%04x\n", number);
  fclose(fp);
}

main(argc, argv)
int argc;
char *argv[];
{
  struct sockaddr_in sin;
  register int i;
  int pid, sr, newsock, sinsize;
  fd_set readfds;
  struct timeval *tvptr = NULL;

#ifdef DEBUG
  open_bbslog("chat.debug", 6);
#endif

  if (argc < 2) {
    fprintf(stderr, "Usage: %s numusers\n" ,argv[0]);
#ifdef DEBUG
    close_bbslog();
#endif
    return 1;
  }
  
  bbs_max_users = atoi(argv[1]);

  if (bbs_max_users == 0) {
    fprintf(stderr, "maxusers cannot be zero\n");
#ifdef DEBUG
    close_bbslog();
#endif
    return 1;
  }

  manager_list = restricted_list = NULL;
  create_namelist (&manager_list, bbs_max_users);
  create_namelist (&restricted_list, bbs_max_users);
  strcpy(mainroom, "main");    
  chat_init_config();

  users = (struct chatuser *)calloc(bbs_max_users, sizeof(*users));
  if (users == NULL) {
    perror("calloc");
#ifdef DEBUG
    close_bbslog();
#endif
    return 1;
  }
  for (i=0; i<bbs_max_users; i++) users[i].sockfd = users[i].utent = -1;

  rooms = (struct chatroom *)calloc(bbs_max_users, sizeof(*rooms));
  if (rooms == NULL || 
     (rooms[0].invites = (char *)malloc(bbs_max_users)) == NULL) {
    perror("calloc");
#ifdef DEBUG
    close_bbslog();
#endif
    return 1;
  }
  strcpy(rooms[0].name, mainroom);

  if (utable_attach(bbs_max_users) != S_OK) {
    fprintf(stderr, "cannot attach to utable\n");
#ifdef DEBUG
    return 1;
#endif
  }

  if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
    perror("socket");
    exit_chatd(1, "socket failed");
  }

  sin.sin_family = AF_INET;
  sin.sin_port = 0;
  sin.sin_addr.s_addr = INADDR_ANY;

  if (bind(sock, (struct sockaddr *)&sin, sizeof sin) == -1) {
    perror("bind");
    exit_chatd(1, "bind failed");
  }

  sinsize = sizeof sin;
  if (getsockname(sock, (struct sockaddr *)&sin, &sinsize) == -1) {
    perror("getsockname");
    exit_chatd(1, "getsockname failed");
  }

  if (listen(sock, SOMAXCONN) == -1) {
    perror("listen");
    exit_chatd(1, "listen failed");
  }

  /* race condition here if two daemons start up at once? */
  _write_daemoninfo(PATH_CHATPORT, htons(sin.sin_port));

#if !DEBUG
  switch (pid = fork()) {
  case -1:
    perror("fork");
    exit_chatd(1, "fork failed");
  case 0:
    setpgid(0, 0);
    break;
  default:
    /* Assuming that a pid fits into a ushort may be a bad idea. */
    _write_daemoninfo(PATH_CHATPID, (unsigned short)pid);
    return 0;
  }
#else
  printf("Server bound to port %d\n", htons(sin.sin_port));
#endif

  signal(SIGHUP, sig_catcher);
  signal(SIGINT, sig_catcher);
#if !DEBUG
  signal(SIGQUIT, sig_catcher);
#endif
  signal(SIGILL, sig_catcher);
  signal(SIGIOT, sig_catcher);
#ifdef SIGEMT
  signal(SIGEMT, sig_catcher);
#endif
  signal(SIGFPE, sig_catcher);
#ifdef SIGBUS
  signal(SIGBUS, sig_catcher);
#endif
  signal(SIGSEGV, sig_catcher);
#ifdef SIGSYS
  signal(SIGSYS, sig_catcher);
#endif
  signal(SIGPIPE, SIG_IGN);
  signal(SIGTERM, sig_catcher);
  signal(SIGALRM, SIG_IGN);
#ifdef SIGIO
  signal(SIGIO, SIG_IGN);
#endif
#ifdef SIGURG
  signal(SIGURG, SIG_IGN);
#endif
#ifdef SIGPWR
  signal(SIGPWR, sig_catcher);
#endif

  FD_ZERO(&allfds);
  FD_SET(sock, &allfds);
  nfds = sock+1;

  while (1) {
    memcpy(&readfds, &allfds, sizeof readfds);
#if DEBUG
    bbslog("Selecting...");
#endif
    sr = select(nfds, &readfds, NULL, NULL, tvptr);
#if DEBUG
    bbslog("done: returned %d\n", sr);
#endif
    if (sr == 0) {
      exit_chatd(0, "normal chat server shutdown");      
    }

    if (sr == -1) {
      if (errno == EINTR) continue;
      else {
	exit_chatd(1, "select failed");
      }
    }

    if (tvptr) tvptr = NULL;

    if (FD_ISSET(sock, &readfds)) {
      sinsize = sizeof sin;
      newsock = accept(sock, (struct sockaddr *)&sin, &sinsize);
      if (newsock == -1) {
#if DEBUG
        bbslog("accept failed: errno %d\n", errno);
#endif	
	continue;
      }
      for (i=0; i<bbs_max_users; i++) {
        if (users[i].sockfd == -1) {
          users[i].sockfd = newsock;
          users[i].room = -1;
	  users[i].ibufsize = 0;
#if DEBUG
	  bbslog("Connection to slot %2d, fd %d\n", i, newsock);
#endif
          break;
        }
      }
      if (i >= bbs_max_users) {
        /* full -- no more chat users */
        close(newsock);
      }
      else {
#if !RELIABLE_SELECT_FOR_WRITE
        int flags = fcntl(newsock, F_GETFL, 0);
        flags |= O_NDELAY;
        fcntl(newsock, F_SETFL, flags);
#endif
        FD_SET(newsock, &allfds);
        if (newsock >= nfds) nfds = newsock+1;
        num_conns++;
      }
    }

    for (i=0; i<bbs_max_users; i++) {
      /* we are done with newsock, so re-use the variable */
      newsock = users[i].sockfd;
      if (newsock != -1 && FD_ISSET(newsock, &readfds)) {
        if (process_chat_command(i) == -1) {
          logout_user(i);  /* this clear the bit in allfds & dec. num_conns */
	}
      }
    }

    if (num_conns <= 0) {
      /* one more pass at select, then we go bye-bye */
      tvptr = &zerotv;
    }
  }
  /*NOTREACHED*/
  return 0;
}

nvite", chat_invite, 0,
  "join", chat_join, 0,
  "kick", chat_kick, 0,
  "me", chat_emote, 1,
  "msg", chat_private, 0,
  DarkNET-1.08/Install                                                                                   755   21270   21270         3743  5650501026   7413                                                                                                                                                                                                                                                                                                                                                                      #!/bin/sh
# 
# Eagles BBS 3.0 install script
#

homedir=$1
if [ "$homedir" = "" ]
then
    homedir=$BBSHOME;
    if [ "$homedir" = "" ]
    then
        homedir=`grep ^newbbs: /etc/passwd | cut -d: -f6`
        if [ "$homedir" = "" ]
        then
    	    echo Cannot determine bbs home directory\!
	    echo You must do one of the following\:
	    echo \ \ \ \ \-\- define INSTALLDIR in the Makefile
	    echo \ \ \ \ \-\- define BBSHOME in the environment
	    echo \ \ \ \ \-\- add an entry for 'bbs' into /etc/passwd.
	    exit 1
	fi
    fi
fi

echo Checking directories
if [ ! -d "$homedir" ]
then
    echo Creating "$homedir"
    mkdir $homedir
    chmod 770 $homedir
fi

if [ ! -d "$homedir/bin" ]
then
    echo Creating $homedir/bin
    mkdir $homedir/bin
fi

if [ -f "$homedir/bin/lbbs" ]
then
    echo Moving existing lbbs to lbbs.old
    mv $homedir/bin/lbbs $homedir/bin/lbbs.old
fi

if [ -f "$homedir/bin/chatd" ]
then
    echo Moving existing chatd to chatd.old
    mv $homedir/bin/chatd $homedir/bin/chatd.old
fi

echo Copying new executables
cp lbbs chatd addacct delacct bbslog bbfinger $homedir/bin
(cd $homedir/bin; strip lbbs chatd addacct delacct bbslog bbfinger)
cp mkftplist.pl $homedir/bin
chmod 6755 $homedir/bin/lbbs

if [ ! -d "$homedir/etc" ]
then
    echo Creating $homedir/etc
    mkdir $homedir/etc
    echo Copying configuration files
    cp config/* $homedir/etc    
fi

if [ ! -d "$homedir/tmp" ]
then 
    echo Creatimg $homedir/tmp
    mkdir $homedir/tmp
fi

if [ ! -d "$homedir/tmp" ]
then 
    echo Creatimg $homedir/tmp
    mkdir $homedir/tmp
fi

if [ ! -d "$homedir/home" ]
then 
    echo Creatimg $homedir/home
    mkdir $homedir/home
fi

if [ ! -d "$homedir/home/SYSOP" ]
then 
    echo Creatimg $homedir/home/SYSOP
    mkdir $homedir/home/SYSOP
fi

if [ ! -d "$homedir/home/SYSOP/mail" ]
then 
    echo Creatimg $homedir/home/SYSOP/mail
    mkdir $homedir/home/SYSOP/mail
fi

if [ ! -d "$homedir/boards" ]
then 
    echo Creatimg $homedir/boards
    mkdir $homedir/boards
fi

                             DarkNET-1.08/lang.c                                                                                    644   21270   21270         1070  5731467056   7151                                                                                                                                                                                                                                                                                                                                                                      #include "server.h"

int lang = 0;	/* default Eng */

local_bbs_set_lang(mode)
int mode;
{
  ACCOUNT acct;
  extern USERDATA user_params;
  extern int user_number;

  utable_get_record(user_number, &user_params);

  if (mode == 0) {
    strcpy(acct.lang, "Kr");
    acct.flags = FLG_KOREAN;
    user_params.u.flags |= FLG_KOREAN;
    lang = 1;
  } else {
    strcpy(acct.lang, "Eng");
    acct.flags = 0;
    user_params.u.flags &= ~FLG_KOREAN;
    lang = 0;
  }
  utable_set_record(user_number, &user_params);
  return (_set_account(my_userid(), &acct, MOD_LANG));
}
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        DarkNET-1.08/README.UnderB                                                                             644   21270   21270        12125  5751546705  10146                                                                                                                                                                                                                                                                                                                                                                      -------------------------------------------------------------------------------
	[¾ð´õºñ 1.07]

	That buggy IYAGI 5.3 does not supports scrolling either!

	If Post right after Select as soon as Login, the
	selected board is not opened which can cause the readbit
	file info. corrupted.

        À¯Àú ÀÌ¸§ÀÌ 25 ·Î ±æ°æ¿ì char array buffer °¡ overflow µÇ¾î¼­
	crash µË´Ï´Ù.

	¶ÇÇÑ À§ÀÇ °æ¿ì menu ÀÇ ½ºÆ®¸µÀÌ ±æ°æ¿ì¿¡ È­¸é¿¡ °ãÄ¨´Ï´Ù.
	(etc/menu.desc needs change)

	º»ÀÎÀÌ Æ÷½ºÆÃ Çß´ø ¸Þ¼¼Áö´Â ÆíÁýÀÌ °¡´ÉÇÕ´Ï´Ù.
	(etc/access needs change)

	À§¿¡¼­ menu.desc ¿Í access °¡ ¹Ù²ï ºÎºÐÀº config ¿¡ »õ°ÍÀ» ³Ö¾ú½À´Ï´Ù.
-------------------------------------------------------------------------------
	[¾ð´õºñ 1.06]

	talk ÇÒ¶§ ±úÁö´Â ÇÑ±Û ¹®Á¦ º¸¿Ï - ÇÑÁÙÀÌ ³Ñ°Ô ±ÛÀ» ÃÄ¼­ wrap µÉ¶§
	ÁÖ·Î »ý±â´Â ¹®Á¦.

	irc »ç¿ëÁß idle timeout ¿¡ °É¸®¸é irc °¡ Á×Áö ¾ÊÀº »óÅÂ¿¡¼­
	bbs ·Î ¸®ÅÏ µÇ¾î È­¸éÀÌ ¿ÏÀüÈ÷ ±úÁö°í.. irc ´Â »ì¾Æ ³²¾Æ¼­
	¹®Á¦°¡ »ý±è.

	osdeps.h ¿¡ #define LINUX 1 ÀÌ µÇ°í #define SUNOS 0 ¶Ç´Â ´Ù¸¥
	OS ¸¦ 0 À¸·Î define ÇßÀ»¶§ #ifdef SUNOS ´Â true °¡ µÇ¾î ¹ö¸²
	#if SUNOS == 1 °ú °°Àº ÇüÅÂ·Î ¹Ù²î¾î¾ß ÇÔ.

-------------------------------------------------------------------------------
	[¾ð´õºñ 1.05]
	helvis1.8h1+ ¼³Ä¡ (modified for BBS).

	Ã¤ÆÃ ÇÑ±Û 2 ¹ÙÀÌÆ® ÄÚµå ¹öÆÛ¸µ.

	»ç¿ë¾ð¾î º¯È¯½Ã¿¡ »ç¿ëÀÚÀÇ ¸ðµå ½ºÆ®¸µ ÃÊ±âÈ­ ¿¡·¯ °íÄ§.

	µµ¿ò¸» ½ºÅ©¸° µð½ºÇÃ·¹ÀÌ ·çÆ¾ optimized for slow link speed.

	talk ÇÑ±Û 2 ¹ÙÀÌÆ®ÄÚµå ¹öÆÛ¸µ ÀÌ¹Ì ´õÇØÁ³Áö¸¸ changelog ¿¡
	ºüÁ³À½.

-------------------------------------------------------------------------------
	[¾ð´õºñ 1.041]
	vedit ¹é½ºÆäÀÌ½º ¹ú·¹ ¼öÁ¤

-------------------------------------------------------------------------------
	[¾ð´õºñ 1.04]

	vedit ÇÑ±Û ÆíÁý±â´É °­È­.

	¿ÜºÎÆíÁý±â - pico & vi (helvis) - »ç¿ë½Ã ¿¡µðÆ® ÈÄ¿¡
	ÀçÆíÁý ÇÒ°ÍÀÎÁö confirm ÇÏ´Â ºÎºÐ Ãß°¡.

	pico »ç¿ë½Ã Ä¿¼­ ¿òÁ÷ÀÓ ºÎºÐ ÇÑ±Û ´ÜÀ§·Î ¿òÁ÷ÀÌ°Ô ¹Ù²Þ.

	ÇÑ±Û ±úÁö´Â °ÍÀ» Á¶±ÝÀÌ³ª¸¶ ´õ ¸·°íÀÚ,
	ÅäÅ© ÇÒ¶§ ÇÑ±Û ´ÜÀ§·Î erase ±×¸®°í ÇÑ±Û ´ÜÀ§·Î ¾²°Ô²û ÇØÁÜ

	±×¿Ü¿¡´Â »ç¼ÒÇÑ ¹®Á¦µé.. º¯È­.

 	ÀÌÁ¦´Â ¾î´ÀÁ¤µµ ±â´É»óÀÇ ¹ú·¹´Â »ç¶óÁø °Í °°³×¿ä..

-------------------------------------------------------------------------------
	[¾ð´õ ºñºñ¿¡½º 1.03]

	¿©·¯°¡Áö ÀÚÁú ±¸·¡ÇÑ ¹ú·¹ÀâÀÌ.

	¾ÆÀÌµé Å¸ÀÓ¾Æ¿ìÆ® ½º¿¡ irc ½ÃÃ¼ ³²À» °¡´É¼º Á¦°Å.

	³»¿ëÀÌ ¾ø´Â È­ÀÏÀº Æ÷½ºÆÃ ¾ÈÇÔ.

	c_msg.c/c_msg.h ³¡.

	Á¶È¸¼ö ±â´É Ãß°¡.

	ÄÞ¸Çµå ÇÁ¶÷ÇÁÆ®¿¡ ÇöÀç È¯°æ º¸¿©ÁÜ - [¿¡Æ¼ÅÍ/ÅÍ¹Ì³¯Å¸ÀÙ/À¯ÀúÀÌ¸§]
	Çü½ÄÀ¸·Î..
------------------------------------------------------------------------------
	[¾ð´õ ºñºñ¿¡½º 1.02]

	¿ª½Ã ¹ú·¹ÀâÀÌ.

	name.c º¯È­·Î ÀÎÇØ À¯Àú°¡ free_namelist() ¸¦ ¸®½ºÆ® ¸¸µé¾î
	»ç¿ëÇÑÈÄ¿¡ ºÒ·¯ Áà¾ß ÇÔ.

	Mail ¿¡¼­ ºó ÆíÁö´Â ¾Èº¸³¿.

	¿À¹ö¸®¾Æµå ¸®½ºÆ®, º¸µå¸Å´ÏÁ® ¸®½ºÆ® ¹ú·¹ ÀâÀÌ.

	c_msg.c/c_msg.h ¸¦ »ç¿ëÇØ ¿¡·¯¸Þ¼¼Áö/·Î±×¸Þ¼¼Áö µîÀº
	ÇÑ±ºµ¥ ¸ô°í ÀÖ´ÂÁß - ¾ÆÁ÷ ¹ÝÁ¤µµ ¹Û¿¡ ¾È³¡³µÀ½..°è¼Ó ÁøÇàÁß.

	note: ¾ð´õºñ 1.00 °¡ ¿ª½Ã »ç¶÷µéÀÌ ´Þ¶õ´Ù°í ¹Ù²ÛÁö ¾ó¸¶ ¾ÈµÇ´Â
	´ë¿¡µµ ºÒ±¸ÇÏ°í ±×³É ³¯·¡¹Ì·Î Å×½ºÆÃµµ º°·Î ¾øÀÌ °ø°³ÇÑ Æ¼°¡
	ÆÅÆÅ ³ª°í ÀÖÀ½.
-------------------------------------------------------------------------------
	[¾ð´õ ºñºñ¿¡½º 1.01]

	¾ð´õºñ 1.0 ¿¡¼­ name.c °ü°èµÈ ¹ú·¹µéÀÌ ÀÖ¾ú½À´Ï´Ù.
	ÁÖ·Î mail °ü°è ¹ú·¹¿´´Âµ¥.. ´ëÃæ ´Ù ÀâÀº °Í °°½À´Ï´Ù.
-------------------------------------------------------------------------------
	[¾ð´õ ºñºñ¿¡½º 1.00]

	Eagle BBS 3.0 ÄÚµå¿¡ 3.01 ÆÐÄ¡ ÇÊ¿ä ÇÑ°Í ³Ö°í
	¿©·¯°¡Áö ÀÚÁú ±¸·¹ÇÑ ÀÌ±Û ºñºñ¿¡½º ¹ú·¹ °íÄ£ÈÄ¿¡
	ÇÑ±Û ¼­Æ÷Æ®¸¦ À§ÇØ °íÃÆ½À´Ï´Ù.

	ÇÑ±Û irc ¸¦ ¸î°¡Áö ½ÃÅ¥¸®Æ¼ ¹®Á¦ µÉ ºÎºÐÀº »èÁ¦ ÇØ¼­
	ÆÐÅ°Áö ÇØ³Ö¾úÀ¸¸ç.

	PICO ¿¡µðÅÍ¸¦ ³ª¸§´ë·Î ÇÑ±Û Áö¿ø¿¡ ºñºñ¿¡½º¿ëÀ¸·Î
	¸î°¡Áö º¸¾È»ó ¹®Á¦ »©¾úÀ¸¸ç.
	
	¸¶Âù°¡Áö·Î helvis ¿¡¼­µµ ¸î°¡Áö »©°í ÆÐÅ°Â¡ Çß½À´Ï´Ù.

	external tool ¸î°¡Áö¸¦ ´õÇØÁÖ¾ú°í

	config ¾È¿¡´Â ÇöÀç ¾ð´õºñÀÇ »óÅÂ´ë·Î ³Ö¾ú½À´Ï´Ù.

	¿©·¯°¡Áö ½ºÇÇµå ¾÷À» À§ÇØ name.c ¿Í complete.c ´Â
	°ÅÀÇ ¿À¸®Áö³¯ ÄÚµå¿Í´Â ¿ÏÀüÈ÷ µýÆÇÀ¸·Î º¯ÇßÀ¸¸ç.

	´º Æ÷½ºÆÃÀ» ÇÞÀ»¶§ ÀÚ±â ÀÚ½Å¿¡°Ôµµ ´º ¾ÆÆ¼Å¬·Î º¸ÀÌ´Â ¹ú·¹
	Àâ¾Ò½À´Ï´Ù.

	irc »ç¿ëÁß¿¡ page °¡ ¿Ã°æ¿ì ½Ã±×³¯À» ¸±·¹ÀÌ ÇØÁà¼­
	irc È­¸é¿¡ ÆäÀÌÁö ³ëÆ¼½º°¡ ÂïÈ÷µµ·Ï ÇØÁÖ¾ú½À´Ï´Ù.

	È­¸éÁ¶Á¤Àº full screen ¸ðµå°¡ °¡´ÉÇÏ°Ô Æ¯È÷ hanterm °ú
	°°Àº °æ¿ì..  °íÃÆÀ¸³ª.. ´ÜÁö irc »ç¿ëÁß¿¡ È­¸é½ÎÀÌÁî¸¦
	Á¶Á¤ÇÒ °æ¿ì ¹®Á¦°¡ »ý±é´Ï´Ù.

	¾ÆÁ÷ ¿©·¯°¡Áö ¹ÌºñÇÑ Á¡ÀÌ ¸¹À¸³ª ¿ì¼± ÄÚµå¸¦ ¿äÃ»ÇÏ´Â »ç¶÷ÀÌ
	¸¹°í ÇØ¼­..´ëÃæ ÆÐÅ°Â¡ ÇØ¼­ ¸±¸®½º ÇÕ´Ï´Ù.

	¾ÆÁ÷ make ÇÏ°í make install ÇÏ´Âµ¥¿¡..¿©·¯°¡Áö ÀÚÁú±¸·¹ÇÑ
	¹®Á¦°¡ »ý±æ¼ö ÀÖ½À´Ï´Ù.

	¿ì¼± Ã¹¹øÂ°·Î Makefile ¿¡¼­ INSTALLDIR ¸¦ ÁöÁ¤ÇØ ÁÖ½Ã°í
	make irc; make ÇÏ½Å ´ÙÀ½¿¡ make install À» ÇÏ¼¼¿ä.

	ÇöÀç ÆÐÅ°Áö µÇ¾îÀÖ´Â ¸ðµç °ÍÀº Linux 1.2.2 ¿¡¼­
	-mpentium ÇÃ·¡±×°¡ µé¾î°¡ ÀÖ±â ¶§¹®¿¡..¸¸¾à º¸Åë GCC ¸¦
	»ç¿ëÇÏ½Ç°æ¿ì -mpentium ÇÃ·¡±×¸¦ ¸ðµÎ Ã£¾Æ¼­ »Ì¾Æ ÁÖ¼Å¾ß ÇÕ´Ï´Ù.

	ÀÌÀü¿¡ SunOS 4.1.3 ¿¡¼­ µ¹¸®´ø ÄÚµå ÀÌ¹Ç·Î
	¾à°£ÀÇ ¼ÕÁú·Î SunOS ³ª À¯»ç Unix ¿¡¼­ ÀÎ½ºÅç ÇÏ´Âµ¥¿¡
	º° ¹®Á¦°¡ ¾øÀ¸¸®¶ó º¾´Ï´Ù.

	¹ú·¹°¡ ¹ß°ßµÇ¸é Áï½Ã ¿¬¶ôÇØ ÁÖ½Ã¸é °í¸¿°Ú½À´Ï´Ù.


	¸ðµç change ´Â ´ÙÀ½ copyright ¸¦ ´Þ¾Æ¾ß ÇÏ³ª ±×³É ¿©±â¿¡
	ÇÏ³ª ³Ö°í »ý·«ÇÕ´Ï´Ù.

	»ó¾÷Àû ¿ëµµ·Î »ç¿ëÇÏÁö ¾Ê´Â ÀÌ»ó ÄÚµå¸¦ °¥¾Æ ¸¶½Ã´ø ¾îÄÉ ÇÏ´ø
	»ó°ü¾øÁö¸¸ °¡´ÉÇÏ¸é ÄÚµå º¯È¯Àº ¾Ë·Á ÁÖ¼ÌÀ¸¸é ÇÕ´Ï´Ù.
	±×¸®°í °¡´ÉÇÏ¸é ÀÌÁ¦ºÎÅÒÀº changelog ¸¦ ¸¸µé¾úÀ¸¸é ÇÕ´Ï´Ù¸¸
	»ç¿ëÀÚ ¿©·¯ºÐÀÇ Çù·ÂÀÌ ÀÖ±â Àü¿¡´Â Èûµå´Ï °£´ÜÇÏ°Ô ³ª¸¶
	¹®Á¦Á¡°ú ÄÚµåº¯µ¿Àº ÆíÁö¸¦ ÁÖ¼ÌÀ¸¸é ÇÕ´Ï´Ù.

	Copyright (C) 1995, Daeshik Kim
		hellcat@korea.slip.umd.edu
		dkim@hq.si.net
                                                                                                                                                                                                                                                                                                                                                                                                                                           DarkNET-1.08/ircii-2.8.H1/                                                                             755   21270   21270            0  5742066134   7646                                                                                                                                                                                                                                                                                                                                                                      DarkNET-1.08/ircii-2.8.H1/.cvsignore                                                                   644   21270   21270           75  5704230432  11665                                                                                                                                                                                                                                                                                                                                                                      core
irc.core
config.status
config.log
config.cache
Makefile
                                                                                                                                                                                                                                                                                                                                                                                                                                                                   DarkNET-1.08/ircii-2.8.H1/ChangeLog                                                                    644   21270   21270       174626  5711645766  11577                                                                                                                                                                                                                                                                                                                                                                      /*
 * ChangeLog: Dealing with the actual changes of code in ircII, leaving
 * UPDATES for actual user changes.
 *
 * Matthew Green, 1993.
 *
 * Copyright(c) 1993, 1994, 1995
 *
 * See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT
 *
 * @(#)$Id: ChangeLog,v 2.22 1995/01/26 07:15:02 mrg Exp $
 */

2.8
Thu Jan 26 18:13:57 EST 1995 - matthew green <mrg@mame.mu.oz.au>
	released to the public.

2.7.3
Tue Jan 24 00:13:28 EST 1995 - matthew green <mrg@mame.mu.oz.au>
	configure, configure.in, include/exec.h, include/irc_std.h
	source/exec.c:
		some fixes for next:  major lossage head damaged
		i don't know how to organise an operating system
		such that it works -or- i'm just a stupid git who
		has no idea about standards.  you choose.

2.7.2
Sat Jan 21 12:34:02 EST 1995 - matthew green <mrg@mame.mu.oz.au>
	source/dcc.c:
		always make sure from_server is set in dcc_open.
	source/edit.c:
		some zcat fixes.
	configure, configure.in:
		-lc -lposix for NeXT.

2.7.1
Mon Jan 16 20:14:59 EST 1995 - matthew green <mrg@mame.mu.oz.au>
	source/server.c, source/edit.c, include/server.h:
		added /disconnect.

Mon Jan 16 17:23:38 EST 1995 - matthew green <mrg@mame.mu.oz.au>
	source/parse.c:
		can't use '\a' on broken compilers.  what a pile
		of shit they are.  found by comstud.

Sun Jan 15 12:14:39 EST 1995 - matthew green <mrg@mame.mu.oz.au>
	source/newio.c:
		fixed bug caused with /flush sending a null rd
		value to new_select().  duh.  found by
		arnaud.girsch@insa-lyon.fr.

2.7
Thu Jan 12 21:20:04 EST 1995 - matthew green <mrg@mame.mu.oz.au>
	2.7 released to the world.

Wed Jan 11 14:16:34 EST 1995 - matthew green <mrg@mame.mu.oz.au>
	source/server.c:
		fixed for new dgets_errno being -1 for read == 0.
		broken strerror() on losing systems.

Tue Jan 10 23:40:24 EST 1995 - matthew green <mrg@mame.mu.oz.au>
	source/whois.c:
		i hate c.  stdarg fixes me and glen bashed into
		working.
	source/window.c:
		doh!  thanks glen.

2.6.10
Sat Jan  7 01:30:11 EST 1995 - matthew green <mrg@mame.mu.oz.au>
	configure.in:
		fixed typo.
	NEWS:
		updated for 2.7
	source/server.c:
		fixed bug in dcc send/chat and non-first server
		connected to.
	include/vars.h.proto, include/keys.h.proto,
	include/hook.h.proto:
		changed __P macro.
	source/ctcp.c source/debug.c source/file.c source/flood.c
	source/funny.c source/hold.c source/ircflush.c
	source/ircserv.c source/lastlog.c source/list.c
	source/menu.c source/notice.c source/output.c source/reg.c:
		reformat.  nothing else needed now.

2.6.9
Thu Jan  5 17:52:00 EST 1995 - matthew green <mrg@mame.mu.oz.au>
	source/vars.c:
		fixed losing ansi stuff.
	Makefile.in:
		added cleandir and realclean targets.

Wed Jan  4 22:44:18 EST 1995 - matthew green <mrg@mame.mu.oz.au>
	configure.in, source/help.c, source/mail.c:
		updated fully for autoconf 2.x.  this could lead
		to some breakage.  we'll see.
	source/edit.c:
		make `/topic * foo' work as expected.
	source/keys.c, source/term.c:
		fixed eight_bit_mode and /bind'ing char's with an
		eigth bit set.

2.6.8
Tue Jan  3 01:14:53 EST 1995 - matthew green <mrg@mame.mu.oz.au>
	source/
		removed all occurances of "index" as a variable.
		move the ansi prototype macro from __P() to _()
	code "freeze" for 2.7

Mon Jan  2 16:44:10 EST 1995 - matthew green <mrg@mame.mu.oz.au>
	source/names.c, source/funny.c, source/parse.c,
	include/names.h:
		added new method of user joining for irc 2.9 (
		JOIN #foo^G[ov]) handling.

Sun Jan  1 21:39:58 EST 1995 - matthew green <mrg@mame.mu.oz.au>
	source/dcc.c, source/server.c, include/server.h
		added struct in_addr to server structure that is
		filled in with getsockname() and is used in dcc
		requests.
	source/dcc.c:
		added idea from mark to show unknown dcc requests.
	source/newio.c:
		fixed new_select() to call select with the correct
		first argument.

2.6.7
Thu Dec 29 22:22:34 EST 1994 - matthew green <mrg@mame.mu.oz.au>
	source/Makefile.in:
		fixed lossage with wterm dependancies.
	source/irc.c:
		fixed "irc --" and "irc -q nick" core dumps.
	source/input.c:
		make transpose chars work at the end of line.
	doc/ircII.1:
		updated my email address.

2.6.6
Wed Dec 21 20:43:04 EST 1994 - matthew green <mrg@mame.mu.oz.au>
	source/Makefile.in:
		updated dependancies.  (problems pointed out by
		daniel carosone).
	source/dcc.c:
		read in to the *end* of the buffer, dork.

2.6.5
Mon Dec 19 02:57:38 EST 1994 - matthew green <mrg@mame.mu.oz.au>
	Makefile.in, configure.in:
		some changes as needed for autoconf 2.x.
	source/dcc.c, source/window.c, include/dcc.h:
		might have fixed the bug with bsd/dcc chat.

2.6.4
Mon Dec 19 01:47:21 EST 1994 - matthew green <mrg@mame.mu.oz.au>
	source/irc.c, source/notice.c, include/irc.h:
		added -q option for quick startup.

Mon Dec 19 01:32:15 EST 1994 - matthew green <mrg@mame.mu.oz.au>

	source/edit.c, source/names.c, source/screen.c,
	source/window.c, include/window.h
		added 'bind' and 'unbind' window commands.
	source/edit.c:
		moved NOVICE /part stuff to only be when we are
		actually sending a JOIN to the server.

Sun Dec 18 23:00:54 EST 1994 - matthew green <mrg@mame.mu.oz.au>
	easyinst:
		fixed bug in question asking.
	source/server.c:
		fixed lossage with /server -delete, reported by
		scottr.
	source/parse.c:
		removed bogus fix from cjs@netcom.com.
	source/alias.c:
		still fixing chanusers().
	source/exec.c:
		close all unneeded fd's in /exec now.
	source/numbers.c:
		try to set the message_from level to the channel
		the numeric is about, if we can.
	source/screen.c:
		move closing in to close_all_screen() so we can
		call it for /exec also.

2.6.3
Sun Nov 27 03:16:16 EST 1994 - matthew green <mrg@mame.mu.oz.au>

	source/alias.c:
		fix for chanusers() from Greg Jarman <amigo@deakin.edu.au>
	source/ctcp.c
		fix for do_echo() from taner
	source/window.c
		made default JOIN rather than CHANNEL for /win join
	source/parse.c
		fix for /server lossage from cjs@netcom.com
	source/translat.c:
		fix for /set -translation

Sun Nov 27 02:36:23 EST 1994 - matthew green <mrg@mame.mu.oz.au>

	source/screen.c, source/vars.c, include/vars.h.proto:
		added dave leonard's screen_options stuff, as well
		as some bug fixes he found.

Fri Nov 25 16:58:00 EST 1994 - matthew green <mrg@mame.mu.oz.au>

	source/dcc.c:
		got fix for dcc problems from Scott Johnson
		<scottj@neuron.cs.tamu.edu>

Tue Nov 15 01:27:40 EST 1994 - matthew green <mrg@mame.mu.oz.au>

	source/dcc.c:
		added diagnostic to attempt to observe losing dcc
		chat and newer-bsd's.  it appears that somewhere
		between 2.5 and 2.6.2 it was fixed -- perhaps the
		edit.c lossage fixed in 2.6.1.
	source/edit.c:
		/join now defaults to sending a JOIN command rather
		than sending a CHANNEL command... duh!

2.6.2
Mon Nov 14 01:23:44 EST 1994 - matthew green <mrg@mame.mu.oz.au>

	source/names.c, source/server.c:
		fixed bug avalon found where death of other
		servers would cause channel lists to be broken.
	source/screen.c:
		fully initialised struct timeval for window create.
		
2.6.1
Tue Nov 08 02:35:r9 EST 1994 - matthew green <mrg@mame.mu.oz.au>

	Makefile.in, mkinstalldirs:
		removed old garbage, and we now use noah's
		mkinstalldirs..
	include/help.h, include/if.h, include/queue.h:
		added to help fix edit.c lossage.
	include/alias.h, include/crypt.h, include/edit.h,
	include/exec.h, include/history.h, include/hook.h.proto,
	include/ignore.h, include/irc.h, include/keys.h.proto,
	include/notify.h, include/parse.h, include/server.h,
	include/stack.h, include/parse.h, include/vars.h.proto,
	include/window.h, source/alias.c, source/crypt.c,
	source/edit.c, source/exec.c, source/help.c,
	source/history.c, source/hook.c, source/if.c,
	source/ignore.c, source/keys.c, source/match.c,
	source/names.c, source/notice.c, source/notify.c,
	source/queue.c, source/server.c, source/stack.c,
	source/translat.c, source/vars.c, source/window.c,
	source/irc.c:
		many of the functions in the edit.c command array
		were called with three args, but these functions
		only took 2 args.  all fixed up and prototyped now.
		who knows what lossage this caused.  found by
		diane bruce (db@diana.ocunix.on.ca).

2.6
Tue Oct 18 19:17:49 EST 1994 - matthew green <mrg@mame.mu.oz.au>

	script/newformat
		does $R processing for stats l output.  works only
		on the local server, though.  from ian.

Mon Oct 17 21:59:21 EST 1994 - matthew green <mrg@mame.mu.oz.au>

	source/reg.c:
		% was broken in pattern matching.  got a fix from
		ian and no_nick for this.  grumble.
	source/server.c, include/config.h.dist
		got a patch from ian to make ircii do dynamic
		ip number stuff.

2.5
Sun Oct 16 15:45:47 EST 1994 - matthew green <mrg@mame.mu.oz.au>

	more general clean up.

2.4
Sun Oct 16 09:48:53 EST 1994 - matthew green <mrg@mame.mu.oz.au>

	source/edit.c:
		turned on hop's for, fe and fec commands.

Sat Oct 15 13:25:47 EST 1994 - matthew green <mrg@mame.mu.oz.au>

	general clean up of everything.

2.3.24
Wed Oct 12 09:24:36 EST 1994 - matthew green <mrg@mame.mu.oz.au>

	source/debug.c:
		added fixes.
	source/irc.c, source/screen.c:
		added debugging info in forward_scroll. (not part
		of release tree).
	source/stack.c:
		begun finishing.

Sun Oct  9 16:42:44 EST 1994 - matthew green <mrg@mame.mu.oz.au>

	configure.in source/crypt.c source/dcc.c source/debug.c
	source/edit.c source/exec.c source/help.c source/history.c
	source/hook.c source/ircaux.c source/server.c source/log.c
	source/term.c source/whois.c source/window.c source/output.c
	source/ctcp.c:
		stdarg.h patches from brianc@qnx.com and glen@qnx.com,
		plus some other minor fixes.  qnx support, also.

Thu Oct  6 22:16:42 EST 1994 - matthew green <mrg@mame.mu.oz.au>

	source/server.c:
		fixed `bug' in -DPHONE where /window server + was
		setting the window level to ALL.  eeew.

Mon Sep 26 14:38:17 EST 1994 - matthew green <mrg@mame.mu.oz.au>

	source/alias.c:
		fix for onchannel() from Scott Reynolds
		<scott@lisa.acs.nmu.edu>

2.3.23beta
Sun Sep  4 00:24:13 EST 1994 - matthew green <mrg@mame.mu.oz.au>

	source/names.c:
		fixed /part bug,and a fix (finally!) for ischanop()
		from <cbehrens@iastate.edu>.
	source/dcc.c:
		fixed bug where you could not dcc send to one person
		more than once.
	source/screen.c:
		fixed resize bug when going to s smaller window and
		a line would be cut off.  how did this last so long?

Tue Aug  2 00:30:33 EST 1994 - matthew green <mrg@mame.mu.oz.au>

	configure.in, include/irc.h, include/term.h, source/scandir.c,
	source/term.c:
		fixed hpux autoconf problems.
		configure now checks that -lresolv actually works,
		and doesn't break compiles.
		configure doesn't use BSDWAIT if POSIX is defined,
		so that newer bsd systems (like netbsd) will use the
		POSIX waitpid() stuff, not causes warnings..

Sun Jul 31 21:53:03 EST 1994 - matthew green <mrg@mame.mu.oz.au>

	source/dcc.c:
		removed debug message, and a fix for DCC_RAW from
		jim_bob (jrg@doc.ic.ac.uk).

2.3.22beta
Sun Jul 31 03:07:00 EST 1994 - matthew green <mrg@mame.mu.oz.au>

	source/names.c, source/parse.c, include/names.h
		fixed ircii not forgetting about remembered channel
		modes after the channel has been joined.
	source/queue.c, source/notify.c, source/mail.c:
		fixed compatibilty problems found with sunos cc.
	source/irc.c:
		versions.
	script/autoop, script/list, script/functions, script/imap,
	script/history-match:
		fixed autoop & list, cleaned up functions and imap,
		added history-match (Daemon).

Tue Jul 26 22:12:42 EST 1994 - matthew green <mrg@mame.mu.oz.au>

	source/edit.c, source/alias.c:
		getcwd() fixes from cgw.
	source/dcc.h, include/dcc.h:
		added new member to the client struct, othername.
		it's currently only used by dcc_filesend() to save
		the name given as well as the full path - so that
		/dcc send file nick file works, without giving the
		full pathname for 'file'.

2.3.21b
Mon Jul 25 23:27:09 EST 1994 - matthew green <mrg@mame.mu.oz.au>

	source/window.c:
		window() - added new commands REMOVE, which is the
		opposite of ADD, and NUMBER, which changes the refnum
		of a window, forcing a swap if needed.
	source/ircserv.c:
		removed printf()'s. no more lame messages at startup
		now.
	acconfig.h, configure.in, include/irc.h, source/alias.c,
	source/dcc.c, source/edit.c:
		configure now checks for getcwd() not getwd(), and
		everything now uses getcwd() not getwd().
	source/term.c:
		cleaned up a bit.
	script/uhnotify:
		got a fix from taner <taner@ucsd.edu>.


2.3.21a
Sat Jul 23 23:30:53 EST 1994 - matthew green <mrg@mame.mu.oz.au>

	source/alias.c:
		fixed the broken $, bug introduced from hop's alias.c
		changes.  blah.

Sat Jul 23 18:37:25 EST 1994 - matthew green <mrg@mame.mu.oz.au>

	source/alias.c, include/irc_std.h, source/term.c:
		removed sys/param.h, and moved it into irc_std.h.
		this was to get the newer bsd's define of BSD4_4
		(net/2 defines this as 0.5), which was then used
		in term.c to use termios.
	source/ctcp.c:
		also prints unix version (uname) in ctcp finger
		reply.
	source/scandir.c:
		removed sunos4 readdir_r() stuff.  it used to fail
		because we were getting the ucblib's readdir() but
		not using the right header files.
	include/irc_std.h, configure.in, acconfig.h:
		added a check for memmove(), which we now use if we
		are missing bcopy().


2.3.21
Sun Jul  3 17:03:52 EST 1994 - matthew green <mrg@mame.mu.oz.au>

	source/alias.c:
		fixed bug that broke /if and chewed cpu time.

2.3.20
Sat Jul  2 17:36:41 EST 1994 - matthew green <mrg@mame.mu.oz.au>

	this version was mostly updates from jeremy nelson
	(jnelson@iastate.edu), with a few other bits from me.

	configure, acconfig.h:
		bug fix for signal() test, and check for uname(2).
	include/dcc.h, source/notice.c, source/whois.c:
		added new hooks ENCRYPTED_NOTICE and
		ENCRYPTED_PRIVMSG from hop (jnelson@iastate.edu)
	include/names.h, source/names.c:
		fixed memory leak in recreate_mode() that hop found,
		but patched badly ;).  it now caches the string
		version of the mode for each channel, in each channel's
		channel struct.
	source/Makefile.in:
		updated dependancies.
	source/alias.c:
		reworked parser stuff from hop, plus a few new goodies.
	source/ctcp.c:
		added special parsing of ctcp SED.
		added posix uname() handling for ctcp FINGER.
	source/help.c:
		temporary fix for compressed help pages.
	source/hook.c:
		added hop's new do_hook() and assiciated routines that
		fix the bugs we had in serial numbers.
	source/if.c:
		added some of hop's if.c hacks
	source/ircaux.c:
		added hop's stristr() and rstristr() functions.
	source/parse.c:
		many bug fixes from hop.
	source/queue.c:
		added hop's queue.c after cleaning it up a bit.
	source/whois.c:
		various bug fixes from hop and myself.

version 2.3.19 never really existed.

2.3.18
Sun Mar 27 22:41:02 EST 1994 - matthew green <mrg@mame.mu.oz.au>

	source/reg.c:
		fixed bug in matching where the string ended in \.
		found by avalon (avalon@coombs.anu.edu.au)
	source/input.c:
		fixed bug in transpose characters (avalon).
	source/alias.c:
		fixed pathetic code for showing aliases.
	source/dcc.c:
		fixed window level stuff.. bry (b@ctpm.org).
	source/hook.c 
		removing all hooks with a specific serial number
		works now (/on #hook 1 -).
	source/parse.c, source/numbers.c:
		fixed bugs with missing args

2.3.17beta
Mon Mar 21 00:08:15 EST 1994 - matthew green <mrg@mame.mu.oz.au>

	source/crypt.c, source/help.c, source/vars.c, source/screen.c,
	source/Makefile.in:
		fixed security bugs in /help and some /set's and in
		/window create.
	configure.in:
		moved AC_PROG_CPP.
	translation/RUSSIAN*:
		added this.  thanks to dima@demos.su (Dima Ruban)
		for these.

Sat Mar 19 00:04:42 EST 1994 - matthew green <mrg@mame.mu.oz.au>

	source/window.c:
		fixed bug in /on window_kill
	source/help.c:
		fixed lame bug in freeing nonallocated memory
	source/exec.c:
		fixed bugs in getpgrp() stuff
	source/dcc.c:
		dcc requests with the port < 1024 are now rejceted.
	source/scandir.c
		hopefully got the solaris 2 stuff right here.  i
		hate solaris 2.

2.3.16beta
Thu Feb  3 20:11:11 EST 1994 - matthew green <mrg@mame.mu.oz.au>

	source/ctcp.c:
		fixed stupid bug
	source/parse.c:
		fixed window level problems.

2.3.15beta
Tue Feb  1 19:18:23 EST 1994 - matthew green <mrg@mame.mu.oz.au>

	source/config.h:
		updated for the beta release.
	source/scandir.c:
		memory leak fixes, and solaris fixes.
	source/status.c:
		'mode k' bug fixed.  any non printables chars are now
		hanlded properly in the status line..

Mon Jan 17 18:48:54 EST 1994 - matthew green <mrg@mame.mu.oz.au>

	source/parse.c:
		fixed the level of topic changes
	source/server.c, source/notice.c:
		fixed resending away's on reconnect/changing servers.
	source/notify.c:
		made `notify -' delete all the nicks in the list.

Sun Jan  9 22:47:09 EST 1994 - matthew green <mrg@mame.mu.oz.au>

	source/ctcp.c:
		fixed ctcp flooding so that we don't see multiple
		`ctcp flood from nick'.
	source/whois.c:
		added notify_mark() all for 401.
	source/screen.c, source/wserv.c, include/screen.h:
		added the ttyname stuff, but aren't using it yet.
	source/alias.c:
		fixed stupid bug in alias parsing that gave core dumps.
		how this lasted this long i have no idea.
	source/dcc.c:
		remove the broken-dcc-times stuff, and now we just use
		the anal-ultrix stuff.
	source/parse.c:
		added message_from() things for p_channel().
	source/stack.c, source/stack.h:
		played some more.  things actually compile again here,
		but nothing new works.

2.3.14
Wed Jan  5 22:43:08 EST 1994 - matthew green <mrg@mame.mu.oz.au>

	source/notify.c, source/notice.c, source/parse.c, source/whois.c,
	source/vars.c, include/config.h*, include/vars.h.proto,
	include/notify.h
		added notify_handler variable.
	source/irc.c:
		fixed bug in /wait.  god, what a stupid bug.

Sun Jan  2 02:36:11 EST 1994 - matthew green <mrg@mame.mu.oz.au>

	source/scandir.c:
		fixed for readdir_r() with solaris 2.  thanks to
		Travis L Priest <T.L.Priest@LaRC.NASA.GOV> for this one.
	source/names.c:
		fixed sending of modes to server on rejoin.
	source/alias.c:
		fixed bug in $N where from_server != current_screen->
		current_window->server.
	source/ctcp.c:
		made `ctcp time' more `date' like.
	source/window.c:
		made continued line be up to 1/2 the screen.

Thu Dec 30 23:47:01 EST 1993 - matthew green <mrg@mame.mu.oz.au>

	source/unotify:
		updated to not show UNKNOWN crap.
	source/help.c:
		fixed set help_window.  i hate help.c
	source/numbers.c:
		changed reset_nickname() etc to not have more than
		one `Nickname:' prompt waiting at a time.

Wed Dec 29 01:08:13 EST 1993 - matthew green <mrg@mame.mu.oz.au>

	script/uhnotify:
		added new script to do cached userhost lookups for
		notify.

2.3.13
Tue Dec 28 03:26:13 EST 1993 - matthew green <mrg@mame.mu.oz.au>

	source/edit.c:
		userhost() - now lets any number of nick's for -cmd.
	configure.in:
		fixed lame bugs in 2.3.12 that prevented it from
		even compiling.

2.3.12
Fri Dec 24 00:50:11 EST 1993 - matthew green <mrg@mame.mu.oz.au>

	source/vars.c, source/whois.c, source/notify.c, source/parse.c
	include/vars.h.proto, include/notify.h:
		added notify stuff from checking join's, etc.
	source/help.c
		fixed typo-bug.
	source/edit.c, source/server.c:
		added /clear -unhold

Wed Dec 22 23:30:15 EST 1993 - matthew green <mrg@mame.mu.oz.au>

	source/exec.c, configure.in, acconfig.h:
		finished svr3/twg patches, fixed the UNIX_MAIL stuff,
		finished the auto-grok signals for exec.c.

2.3.11c
2.3.11b
	source/server.c:
		fixed all known bugs in server.c ;-)
2.3.11a
Thu Dec  2 21:05:56 EST 1993 - matthew green <mrg@mame.mu.oz.au>

	source/server.c:
		added extra debugging to dgets stuff.

2.3.11
Thu Dec  2 01:50:31 EST 1993 - matthew green <mrg@mame.mu.oz.au>

	source/dcc.c, source/exec,c, source/irc.c, source/server.c
	source/newioc, source/screen.c:
		fixed lame bug's introduced in 2.3.9 that caused
		bogus server connections closing.

2.3.10
Sun Nov 28 13:15:14 EST 1993 - matthew green <mrg@mame.mu.oz.au>

	source/exec.c:
		fixed POSIX kill(-pid).

Mon Nov 15 23:32:22 EST 1993 - matthew green <mrg@mame.mu.oz.au>

	source/crypt.c source/exec.c source/file.c source/help.c
	source/irc.c source/ircaux.c source/ircflush.c source/log.c
	source/mail.c source/notice.c source/parse.c source/scandir.c
	source/term.c include/irc.h:
		svr3/wollongong tcp/ip patches applied from entropy
		(entropy@parakeet.con.wesleyan.edu)

2.3.9
Mon Nov 15 00:58:56 EST 1993 - matthew green <mrg@mame.mu.oz.au>

	source/..:
		various fixes to remove the `stricmp' stuff so that
		ircii always uses it's own `my_stricmp'
	source/server.c, source/parse.c, source/window.c:
		fixed bug where ircii wouldn't let you /server after
		a oper kill.  removed the kludge `CLOSING_SERVER'
		code (oops, for got to remove the #define from server.h
		oh well).
	source/irc.c:
		fixed notify/clock scheluding.
	
Tue Nov  2 21:17:59 EST 1993 - matthew green <mrg@mame.mu.oz.au>

	source/exec.c, include/irc.h:
		exec.c defines IN_EXEC_C so that in include/irc.h we
		don't include unistd.h

	source/dcc.c, source/ircserv.c, source/ircaux.c, source/newio.c
		added set_socket_options() which either calls the
		ESIX mark_socket() thing, or sets off linger and sets
		keepaline and reuseaddr on.

2.3.8
Mon Nov  1 00:45:13 EST 1993 - matthew green <mrg@mame.mu.oz.au>

	source/edit.c:
		added /beep command which just beeps the terminal.
	source/edit.c, source/keys.c:
		added rbind command that is a reverse bind lookup.
		`/rbind parse_command' shows all keys bound to
		parse_command.
	source/status.c:
		fixed problem with alarm clock (shulick@indiana.edu)
	source/irc.c:
		handlers for SIGHUP/SIGTERM that call irc_exit().

Sun Oct 31 18:01:12 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/server.c:
		fixed bug where primary_server was -1 and used as an
		index.
	source/vars.c, source/hook.c, source/edit.c, source/alias.c,
	source/keys.c, source/notice.c:
		changed the way /save works.  you can use -bind -on
		-alias -digraph -set -notify to save just those types
		(default is all of them), and the -all switch also
		saves things that were generated by the global script.
		these are not saved by default.

Sun Oct 31 05:10:14 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	configure.in:
		updated for autoconf 1.7, couple of other small
		bugs fixed
	source/vars.c, include/vars.h.proto:
		added REALNAME varaible.

2.3.7
Sun Oct 24 21:47:10 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	too many to remember.  many bugs fixed.  hide_private_channels,
	mode #foo +l 0, away when changing servers.  on connect now has
	the port.  added posix signals when avaliable.  more real svr4
	support.  various little bits of other peoples patches added
	where still needed.

2.3.6
Mon Oct  4 02:37:27 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/status.c:
		yay!!!!!! fixed the `cursor gets lost with /window
		create' bug finally.  added a cursor_to_display() in
		update_status().
	source/alias.c:
		new funcitons pid() and ppid() (and thus function_pid()
		and function_ppid()).

Sat Sep 25 20:13:38 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/server.c:
		fixed the long know bug in bad link on /server.  also
		fixed setting of closed fd to -1.

Sun Sep  5 23:52:39 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	easyinst:
		shell script from end to configure that also sets up
		the default server and default help service.
	source/, include/
		removed `SCO' and replaced it with either `M_UNIX' or
		with `HAVE_SYS_UN_H'.
	source/dcc.c:
		now shows the port as well as the ip address.

Thu Aug 26 00:09:11 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/dcc.c, source/window.c, include/lastlog.h:
		fixed bugs in 2.3.3 relating to window level LOG_DCC.
		LOG_DCC is back in level LOG_ALL 'cause now only one
		window can have it at once.
		oh god i am so lame.  fixed /dcc get bug.
	
	configure.in:
		added tests for testing getpgrp() to grok non-posix
		getpgrp() regardless what <unistd.h> says.

2.3.3
Sun Aug 22 18:29:21 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/, include/irc.h
		removed all occurances of the lame null() macro.
	
2.3.2
Sun Aug  1 02:25:21 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	configure.in, source/Makefile.in, Makefile.in
		no longer creates source/Makefile from
		source/Makefile.proto, but rather configure does.  we
		call the make in source/ with the righ aruments.
	source/, include/dcc.h, include/irc.h
		general clean up with some header files, fixed time.h
		and sys/time.h, netinet/in.h (thanks 386bsd for broken
		header files)..

Wed Jul 28 23:39:51 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/stack.c:
		fixed stack pop on <number> so that the list from the
		stack is actually added to the numeric list, if it was
		empty, currently.

Tue Jul 27 23:59:45 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/ctcp.c:
		fixed bugs in send_action() where it was sending the
		message as the format string, and in do_sed() where it
		was calling crypt_msg() with a null key.

2.3.1
Sat Jul 24 03:47:26 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	script/dmsg
		added this finally..

2.3.0
Sun Jul 18 04:36:04 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/dcc.c:
		fixed lame bug with the dcc deadlists.
	source/ircaux.c:
		null() -=> NULL

2.3beta1.9
Mon Jul 12 20:43:55 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/stack.c source/hook.c, include/stack.h:
		got /stack working with on's.  yay
	configure.in, Makefile.in, acconfig.h:
		updated for use with autoheader, acconfig.h added for
		this purpose (thanks noah).  defs.h is much nicer than
		-DBLAH all the way across the screen.
	source/scandir.c, configure.in:
		whole thing put in a #ifdef HAVE_SCANDIR, that is grokked
		in configure ..

2.3beta1.8
Sat Jul 10 13:11:48 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	configure.in, Makefile.in:
		fiddled with, added questions for DEFAULT_SERVER and 
		DEFAULT_HELP_SERVICE, unused so far..
	source/dcc.c, source/edit.c, source/numbers.c:
		fixed some level things.
	source/edit.c:
		made NUMBER_OF_COMMANDS groked automatically..

2.3beta1.7
Sun Jul  4 19:49:36 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	NeXT port for 2.3 ..  cleaned up all the .. `suggest parentheses'
	warnings from gcc -Wparentheses ..

2.3beta1.6
Thu Jul  1 23:06:14 EST 1993 - Matthew Green <matthew@valiant.vut.edu.au>

	hpux/osf1/sgi/osx/ptx stuff for 2.3 ..

2.3beta1.2
Tue Jun 29 14:14:29 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	.. added gnu's autoconf to ircII, it works for sunos, and mostly
	for sgi so far ..

2.2.9
Tue Jun 29 00:05:04 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>
	
	source/newio.c;
		new_select() - once again, linux proves to be painful.
		previous `fixes' to this routine were lame, and leaked
		memory.

2.2.8
Sat Jun 26 14:45:10 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/hook.c:
		fixed stupid bug in do_hook() which ignored the last
		/on in each list.

2.2.7
Sat Jun 26 05:15:35 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	.. clean up for release ..

Fri Jun 18 12:25:18 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	.. various bugs for dynix/ptx, linux, hpux .. fixed.. general
	clean up for the release.

(2.3beta1.1)
Sun Jun 13 01:10:07 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	Wow.  ircII is now under RCS.

2.2.7pre2
Fri Jun 11 03:44:25 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	ctcp.c:
		do_finger() - fixed type for replies for daemon clients..
	server.c:
		server() - fixed setting of away's, was causing core dumps,
		and general lossage.

Wed Jun  9 23:30:33 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/server.c:
		fixed sending AWAY's when reconnecting.. by adding the
		: prefix..

(2.3beta1.0)
Wed Jun  9 00:20:19 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	the lot,
		gah, huge clean up.  changed the lame alpha `port' Long
		stuff back to long, and started using the types for lots
		of things.. like time_t, etc..
		created include/ and moved every header in here..  major
		changes to source/Makefile.proto for this..
		added debug.c and debug.h..  and debug define to config.h

Wed Jun  2 23:07:25 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/term.c, source/irc.c:
		added support to reset signal handlers under ESIX.
	source/edit.c, source/server.h, source/server.c:
		made /redirect smarter about if it needs to wait on
		server output, by setting something in send_to_server(),
		that is checked after the end of the parse_line() in
		redirect().
	source/dcc.c:
		fixed varoius DYNIX/ptx problems that got introduced..
	source/window.c:
		create_additional_screen() - close() and unlink() when
		the create fails...

Tue Jun  1 23:41:08 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/term.c:
		term_cont() - added signal for linux..

2.2.7pre1
Tue Jun  1 20:00:02 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/vars.c, source/edit.c:
		Changed the way EIGHT_BIT_CHARACTERS works so that if you
		set it, its honoured.
	source/ctcp.c:
		fixed UTC bug.
	source/, Makefile.
		Added patch from Fuzzy to give SCO UNIX support.
		<adrian@cursci.co.uk>

Sun May 30 01:36:18 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/help.c:
		fixed the linux/help bug finally.  not exactly sure what
		was wrong with it, but Veep <eric@blahrvares.er.usgs.gov>
		found the problem, and i fixed it.

Fri May 28 23:10:47 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/parse.c:
		p_privmsg() - fixed beep_when_away with /on msg..

Thu May 20 03:25:57 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/irc.c:
		irc_io() - when reading from stdin (for any screen) we
		read up to BIG_BUFFER_SIZE chars at a time now.
	source/ctcp.c, source/dcc.c:
		added sizes to dcc send/get.
	source/names.c:
		decipher_mode() - bug with loosing track of mode string
		for mode's v and b (Aiken).
	source/alias.c:
		added randm(), a better random function (Sarayan) and
		fixed bug in function_srand() if input was an empty
		string.
	source/edit.c:
		load() - now allows \ at the end of a line to continue
		the line (Stargazer <spz@specklec.mpifr-bonn.mpg.de>)

Tue May 18 01:20:50 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/numbers.c:
		stupid stupid stupid bug in 433 handling fix.
	source/screen.c:
		over zealousness with unsigned char's removed.

2.2.6+
Wed May 12 20:39:01 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/numbers.c:
		fixed various bugs in the handling of some of the more
		important numerics.  every numeric should be able to
		be caught in a /on now.
	source/notice.c:
		parse_server_notice() - if from is null, use the server's
		name as far as its concerned, if it exists (.itsname).
	source/screen.c:
		change the handling of lines that are null being written to
		the screen, that was causing core dumps in places. (Rogue_F)
	source/keys.c:
		write_bindings() - changed char to unsigned char.

Fri May  7 22:54:58 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/names.c:
		blah, fixed show_channel() to not assume buffer isn't
		changed ever.

Thu May  6 04:41:24 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/numbers.c, source/parse.c, source/funny.c:
		fixed some numerics that were in accessable from /on
		<num> (353 and 366), and removed the away-time from
		the /on msg hook.
	script/finger:
		updated so it doesn't cause core dumps on AIX (Daemon)
	install:
		updated to work with the new config.h (Daemon)

Wed May  5 21:43:35 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/new_io.c:
		new_select() - if timeout == NULL, then we bzero() the
		newtimeval .. stops ircserv from hanging... thanks to
		Kenny Zalewski <zalewk@rpi.edu> for this.

2.2.5
Tue May  4 17:12:03 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/keys.h.proto, source/keys.c, source/screen.c
		Added new binding SCROLL_START, and new function 
		scrollback_start() to do it.
	source/ircaux.c:
		check_nickname() - fixed bug where it was returning `s'.

Tue May  4 02:11:02 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/exec.c:
		various patches from avalon added to help speed up
		exec handling.

Mon May  3 21:32:49 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaargh.
	Turning bold or inverse off turns everything off.  its a bug in
	termcap. sigh.

Mon May  3 01:26:18 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/irc.c:
		added HPUX and linux to the re-issue list for signals
		that are handled seeing the internal process handlers
		aren't always re-set properly -=> ^C making the client
		exit untimely.

Sun May  2 23:06:08 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/parse.c, source/notice.c, source/ignore.c, source/ignore.h:
		changed the handling of ignore_combo, introducing
		a new function double_ignore().
	source/parse.c, source/ignore.c
		moved IgnoreCombo() into ingore.c from parse.c and 
		renamed it ignore_combo()
	source/window.c, source/screen.c, source/dcc.c:
		removed netinet/in.h and arpa/inet.h includes where they
		existed as dcc.h includes them, and 386BSD has lame
		header files.
	source/pares.c:
		p_nick() - if its mynick then its shown to the current
		window.
	source/lastlog.c:
		lastlog() - added -literal switch.

Sun May  2 05:03:27 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/names.c, source/names.h:
		Added channels keys to the channel stuff, and it also
		gets shown in the mode returned.
	source/numbers.c:
		Fixed bug in 002 handling with SHOW_NUMERICS on.

Fri Apr 30 18:48:04 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/ircux.c:
		check_nickname() - rewritten, and handles things better.
	source/irc.c:
		parse_args() - we now call check_nickname() to make
		sure the nick given is "ok".  If not, we don't start.

Wed Apr 28 19:55:43 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/ctcp.c:
		fixed bug in ctcp ping reply.
	source/parse.c, source/edit.c:
		prefixed duplicate funcion names with p_ and e_.
	source/screen.c:
		fixed lame bug in add_to_window() where the arguments
		to strmcat() were wrong.  (wall privmsg quit channel
		invite nick)
	source/keys.c:
		added emacs bindings to 0x80 + b/d/f/h/^? for people
		with meta keys.
	source/keys.h:
		removed.  wasn't used anywhere.
	source/dcc.c:
		DCC connections are now shown with the ip number, to
		provide a little extra security (Avalon).

Tue Apr 27 02:33:03 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/dcc.c:
		"blah". fixing put_it() et al, didn't fix the lame
		ultrix float bug after all.  stupid ultrix.

2.2.4
Mon Apr 26 12:01:58 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/ctcp.c:
		fixed lame bug in do_atmosphere() that was making channels
		leave windows because of a missing 2nd argument to
		is_current_channel().

2.2.3
Mon Apr 26 00:42:21 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/screen.c, source/irc.h, source/irc.c:
		added new global variable, char global_all_off[] that 
		holds a string with the ALL_OFF character in it.  Fixes
		bug with crap getting on the screen.
	source/Makefile.proto:
		Added dependancies for crypt.o.

pre2.2.3
Sun Apr 25 11:17:29 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/exec.c:
		fixed lameness with wait3() arguements.
	source/screen.c:
		added a `:' to the send_to_server() call when redirecting.
		makes it so that 2.8 servers get everything.

Sun Apr 25 01:35:35 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/
		blah. fixed several problems in lots of stupid things
		i did for the release.
	source/screen.c, source/status.c, source/irc.h:
		changed bold, inverse and underline characters to
		^B, ^V and ^_ respectively.  wow.  it makes some sense
		now.
	Makefile:
		Some rearrangements, and general updating.  its now
		easier to install, or at least i hope so.
	config.h:
		several things updated, AUTO_RECONNECT removed..

2.2.2
Fri Apr 23 05:44:29 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/
		fixed all of the implicit functions declartions, and
		several other compiler warnings. wheeeeeeeeeee.

Thu Apr 22 14:42:07 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/numbers.c:
		fixed handling of RPL_LINKS (364) so that 2.8 servers
		would be cool.

Thu Apr 22 04:18:53 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/
		fixeds 1000's olf lines of warnings from gcc -Wall.

Tue Apr 20 22:29:05 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/term.c:
		fixed lame hpux bugs, got term.c back to working again.
	source/keys.c, source/edit.c:
		fixed 8-bit stuff again in edit_char(), by using 
		unsigned char.

pre2.2.pl12
Mon Apr 19 21:54:09 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/term.c:
		blah.  i hate sun tty drivers.  we're back to sgtty.

Sat Apr 17 21:28:42 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/alias.c, source/alias.h, source/parse.c, source/ctcp.c,
	source/dcc.c, source/dcc.h, source/edit.c, source/edit.h,
	sourec/exec.c, source/flood.c, source/help.c, source/history.c,
	source/irc.c, source/irc.h, source/ircaux.c, source/log.c,
	source/mail.c, source/notice.c, source/scandir.c, source/server.c,
	source/status.c, source/whois.c, source/dcc.c.orig, source/screen.c:
		Added OSF/1 support.  Made `long' a define, Long.
	source/output.c, source/ctcp.c, source/server.c, source/hook.c:
		put_it(), say(), yell(), send_to_server(), do_hook(),
		send_ctcp() and send_ctcp_notice() - changed from being
		`int' to `char *' being passed.  Fixes several lame
		problems.

Thu Apr 15 17:09:16 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/whois.c:
		whois_operator() - fixed 313 reply, so that 2.8 
		servers look cool.
	source/numbres.c
		cannot_join_channel() - now switch on -current_numeric,
		not current_numeric.
	source/term.c:
		Changed terminal handling from sgtty to termios for 
		SUNOS.

Tue Apr 13 13:39:09 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/ctcp.c:
		fixed various bugs with ctcp floods,
	source/
		fixed lots of compiler warnings, thanks to Vesa.

pre2.2.2pl10
Mon Apr 12 18:39:55 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	all:
		fixed various .h and .c files, removing a few compiler
		warnings.
	source/alias.c:
		changed $channels() and $servers() to $mychannels and
		$myservers().
	source/edit.c:
		Added new command XTYPE [-LITERAL] <text>, function
		xtypecmd().

Mon Apr 12 03:26:44 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	Makefile, source/Makefile.proto
		Added LEX and LEXLIB.

Sat Apr 10 02:42:55 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/dcc.c;
		close_all_dcc() - fixed bug where the list was merely
		being lost, not removed (so not closing fd's)

pre2.2.2pl9
Fri Apr  9 02:27:26 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	Makefile, source/dcc.c:
		Added PTX patches.
	source/exec.c, source/edit.c, source/screen.c:
		changed test_to_process() to have switch if it would
		call put_it() or not - fixed recusive bug with /redirectign
		to a process.

Thu Apr  8 01:17:41 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/window.c, source/server.c:
		Fixed /window server, and /server so that ircii would
		use the old port numbers.

Wed Apr  7 13:31:23 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/hook.c:
		Made save_hooks() include the serial number.
	source/edit.c:
		parse_line() - \r and \n are not treated as special from
		within a loaded script anymore.

pre2.2.2pl8
Tue Apr  6 23:37:27 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/history.c:
		Fixed history scrolling from the initial input line.
	source/server.c:
		Fixed bug in server -delete where Window->server's
		were left the old value.
	source/mail.c:
		Made it so mail type messages go to level CRAP.
	soucre/alias.c:
		Added poxaV's curpos patch.
	source/edit.c:
		Changed /WAIT to use unknown command, not WHOIS.
	
pre2.2.2pl7
Tue Apr  6 01:01:46 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/notice.c:
		fixed lame bug where the server version/name NOTICE was
		being shown twice.
	source/numbers.c:
		Added lastlog saving to all numeric messages.
	source/mail.c:
		init_mail() - fixed handling of env var MAIL where it was
		strcat()ing not strcpy()ing (Glenn!)
	source/status.c:
		Added Aiken's right justification patch to the status
		line (%>).
	source/screen.c, source/window.c, source/window.h:
		Fixed lame bug where I'd left variables in screen.c and
		window.c.
	source/?:
		Added various things from Lynx.

Mon Apr  5 05:15:16 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/numerics.c:
		made numerics 471 473 474 475 476 show what sort of
		cannot join channel they are.
	source/whois.c:
		made 313 replies (whois operator) only add the
		"(is an IRC operator)" if the server is < 2.8.

Tue Mar 30 03:58:27 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/dcc.c, Makefile:
		Added support for A/UX, thanks to Helen Rose for help
		with this (hrose@eff.org).

pre2.2.2pl6
Tue Mar 30 02:02:22 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/term.c, source/term.h:
		changed various things for hpux terminal emulation. .now
		uses sysV style (termio).  Fixes problem with getting
		info about the terminal out of the tty.  Also added
		support for irix.

pre2.2.2pl5
Mon Mar 29 18:50:25 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/window.c, source/window.h, source/screen.c, source/screen.h
	source/names.c, source/lastlog.c, source/hold.c, source/exec.c,
	source/translat.c, source/term.c, source/status.c, source/menu.c,
	source/irc.c, source/input.c, source/help.c, source/edit.c,
	source/alias.c
		window.c was split into window.c and screen.c today, and
		these files had various changes to fit to this.

Mon Mar 29 01:13:30 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/count.l, source/count.c, source/Makefile.proto:
		Added count.l, removed count.c, and updated Makefile.proto
		to use these changes.
	
	source/irc.c, source/dcc.c, source/exec.c
		Fixed close_all_dcc(), and close_all_exec().  Added
		signal handlers for SIGUSR1 (sig_user1) and SIGUSR2
		(sig_user2).  USR1 closes all dcc and exec connections,
		and USR2 uses setjmp()/longjmp() to break out of where
		it is, and start processing from irc_io() again.  USR2
		doesn't seem to work.  sigh.

pre2.2.2pl4
Sat Mar 27 04:18:29 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/edit.c:
		fixed lame bugs for some commands losing parameters.
	source/window.h, source/window.c:
		Fixed bugs in scroll functions where wrong lines were
		displayed when new lines had been added to the window.
		New Window element int new_scrolled_lines.
	source/server.c:
		fixed ircserv to show the real name of the program in
		argv[0], not "ircserv".
	source/edit.c:
		Fixed handling of literal ^J and ^M's to the way they were
		originally documented in UPDATES (the same as \n used to do).
	source/hook.c:
		ugh, do_hook().  added a bzero().  see comments.  ha ha ha.
	source/lastlog.h:
		Added LOG_SNOTE to LOG_ALL.

Thu Mar 25 23:58:58 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/ctcp.c, source/parse.c:
		Finished the ignore ctcps and crap stuff.
	source/parse.c:
		ON PUBLIC has $1 as channel, and $2- as message.

Thu Mar 25 02:19:04 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/edit.c:
		fixed send_com() so that it would only use "%s :%s" when
		the argument existed.
	source/ignore.c, source/ignore.h:
		changed level from unsigned char to int, to allow more than
		8 level's of ignore to work.  Reformatted the  output ..

Wed Mar 24 19:57:03 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/numbers.c:
		Fixed motd numerics for 2.8 properly..
	source/vars.h.proto, source/vars.c, config.h, config.h.lynx:
		Added new variable NOTIFY_LEVEL, which is used by default
		for new windows.
	source/edit.c:
		Fixed bug in quote(), where the arguement was being sent
		as the format string.  Real dumb.
	source/ctcp.c, source/ignore.c, source/ignore.h, source/lastlog.c,
	source/lastlog.c:
		Added ignore levels CTCP and CRAP.

Tue Mar 23 01:58:34 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/edit.c, source/numbers.c, source/window.c, source/whois.c,
	source/irc.c:
		Changed redirect to use unknown command, and fixed some
		strange bugs.  Some still exist with 2.8 servers.  Also
		made all numerics work with /on <num>.  Some (318 eg)
		didn't have hook code for it.
	source/input.c:
		Fixed lame bug in write a character to the screen.

Mon Mar 22 02:24:43 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/window.c, source/window.h:
		Added window notify levels, with /window notify_level
		level ..
	source/vars.h.proto, source/vars.c, source/window.c, source/keys.c,
	config.h, config.h.lynx:
		Added two new variables, XTERM_OPTIONS, whose value is
		passed to xterm, when using WINDOW CREATE, and 
		EIGHT_BIT_CHARACTERS, which, if set, doesn't strip the
		8th bit off the input streams.
	source/alias.c, source/names.c, source/names.h, source/server.c,
	source/server.h:
		Added new functions $channels() and $servers().

Sun Mar 21 02:31:25 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/edit.c:
		privmsg() - changed so that /msg =nick and @nick both
		set from_server to -1.. fixes lame level bug..

Sat Mar 20 02:16:34 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/window.c:
		window() - made /window server make the window level
		ALL -DCC, not just ALL.
	source/numbers.c:
		Fixed the INFO and MOTD numerics so that they will work
		with the new ones from ircd 2.8-7+ .. blah ..
	source/newio.c:
		new_select() - fixed so that select() wouldn't over right
		the struct timeval...
		

Fri Mar 12 18:27:31 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/edit.c:
		send_com() - wasn't prefixing the arguements with a
		: which meant ircd 2.8 was being lame ...  For some
		commands, using send_comm()

Mon Mar  8 10:22:03 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/exec.c:
		fixed bug in /exec -in
	source/server.c:
		added support for /server -delete
	source/edit.c, source/keys.c:
		Added support for 8 bit input.
	source/irc.c:
		Added command line option -v, version.

2.2.1.2
Sun Feb 28 13:35:19 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/whois.c:
		add_to_whois_queue() - finished fixing another bug in
		/userhost -cmd..
	source/names.c:
		ignore() - made /IGNORE use the HIGHLIGHT_CHARACTER.
		reconnect_all_channels() - fixed bug from 2.2.1

2.2.1.1
Wed Feb 24 17:43:55 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/whois.c:
		Fixed bug in /userhost.
	source/parse.c:
		Fixed bug in ON RAW_IRC.

Tue Feb 23 18:56:54 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/reg.c:
		Fixed bug in \escaping. (Troy)

Sun Feb 21 16:36:22 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	script/troy, script/killpath, script/kpstat, script/traces:
		Updatd scripts for 2.2.1.

Sat Feb 20 00:36:12 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/edit.c, source/irc.c
		Finally did The Right Thing (tm) with the wait key junk
		that help uses, and moved it from irc_io() to edit_char()
		where I should have put it originally.  Also fixes a bug
		in dumb mode.

Thu Feb 18 01:48:05 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/window.c, source/window.h:
		window() - added new command LOGFILE for window logging.
	source/dcc.c:
		We now use wait_new_free() for dcc_erase().
	Makefile:
		Removed makehelps and changed installhelp.

Wed Feb 17 06:13:34 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/notice.c:
		changed ON SERVER_NOTICE for $0 to be the server name.
		Changed the AIX_370 #if's to BROKEN_SCANF.
	source/ctcp.c:
		Fixed bugs in CTCP PING.
	source/edit.c:
		Fixed bugs in me() and describe().

Thu Feb 11 14:57:10 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/server.c:
		do_server() - actually fixed the autoreconect problems
		when there is only one server in the server list this
		time. ugh.
	config.h, source/vars.h.proto, source/vars.c, source/parse.c
		Added new variable SHOW_WHO_HOPCOUNT, whoreply().

Wed Feb 10 19:53:32 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	script/whowas
		New whowas script for 2.2 from Mycroft.
	source/ctpc.c
		Fixed NO_CTCP_FLOOD, changed do_errmsg() to do_echo(),
		and moved do_ping() to this, and added CTCP ECHO.
	Numerous other bugs fixes from various people.

2.2
Tue Feb  9 16:46:39 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/dcc.c, source/scandir.c, source/help.c, source/edit.c:
		couple of bugs fixes here and there ...
	source/edit.c:
		bug in who() with -operator switch..

Sun Feb  7 17:35:03 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/window.c, source/server.c, source/edit.c;
		Fixed away bugs..
	source/window.c:
		update_all_status() - doesn't call traverse_all_windows()
		anymore, as it was calling it recusively.  Should rewrite
		traverse_all_winodws().
	source/
		Support for Solaris 2 added (spot <raob@ee.mu.oz.au>)
	source/
		Support for 386BSD added (Mycroft)

Sun Feb  7 05:04:23 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/alias.c:
		alias_currdir(), and `$W' now return the current working
		directory. alias_version(), and '$V' give the version
		(poxaV).
	source/alias.c:
		alias_current_numeric(), and `$H' now return the current
		numeric.
	source/edit.c;
		fixed couple of memory leaks, made `:' not a special
		character in command mode, as it is now the no-op command.
		me(), describe() and prepare_action() - changed to not
		add the offensive period.
	source/window.c:
		window() - fixed bugs in WINDOW SERVER and WINDOW NAME.
	source/help.c:
		help() - bit of cleaning up..
	source/ctcp.c:
		do_version() - made it use IRCII_COMMENT if the value for
		CLIENT_INFORMATION is null.

Thu Feb  4 17:59:23 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/
		Various unused variables removed, uninitialised variables
		initilised..
	source/status.c, source/window.c, source/hook.c, source/edit.c,
	source/if.c:
		Few bug fixes here and there, and a couple of very nasty
		memory leaks..  thanks to jlemon..
	source/hook.c:
		do_hook() - fixed the `Dumb mode' bug that Daemon, then
		recently poxaV had trouble with (Mycroft)
		
Wed Feb  3 18:30:04 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/ctcp.c, source/vars.h.proto, source/vars.c, config.h:
		New variable NO_CTCP_FLOOD, which when set makes ircii
		only send one CTCP reply per second.
	source/numbers.c, source/whois.c, source/names.c, source/funny.c:
		Changed all the numerics replies so that $0 is now the
		server name (if it want't already), except for ISON and
		USERHOST, as these are server local anyway.

Tue Feb  2 21:40:46 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/edit.c, source/whois.c:
		Removed /msg -channel as it doesn't make sense anymore.
	source/dcc.c:
		process_dcc_request() - fixed start times in dcc requests.
	source/status.c:
		status_mail() - fixed stupid bug (Mycroft).
	source/whois.c:
		no_such_nickname() - fixed so that $0 is now the server name.

Sun Jan 31 23:33:18 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/window.c:
		kill_screen() - fixed more lame bugs left for me to fix.
	source/term.h, source/scandir.c, source/ircflush.c:
		Fixed various hpux problems.
	Makefile, config.h, source/dcc.c, source/edit.c,source/exec.c,
	source/irc.c, source/irc.h, source/mail.c, source/scandir.c,
	source/term.c, source/hook.c:
		Fixed various AIX 3.1/3.2 problems.  (Mycroft)

Sat Jan 30 18:28:31 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/edit.c, source/ctcp.c:
		Added CTCP PING to ircII...  pingcmd() and special case
		handling for the reply .. convert_ping_args()..
	source/edit.c
		waitcmd() - fixed stupid bug that Troy left in the code
		to set up a WAIT -CMD.

Thu Jan 28 23:37:19 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/names.c:
		Fixed bug in irc -c that I broke when fixing the phone bug.

Wed Jan 27 22:48:46 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/window.c, source/irc.c:
		Changed create_additional_screen() to select on the listening
		socket, and timeout after 5 seconds, returning an error, 
		rather than just calling accept().  This stops the case where
		the wserv process doesn't get started, and the client will
		hang in the accept().  Removed the force arguement from
		kill_screen(), and all the calls to it.

	source/edit.c:
		renamed new_send_line() to sendlinecmd() so that it follows
		the general ircII pattern (is there such a thing ? - phone :)
		
Tue Jan 26 19:03:51 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/status.c
		Added poxaV's patch to put time in standard format.

Mon Jan 25 09:14:10 EST 1993 - Brian Koehmstedt <bpk@gnu.ai.mit.edu>

	source/crypt.c, source/dcc.c, source/exec.c, source/help.c,
	source/irc.c, source/ircaux.c, source/notice.c, source/scandir.c,
	source/term.c, source/ircflush.c:
		added support for Linux

Mon Jan 25 02:52:14 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/dcc.c, source/exec.c, source/server.c, source/window.c:
		added close_all_dcc(), close_all_exec() and close_all_server(),
		which are called from create_additional_screen(), from the
		forked process to close all unneeded file descriptors.
		create_screen() - fixed bug when create_screen() returns a
		screen that was marked as being !alive.
		Hmm, somewhere here I think I have fixed the bug with the
		position of the cursor, when using more than one screen.
		No idea if it is fixed, but I can't get it to happen.
	source/names.c:
		set_window_channel() - fixed bug when channel was NULL.

Mon Jan 25 11:44:20 EST 1993 - Charles Hannum <mycroft@gnu.ai.mit.edu>

	source/window.c:
		scroll_window() - fixed bug that deleted text from the
		input prompt

Thu Jan 21 18:16:16 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/window.c, source/dcc.c:
		Added flag to dcc_message_transmit(), to indicate if the
		hook/put_it() call should be made.  Used when redirecting
		to a dcc chat connection, which is now possible.

Wed Jan 20 23:41:50 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/window.c, source/edit.c, source/whois.c, source/window.h:
		Changed how REDIRECT works.  We now send a redirect token
		to the server when redirecting, not a wait token.  It is in
		the form of #RED#nnnn where nnnn is the screen's number
		(internal).  Redirect also is a property of the screen, not
		of the whole of ircII.  This means that there are no more
		valid reasons to call irc_io() recursively.
	source/mysetjmp.h, source/mysetjmp.c, source/irc.c, source/alias.c,
	source/window.c, source/window.h:
		Removed all the code that was applicable to the mysetjmp()
		code, as there are no need for it anymore - only /WAIT and
		$".." call irc_io() recursively, and they can be used in
		other (better) ways.

Tue Jan 19 14:05:52 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/help.c:
		You guessed it.. another bug.. fixed.
	source/window.c;
		window() - fixed bugs in WINDOW SERVER.
	source/parse.c, source/edit.c, source/exec.c:
		Added doing_privmsg, which makes ircII convert all attempts
		to PRIVMSG from a PRIVMSG in to a NOTICE.
	source/parse.c, source/whois.c:
		Added flag to HOST and USERHOST commands.  It allows a command
		to be executed when the the userhost (302) reply comes back
		from the server - userhost_cmd_returned().
	source/edit.c;
		Added new command INPUT.  Takes a ".." prompt as its first
		parameter, and displays this, and prompts for input that
		expanded, and passed to the command that is its second arg.
		(ie, /INPUT "prompt> " echo $*).  This should be used as
		a replacement for $".." type variables.

Sun Jan 17 22:01:34 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/help.c:
		help_prompt() - fixed another bug..  when will it end..?
	source/dcc.c:
		register_dcc_offer() - made dcc collisions for DCC CHAT
		automatically connect to the other party.  Impressed.
	source/window.h, source/window.c:
		Added new define in winodw.h SCROLL_AFTER_DISPLAY .. which
		makes the display scroll like it used to in 2.1.5.

Sun Jan 17 01:16:37 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/funny.c:
		Fixed lame bug in funny_list() which caused the wide list
		to be corrupted when more than 50 in it.

Sat Jan 16 17:42:41 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/window.c:
		Fixed stupid bug in window(), in the CHANNEL command.
	source/dcc.c:
		Forgot dcc get for lame ultrix - fixed.
	source/lastlog.c:
		lastlog() - made it possible to /lastlog <pattern> <count>
		now.
	source/help.c:
		help_me() - fixed a stupid bug that would cause help to
		become trapped, and unusable for that session.

Fri Jan 15 16:26:13 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/irc.c, source/window.c:
		Finally got irc_io() knowing when a socket connection to
		a wserv process closes, and to kill that screen, I know
		don't know of any pending bugs directly related to
		WINDOW CREATE.

	source/irc.c, source/help.c:
		Got help working properly again (I think), and all the
		checking to make sure ircII won't get confused, etc.

Fri Jan 15 03:07:48 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/help.c:
		Added variable help_screen, that is set when we enter a
		help command, and is set to NULL when we exit.  In help(),
		I made it illegal to call help from more then one screen
		at the same time.
	source/irc.c, source/window.c:
		Added new function is_main_screen(), and added code to 
		irc_io() to detect if a screen is closed from something
		other than window delete.

Thu Jan 14 12:37:10 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	Makefile, source/Makefile.proto:
		Removed the INSTALL section of this, replacing it with a
		cp, strip, and chmod, as not all machines support install.
		Also added new target `everything' to the Makefile.. that
		does the same as `make all ircflush ircserv wserv'.

Wed Jan 13 18:19:26 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/alias.c, source/edit.c:
		Smallish revamp of the whole modules, formatting for 80 columns
		and smallish optimizations here and there.  Could be bugs here
		I guess.
	source/crypt.c, source/ctcp.c, source/dcc.c, source/exec.c,
	source/flood.c, source/funny.c, source/help.c, source/history.c,
	source/hold.c, source/hook.c, source/if.c, source/ignore.c,
	source/input.c, source/irc.c, source/ircaux.c, source/ircflush.c,
	source/ircserv.c, source/key.c, source/lastlog.c, source/list.c,
	source/log.c, source/mail.c, source/menu.c, source/mysetjmp.c
	source/names.c, source/newio.c, source/notice.c, source/notify.c
	source/numbers.c, source/output.c, source/parse.c source/reg.c,
	source/status.c, source/server.c, source/term.c source/translat.c,
	source/vars.c, source/whois.c, source/window.c, source/wserv.c:
		reformatted for 80 columns, hopefully thats the end of the
		formatting saga..  :)

Tue Jan 12 16:42:55 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/dcc.c:
		Changed the call to put_it() for ultrix machines so that
		the floating pointers won't get garbled.
	source/ctcp.c, source/ctcp.h:
		Fixed send_ctcp_reply(), and removed Transmit_CTCP() moving
		the 2 lines to the only place it was called from.
	source/translat.c, source/term.c, source/ignore.c:
		reformatted.

Mon Jan 11 16:40:14 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/window.c:
		Changed window() so that the handling of HOLD_MODE called
		set_int_var() rather than reset_line_cnt().  Fixed a problem
		with /flush.

Mon Jan 11 01:35:22 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/lastlog.c, source/file.c, source/crypt.c, source/list.c:
		reformatted.

Mon Jan 11 00:29:41 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/names.h, source/names.c, source/window.c, source/window.h,
	source/edit.c, source/parse.c:
		Changed the handing of WINDOW CHANNEL, and JOIN so that
		ircII now remembers what window a channel was joined on.
		channel() in both parse.c and edit.c were changed, 
		add_channel() in names.c.  New function, set_channel_window()
		added, in names.c thats sets a channel's window, and as such,
		Window * added to ChannelList.  This sometimes helps ircII
		remember what channels were on which windows, when
		re-connecting to a server.  Sometimes.

	source/ctcp.c, source/output.c, source/hook.h.proto, source/parse.c,
	source/output.h:
		Moved the ctcp_* functions in output.c to ctcp.c, where they
		belong, and also put in_on_who in hook.h.proto, and fixed
		those fucntions that used it.

Sun Jan 10 10:30:20 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/funny.c:
		Changed funny_list(), fixing the -TOPIC argument to the
		LIST command.  Changed the functionality of -TOPIC so
		that it works *with* the other arguements, not against
		them.

Sun Jan 10 09:23:43 EST 1993 - poxaV <cgw@unt.edu>

	source/vars.h.proto, source/vars.c, source/status.c, config.h:
		renamed status_user() to status_user0(), and added 3
		new functions, status_user[123]()..  New variables
		STATUS_USER[0-3] ..  to go with the new status line
		functions, %X, %Y and %Z.

Thu Jan  7 00:13:14 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/status.c:
		Fixed status_oper() so that it wouldn't show
		if SHOW_STATUS_ALL wasn't set.

Wed Jan  6 19:04:42 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/funny.c:
		Changed funny_print_widelist() ..  it now works
		again, I don't know when I broke it.

Wed Jan  6 11:59:11 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/term.c, source/wserv.c:
		Made the term_init() call used in wserv to set the
		line discipline to RAW, so I could forget about
		having to worry about signals, and removed the
		SIGINT handling from wserv.c.  Hopefully this means
		that wserv works properly now.  (thanks to Dizzy
		<nathan@eas.gatech.edu> for help with this).

Wed Jan  6 00:03:00 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/Makefile.proto:
		updated depandancies, and re-organised the
		SOURCES and OBJECTS.

	source/timer.c, source/edit.c, source/irc.c, source/irc.h,
	source/mysetjmp.c, source/mysetjmp.h, source/window.c:
		Moved everything from timer.c into either edit.c
		or irc.c.  Made WINDOW_CREATE define more parts
		out, in irc.c, mysetjmp.[ch], and window.c.

Tue Jan  5 20:59:36 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/exec.c:
		Reformatted, and new element of the process list
		added, server, to allow /exec -out/msg/notice
		to go to the right server.

	source/newio.c:
		reformatted.

Tue Jan  5 18:06:25 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/edit.c, source/keys.c:
		Added new function parsekeycmd(), and new command,
		PARSEKEY which calls it - does the same as typing
		a key which is bound the the arguement.

Tue Jan  5 17:03:04 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/window.c:
		Changed window() so that the WINDOW CHANNEL
		command with no arguments make the current
		window's channel null.

Tue Jan  5 16:15:51 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/wserv.c:
		Changed got_sigint() to send the ^C down the pipe,
		rather than kill SIGINT the ircII process, as this
		was causing the ^C to be read as though it was from
		the main screen.

Tue Jan  5 01:57:58 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/edit.c:
		Changed new_send_line() to set the display on.

Mon Jan  4 23:46:58 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	source/vars.h.proto, source/vars.c, source/hook.c, source/edit.c,
	config.h:
		New variable INPUT_PROTECTION.  Doesn't allow any
		ON INPUT's to be added when set.  ON INPUT moved to
		send_line(), so that all input is caught in the hook,
		SENDLINE command added, that calls the new function,
		new_send_line, that does a simliar thing to the send_line
		command, except, no handling for prompts, or ON INPUT is
		done during this.

Mon Jan  4 15:23:34 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	hook.c:
		reformatted.

Fri Jan  1 23:46:03 EST 1993 - Matthew Green <mrg@mame.mu.oz.au>

	*.h:
		Fixed all the header files, so that if included more than
		once, they are only parsed once.
lly connect to the other party.  Impressed.
	source/window.h, source/window.c:
		Added new define in winodDarkNET-1.08/ircii-2.8.H1/INSTALL                                                                      644   21270   21270         7165  5710725520  10771                                                                                                                                                                                                                                                                                                                                                                      @(#)$Id: INSTALL,v 2.5 1995/01/23 13:12:48 mrg Exp $

to compile ircii

  o  there are 2 main ways of configuring ircii for your system.  you
     can either run the `easyinst' script, or, if you know how to use
     gnu configure scripts, you can use that directly, and then edit
     include/config.h yourself.

  o  using easyinst:
      - in the same directory that this file is in, type `./easyinst'.
	if you are using an old version of system v, you might need
	`sh easyinst'.
      - this script asks you a few questions and then calls configure
        for you.
      - you will then need to run `make' and `make install'.

  o  using configure directly:
      - in the same directory that this file is in, type `./configure'.
	if you are using an old version of system v, you might need
	`sh configure'.

      - this script tries to guess various things about your system
        that are important to it compiling.  it creates various files
        in this process.  configure takes a couple of minutes to run.

     WARNING: gnu sed vesrion 2.05 (and maybe 2.04 -- i don't know)
     will not function properly with this configure script.  gnu
     sed version 2.03 does.  please do not send me a bug report if
     you are using gnu sed version 2.05 (such as linux systems)

      - when this has finished, you might want to check the Makefile
        for the places ircii will be installed.  the defaults are
        /usr/local/lib, /usr/local/bin and /usr/local/man.  you can
        either do `make prefix=/local' or set it with configure, by
        calling configure with the `--prefix=/local' switch.

  o  compiling ircii - type `make' in the main ircii directory.  this
     will compile the `irc', `ircflush', `ircserv', and `wserv'
     programs that reside in the source sub directory.

  o  once the programs are compiled, you can install them with
     `make install'.  this will install all the binaries, scripts,
     translation tables, and the ircii man page.

  o  you can now delete the object files and binaries from the source
     directory with `make clean'.  `make distclean' will also delete
     any file that `configure' created.  this is useful for then
     using the same sources to compile on a different architecture.


notes on portability.

  o  there is a bug in the compiler shipped with bsdi's operating
     sytem that causes ircii to fail to compile.  if you use the
     `gcc2' compiler rather than `gcc' or `cc' this problem is
     alleviated.  complain to bsdi about their broken compiler.
     the configure process also seems to fail to add `-ll' to the
     LEXLIB variable in the Makefile.

  o  some exotic mips machines are not yet accounted for in the
     configuration process, and must have certain things set
     specially in the Makefile (these are noted in the Makefile
     itself).

  o  there are problems with the configure script running under qnx.
     in the file qnx.patch exist patches for the defs.h.in and
     Makefile files that may need to be applied.  there is also an
     experimental patch to irc.c that qnx needs, but has not been
     tested on other operating systems yet that needs to be applied.
     these can be applied by running `patch -p0 < qnx.pach' in the
     ircii directory.

  o  some versions of nextstep (3.x?) require some serious kludges
     to get ircii to compile and work.  if you have problems with
     missing __environ, __NXArgc, etc, run the make command again
     with "make CFLAGS=-O" (or `-g\ -O' if you want debugging as
     well) for the final link, and see if that works.  if not, you'll
     have to hack around with various flags, or the LIBS variable
     in the Makefile.
                                                                                                                                                                                                                                                                                                                                                                                                           DarkNET-1.08/ircii-2.8.H1/Makefile.in                                                                  644   21270   21270        17227  5702712127  12025                                                                                                                                                                                                                                                                                                                                                                      # IRC II - written by Michael Sandrof
# Copyright (c) 1991 - All Rights Reserved
# Modified by Matthew Green, 1993.
#
# @(#)$Id: Makefile.in,v 1.27 1995/01/05 06:40:23 mrg stable $

# targets recognised by this makefile:
#   all, everything	- compiles ircii, ircserv, ircflush and wserv
#   ircserv		- compiles ircserv
#   ircflush		- compiles ircflush
#   wserv		- compiles wserv
#   install		- installs ircii, ircserv, ircflush and wserv the scripts
#			  and the translation tables.
#   installirc		- installs ircii
#   installserv		- installs ircserv
#   installwserv	- installs wserv
#   installflush	- installs ircflush
#   installscript 	- installs the scripts
#   installtranslation	- installs the translation tables
#   installeverything   - all of the above
#   clean               - remove all .o files, core, and binaries
#   disclean            - remove all files geneated by compilation/installation.

prefix = @prefix@
exec_prefix = @exec_prefix@
bindir = @bindir@

# Where the ircII binary will be installed.
# 'make install' will compile and install the program
INSTALL_IRC = $(bindir)/irc

# Where the ircII library will be.  Generally this is the place that
# you put the scripts, help pages and translation tables.  It is
# very important that you set this correctly.
IRCLIB = @IRCLIB@

# Set this to the lex you want to use, and if they lex uses a library.

LEX = @LEX@
LEXLIB = @LEXLIB@

CC = @CC@
DEFS = @DEFS@
LIBS = @LIBS@

# Set this to -g if you want to be able to debug the client, otherwise
# use -O to have the compiler do some optimization instead.
CFLAGS = @CFLAGS@

# Set this to -s if you want the binary to be striped.
LDFLAGS = @LDFLAGS@

# these are legacy things from ircii 2.2 that haven't yet been
# handled with autoconf.

# For Apollo systems (10.2 and upwards) use the following with BSD defaults:
# DEFS = -Asys,bsd4.3

# Use one of the following for mips systems:
# Choice 1, if your system has the wait3() call
# DEFS = -systype bsd43
# Choice 2, if your system has the wait2() call
# DEFS = -systype bsd43 -Duse_wait2
#
# Or, if you only have sysv installed, use one of the following:
# DEFS = -DMIPS_SYSV
# DEFS = -DMIPS_SYSV -Duse_wait2

## You probably don't need to change anything below this line

# Uncomment the following if you want a secure IRC which binds to a
# privileged port. This feature is completely useless in the current
# IRC environment, but in the future some servers may use privileged
# port systems to verify users connecting to them. The value of
# PRIV_PORT determines the minimum port number to use.
# If you modify these (including uncommenting them) you will need to
# touch config.h
#
# If you are on a system where test-suid works, you can simply define
# PP_DEFS to be PRIV_PORT_ULC and irc will change effective UID back
# to a normal user immediately, and change to root when binding a port.
# This feature is undocumented, but is known to work on Sun, MIPS and
# Apollo (Cos we've tested them already).
# PP_DEFINES = -DPRIV_PORT=667
# PP_OBJS = file.o
# PP_DEFINES = -DPRIV_PORT_ULC

# Full path of the directory for ircII help files.  
# The help files are not within the source distribution, if you don't have
# them and want them, check out your nearest ircII archive.
# You may comment HELP_DIR, then the ircIIhelp service will be used.
# If you don't comment it out and want to use the IRCIIHelp service anyway,
# you must make sure that the directory doesn't exist.
HELP_DIR = $(IRCLIB)/help

# Full path of the directory in which to copy the
# IRCII scripts supplied with the code.  These scripts
# may be loaded by using the LOAD command in IRCII.
INSTALL_SCRIPT = $(IRCLIB)/script

# Default setting for IRC_PATH where irc will look for
# its script files if the environment variable is undefined.
# Usually, this should contain the same path as used for INSTALL_SCRIPT in
# the Makefile, but it can contain multiple path elements
# separated by colons. The path MUST lead to an existing directory,
# because the 'global' script is expected to be found there.
IRC_PATH = ~/.irc:$(INSTALL_SCRIPT):.

# Path for TRANSLATION variable.
TRANS_PATH = $(IRCLIB)/translation

# Set the next line to the full path for installation of the ircserv program
# if you wish to use it. 
INSTALL_IRCSERV = $(bindir)/ircserv

# This little program is necessary to have an interactive shell
# in a window of ircII. The 'shell' script uses it, so also update
# the path in there, if you want to enable this.
INSTALL_IRCFLUSH = $(bindir)/ircflush

# This program allows you to use screen/xterm's to put new irc windows
# on new screen/xterm windows.
INSTALL_WSERV = $(bindir)/wserv

## You shouldn't have to change anything below here

srcdir = .

RM = @RM@
LN = @LN@
CP = cp
MV = mv
INSTALL = ./bsdinstall -c -m 755
INSTALL_DATA = ../bsdinstall -c -m 644

VERSION = @VERSION@

SHELL = /bin/sh
MAKE = make $(MFLAGS)
MFLAGS ='CC=$(CC)'					\
	'CFLAGS=$(CFLAGS)'				\
	'DEFS=$(DEFS)'					\
	'HELP_DIR=$(HELP_DIR)'				\
	'INSTALL_IRC=$(INSTALL_IRC)'			\
	'INSTALL_IRCSERV=$(INSTALL_IRCSERV)'		\
	'INSTALL_WSERV=$(INSTALL_WSERV)'		\
	'IRCLIB=$(IRCLIB)'				\
	'IRCPATH=$(IRC_PATH)'				\
	'LDFLAGS=$(LDFLAGS)'				\
	'LEX=$(LEX)'					\
	'LEXLIB=$(LEXLIB)'				\
	'LIBS=$(LIBS)'					\
	'LN=$(LN)'					\
	'PP_DEFS=$(PP_DEFS)'				\
	'PP_OBJS=$(PP_OBJS)'				\
	'PPS_DEFS=$(PPS_DEFS)'				\
	'RM=$(RM)'					\
	'TRANS_DIR=$(TRANS_PATH)'

all: irc ircserv ircflush wserv

install: all installbin installscript installtranslation

irc: source/Makefile Makefile
	@cd source; $(MAKE) all

installeverything: install installflush installserv installwserv \
	installscript installtranslation

everything: all ircflush ircserv wserv

ircserv: source/Makefile
	@cd source; $(MAKE) ircserv

ircflush: source/ircflush.c source/Makefile
	@cd source; $(MAKE) ircflush

wserv: source/wserv.c source/term.c source/Makefile
	@cd source; $(MAKE) wserv

installbin: installirc installserv installflush installwserv

installirc: irc installdirs
	$(INSTALL) source/irc $(INSTALL_IRC)-$(VERSION)
	@if test -f $(INSTALL_IRC).old; then $(RM) $(INSTALL_IRC).old; fi
	@if test -f $(INSTALL_IRC); then $(MV) $(INSTALL_IRC) $(INSTALL_IRC).old; fi
	$(RM) $(INSTALL_IRC)
	$(LN) $(INSTALL_IRC)-$(VERSION) $(INSTALL_IRC)

installscript: installdirs
	-chmod -x script/*
	-@(								\
		if test -f $(INSTALL_SCRIPT)/local; then		\
			if test -f script/local; then 			\
				$(MV) script/local script/local.orig;	\
			fi;						\
		fi							\
	)
	cd script; for i in *; do $(INSTALL_DATA) $$i $(INSTALL_SCRIPT); done

installtranslation: installdirs
	-chmod -x translation/*
	cd translation; for i in *; do $(INSTALL_DATA) $$i $(TRANS_PATH); done

installserv: ircserv installdirs
	$(INSTALL) source/ircserv $(INSTALL_IRCSERV)

installflush: ircflush installdirs
	$(INSTALL) source/ircflush $(INSTALL_IRCFLUSH)

installwserv: wserv installdirs
	$(INSTALL) source/wserv $(INSTALL_WSERV)

installhelp:
	@echo Help files are no more within this package.  You
	@echo can probably get them from the same place you got
	@echo this source from.

installdirs:
	umask 022; ./mkinstalldirs $(IRCLIB) $(bindir) $(TRANS_PATH) $(INSTALL_SCRIPT)

clena clean:
	@-if test -f source/Makefile; then cd source; $(MAKE) clean; fi

distclean cleandir realclean: clean
	$(RM) Makefile source/Makefile source/sig.inc config.status config.cache config.log easyinst.status include/defs.h

lint:
	@if test -f source/Makefile; then cd source; $(MAKE) lint; fi

autoconf: configure

configure: configure.in acconfig.h
	autoconf

autoheader: include/defs.h.in

include/defs.h.in: configure.in acconfig.h
	autoheader

config_h:
	$(RM) include/config.h
	ln include/config.h.dist include/config.h

export: distclean autoconf autoheader config_h

dist: export
	( \
		cd ..; \
		tar --exclude .CVS -z -c -f ircii-$(VERSION).tar.z ircii; \
	)
5/01/05 06:40:23 mrg stable $

# targets recognised by this makefile:
#   all, everything	- compiles ircii, ircserv, ircflush and wserv
#   ircserv		- compiles ircserv
#   ircflush		- compiles ircflush
#   wserv		- compiles wserv
#   install		- installs ircii, ircserv, ircflush and wserv the scripts
#			  and the translation tables.
#   installirc		- installsDarkNET-1.08/ircii-2.8.H1/NEWS                                                                         644   21270   21270        10433  5706437464  10463                                                                                                                                                                                                                                                                                                                                                                      @(#)$Id: NEWS,v 1.8 1995/01/16 09:41:08 mrg Exp $

New functions:

  o  onchannel(nick #channel)   is `nick' on `#channel' ?
  o  pid()                      returns the pid of this client
  o  ppid()                     returns the parent pid of this client
  o  chanusers(#channel)        returns a list of the users on this channel
  o  for()                      like c's for with the separator being `,' not
                                `;'.  (hop)
  o  fe() and fec()             an alternative to recursion.  (hop)

New commands:

  o  beep                       sends a beep to the terminal
  o  rbind function             shows the keys bound to `function'
  o  stack action list arg      `action' is either push or pop. list is one
                                of `on', `alias', `assign', `bind', or `set'.
                                only `on' is implemented currently
  o  window remove nick         the opposite of window add.
  o  window number num          changes the refnum of a window, forcing a
                                swap if so needed.
  o  window bind #chan          permanently bind a channel to a window.
  o  window unbind [#chan]      remove permanent binding to a window.
  o  abort                      drops a core file, and a saved file (hop).
  o  disconnect [ser [reason]]  disconnects from the named server (number) with
                                the given reason.

Fixed commands:

  o  set help_window            now works.
  o  dcc close send nick file   no longer requires the full path for `file'.
  o  transpose_characters       now works with the cursor at the `end' of the
                                screen.
  o  topic *                    now works as expected.

Changed commands:

  o  userhost [nicks] -cmd      now accepts any number of nicks.
  o  save [-all] [...]          save `all' values, or any part.  valid parts
                                are: assign, alias, all, bind, notify, on,
                                set and digraph.

  o  clear -unhold              as well as clearing the screen, it also
                                unholds one screen.  same as the binding
                                clear_screen

New scripts:

  o  newaway                    does `set show_away_once on' in scripts and
                                with as many nicks as you want
  o  uhnotify                   gives userhost with the notify list.  works
                                much better with the new userhost syntax.
  o  complete, compl.mods       tcsh-like complete scripts.  see script for
                                more information.
  o  imap                       creates an irc map.  see script for more info.

Changed scripts:

  o  2.8script
  o  finger
  o  newformat
  o  netsplit

New variables:

  o  realname                   changes the value of your `realname' the
                                next time you change servers (or use 
                                `/quote quit').
  o  notify_handler             three values.  `noisy', `quiet', and `old'
                                old makes /notify work like it did for 2.2,
                                `noisy'  and `quiet' make it work on a lot
                                more events.  join/quit/message/etc trigger
                                the notify, the difference being that `quiet'
                                won't show these extra differences, where as
                                `noisy' will.  they both add/remove the
                                name to the internal `notified' list.
  o  screen_options             this is orthogonal to xterm_options for
                                /window create.

Other things:

  o  redirect works much better.  it doesn't `catch' things it shouldn't in
     most cases.
  o  lots and lots and logs of bug fixes
  o  ctcp flooding is handled better.
  o  lots and lots of bug fixes.
  o  on dcc_raw dcc close works.
  o  all dcc messages go to level dcc
  o  level all contains `dcc' again.
  o  lots of bug fixes.
  o  gnu `autoconf'ified.
  o  did i meantion lots of bug fixes?
  o  if you add #define DYNAMIC_SLIP, you don't need to restart ircii
     for it to notice the ip number of the local machine has changed.
  o  /window create might be stabler.
  o  new `-q' switch does `quick start' (no .ircrc processing)
                                                                                                                                                                                                                                     DarkNET-1.08/ircii-2.8.H1/README                                                                       644   21270   21270          746  5705201433  10572                                                                                                                                                                                                                                                                                                                                                                      @(#)$Id: README,v 2.2 1995/01/12 10:23:23 mrg stable $

please read the NEWS file to find out what is new in this
version of ircii, and the INSTALL file to find out how to
compile and install this version of ircii.

this is a proper release of ircii.  it has bugs (ircii always
has bugs).  feel free to send me context diffs to fix them,
or at least a sequence of actions to show the bug.

the INSTALL file also has some additional notes on portability
issues.

mrg (mrg@mame.mu.oz.au)
                          DarkNET-1.08/ircii-2.8.H1/acconfig.h                                                                   644   21270   21270         6460  5650072523  11660                                                                                                                                                                                                                                                                                                                                                                      /*
 * @(#)$Id: acconfig.h,v 1.17 1994/10/16 00:35:31 mrg stable $
 */

/* define if allow sys/time.h with time.h */
#undef TIME_WITH_SYS_TIME

/* define this if you are using BSD wait union thigs */
#undef BSDWAIT

/* define this if you are using -ltermcap */
#undef USING_TERMCAP

/* define this if you are using -lcurses */
#undef USING_CURSES

/* define this if you are using -lxtermcap */
#undef USING_XTERMCAP

/* define this if you are using -ltermlib */
#undef USING_TERMLIB

/* define this if signal's return void */
#undef SIGVOID

/* define this if you are using sigaction() instead of signal() */
#undef USE_SIGACTION

/* define this if you are using sigset() instead of signal() */
#undef USE_SIGSET

/* define this if you are using system V (unreliable) signals */
#undef SYSVSIGNALS

/* define this if wait3() is declared */
#undef WAIT3_DECLARED

/* define this if waitpid() is declared */
#undef WAITPID_DECLARED

/* define this if waitpid() is unavailable */
#undef NEED_WAITPID

/* define this if -lnls exists */
#undef HAVE_LIB_NLS

/* define this if -lnsl exists */
#undef HAVE_LIB_NSL

/* define his if -lPW exists */
#undef HAVE_LIB_PW

/* define this to the mail spool */
#undef MAIL_DIR

/* define this if you have scandir() */
#undef HAVE_SCANDIR

/* define this if you have memmove() */
#undef HAVE_MEMMOVE

/* define this if you have setsid() */
#undef HAVE_SETSID

/* define this if you have getsid() */
#undef HAVE_GETSID

/* define this if you have getpgid() */
#undef HAVE_GETPGID

/* define this if your getpgrp() doesn't take a pid argument */
#undef BROKEN_GETPGRP

/* define this if you have sys/select.h */
#undef HAVE_SYS_SELECT_H

/* define this if you have sys/fcntl.h */
#undef HAVE_SYS_FCNTL_H

/* define this if you have fcntl.h */
#undef HAVE_FCNTL_H

/* define this if you have sys/file.h */
#undef HAVE_SYS_FILE_H

/* define this if you have sys/time.h */
#undef HAVE_SYS_TIME_H

/* define this if you have sys/wait.h */
#undef HAVE_SYS_WAIT_H

/* define this if you have string.h */
#undef HAVE_STRING_H

/* define this if you have memory.h */
#undef HAVE_MEMORY_H

/* define this if you have netdb.h */
#undef HAVE_NETDB_H

/* define this if you have sys/ptem.h */
#undef HAVE_SYS_PTEM_H

/* define this if you need getcwd() */
#undef NEED_GETCWD 

/* define this if you have hpux version 7 */
#undef HPUX7

/* define this if you have hpux version 8 */
#undef HPUX8

/* define this if you have an unknown hpux version (pre ver 7) */
#undef HPUXUNKNOWN

/* define this if an unsigned long is 32 bits */
#undef UNSIGNED_LONG32

/* define this if an unsigned int is 32 bits */
#undef UNSIGNED_INT32

/* define this if you are unsure what is is 32 bits */
#undef UNKNOWN_32INT

/* define this if you are on a svr4 derivative */
#undef SVR4

/* define this if you are on solaris 2.x */
#undef __solaris__

/* define this if you don't have struct linger */
#undef NO_STRUCT_LINGER

/* define this if you are on svr3/twg */
#undef WINS

/* define this if you need fchmod */
#undef NEED_FCHMOD

/* define this to the location of normal unix mail */
#undef UNIX_MAIL

/* define this if your header files declare sys_errlist */
#undef SYS_ERRLIST_DECLARED

/* define this if you have uname(2) */
#undef HAVE_UNAME

/* define this if you need strerror(3) */
#undef NEED_STRERROR

/* define this if you have stdarg.h */
#undef HAVE_STDARG_H
                                                                                                                                                                                                                DarkNET-1.08/ircii-2.8.H1/bsdinstall                                                                   755   21270   21270         2303  5657044722  12022                                                                                                                                                                                                                                                                                                                                                                      #! /bin/sh
#
#	@(#)install.sh	4.5	(Berkeley)	10/12/83
#
# @(#)$Id: bsdinstall,v 2.1 1994/11/06 03:13:22 mrg stable $
#
cmd=/bin/mv
strip=""
chmod="/bin/chmod 755"
chown=""
chgrp=""
while true ; do
	case $1 in
		-s )	strip="/bin/strip"
			shift
			;;
		-c )	cmd="/bin/cp"
			shift
			;;
		-m )	chmod="/bin/chmod $2"
			shift
			shift
			;;
		-o )	chown="/etc/chown -f $2"
			shift
			shift
			;;
		-g )	chgrp="/bin/chgrp -f $2"
			shift
			shift
			;;
		-d )	cmd="/bin/mkdir"
			shift
			;;
		* )	break
			;;
	esac
done

if test ! ${2-""}; then
	echo "install: no destination specified"
	exit 1
fi
if test ${3-""}; then
	echo "install: too many files specified -> $*"
	exit 1
fi
if test $1 = $2 -o $2 = .; then
	echo "install: can't move $1 onto itself"
	exit 1
fi
case $cmd in
/bin/mkdir )
	file=$2/$1
	;;
* )
	if test '!' -f $1; then
		echo "install: can't open $1"
		exit 1
	fi
	if test -d $2; then
		file=$2/$1
	else
		file=$2
	fi
	/bin/rm -f $file
	;;
esac

case $cmd in
/bin/mkdir )
	if test ! -d "$file"; then
		$cmd $file
	fi
	;;
* )
	$cmd $1 $file
	if test -n "$strip"; then
		$strip $file
	fi
	;;
esac

if test -n "$chown"; then
	$chown $file
fi
if test -n "$chgrp"; then
	$chgrp $file
fi
$chmod $file

exit 0
                                                                                                                                                                                                                                                                                                                             DarkNET-1.08/ircii-2.8.H1/configure                                                                    755   21270   21270       220655  5710725525  11715                                                                                                                                                                                                                                                                                                                                                                      #!/bin/sh

# From configure.in Revision: 1.46 # Guess values for system-dependent variables and create Makefiles.
# Generated automatically using autoconf version 2.1 
# Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc.
#
# This configure script is free software; the Free Software Foundation
# gives unlimited permission to copy, distribute and modify it.

# Defaults:
ac_help=
ac_default_prefix=/usr/local
# Any additions from configure.in:

# Initialize some variables set by options.
# The variables have the same names as the options, with
# dashes changed to underlines.
build=NONE
cache_file=./config.cache
exec_prefix=NONE
host=NONE
no_create=
nonopt=NONE
no_recursion=
prefix=NONE
program_prefix=NONE
program_suffix=NONE
program_transform_name=s,x,x,
silent=
site=
srcdir=
target=NONE
verbose=
x_includes=NONE
x_libraries=NONE

# Initialize some other variables.
subdirs=

ac_prev=
for ac_option
do

  # If the previous option needs an argument, assign it.
  if test -n "$ac_prev"; then
    eval "$ac_prev=\$ac_option"
    ac_prev=
    continue
  fi

  case "$ac_option" in
  -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
  *) ac_optarg= ;;
  esac

  # Accept the important Cygnus configure options, so we can diagnose typos.

  case "$ac_option" in

  -build | --build | --buil | --bui | --bu | --b)
    ac_prev=build ;;
  -build=* | --build=* | --buil=* | --bui=* | --bu=* | --b=*)
    build="$ac_optarg" ;;

  -cache-file | --cache-file | --cache-fil | --cache-fi \
  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
    ac_prev=cache_file ;;
  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
    cache_file="$ac_optarg" ;;

  -disable-* | --disable-*)
    ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
    # Reject names that are not valid shell variable names.
    if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
      { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
    fi
    ac_feature=`echo $ac_feature| sed 's/-/_/g'`
    eval "enable_${ac_feature}=no" ;;

  -enable-* | --enable-*)
    ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
    # Reject names that are not valid shell variable names.
    if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
      { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
    fi
    ac_feature=`echo $ac_feature| sed 's/-/_/g'`
    case "$ac_option" in
      *=*) ;;
      *) ac_optarg=yes ;;
    esac
    eval "enable_${ac_feature}='$ac_optarg'" ;;

  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
  | --exec | --exe | --ex)
    ac_prev=exec_prefix ;;
  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
  | --exec=* | --exe=* | --ex=*)
    exec_prefix="$ac_optarg" ;;

  -gas | --gas | --ga | --g)
    # Obsolete; use --with-gas.
    with_gas=yes ;;

  -help | --help | --hel | --he)
    # Omit some internal or obsolete options to make the list less imposing.
    # This message is too long to be a string in the A/UX 3.1 sh.
    cat << EOF
Usage: configure [options] [host]
Options: [defaults in brackets after descriptions]
Configuration:
  --cache-file=FILE       cache test results in FILE
  --help                  print this message
  --no-create             do not create output files
  --quiet, --silent       do not print \`checking...' messages
  --version               print the version of autoconf that created configure
Directory and file names:
  --prefix=PREFIX         install architecture-independent files in PREFIX
                          [$ac_default_prefix]
  --exec-prefix=PREFIX    install architecture-dependent files in PREFIX
                          [same as prefix]
  --srcdir=DIR            find the sources in DIR [configure dir or ..]
  --program-prefix=PREFIX prepend PREFIX to installed program names
  --program-suffix=SUFFIX append SUFFIX to installed program names
  --program-transform-name=PROGRAM run sed PROGRAM on installed program names
Host type:
  --build=BUILD           configure for building on BUILD [BUILD=HOST]
  --host=HOST             configure for HOST [guessed]
  --target=TARGET         configure for TARGET [TARGET=HOST]
Features and packages:
  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
  --x-includes=DIR        X include files are in DIR
  --x-libraries=DIR       X library files are in DIR
--enable and --with options recognized:$ac_help
EOF
    exit 0 ;;

  -host | --host | --hos | --ho)
    ac_prev=host ;;
  -host=* | --host=* | --hos=* | --ho=*)
    host="$ac_optarg" ;;

  -nfp | --nfp | --nf)
    # Obsolete; use --without-fp.
    with_fp=no ;;

  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
  | --no-cr | --no-c)
    no_create=yes ;;

  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
    no_recursion=yes ;;

  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
    ac_prev=prefix ;;
  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
    prefix="$ac_optarg" ;;

  -program-prefix | --program-prefix | --program-prefi | --program-pref \
  | --program-pre | --program-pr | --program-p)
    ac_prev=program_prefix ;;
  -program-prefix=* | --program-prefix=* | --program-prefi=* \
  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
    program_prefix="$ac_optarg" ;;

  -program-suffix | --program-suffix | --program-suffi | --program-suff \
  | --program-suf | --program-su | --program-s)
    ac_prev=program_suffix ;;
  -program-suffix=* | --program-suffix=* | --program-suffi=* \
  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
    program_suffix="$ac_optarg" ;;

  -program-transform-name | --program-transform-name \
  | --program-transform-nam | --program-transform-na \
  | --program-transform-n | --program-transform- \
  | --program-transform | --program-transfor \
  | --program-transfo | --program-transf \
  | --program-trans | --program-tran \
  | --progr-tra | --program-tr | --program-t)
    ac_prev=program_transform_name ;;
  -program-transform-name=* | --program-transform-name=* \
  | --program-transform-nam=* | --program-transform-na=* \
  | --program-transform-n=* | --program-transform-=* \
  | --program-transform=* | --program-transfor=* \
  | --program-transfo=* | --program-transf=* \
  | --program-trans=* | --program-tran=* \
  | --progr-tra=* | --program-tr=* | --program-t=*)
    program_transform_name="$ac_optarg" ;;

  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
  | -silent | --silent | --silen | --sile | --sil)
    silent=yes ;;

  -site | --site | --sit)
    ac_prev=site ;;
  -site=* | --site=* | --sit=*)
    site="$ac_optarg" ;;

  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
    ac_prev=srcdir ;;
  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
    srcdir="$ac_optarg" ;;

  -target | --target | --targe | --targ | --tar | --ta | --t)
    ac_prev=target ;;
  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
    target="$ac_optarg" ;;

  -v | -verbose | --verbose | --verbos | --verbo | --verb)
    verbose=yes ;;

  -version | --version | --versio | --versi | --vers)
    echo "configure generated by autoconf version 2.1"
    exit 0 ;;

  -with-* | --with-*)
    ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
    # Reject names that are not valid shell variable names.
    if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
      { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
    fi
    ac_package=`echo $ac_package| sed 's/-/_/g'`
    case "$ac_option" in
      *=*) ;;
      *) ac_optarg=yes ;;
    esac
    eval "with_${ac_package}='$ac_optarg'" ;;

  -without-* | --without-*)
    ac_package=`echo $ac_option|sed -e 's/-*without-//'`
    # Reject names that are not valid shell variable names.
    if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
      { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
    fi
    ac_package=`echo $ac_package| sed 's/-/_/g'`
    eval "with_${ac_package}=no" ;;

  --x)
    # Obsolete; use --with-x.
    with_x=yes ;;

  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
  | --x-incl | --x-inc | --x-in | --x-i)
    ac_prev=x_includes ;;
  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
    x_includes="$ac_optarg" ;;

  -x-libraries | --x-libraries | --x-librarie | --x-librari \
  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
    ac_prev=x_libraries ;;
  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
    x_libraries="$ac_optarg" ;;

  -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
    ;;

  *) 
    if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
      echo "configure: warning: $ac_option: invalid host type" 1>&2
    fi
    if test "x$nonopt" != xNONE; then
      { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
    fi
    nonopt="$ac_option"
    ;;

  esac
done

if test -n "$ac_prev"; then
  { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
fi

trap 'rm -fr conftest* confdefs* core $ac_clean_files; exit 1' 1 2 15

# File descriptor usage:
# 0 unused; standard input
# 1 file creation
# 2 errors and warnings
# 3 unused; some systems may open it to /dev/tty
# 4 checking for... messages and results
# 5 compiler messages saved in config.log
if test "$silent" = yes; then
  exec 4>/dev/null
else
  exec 4>&1
fi
exec 5>./config.log

echo "\
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
" 1>&5

# Strip out --no-create and --no-recursion so they do not pile up.
# Also quote any args containing shell metacharacters.
ac_configure_args=
for ac_arg
do
  case "$ac_arg" in
  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
  | --no-cr | --no-c) ;;
  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
  *" "*|*"	"*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
  ac_configure_args="$ac_configure_args '$ac_arg'" ;;
  *) ac_configure_args="$ac_configure_args $ac_arg" ;;
  esac
done

# NLS nuisances.
# Only set LANG and LC_ALL to C if already set.
# These must not be set unconditionally because not all systems understand
# e.g. LANG=C (notably SCO).
if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
if test "${LANG+set}"   = set; then LANG=C;   export LANG;   fi

# confdefs.h avoids OS command line length limits that DEFS can exceed.
rm -rf conftest* confdefs.h
# AIX cpp loses on an empty file, so make sure it contains at least a newline.
echo > confdefs.h

# A filename unique to this package, relative to the directory that
# configure is in, which we can look for to find out if srcdir is correct.
ac_unique_file=source/irc.c

# Find the source files, if location was not specified.
if test -z "$srcdir"; then
  ac_srcdir_defaulted=yes
  # Try the directory containing this script, then its parent.
  ac_prog=$0
  ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
  test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
  srcdir=$ac_confdir
  if test ! -r $srcdir/$ac_unique_file; then
    srcdir=..
  fi
else
  ac_srcdir_defaulted=no
fi
if test ! -r $srcdir/$ac_unique_file; then
  if test "$ac_srcdir_defaulted" = yes; then
    { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
  else
    { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
  fi
fi
srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`

# Prefer explicitly selected file to automatically selected ones.
if test -z "$CONFIG_SITE"; then
  if test "x$prefix" != xNONE; then
    CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
  else
    CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
  fi
fi
for ac_site_file in $CONFIG_SITE; do
  if test -r "$ac_site_file"; then
    echo "loading site script $ac_site_file"
    . "$ac_site_file"
  fi
done

if test -r "$cache_file"; then
  echo "loading cache $cache_file"
  . $cache_file
else
  echo "creating cache $cache_file"
  > $cache_file
fi

ac_ext=c
# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
ac_cpp='$CPP $CPPFLAGS'
ac_compile='${CC-cc} $CFLAGS $CPPFLAGS conftest.$ac_ext -c 1>&5 2>&5'
ac_link='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext -o conftest $LIBS 1>&5 2>&5'

if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
  # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
  if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
    ac_n= ac_c='
' ac_t='	'
  else
    ac_n=-n ac_c= ac_t=
  fi
else
  ac_n= ac_c='\c' ac_t=
fi





VERSION=`sed -n -e 's/"$//' -e '/#define IRCII_VERSION	*"/s///p' -e '/#define IRCII_VERSION/q' < source/irc.c` 
echo this is ircii version $VERSION
echo



# Extract the first word of "gcc", so it can be a program name with args.
set dummy gcc; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&4
if eval "test \"`echo '${'ac_cv_prog_CC'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&4
else
  if test -n "$CC"; then
  ac_cv_prog_CC="$CC" # Let the user override the test.
else
  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:"
  for ac_dir in $PATH; do
    test -z "$ac_dir" && ac_dir=.
    if test -f $ac_dir/$ac_word; then
      ac_cv_prog_CC="gcc"
      break
    fi
  done
  IFS="$ac_save_ifs"
  test -z "$ac_cv_prog_CC" && ac_cv_prog_CC="cc"
fi
fi
CC="$ac_cv_prog_CC"
if test -n "$CC"; then
  echo "$ac_t""$CC" 1>&4
else
  echo "$ac_t""no" 1>&4
fi


echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&4
if eval "test \"`echo '${'ac_cv_prog_gcc'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&4
else
  cat > conftest.c <<EOF
#ifdef __GNUC__
  yes;
#endif
EOF
if ${CC-cc} -E conftest.c 2>&5 | egrep yes >/dev/null 2>&1; then
  ac_cv_prog_gcc=yes
else
  ac_cv_prog_gcc=no
fi
fi
echo "$ac_t""$ac_cv_prog_gcc" 1>&4
if test $ac_cv_prog_gcc = yes; then
  GCC=yes
  if test "${CFLAGS+set}" != set; then
    echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&4
if eval "test \"`echo '${'ac_cv_prog_gcc_g'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&4
else
  echo 'void f(){}' > conftest.c
if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
  ac_cv_prog_gcc_g=yes
else
  ac_cv_prog_gcc_g=no
fi
rm -f conftest*

fi
    echo "$ac_t""$ac_cv_prog_gcc_g" 1>&4
    if test $ac_cv_prog_gcc_g = yes; then
      CFLAGS="-g -O"
    else
      CFLAGS="-O"
    fi
  fi
else
  GCC=
  test "${CFLAGS+set}" = set || CFLAGS="-g"
fi

echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&4
# On Suns, sometimes $CPP names a directory.
if test -n "$CPP" && test -d "$CPP"; then
  CPP=
fi
if test -z "$CPP"; then
if eval "test \"`echo '${'ac_cv_prog_CPP'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&4
else
    # This must be in double quotes, not single quotes, because CPP may get
  # substituted into the Makefile and "${CC-cc}" will confuse make.
  CPP="${CC-cc} -E"
  # On the NeXT, cc -E runs the code through the compiler's parser,
  # not just through cpp.
  cat > conftest.$ac_ext <<EOF
#line 498 "configure"
#include "confdefs.h"
#include <assert.h>
Syntax Error
EOF
eval "$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
  :
else
  echo "$ac_err" >&5
  rm -rf conftest*
  CPP="${CC-cc} -E -traditional-cpp"
  cat > conftest.$ac_ext <<EOF
#line 512 "configure"
#include "confdefs.h"
#include <assert.h>
Syntax Error
EOF
eval "$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
  :
else
  echo "$ac_err" >&5
  rm -rf conftest*
  CPP=/lib/cpp
fi
rm -f conftest*
fi
rm -f conftest*
  ac_cv_prog_CPP="$CPP"
fi
fi
CPP="$ac_cv_prog_CPP"
echo "$ac_t""$CPP" 1>&4

echo $ac_n "checking for POSIXized ISC""... $ac_c" 1>&4
if test -d /etc/conf/kconfig.d &&
  grep _POSIX_VERSION /usr/include/sys/unistd.h >/dev/null 2>&1
then
  echo "$ac_t""yes" 1>&4
  ISC=yes # If later tests want to check for ISC.
  cat >> confdefs.h <<\EOF
#define _POSIX_SOURCE 1
EOF

  if test "$GCC" = yes; then
    CC="$CC -posix"
  else
    CC="$CC -Xp"
  fi
else
  echo "$ac_t""no" 1>&4
  ISC=
fi



echo $ac_n "checking for NeXT""... $ac_c" 1>&4
cat > conftest.$ac_ext <<EOF
#line 559 "configure"
#include "confdefs.h"
#if defined(NeXT) || defined(__NeXT) || defined(__NeXT__)
  yes
#endif

EOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
  egrep "yes" >/dev/null 2>&1; then
  rm -rf conftest*
  nextstep=1
fi
rm -f conftest*


if test -n "$nextstep"; then
  echo "$ac_t""yes" 1>&4
  CFLAGS="$CFLAGS -posix"
  LIBS="$LIBS -lposix"
else
  echo "$ac_t""no" 1>&4
fi


echo $ac_n "checking for AIX""... $ac_c" 1>&4
cat > conftest.$ac_ext <<EOF
#line 585 "configure"
#include "confdefs.h"

#ifdef _AIX
  yes
#endif

EOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
  egrep "yes" >/dev/null 2>&1; then
  rm -rf conftest*
  echo "$ac_t""yes" 1>&4
  aix=1
  cat >> confdefs.h <<\EOF
#define _ALL_SOURCE 1
EOF

else
  rm -rf conftest*
  echo "$ac_t""no" 1>&4
fi
rm -f conftest*


# Extract the first word of "flex", so it can be a program name with args.
set dummy flex; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&4
if eval "test \"`echo '${'ac_cv_prog_LEX'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&4
else
  if test -n "$LEX"; then
  ac_cv_prog_LEX="$LEX" # Let the user override the test.
else
  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:"
  for ac_dir in $PATH; do
    test -z "$ac_dir" && ac_dir=.
    if test -f $ac_dir/$ac_word; then
      ac_cv_prog_LEX="flex"
      break
    fi
  done
  IFS="$ac_save_ifs"
  test -z "$ac_cv_prog_LEX" && ac_cv_prog_LEX="lex"
fi
fi
LEX="$ac_cv_prog_LEX"
if test -n "$LEX"; then
  echo "$ac_t""$LEX" 1>&4
else
  echo "$ac_t""no" 1>&4
fi

if test -z "$LEXLIB"
then
  case "$LEX" in
  flex*) ac_lib=fl ;;
  *) ac_lib=l ;;
  esac
  echo $ac_n "checking for -l$ac_lib""... $ac_c" 1>&4
if eval "test \"`echo '${'ac_cv_lib_$ac_lib'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&4
else
  ac_save_LIBS="$LIBS"
LIBS="$LIBS -l$ac_lib "
cat > conftest.$ac_ext <<EOF
#line 650 "configure"
#include "confdefs.h"

int main() { return 0; }
int t() {
main()
; return 0; }
EOF
if eval $ac_link; then
  rm -rf conftest*
  eval "ac_cv_lib_$ac_lib=yes"
else
  rm -rf conftest*
  eval "ac_cv_lib_$ac_lib=no"
fi
rm -f conftest*
LIBS="$ac_save_LIBS"

fi
if eval "test \"`echo '$ac_cv_lib_'$ac_lib`\" = yes"; then
  echo "$ac_t""yes" 1>&4
  LEXLIB="-l$ac_lib"
else
  echo "$ac_t""no" 1>&4
fi

fi

if test $ac_cv_prog_gcc = yes; then
  echo $ac_n "checking whether ${CC-cc} needs -traditional""... $ac_c" 1>&4
if eval "test \"`echo '${'ac_cv_prog_gcc_traditional'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&4
else
    ac_pattern="Autoconf.*'x'"
  cat > conftest.$ac_ext <<EOF
#line 685 "configure"
#include "confdefs.h"
#include <sgtty.h>
Autoconf TIOCGETP
EOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
  egrep "$ac_pattern" >/dev/null 2>&1; then
  rm -rf conftest*
  ac_cv_prog_gcc_traditional=yes
else
  rm -rf conftest*
  ac_cv_prog_gcc_traditional=no
fi
rm -f conftest*


  if test $ac_cv_prog_gcc_traditional = no; then
    cat > conftest.$ac_ext <<EOF
#line 703 "configure"
#include "confdefs.h"
#include <termio.h>
Autoconf TCGETA
EOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
  egrep "$ac_pattern" >/dev/null 2>&1; then
  rm -rf conftest*
  ac_cv_prog_gcc_traditional=yes
fi
rm -f conftest*

  fi
fi
  echo "$ac_t""$ac_cv_prog_gcc_traditional" 1>&4
  if test $ac_cv_prog_gcc_traditional = yes; then
    CC="$CC -traditional"
  fi
fi

echo $ac_n "checking for -lsun""... $ac_c" 1>&4
if eval "test \"`echo '${'ac_cv_lib_sun'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&4
else
  ac_save_LIBS="$LIBS"
LIBS="$LIBS -lsun "
cat > conftest.$ac_ext <<EOF
#line 730 "configure"
#include "confdefs.h"

int main() { return 0; }
int t() {
getpwnam()
; return 0; }
EOF
if eval $ac_link; then
  rm -rf conftest*
  eval "ac_cv_lib_sun=yes"
else
  rm -rf conftest*
  eval "ac_cv_lib_sun=no"
fi
rm -f conftest*
LIBS="$ac_save_LIBS"

fi
if eval "test \"`echo '$ac_cv_lib_'sun`\" = yes"; then
  echo "$ac_t""yes" 1>&4
    ac_tr_lib=HAVE_LIB`echo sun | tr '[a-z]' '[A-Z]'`
  cat >> confdefs.h <<EOF
#define $ac_tr_lib 1
EOF

  LIBS="$LIBS -lsun"

else
  echo "$ac_t""no" 1>&4
fi


echo $ac_n "checking for qnx""... $ac_c" 1>&4
case "$(uname -s)" in
  QNX*)
    echo "$ac_t""yes" 1>&4
    LDFLAGS=-N64k                      CFLAGS="-w4 -O -g -fi=unix.h"    ;;
  *)
    echo "$ac_t""no" 1>&4
esac

echo $ac_n "checking for solaris""... $ac_c" 1>&4
if /bin/sun 2> /dev/null
then
  uname=`uname -r`
  case "$uname" in
    4.*)
      echo "$ac_t""no" 1>&4 
      ;;
    5.*)
      echo "$ac_t""yes" 1>&4
      cat >> confdefs.h <<\EOF
#define __solaris__ 1
EOF

      cat >> confdefs.h <<\EOF
#define SVR4 1
EOF

      svr4=1
      ;;
  esac
else
  echo "$ac_t""no" 1>&4
  echo $ac_n "checking for SVR4""... $ac_c" 1>&4
  cat > conftest.$ac_ext <<EOF
#line 797 "configure"
#include "confdefs.h"
#if defined(SVR4) || defined(__svr4__)
  yes
#endif

EOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
  egrep "yes" >/dev/null 2>&1; then
  rm -rf conftest*
  svr4=1
fi
rm -f conftest*

fi

if test -n "$svr4"
then
  echo "$ac_t""yes" 1>&4
  LIBS="-L/usr/ccs/lib $LIBS"
  cat >> confdefs.h <<\EOF
#define SVR4 1
EOF

else
  echo "$ac_t""no" 1>&4
fi


echo $ac_n "checking for -I/usr/netinclude""... $ac_c" 1>&4
if test -d /usr/netinclude; then
  echo "$ac_t""yes" 1>&4
  CFLAGS="$CFLAGS -I/usr/netinclude"
else
  echo "$ac_t""no" 1>&4
fi
  
for ac_hdr in sys/un.h sys/select.h sys/fcntl.h sys/file.h sys/time.h sys/wait.h sys/twg_config.h sys/ptem.h
do
ac_safe=`echo "$ac_hdr" | tr './\055' '___'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&4
if eval "test \"`echo '${'ac_cv_header_$ac_safe'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&4
else
  cat > conftest.$ac_ext <<EOF
#line 842 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
eval "$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
  rm -rf conftest*
  eval "ac_cv_header_$ac_safe=yes"
else
  echo "$ac_err" >&5
  rm -rf conftest*
  eval "ac_cv_header_$ac_safe=no"
fi
rm -f conftest*
fi
if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
  echo "$ac_t""yes" 1>&4
    ac_tr_hdr=HAVE_`echo $ac_hdr | tr '[a-z]./\055' '[A-Z]___'`
  cat >> confdefs.h <<EOF
#define $ac_tr_hdr 1
EOF
 
else
  echo "$ac_t""no" 1>&4
fi
done
for ac_hdr in stdarg.h unistd.h fcntl.h string.h memory.h netdb.h limits.h
do
ac_safe=`echo "$ac_hdr" | tr './\055' '___'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&4
if eval "test \"`echo '${'ac_cv_header_$ac_safe'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&4
else
  cat > conftest.$ac_ext <<EOF
#line 877 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
eval "$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
  rm -rf conftest*
  eval "ac_cv_header_$ac_safe=yes"
else
  echo "$ac_err" >&5
  rm -rf conftest*
  eval "ac_cv_header_$ac_safe=no"
fi
rm -f conftest*
fi
if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
  echo "$ac_t""yes" 1>&4
    ac_tr_hdr=HAVE_`echo $ac_hdr | tr '[a-z]./\055' '[A-Z]___'`
  cat >> confdefs.h <<EOF
#define $ac_tr_hdr 1
EOF
 
else
  echo "$ac_t""no" 1>&4
fi
done
echo $ac_n "checking for setsid""... $ac_c" 1>&4
if eval "test \"`echo '${'ac_cv_func_setsid'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&4
else
  cat > conftest.$ac_ext <<EOF
#line 909 "configure"
#include "confdefs.h"
#include <ctype.h> /* Arbitrary system header to define __stub macros. */
/* Override any gcc2 internal prototype to avoid an error.  */
char setsid(); 

int main() { return 0; }
int t() {

/* The GNU C library defines this for functions which it implements
    to always fail with ENOSYS.  Some functions are actually named
    something starting with __ and the normal name is an alias.  */
#if defined (__stub_setsid) || defined (__stub___setsid)
choke me
#else
setsid();
#endif

; return 0; }
EOF
if eval $ac_link; then
  rm -rf conftest*
  eval "ac_cv_func_setsid=yes"
else
  rm -rf conftest*
  eval "ac_cv_func_setsid=no"
fi
rm -f conftest*

fi
if eval "test \"`echo '$ac_cv_func_'setsid`\" = yes"; then
  echo "$ac_t""yes" 1>&4
  cat >> confdefs.h <<\EOF
#define HAVE_SETSID 1
EOF

else
  echo "$ac_t""no" 1>&4
fi

echo $ac_n "checking for getpgid""... $ac_c" 1>&4
if eval "test \"`echo '${'ac_cv_func_getpgid'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&4
else
  cat > conftest.$ac_ext <<EOF
#line 954 "configure"
#include "confdefs.h"
#include <ctype.h> /* Arbitrary system header to define __stub macros. */
/* Override any gcc2 internal prototype to avoid an error.  */
char getpgid(); 

int main() { return 0; }
int t() {

/* The GNU C library defines this for functions which it implements
    to always fail with ENOSYS.  Some functions are actually named
    something starting with __ and the normal name is an alias.  */
#if defined (__stub_getpgid) || defined (__stub___getpgid)
choke me
#else
getpgid();
#endif

; return 0; }
EOF
if eval $ac_link; then
  rm -rf conftest*
  eval "ac_cv_func_getpgid=yes"
else
  rm -rf conftest*
  eval "ac_cv_func_getpgid=no"
fi
rm -f conftest*

fi
if eval "test \"`echo '$ac_cv_func_'getpgid`\" = yes"; then
  echo "$ac_t""yes" 1>&4
  cat >> confdefs.h <<\EOF
#define HAVE_GETPGID 1
EOF

else
  echo "$ac_t""no" 1>&4
fi

echo $ac_n "checking for getsid""... $ac_c" 1>&4
if eval "test \"`echo '${'ac_cv_func_getsid'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&4
else
  cat > conftest.$ac_ext <<EOF
#line 999 "configure"
#include "confdefs.h"
#include <ctype.h> /* Arbitrary system header to define __stub macros. */
/* Override any gcc2 internal prototype to avoid an error.  */
char getsid(); 

int main() { return 0; }
int t() {

/* The GNU C library defines this for functions which it implements
    to always fail with ENOSYS.  Some functions are actually named
    something starting with __ and the normal name is an alias.  */
#if defined (__stub_getsid) || defined (__stub___getsid)
choke me
#else
getsid();
#endif

; return 0; }
EOF
if eval $ac_link; then
  rm -rf conftest*
  eval "ac_cv_func_getsid=yes"
else
  rm -rf conftest*
  eval "ac_cv_func_getsid=no"
fi
rm -f conftest*

fi
if eval "test \"`echo '$ac_cv_func_'getsid`\" = yes"; then
  echo "$ac_t""yes" 1>&4
  cat >> confdefs.h <<\EOF
#define HAVE_GETSID 1
EOF

else
  echo "$ac_t""no" 1>&4
fi

echo $ac_n "checking for scandir""... $ac_c" 1>&4
if eval "test \"`echo '${'ac_cv_func_scandir'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&4
else
  cat > conftest.$ac_ext <<EOF
#line 1044 "configure"
#include "confdefs.h"
#include <ctype.h> /* Arbitrary system header to define __stub macros. */
/* Override any gcc2 internal prototype to avoid an error.  */
char scandir(); 

int main() { return 0; }
int t() {

/* The GNU C library defines this for functions which it implements
    to always fail with ENOSYS.  Some functions are actually named
    something starting with __ and the normal name is an alias.  */
#if defined (__stub_scandir) || defined (__stub___scandir)
choke me
#else
scandir();
#endif

; return 0; }
EOF
if eval $ac_link; then
  rm -rf conftest*
  eval "ac_cv_func_scandir=yes"
else
  rm -rf conftest*
  eval "ac_cv_func_scandir=no"
fi
rm -f conftest*

fi
if eval "test \"`echo '$ac_cv_func_'scandir`\" = yes"; then
  echo "$ac_t""yes" 1>&4
  cat >> confdefs.h <<\EOF
#define HAVE_SCANDIR 1
EOF

else
  echo "$ac_t""no" 1>&4
fi

echo $ac_n "checking for memmove""... $ac_c" 1>&4
if eval "test \"`echo '${'ac_cv_func_memmove'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&4
else
  cat > conftest.$ac_ext <<EOF
#line 1089 "configure"
#include "confdefs.h"
#include <ctype.h> /* Arbitrary system header to define __stub macros. */
/* Override any gcc2 internal prototype to avoid an error.  */
char memmove(); 

int main() { return 0; }
int t() {

/* The GNU C library defines this for functions which it implements
    to always fail with ENOSYS.  Some functions are actually named
    something starting with __ and the normal name is an alias.  */
#if defined (__stub_memmove) || defined (__stub___memmove)
choke me
#else
memmove();
#endif

; return 0; }
EOF
if eval $ac_link; then
  rm -rf conftest*
  eval "ac_cv_func_memmove=yes"
else
  rm -rf conftest*
  eval "ac_cv_func_memmove=no"
fi
rm -f conftest*

fi
if eval "test \"`echo '$ac_cv_func_'memmove`\" = yes"; then
  echo "$ac_t""yes" 1>&4
  cat >> confdefs.h <<\EOF
#define HAVE_MEMMOVE 1
EOF

else
  echo "$ac_t""no" 1>&4
fi

echo $ac_n "checking for uname""... $ac_c" 1>&4
if eval "test \"`echo '${'ac_cv_func_uname'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&4
else
  cat > conftest.$ac_ext <<EOF
#line 1134 "configure"
#include "confdefs.h"
#include <ctype.h> /* Arbitrary system header to define __stub macros. */
/* Override any gcc2 internal prototype to avoid an error.  */
char uname(); 

int main() { return 0; }
int t() {

/* The GNU C library defines this for functions which it implements
    to always fail with ENOSYS.  Some functions are actually named
    something starting with __ and the normal name is an alias.  */
#if defined (__stub_uname) || defined (__stub___uname)
choke me
#else
uname();
#endif

; return 0; }
EOF
if eval $ac_link; then
  rm -rf conftest*
  eval "ac_cv_func_uname=yes"
else
  rm -rf conftest*
  eval "ac_cv_func_uname=no"
fi
rm -f conftest*

fi
if eval "test \"`echo '$ac_cv_func_'uname`\" = yes"; then
  echo "$ac_t""yes" 1>&4
  cat >> confdefs.h <<\EOF
#define HAVE_UNAME 1
EOF

else
  echo "$ac_t""no" 1>&4
fi

echo $ac_n "checking for getcwd""... $ac_c" 1>&4
if eval "test \"`echo '${'ac_cv_func_getcwd'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&4
else
  cat > conftest.$ac_ext <<EOF
#line 1179 "configure"
#include "confdefs.h"
#include <ctype.h> /* Arbitrary system header to define __stub macros. */
/* Override any gcc2 internal prototype to avoid an error.  */
char getcwd(); 

int main() { return 0; }
int t() {

/* The GNU C library defines this for functions which it implements
    to always fail with ENOSYS.  Some functions are actually named
    something starting with __ and the normal name is an alias.  */
#if defined (__stub_getcwd) || defined (__stub___getcwd)
choke me
#else
getcwd();
#endif

; return 0; }
EOF
if eval $ac_link; then
  rm -rf conftest*
  eval "ac_cv_func_getcwd=yes"
else
  rm -rf conftest*
  eval "ac_cv_func_getcwd=no"
fi
rm -f conftest*

fi
if eval "test \"`echo '$ac_cv_func_'getcwd`\" = yes"; then
  echo "$ac_t""yes" 1>&4
  :
else
  echo "$ac_t""no" 1>&4
cat >> confdefs.h <<\EOF
#define NEED_GETCWD 1
EOF

fi

echo $ac_n "checking for fchmod""... $ac_c" 1>&4
if eval "test \"`echo '${'ac_cv_func_fchmod'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&4
else
  cat > conftest.$ac_ext <<EOF
#line 1225 "configure"
#include "confdefs.h"
#include <ctype.h> /* Arbitrary system header to define __stub macros. */
/* Override any gcc2 internal prototype to avoid an error.  */
char fchmod(); 

int main() { return 0; }
int t() {

/* The GNU C library defines this for functions which it implements
    to always fail with ENOSYS.  Some functions are actually named
    something starting with __ and the normal name is an alias.  */
#if defined (__stub_fchmod) || defined (__stub___fchmod)
choke me
#else
fchmod();
#endif

; return 0; }
EOF
if eval $ac_link; then
  rm -rf conftest*
  eval "ac_cv_func_fchmod=yes"
else
  rm -rf conftest*
  eval "ac_cv_func_fchmod=no"
fi
rm -f conftest*

fi
if eval "test \"`echo '$ac_cv_func_'fchmod`\" = yes"; then
  echo "$ac_t""yes" 1>&4
  :
else
  echo "$ac_t""no" 1>&4
cat >> confdefs.h <<\EOF
#define NEED_FCHMOD 1
EOF

fi

echo $ac_n "checking for strerror""... $ac_c" 1>&4
if eval "test \"`echo '${'ac_cv_func_strerror'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&4
else
  cat > conftest.$ac_ext <<EOF
#line 1271 "configure"
#include "confdefs.h"
#include <ctype.h> /* Arbitrary system header to define __stub macros. */
/* Override any gcc2 internal prototype to avoid an error.  */
char strerror(); 

int main() { return 0; }
int t() {

/* The GNU C library defines this for functions which it implements
    to always fail with ENOSYS.  Some functions are actually named
    something starting with __ and the normal name is an alias.  */
#if defined (__stub_strerror) || defined (__stub___strerror)
choke me
#else
strerror();
#endif

; return 0; }
EOF
if eval $ac_link; then
  rm -rf conftest*
  eval "ac_cv_func_strerror=yes"
else
  rm -rf conftest*
  eval "ac_cv_func_strerror=no"
fi
rm -f conftest*

fi
if eval "test \"`echo '$ac_cv_func_'strerror`\" = yes"; then
  echo "$ac_t""yes" 1>&4
  :
else
  echo "$ac_t""no" 1>&4
cat >> confdefs.h <<\EOF
#define NEED_STRERROR 1
EOF

fi

# If we cannot run a trivial program, we must be cross compiling.
echo $ac_n "checking whether cross-compiling""... $ac_c" 1>&4
if eval "test \"`echo '${'ac_cv_c_cross'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&4
else
  if test "$cross_compiling" = yes; then
  ac_cv_cross=yes
else
cat > conftest.$ac_ext <<EOF
#line 1321 "configure"
#include "confdefs.h"
main(){return(0);}
EOF
eval $ac_link
if test -s conftest && (./conftest; exit) 2>/dev/null; then
  ac_cv_c_cross=no
else
  ac_cv_c_cross=yes
fi
fi
rm -fr conftest*
fi
cross_compiling=$ac_cv_c_cross
echo "$ac_t""$ac_cv_c_cross" 1>&4

echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&4
if eval "test \"`echo '${'ac_cv_header_stdc'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&4
else
  cat > conftest.$ac_ext <<EOF
#line 1342 "configure"
#include "confdefs.h"
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <float.h>
EOF
eval "$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
  rm -rf conftest*
  ac_cv_header_stdc=yes
else
  echo "$ac_err" >&5
  rm -rf conftest*
  ac_cv_header_stdc=no
fi
rm -f conftest*

if test $ac_cv_header_stdc = yes; then
  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
cat > conftest.$ac_ext <<EOF
#line 1364 "configure"
#include "confdefs.h"
#include <string.h>
EOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
  egrep "memchr" >/dev/null 2>&1; then
  :
else
  rm -rf conftest*
  ac_cv_header_stdc=no
fi
rm -f conftest*

fi

if test $ac_cv_header_stdc = yes; then
  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
cat > conftest.$ac_ext <<EOF
#line 1382 "configure"
#include "confdefs.h"
#include <stdlib.h>
EOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
  egrep "free" >/dev/null 2>&1; then
  :
else
  rm -rf conftest*
  ac_cv_header_stdc=no
fi
rm -f conftest*

fi

if test $ac_cv_header_stdc = yes; then
  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
if test "$cross_compiling" = yes; then
  ac_cv_header_stdc=no
else
cat > conftest.$ac_ext <<EOF
#line 1403 "configure"
#include "confdefs.h"
#include <ctype.h>
#define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
int main () { int i; for (i = 0; i < 256; i++)
if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2);
exit (0); }

EOF
eval $ac_link
if test -s conftest && (./conftest; exit) 2>/dev/null; then
  :
else
  ac_cv_header_stdc=no
fi
fi
rm -fr conftest*
fi
fi
echo "$ac_t""$ac_cv_header_stdc" 1>&4
if test $ac_cv_header_stdc = yes; then
  cat >> confdefs.h <<\EOF
#define STDC_HEADERS 1
EOF

fi

echo $ac_n "checking whether time.h and sys/time.h may both be included""... $ac_c" 1>&4
if eval "test \"`echo '${'ac_cv_header_time'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&4
else
  cat > conftest.$ac_ext <<EOF
#line 1437 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <sys/time.h>
#include <time.h>
int main() { return 0; }
int t() {
struct tm *tp;
; return 0; }
EOF
if eval $ac_compile; then
  rm -rf conftest*
  ac_cv_header_time=yes
else
  rm -rf conftest*
  ac_cv_header_time=no
fi
rm -f conftest*

fi
echo "$ac_t""$ac_cv_header_time" 1>&4
if test $ac_cv_header_time = yes; then
  cat >> confdefs.h <<\EOF
#define TIME_WITH_SYS_TIME 1
EOF

fi

ac_header_dirent=no
for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h
do
ac_safe=`echo "$ac_hdr" | tr './\055' '___'`
echo $ac_n "checking for $ac_hdr that defines DIR""... $ac_c" 1>&4
if eval "test \"`echo '${'ac_cv_header_dirent_$ac_safe'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&4
else
  cat > conftest.$ac_ext <<EOF
#line 1474 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <$ac_hdr>
int main() { return 0; }
int t() {
DIR *dirp = 0;
; return 0; }
EOF
if eval $ac_compile; then
  rm -rf conftest*
  eval "ac_cv_header_dirent_$ac_safe=yes"
else
  rm -rf conftest*
  eval "ac_cv_header_dirent_$ac_safe=no"
fi
rm -f conftest*

fi
if eval "test \"`echo '$ac_cv_header_dirent_'$ac_safe`\" = yes"; then
  echo "$ac_t""yes" 1>&4
    ac_tr_hdr=HAVE_`echo $ac_hdr | tr '[a-z]./\055' '[A-Z]___'`
  cat >> confdefs.h <<EOF
#define $ac_tr_hdr 1
EOF
 ac_header_dirent=$ac_hdr; break
else
  echo "$ac_t""no" 1>&4
fi
done
# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix.
if test $ac_header_dirent = dirent.h; then
echo $ac_n "checking for -ldir""... $ac_c" 1>&4
if eval "test \"`echo '${'ac_cv_lib_dir'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&4
else
  ac_save_LIBS="$LIBS"
LIBS="$LIBS -ldir "
cat > conftest.$ac_ext <<EOF
#line 1513 "configure"
#include "confdefs.h"

int main() { return 0; }
int t() {
opendir()
; return 0; }
EOF
if eval $ac_link; then
  rm -rf conftest*
  eval "ac_cv_lib_dir=yes"
else
  rm -rf conftest*
  eval "ac_cv_lib_dir=no"
fi
rm -f conftest*
LIBS="$ac_save_LIBS"

fi
if eval "test \"`echo '$ac_cv_lib_'dir`\" = yes"; then
  echo "$ac_t""yes" 1>&4
  LIBS="$LIBS -ldir"
else
  echo "$ac_t""no" 1>&4
fi

else
echo $ac_n "checking for -lx""... $ac_c" 1>&4
if eval "test \"`echo '${'ac_cv_lib_x'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&4
else
  ac_save_LIBS="$LIBS"
LIBS="$LIBS -lx "
cat > conftest.$ac_ext <<EOF
#line 1547 "configure"
#include "confdefs.h"

int main() { return 0; }
int t() {
opendir()
; return 0; }
EOF
if eval $ac_link; then
  rm -rf conftest*
  eval "ac_cv_lib_x=yes"
else
  rm -rf conftest*
  eval "ac_cv_lib_x=no"
fi
rm -f conftest*
LIBS="$ac_save_LIBS"

fi
if eval "test \"`echo '$ac_cv_lib_'x`\" = yes"; then
  echo "$ac_t""yes" 1>&4
  LIBS="$LIBS -lx"
else
  echo "$ac_t""no" 1>&4
fi

fi

echo $ac_n "checking return type of signal handlers""... $ac_c" 1>&4
if eval "test \"`echo '${'ac_cv_type_signal'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&4
else
  cat > conftest.$ac_ext <<EOF
#line 1580 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <signal.h>
#ifdef signal
#undef signal
#endif
extern void (*signal ()) ();
int main() { return 0; }
int t() {
int i;
; return 0; }
EOF
if eval $ac_compile; then
  rm -rf conftest*
  ac_cv_type_signal=void
else
  rm -rf conftest*
  ac_cv_type_signal=int
fi
rm -f conftest*

fi
echo "$ac_t""$ac_cv_type_signal" 1>&4
cat >> confdefs.h <<EOF
#define RETSIGTYPE $ac_cv_type_signal
EOF


echo $ac_n "checking for mode_t""... $ac_c" 1>&4
if eval "test \"`echo '${'ac_cv_type_mode_t'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&4
else
  cat > conftest.$ac_ext <<EOF
#line 1614 "configure"
#include "confdefs.h"
#include <sys/types.h>
#if STDC_HEADERS
#include <stdlib.h>
#endif
EOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
  egrep "mode_t" >/dev/null 2>&1; then
  rm -rf conftest*
  ac_cv_type_mode_t=yes
else
  rm -rf conftest*
  ac_cv_type_mode_t=no
fi
rm -f conftest*

fi
echo "$ac_t""$ac_cv_type_mode_t" 1>&4
if test $ac_cv_type_mode_t = no; then
  cat >> confdefs.h <<\EOF
#define mode_t int
EOF

fi

echo $ac_n "checking for pid_t""... $ac_c" 1>&4
if eval "test \"`echo '${'ac_cv_type_pid_t'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&4
else
  cat > conftest.$ac_ext <<EOF
#line 1645 "configure"
#include "confdefs.h"
#include <sys/types.h>
#if STDC_HEADERS
#include <stdlib.h>
#endif
EOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
  egrep "pid_t" >/dev/null 2>&1; then
  rm -rf conftest*
  ac_cv_type_pid_t=yes
else
  rm -rf conftest*
  ac_cv_type_pid_t=no
fi
rm -f conftest*

fi
echo "$ac_t""$ac_cv_type_pid_t" 1>&4
if test $ac_cv_type_pid_t = no; then
  cat >> confdefs.h <<\EOF
#define pid_t int
EOF

fi

echo $ac_n "checking for size_t""... $ac_c" 1>&4
if eval "test \"`echo '${'ac_cv_type_size_t'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&4
else
  cat > conftest.$ac_ext <<EOF
#line 1676 "configure"
#include "confdefs.h"
#include <sys/types.h>
#if STDC_HEADERS
#include <stdlib.h>
#endif
EOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
  egrep "size_t" >/dev/null 2>&1; then
  rm -rf conftest*
  ac_cv_type_size_t=yes
else
  rm -rf conftest*
  ac_cv_type_size_t=no
fi
rm -f conftest*

fi
echo "$ac_t""$ac_cv_type_size_t" 1>&4
if test $ac_cv_type_size_t = no; then
  cat >> confdefs.h <<\EOF
#define size_t unsigned
EOF

fi

echo $ac_n "checking for uid_t in sys/types.h""... $ac_c" 1>&4
if eval "test \"`echo '${'ac_cv_type_uid_t'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&4
else
  cat > conftest.$ac_ext <<EOF
#line 1707 "configure"
#include "confdefs.h"
#include <sys/types.h>
EOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
  egrep "uid_t" >/dev/null 2>&1; then
  rm -rf conftest*
  ac_cv_type_uid_t=yes
else
  rm -rf conftest*
  ac_cv_type_uid_t=no
fi
rm -f conftest*

fi
echo "$ac_t""$ac_cv_type_uid_t" 1>&4
if test $ac_cv_type_uid_t = no; then
  cat >> confdefs.h <<\EOF
#define uid_t int
EOF

  cat >> confdefs.h <<\EOF
#define gid_t int
EOF

fi


if test x$ac_cv_header_sys_twg_config_h = xyes
then
  cat >> confdefs.h <<\EOF
#define WINS 1
EOF

fi


echo $ac_n "checking for hpux version""... $ac_c" 1>&4
if test -f /hp-ux; then
  echo "$ac_t""yes" 1>&4
  hpux=1
  uname=`uname -r` 2> /dev/null
  case $uname in
	A.09* | A.9* | a.9* | a.09* | 9* | 09*)
		;;
	A.08* | A.8* | a.8* | a.08* | 8* | 08*)
		cat >> confdefs.h <<\EOF
#define HPUX8 1
EOF

		;;
	A.07* | A.B7* | A.7* | a.7* | a.07* | 7* | 07*)
		cat >> confdefs.h <<\EOF
#define HPUX7 1
EOF

		;;
	*)
		cat >> confdefs.h <<\EOF
#define HPUXUNKNOWN 1
EOF

		;;
  esac
else
  echo "$ac_t""no" 1>&4
fi


echo $ac_n "checking for ultrix""... $ac_c" 1>&4
cat > conftest.$ac_ext <<EOF
#line 1778 "configure"
#include "confdefs.h"
#if defined(ultrix) || defined(__ultrix) || defined(__ultrix)
  yes
#endif

EOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
  egrep "yes" >/dev/null 2>&1; then
  rm -rf conftest*
  ultrix=1
fi
rm -f conftest*


if test -n "$ultrix"; then
  echo "$ac_t""yes" 1>&4
  test -z "$GCC" && CC="$CC -YBSD"
else
  echo "$ac_t""no" 1>&4
  # POSIX termios is broken on Ultrix so don't look for it.
echo $ac_n "checking for POSIX.1""... $ac_c" 1>&4
cat > conftest.$ac_ext <<EOF
#line 1801 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <unistd.h>
main () {
#ifdef _POSIX_VERSION
  yes
#endif
}

EOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
  egrep "yes" >/dev/null 2>&1; then
  rm -rf conftest*
  cat >> confdefs.h <<\EOF
#define POSIX 1
EOF
 echo "$ac_t""yes" 1>&4; posix=1
else
  rm -rf conftest*
  echo "$ac_t""no" 1>&4
fi
rm -f conftest*

fi


echo $ac_n "checking for sequent/ptx""... $ac_c" 1>&4
cat > conftest.$ac_ext <<EOF
#line 1830 "configure"
#include "confdefs.h"
#ifdef _SEQUENT_
  yes
#endif

EOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
  egrep "yes" >/dev/null 2>&1; then
  rm -rf conftest*
  LIBS="$LIBS -lseq" seqptx=1 echo "$ac_t""yes" 1>&4
else
  rm -rf conftest*
  echo "$ac_t""no" 1>&4
fi
rm -f conftest*



echo $ac_n "checking for struct linger""... $ac_c" 1>&4
cat > conftest.$ac_ext <<EOF
#line 1851 "configure"
#include "confdefs.h"
#include <sys/socket.h>
EOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
  egrep "struct( |	)*linger" >/dev/null 2>&1; then
  rm -rf conftest*
  echo "$ac_t""yes" 1>&4
else
  rm -rf conftest*
  cat >> confdefs.h <<\EOF
#define NO_STRUCT_LINGER 1
EOF
 echo "$ac_t""no" 1>&4
fi
rm -f conftest*



if test x$ac_cv_func_getsid != xyes && test x$ac_cv_func_getpgid != xyes
then
  echo $ac_n "checking if getpgrp takes an argument""... $ac_c" 1>&4
  if test "$cross_compiling" = yes; then
  :
else
cat > conftest.$ac_ext <<EOF
#line 1877 "configure"
#include "confdefs.h"

main()
{
  int pid;
  int pgid;

  pid = fork();

  if (0 == pid)
  {
#ifdef HAVE_SETSID
    setsid();
#else
    setpgrp(0, getpid());
#endif /* HAVE_SETSID */
    sleep(10);
  }
  else
  {
    sleep(2);
    pgid = getpgrp(pid);
    kill(pid,9);
    if (pid != pgid)
      exit(1);
  }
  exit(0);
}

EOF
eval $ac_link
if test -s conftest && (./conftest; exit) 2>/dev/null; then
  echo "$ac_t""yes" 1>&4
else
  echo "$ac_t""no your getpgrp is painful" 1>&4
  cat >> confdefs.h <<\EOF
#define BROKEN_GETPGRP 1
EOF

fi
fi
rm -fr conftest*
fi


if test x$posix != x1
then
echo $ac_n "checking for bsd wait""... $ac_c" 1>&4
cat > conftest.$ac_ext <<EOF
#line 1927 "configure"
#include "confdefs.h"

#include <sys/types.h>
#include <sys/wait.h>

int main() { return 0; }
int t() {

  union wait x;
  int y;
#ifdef WEXITSTATUS
  y = WEXITSTATUS(x);
#endif

; return 0; }
EOF
if eval $ac_link; then
  rm -rf conftest*
  cat >> confdefs.h <<\EOF
#define BSDWAIT 1
EOF

  bsdwait=1
  echo "$ac_t""yes" 1>&4
else
  rm -rf conftest*
  echo "$ac_t""no" 1>&4
  echo $ac_n "checking for waitpid""... $ac_c" 1>&4
if eval "test \"`echo '${'ac_cv_func_waitpid'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&4
else
  cat > conftest.$ac_ext <<EOF
#line 1960 "configure"
#include "confdefs.h"
#include <ctype.h> /* Arbitrary system header to define __stub macros. */
/* Override any gcc2 internal prototype to avoid an error.  */
char waitpid(); 

int main() { return 0; }
int t() {

/* The GNU C library defines this for functions which it implements
    to always fail with ENOSYS.  Some functions are actually named
    something starting with __ and the normal name is an alias.  */
#if defined (__stub_waitpid) || defined (__stub___waitpid)
choke me
#else
waitpid();
#endif

; return 0; }
EOF
if eval $ac_link; then
  rm -rf conftest*
  eval "ac_cv_func_waitpid=yes"
else
  rm -rf conftest*
  eval "ac_cv_func_waitpid=no"
fi
rm -f conftest*

fi
if eval "test \"`echo '$ac_cv_func_'waitpid`\" = yes"; then
  echo "$ac_t""yes" 1>&4
  :
else
  echo "$ac_t""no" 1>&4
cat >> confdefs.h <<\EOF
#define NEED_WAITPID 1
EOF

fi

fi
rm -f conftest*

fi


olibs="$LIBS"
echo $ac_n "checking for select""... $ac_c" 1>&4
if eval "test \"`echo '${'ac_cv_func_select'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&4
else
  cat > conftest.$ac_ext <<EOF
#line 2013 "configure"
#include "confdefs.h"
#include <ctype.h> /* Arbitrary system header to define __stub macros. */
/* Override any gcc2 internal prototype to avoid an error.  */
char select(); 

int main() { return 0; }
int t() {

/* The GNU C library defines this for functions which it implements
    to always fail with ENOSYS.  Some functions are actually named
    something starting with __ and the normal name is an alias.  */
#if defined (__stub_select) || defined (__stub___select)
choke me
#else
select();
#endif

; return 0; }
EOF
if eval $ac_link; then
  rm -rf conftest*
  eval "ac_cv_func_select=yes"
else
  rm -rf conftest*
  eval "ac_cv_func_select=no"
fi
rm -f conftest*

fi
if eval "test \"`echo '$ac_cv_func_'select`\" = yes"; then
  echo "$ac_t""yes" 1>&4
  :
else
  echo "$ac_t""no" 1>&4
echo $ac_n "checking for -lsocket""... $ac_c" 1>&4
if eval "test \"`echo '${'ac_cv_lib_socket'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&4
else
  ac_save_LIBS="$LIBS"
LIBS="$LIBS -lsocket "
cat > conftest.$ac_ext <<EOF
#line 2055 "configure"
#include "confdefs.h"

int main() { return 0; }
int t() {
select()
; return 0; }
EOF
if eval $ac_link; then
  rm -rf conftest*
  eval "ac_cv_lib_socket=yes"
else
  rm -rf conftest*
  eval "ac_cv_lib_socket=no"
fi
rm -f conftest*
LIBS="$ac_save_LIBS"

fi
if eval "test \"`echo '$ac_cv_lib_'socket`\" = yes"; then
  echo "$ac_t""yes" 1>&4
  LIBS="$LIBS -lsocket"
else
  echo "$ac_t""no" 1>&4
echo $ac_n "checking for -lnsl""... $ac_c" 1>&4
if eval "test \"`echo '${'ac_cv_lib_nsl'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&4
else
  ac_save_LIBS="$LIBS"
LIBS="$LIBS -lnsl "
cat > conftest.$ac_ext <<EOF
#line 2086 "configure"
#include "confdefs.h"

int main() { return 0; }
int t() {
select()
; return 0; }
EOF
if eval $ac_link; then
  rm -rf conftest*
  eval "ac_cv_lib_nsl=yes"
else
  rm -rf conftest*
  eval "ac_cv_lib_nsl=no"
fi
rm -f conftest*
LIBS="$ac_save_LIBS"

fi
if eval "test \"`echo '$ac_cv_lib_'nsl`\" = yes"; then
  echo "$ac_t""yes" 1>&4
  LIBS="$LIBS -lnsl"
else
  echo "$ac_t""no" 1>&4
echo $ac_n "checking for -linet""... $ac_c" 1>&4
if eval "test \"`echo '${'ac_cv_lib_inet'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&4
else
  ac_save_LIBS="$LIBS"
LIBS="$LIBS -linet "
cat > conftest.$ac_ext <<EOF
#line 2117 "configure"
#include "confdefs.h"

int main() { return 0; }
int t() {
select()
; return 0; }
EOF
if eval $ac_link; then
  rm -rf conftest*
  eval "ac_cv_lib_inet=yes"
else
  rm -rf conftest*
  eval "ac_cv_lib_inet=no"
fi
rm -f conftest*
LIBS="$ac_save_LIBS"

fi
if eval "test \"`echo '$ac_cv_lib_'inet`\" = yes"; then
  echo "$ac_t""yes" 1>&4
  LIBS="$LIBS -linet"
else
  echo "$ac_t""no" 1>&4
echo $ac_n "checking for -lcposix""... $ac_c" 1>&4
if eval "test \"`echo '${'ac_cv_lib_cposix'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&4
else
  ac_save_LIBS="$LIBS"
LIBS="$LIBS -lcposix "
cat > conftest.$ac_ext <<EOF
#line 2148 "configure"
#include "confdefs.h"

int main() { return 0; }
int t() {
select()
; return 0; }
EOF
if eval $ac_link; then
  rm -rf conftest*
  eval "ac_cv_lib_cposix=yes"
else
  rm -rf conftest*
  eval "ac_cv_lib_cposix=no"
fi
rm -f conftest*
LIBS="$ac_save_LIBS"

fi
if eval "test \"`echo '$ac_cv_lib_'cposix`\" = yes"; then
  echo "$ac_t""yes" 1>&4
  LIBS="$LIBS -lcposix"
else
  echo "$ac_t""no" 1>&4
echo $ac_n "checking for -lnet""... $ac_c" 1>&4
if eval "test \"`echo '${'ac_cv_lib_net'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&4
else
  ac_save_LIBS="$LIBS"
LIBS="$LIBS -lnet "
cat > conftest.$ac_ext <<EOF
#line 2179 "configure"
#include "confdefs.h"

int main() { return 0; }
int t() {
select()
; return 0; }
EOF
if eval $ac_link; then
  rm -rf conftest*
  eval "ac_cv_lib_net=yes"
else
  rm -rf conftest*
  eval "ac_cv_lib_net=no"
fi
rm -f conftest*
LIBS="$ac_save_LIBS"

fi
if eval "test \"`echo '$ac_cv_lib_'net`\" = yes"; then
  echo "$ac_t""yes" 1>&4
  LIBS="$LIBS -lnet"
else
  echo "$ac_t""no" 1>&4
echo "configure: warning: i can not find select.  you might need to help me" 1>&2
fi

fi

fi

fi

fi

fi


if test x$hpux = x1 -o x$aix = x1
then
  LIBS="-lcurses $LIBS"
  cat >> confdefs.h <<\EOF
#define USING_CURSES 1
EOF

else
  olibs="$LIBS"
  echo $ac_n "checking for -ltermcap""... $ac_c" 1>&4
if eval "test \"`echo '${'ac_cv_lib_termcap'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&4
else
  ac_save_LIBS="$LIBS"
LIBS="$LIBS -ltermcap "
cat > conftest.$ac_ext <<EOF
#line 2233 "configure"
#include "confdefs.h"

int main() { return 0; }
int t() {
tgetent()
; return 0; }
EOF
if eval $ac_link; then
  rm -rf conftest*
  eval "ac_cv_lib_termcap=yes"
else
  rm -rf conftest*
  eval "ac_cv_lib_termcap=no"
fi
rm -f conftest*
LIBS="$ac_save_LIBS"

fi
if eval "test \"`echo '$ac_cv_lib_'termcap`\" = yes"; then
  echo "$ac_t""yes" 1>&4
  LIBS="-ltermcap $olibs"
else
  echo "$ac_t""no" 1>&4
echo $ac_n "checking for -ltermlib""... $ac_c" 1>&4
if eval "test \"`echo '${'ac_cv_lib_termlib'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&4
else
  ac_save_LIBS="$LIBS"
LIBS="$LIBS -ltermlib "
cat > conftest.$ac_ext <<EOF
#line 2264 "configure"
#include "confdefs.h"

int main() { return 0; }
int t() {
tgetent()
; return 0; }
EOF
if eval $ac_link; then
  rm -rf conftest*
  eval "ac_cv_lib_termlib=yes"
else
  rm -rf conftest*
  eval "ac_cv_lib_termlib=no"
fi
rm -f conftest*
LIBS="$ac_save_LIBS"

fi
if eval "test \"`echo '$ac_cv_lib_'termlib`\" = yes"; then
  echo "$ac_t""yes" 1>&4
  LIBS="-ltermlib $olibs"
else
  echo "$ac_t""no" 1>&4
echo $ac_n "checking for -lcurses""... $ac_c" 1>&4
if eval "test \"`echo '${'ac_cv_lib_curses'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&4
else
  ac_save_LIBS="$LIBS"
LIBS="$LIBS -lcurses "
cat > conftest.$ac_ext <<EOF
#line 2295 "configure"
#include "confdefs.h"

int main() { return 0; }
int t() {
tgetent()
; return 0; }
EOF
if eval $ac_link; then
  rm -rf conftest*
  eval "ac_cv_lib_curses=yes"
else
  rm -rf conftest*
  eval "ac_cv_lib_curses=no"
fi
rm -f conftest*
LIBS="$ac_save_LIBS"

fi
if eval "test \"`echo '$ac_cv_lib_'curses`\" = yes"; then
  echo "$ac_t""yes" 1>&4
  LIBS="-lcurses $olibs"
else
  echo "$ac_t""no" 1>&4
echo $ac_n "checking for -lxtermcap""... $ac_c" 1>&4
if eval "test \"`echo '${'ac_cv_lib_xtermcap'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&4
else
  ac_save_LIBS="$LIBS"
LIBS="$LIBS -lxtermcap "
cat > conftest.$ac_ext <<EOF
#line 2326 "configure"
#include "confdefs.h"

int main() { return 0; }
int t() {
tgetent()
; return 0; }
EOF
if eval $ac_link; then
  rm -rf conftest*
  eval "ac_cv_lib_xtermcap=yes"
else
  rm -rf conftest*
  eval "ac_cv_lib_xtermcap=no"
fi
rm -f conftest*
LIBS="$ac_save_LIBS"

fi
if eval "test \"`echo '$ac_cv_lib_'xtermcap`\" = yes"; then
  echo "$ac_t""yes" 1>&4
  LIBS="-lxtermcap $olibs"
else
  echo "$ac_t""no" 1>&4
echo "configure: warning: i can not find tgetent.  you might need to help me" 1>&2
fi

fi

fi

fi

fi


echo "checking signal implimentation" 1>&4
echo $ac_n "checking for sigaction""... $ac_c" 1>&4
if eval "test \"`echo '${'ac_cv_func_sigaction'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&4
else
  cat > conftest.$ac_ext <<EOF
#line 2368 "configure"
#include "confdefs.h"
#include <ctype.h> /* Arbitrary system header to define __stub macros. */
/* Override any gcc2 internal prototype to avoid an error.  */
char sigaction(); 

int main() { return 0; }
int t() {

/* The GNU C library defines this for functions which it implements
    to always fail with ENOSYS.  Some functions are actually named
    something starting with __ and the normal name is an alias.  */
#if defined (__stub_sigaction) || defined (__stub___sigaction)
choke me
#else
sigaction();
#endif

; return 0; }
EOF
if eval $ac_link; then
  rm -rf conftest*
  eval "ac_cv_func_sigaction=yes"
else
  rm -rf conftest*
  eval "ac_cv_func_sigaction=no"
fi
rm -f conftest*

fi
if eval "test \"`echo '$ac_cv_func_'sigaction`\" = yes"; then
  echo "$ac_t""yes" 1>&4
  cat >> confdefs.h <<\EOF
#define USE_SIGACTION 1
EOF

  echo using posix signals
  
else
  echo "$ac_t""no" 1>&4
echo $ac_n "checking for sigset""... $ac_c" 1>&4
if eval "test \"`echo '${'ac_cv_func_sigset'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&4
else
  cat > conftest.$ac_ext <<EOF
#line 2413 "configure"
#include "confdefs.h"
#include <ctype.h> /* Arbitrary system header to define __stub macros. */
/* Override any gcc2 internal prototype to avoid an error.  */
char sigset(); 

int main() { return 0; }
int t() {

/* The GNU C library defines this for functions which it implements
    to always fail with ENOSYS.  Some functions are actually named
    something starting with __ and the normal name is an alias.  */
#if defined (__stub_sigset) || defined (__stub___sigset)
choke me
#else
sigset();
#endif

; return 0; }
EOF
if eval $ac_link; then
  rm -rf conftest*
  eval "ac_cv_func_sigset=yes"
else
  rm -rf conftest*
  eval "ac_cv_func_sigset=no"
fi
rm -f conftest*

fi
if eval "test \"`echo '$ac_cv_func_'sigset`\" = yes"; then
  echo "$ac_t""yes" 1>&4
  cat >> confdefs.h <<\EOF
#define USE_SIGSET 1
EOF

  echo using ok system v signals
  
else
  echo "$ac_t""no" 1>&4
echo checking for reliable signals
if test "$cross_compiling" = yes; then
  you lose.

else
cat > conftest.$ac_ext <<EOF
#line 2459 "configure"
#include "confdefs.h"

#include <sys/types.h>
#include <signal.h>

#ifndef SIGCHLD
# define SIGCHLD SIGCLD
#endif
#ifdef USE_SIGSET
# define signal sigset
#endif

int got;

#ifdef SIGVOID
void
#endif
hand()
{
  got++;
}

main()
{
  (void)signal(SIGCHLD, hand);
  kill(getpid(), SIGCHLD);
  kill(getpid(), SIGCHLD);
  if (got < 2)
    exit(1);
  exit(0);
}

EOF
eval $ac_link
if test -s conftest && (./conftest; exit) 2>/dev/null; then
  echo using bsd signals

else
  cat >> confdefs.h <<\EOF
#define SYSVSIGNALS 1
EOF

echo using system v signals
fi
fi
rm -fr conftest*
fi

fi


if test x$bsdwait = x1
then
  echo $ac_n "checking for wait3 declaration""... $ac_c" 1>&4
  cat > conftest.$ac_ext <<EOF
#line 2515 "configure"
#include "confdefs.h"
#include <sys/types.h> dnl )
#include <signal.h>
#include <sys/wait.h>

EOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
  egrep "wait3( |	|\()" >/dev/null 2>&1; then
  rm -rf conftest*
  cat >> confdefs.h <<\EOF
#define WAIT3_DECLARED 1
EOF
 echo "$ac_t""yes" 1>&4
else
  rm -rf conftest*
  echo "$ac_t""no" 1>&4
fi
rm -f conftest*

else
  echo $ac_n "checking for waitpid declaration""... $ac_c" 1>&4
  cat > conftest.$ac_ext <<EOF
#line 2538 "configure"
#include "confdefs.h"
#include <sys/types.h> dnl )
#include <signal.h>
#include <sys/wait.h>

EOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
  egrep "waitpid( |	|\()" >/dev/null 2>&1; then
  rm -rf conftest*
  cat >> confdefs.h <<\EOF
#define WAITPID_DECLARED 1
EOF
 echo "$ac_t""yes" 1>&4
else
  rm -rf conftest*
  echo "$ac_t""no" 1>&4
fi
rm -f conftest*

fi


echo $ac_n "checking for sys_errlist declaration""... $ac_c" 1>&4
if test "$cross_compiling" = yes; then
  :
else
cat > conftest.$ac_ext <<EOF
#line 2566 "configure"
#include "confdefs.h"

#include <sys/types.h>
#include <stdio.h>
#include <errno.h>
main()
{
  char *s = sys_errlist[0];
  exit(0);
}

EOF
eval $ac_link
if test -s conftest && (./conftest; exit) 2>/dev/null; then
  echo "$ac_t""yes" 1>&4
  cat >> confdefs.h <<\EOF
#define SYS_ERRLIST_DECLARED 1
EOF

else
  echo "$ac_t""no" 1>&4
fi
fi
rm -fr conftest*


echo $ac_n "checking for a 32 bit integer""... $ac_c" 1>&4
if test "$cross_compiling" = yes; then
  :
else
cat > conftest.$ac_ext <<EOF
#line 2598 "configure"
#include "confdefs.h"

main()
{
  if (4 == sizeof(unsigned long))
    exit(0);
  exit(1);
}

EOF
eval $ac_link
if test -s conftest && (./conftest; exit) 2>/dev/null; then
  echo "$ac_t""unsigned long" 1>&4
  cat >> confdefs.h <<\EOF
#define UNSIGNED_LONG32 1
EOF

else
  if test "$cross_compiling" = yes; then
  echo "$ac_t""none" 1>&4
  cat >> confdefs.h <<\EOF
#define UNKNOWN_32INT 1
EOF

else
cat > conftest.$ac_ext <<EOF
#line 2625 "configure"
#include "confdefs.h"

main()
{
  if (4 == sizeof(unsigned int))
    exit(0);
  exit(1);
}

EOF
eval $ac_link
if test -s conftest && (./conftest; exit) 2>/dev/null; then
  echo "$ac_t""unsigned int" 1>&4
else
  cat >> confdefs.h <<\EOF
#define UNSIGNED_INT32 1
EOF

fi
fi
rm -fr conftest*
fi
fi
rm -fr conftest*


if test ! -n "$libsocket"; then
	echo $ac_n "checking for -lsocket""... $ac_c" 1>&4
if eval "test \"`echo '${'ac_cv_lib_socket'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&4
else
  ac_save_LIBS="$LIBS"
LIBS="$LIBS -lsocket "
cat > conftest.$ac_ext <<EOF
#line 2660 "configure"
#include "confdefs.h"

int main() { return 0; }
int t() {
socket()
; return 0; }
EOF
if eval $ac_link; then
  rm -rf conftest*
  eval "ac_cv_lib_socket=yes"
else
  rm -rf conftest*
  eval "ac_cv_lib_socket=no"
fi
rm -f conftest*
LIBS="$ac_save_LIBS"

fi
if eval "test \"`echo '$ac_cv_lib_'socket`\" = yes"; then
  echo "$ac_t""yes" 1>&4
  LIBS="$LIBS -lsocket"
else
  echo "$ac_t""no" 1>&4
fi

fi
if test ! -n "$libinet"; then
	echo $ac_n "checking for -linet""... $ac_c" 1>&4
if eval "test \"`echo '${'ac_cv_lib_inet'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&4
else
  ac_save_LIBS="$LIBS"
LIBS="$LIBS -linet "
cat > conftest.$ac_ext <<EOF
#line 2695 "configure"
#include "confdefs.h"

int main() { return 0; }
int t() {
socket()
; return 0; }
EOF
if eval $ac_link; then
  rm -rf conftest*
  eval "ac_cv_lib_inet=yes"
else
  rm -rf conftest*
  eval "ac_cv_lib_inet=no"
fi
rm -f conftest*
LIBS="$ac_save_LIBS"

fi
if eval "test \"`echo '$ac_cv_lib_'inet`\" = yes"; then
  echo "$ac_t""yes" 1>&4
  libnsl=1; LIBS="$LIBS -linet -lnsl_s"
else
  echo "$ac_t""no" 1>&4
fi

fi
if test ! -n "$libnsl"; then
	echo $ac_n "checking for -lnsl""... $ac_c" 1>&4
if eval "test \"`echo '${'ac_cv_lib_nsl'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&4
else
  ac_save_LIBS="$LIBS"
LIBS="$LIBS -lnsl "
cat > conftest.$ac_ext <<EOF
#line 2730 "configure"
#include "confdefs.h"

int main() { return 0; }
int t() {
gethostname()
; return 0; }
EOF
if eval $ac_link; then
  rm -rf conftest*
  eval "ac_cv_lib_nsl=yes"
else
  rm -rf conftest*
  eval "ac_cv_lib_nsl=no"
fi
rm -f conftest*
LIBS="$ac_save_LIBS"

fi
if eval "test \"`echo '$ac_cv_lib_'nsl`\" = yes"; then
  echo "$ac_t""yes" 1>&4
  LIBS="$LIBS -lnsl"
else
  echo "$ac_t""no" 1>&4
fi

fi
echo $ac_n "checking for -ldgc""... $ac_c" 1>&4
if eval "test \"`echo '${'ac_cv_lib_dgc'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&4
else
  ac_save_LIBS="$LIBS"
LIBS="$LIBS -ldgc "
cat > conftest.$ac_ext <<EOF
#line 2764 "configure"
#include "confdefs.h"

int main() { return 0; }
int t() {
inet_addr()
; return 0; }
EOF
if eval $ac_link; then
  rm -rf conftest*
  eval "ac_cv_lib_dgc=yes"
else
  rm -rf conftest*
  eval "ac_cv_lib_dgc=no"
fi
rm -f conftest*
LIBS="$ac_save_LIBS"

fi
if eval "test \"`echo '$ac_cv_lib_'dgc`\" = yes"; then
  echo "$ac_t""yes" 1>&4
  LIBS="$LIBS -ldgc"
else
  echo "$ac_t""no" 1>&4
fi

echo $ac_n "checking for -lresolv""... $ac_c" 1>&4
if eval "test \"`echo '${'ac_cv_lib_resolv'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&4
else
  ac_save_LIBS="$LIBS"
LIBS="$LIBS -lresolv "
cat > conftest.$ac_ext <<EOF
#line 2797 "configure"
#include "confdefs.h"

int main() { return 0; }
int t() {
gethostbyname()
; return 0; }
EOF
if eval $ac_link; then
  rm -rf conftest*
  eval "ac_cv_lib_resolv=yes"
else
  rm -rf conftest*
  eval "ac_cv_lib_resolv=no"
fi
rm -f conftest*
LIBS="$ac_save_LIBS"

fi
if eval "test \"`echo '$ac_cv_lib_'resolv`\" = yes"; then
  echo "$ac_t""yes" 1>&4
  olibs=$LIBS
  LIBS="$LIBS -lresolv"
  if test "$cross_compiling" = yes; then
  :
else
cat > conftest.$ac_ext <<EOF
#line 2824 "configure"
#include "confdefs.h"

#include <netdb.h>
main()
{
  struct hostent *hp;

  hp = gethostbyname("foo");
  exit(0);
}

EOF
eval $ac_link
if test -s conftest && (./conftest; exit) 2>/dev/null; then
  :
else
  LIBS=$olibs
fi
fi
rm -fr conftest*
else
  echo "$ac_t""no" 1>&4
fi


echo "generating a list of signal names..."
set X `cat /usr/include/signal.h /usr/include/sys/signal.h 2>&1 | awk '
$1 ~ /^#define$/ && $2 ~ /^SIG[A-Z0-9]*$/ && $3 ~ /^[1-9][0-9]*$/ {
  sig[$3] = substr($2,4,20)
  if (max < $3 && $3 < 60) {
	max = $3
  }
}

END {
  for (i=1; i<=max; i++) {
    if (sig[i] == "")
      printf "%d", i
    else
      printf "%s", sig[i]
    if (i < max)
      printf " "
  }
  printf "\n"
}
'`
shift
case $# in
0)
  set X `kill -l 2> /dev/null`
  shift
  case $# in
  0) set HUP INT QUIT ILL TRAP IOT EMT FPE KILL BUS SEGV SYS PIPE ALRM TERM
    ;;
  esac
  ;;
esac
sig_name="ZERO $*"
if test -f source/sig.inc; then
  /bin/rm -f source/sig.inc
fi
echo $sig_name | sed -e 's/$/"};/' -e 's/ /", "/g' -e 's/^/char *signals[] = { "/' >> source/sig.inc


echo $ac_n "checking for unix mail directory""... $ac_c" 1>&4

for foo in /var/spool/mail /usr/spool/mail /var/mail /usr/mail
do
  if test -d $foo; then
    mdir=$foo
    break
  fi
done

if test -n "$mdir"; then
  UNIX_MAIL=\"$mdir\"
else
  UNIX_MAIL=\"unknown\"
fi

echo "$ac_t""$mdir" 1>&4

cat >> confdefs.h <<EOF
#define UNIX_MAIL "$mdir"
EOF


if test -z "$CFLAGS"; then CFLAGS=-O ; fi
if test -z "$LDFLAGS"; then LDFLAGS= ; fi
RM="rm -f"
LN="ln -s"

if test ! -n "$bindir";
then
	bindir=\${exec_prefix}/bin
fi

if test ! -n "$IRCLIB";
then
	IRCLIB=\${prefix}/lib/irc
fi

if test -n "$nextstep"; then
  LIBS=`echo $LIBS | sed -e 's/-lposix/-lsys_s -lposix/'`
fi





trap '' 1 2 15
if test -w $cache_file; then
echo "updating cache $cache_file"
cat > $cache_file <<\EOF
# This file is a shell script that caches the results of configure
# tests run on this system so they can be shared between configure
# scripts and configure runs.  It is not useful on other systems.
# If it contains results you don't want to keep, you may remove or edit it.
#
# By default, configure uses ./config.cache as the cache file,
# creating it if it does not exist already.  You can give configure
# the --cache-file=FILE option to use a different cache file; that is
# what configure does when it calls configure scripts in
# subdirectories, so they share the cache.
# Giving --cache-file=/dev/null disables caching, for debugging configure.
# config.status only pays attention to the cache file if you give it the
# --recheck option to rerun configure.
#
EOF
# Ultrix sh set writes to stderr and can't be redirected directly.
(set) 2>&1 |
  sed -n "s/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/: \${\1='\2'}/p" \
  >> $cache_file
else
echo "not updating unwritable cache $cache_file"
fi

trap 'rm -fr conftest* confdefs* core $ac_clean_files; exit 1' 1 2 15

test "x$prefix" = xNONE && prefix=$ac_default_prefix
# Let make expand exec_prefix.
test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'

# Any assignment to VPATH causes Sun make to only execute
# the first set of double-colon rules, so remove it if not needed.
# If there is a colon in the path, we need to keep it.
if test "x$srcdir" = x.; then
  ac_vpsub='/^[ 	]*VPATH[ 	]*=[^:]*$/d'
fi

trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15

DEFS=-DHAVE_CONFIG_H

# Without the "./", some shells look in PATH for config.status.
: ${CONFIG_STATUS=./config.status}

echo creating $CONFIG_STATUS
rm -f $CONFIG_STATUS
cat > $CONFIG_STATUS <<EOF
#!/bin/sh
# Generated automatically by configure.
# Run this file to recreate the current configuration.
# This directory was configured as follows,
# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
#
# $0 $ac_configure_args
#
# Compiler output produced by configure, useful for debugging
# configure, is in ./config.log if it exists.

ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
for ac_option
do
  case "\$ac_option" in
  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
    echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
    exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
  -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
    echo "$CONFIG_STATUS generated by autoconf version 2.1"
    exit 0 ;;
  -help | --help | --hel | --he | --h)
    echo "\$ac_cs_usage"; exit 0 ;;
  *) echo "\$ac_cs_usage"; exit 1 ;;
  esac
done

ac_given_srcdir=$srcdir

trap 'rm -fr Makefile source/Makefile include/defs.h conftest*; exit 1' 1 2 15

# Protect against being on the right side of a sed subst in config.status. 
sed 's/%@/@@/; s/@%/@@/; s/%g$/@g/; /@g$/s/[\\\\&%]/\\\\&/g; 
 s/@@/%@/; s/@@/@%/; s/@g$/%g/' > conftest.subs <<\CEOF
$ac_vpsub
$extrasub
s%@CFLAGS@%$CFLAGS%g
s%@CPPFLAGS@%$CPPFLAGS%g
s%@CXXFLAGS@%$CXXFLAGS%g
s%@DEFS@%$DEFS%g
s%@LDFLAGS@%$LDFLAGS%g
s%@LIBS@%$LIBS%g
s%@exec_prefix@%$exec_prefix%g
s%@prefix@%$prefix%g
s%@program_transform_name@%$program_transform_name%g
s%@VERSION@%$VERSION%g
s%@CC@%$CC%g
s%@CPP@%$CPP%g
s%@LEX@%$LEX%g
s%@LEXLIB@%$LEXLIB%g
s%@RM@%$RM%g
s%@LN@%$LN%g
s%@IRCLIB@%$IRCLIB%g
s%@bindir@%$bindir%g

CEOF
EOF
cat >> $CONFIG_STATUS <<EOF

CONFIG_FILES=\${CONFIG_FILES-"Makefile source/Makefile"}
EOF
cat >> $CONFIG_STATUS <<\EOF
for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
  # Support "outfile[:infile]", defaulting infile="outfile.in".
  case "$ac_file" in
  *:*) ac_file_in=`echo "$ac_file"|sed 's%.*:%%'`
       ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
  *) ac_file_in="${ac_file}.in" ;;
  esac

  # Adjust relative srcdir, etc. for subdirectories.

  # Remove last slash and all that follows it.  Not all systems have dirname.
  ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
  if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
    # The file is in a subdirectory.
    test ! -d "$ac_dir" && mkdir "$ac_dir"
    ac_dir_suffix="/$ac_dir"
    # A "../" for each directory in $ac_dir_suffix.
    ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
  else
    ac_dir_suffix= ac_dots=
  fi

  case "$ac_given_srcdir" in
  .)  srcdir=.
      if test -z "$ac_dots"; then top_srcdir=.
      else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
  /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
  *) # Relative path.
    srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
    top_srcdir="$ac_dots$ac_given_srcdir" ;;
  esac

  echo creating "$ac_file"
  rm -f "$ac_file"
  configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
  case "$ac_file" in
  *Makefile*) ac_comsub="1i\\
# $configure_input" ;;
  *) ac_comsub= ;;
  esac
  sed -e "$ac_comsub
s%@configure_input@%$configure_input%g
s%@srcdir@%$srcdir%g
s%@top_srcdir@%$top_srcdir%g
" -f conftest.subs $ac_given_srcdir/$ac_file_in > $ac_file
fi; done
rm -f conftest.subs

# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where
# NAME is the cpp macro being defined and VALUE is the value it is being given.
#
# ac_d sets the value in "#define NAME VALUE" lines.
ac_dA='s%^\([ 	]*\)#\([ 	]*define[ 	][ 	]*\)'
ac_dB='\([ 	][ 	]*\)[^ 	]*%\1#\2'
ac_dC='\3'
ac_dD='%g'
# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE".
ac_uA='s%^\([ 	]*\)#\([ 	]*\)undef\([ 	][ 	]*\)'
ac_uB='\([ 	]\)%\1#\2define\3'
ac_uC=' '
ac_uD='\4%g'
# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
ac_eA='s%^\([ 	]*\)#\([ 	]*\)undef\([ 	][ 	]*\)'
ac_eB='$%\1#\2define\3'
ac_eC=' '
ac_eD='%g'

CONFIG_HEADERS=${CONFIG_HEADERS-"include/defs.h"}
for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then
  # Support "outfile[:infile]", defaulting infile="outfile.in".
  case "$ac_file" in
  *:*) ac_file_in=`echo "$ac_file"|sed 's%.*:%%'`
       ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
  *) ac_file_in="${ac_file}.in" ;;
  esac

  echo creating $ac_file

  rm -f conftest.frag conftest.in conftest.out
  cp $ac_given_srcdir/$ac_file_in conftest.in

EOF

# Transform confdefs.h into a sed script conftest.vals that substitutes
# the proper values into config.h.in to produce config.h.  And first:
# Protect against being on the right side of a sed subst in config.status. 
# Protect against being in an unquoted here document in config.status.
rm -f conftest.vals
cat > conftest.hdr <<\EOF
s/[\\&%]/\\&/g
s%[\\$`]%\\&%g
s%#define \([A-Za-z_][A-Za-z0-9_]*\) \(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp
s%ac_d%ac_u%gp
s%ac_u%ac_e%gp
EOF
sed -n -f conftest.hdr confdefs.h > conftest.vals
rm -f conftest.hdr

# This sed command replaces #undef with comments.  This is necessary, for
# example, in the case of _POSIX_SOURCE, which is predefined and required
# on some systems where configure will not decide to define it.
cat >> conftest.vals <<\EOF
s%^[ 	]*#[ 	]*undef[ 	][ 	]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */%
EOF

# Break up conftest.vals because some shells have a limit on
# the size of here documents, and old seds have small limits too.
# Maximum number of lines to put in a single here document.
ac_max_here_lines=12

rm -f conftest.tail
while :
do
  ac_lines=`grep -c . conftest.vals`
  # grep -c gives empty output for an empty file on some AIX systems.
  if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi
  # Write a limited-size here document to conftest.frag.
  echo '  cat > conftest.frag <<CEOF' >> $CONFIG_STATUS
  sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS
  echo 'CEOF
  sed -f conftest.frag conftest.in > conftest.out
  rm -f conftest.in
  mv conftest.out conftest.in
' >> $CONFIG_STATUS
  sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail
  rm -f conftest.vals
  mv conftest.tail conftest.vals
done
rm -f conftest.vals

cat >> $CONFIG_STATUS <<\EOF
  rm -f conftest.frag conftest.h
  echo "/* $ac_file.  Generated automatically by configure.  */" > conftest.h
  cat conftest.in >> conftest.h
  rm -f conftest.in
  if cmp -s $ac_file conftest.h 2>/dev/null; then
    echo "$ac_file is unchanged"
    rm -f conftest.h
  else
    rm -f $ac_file
    mv conftest.h $ac_file
  fi
fi; done



exit 0
EOF
chmod +x $CONFIG_STATUS
rm -fr confdefs* $ac_clean_files
test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS


echo
echo well there we are, you now might want to look in include/config.h
echo and see if there is anything you might want to tune, else you can
echo just run a make here..  good luck!
echo

gure does when it calls configure scripts in
# subdirectories, so they share the caDarkNET-1.08/ircii-2.8.H1/configure.in                                                                 644   21270   21270        25007  5710725530  12265                                                                                                                                                                                                                                                                                                                                                                      dnl configure.in for ircii, 2.3.  copyright (c) matthew green, 1993,
dnl except those bits attributed otherwise.
dnl thanks to the screen 3.3 configure.in for giving me examples to
dnl work from and steal ;)
dnl
dnl @(#)$Id: configure.in,v 1.47 1995/01/23 13:12:56 mrg Exp $

AC_REVISION($Revision: 1.47 $)dnl
AC_INIT(source/irc.c)
AC_CONFIG_HEADER(include/defs.h)

dnl
dnl grok the version number - from source/irc.c
dnl

VERSION=`sed -n -e 's/"$//' -e '/#define IRCII_VERSION	*"/s///p' -e '/#define IRCII_VERSION/q' < source/irc.c` 
echo this is ircii version $VERSION
echo
AC_SUBST(VERSION)

dnl
dnl initial stuff
dnl

AC_PROG_CC
AC_PROG_CPP
AC_ISC_POSIX

dnl
dnl check for NeXT.. and -bsd switch
dnl

AC_MSG_CHECKING(for NeXT)
AC_EGREP_CPP(yes,
[#if defined(NeXT) || defined(__NeXT) || defined(__NeXT__)
  yes
#endif
],nextstep=1)

if test -n "$nextstep"; then
  AC_MSG_RESULT(yes)
  CFLAGS="$CFLAGS -posix"
  LIBS="$LIBS -lposix"
else
  AC_MSG_RESULT(no)
fi

dnl AC_AIX is broken.  blah.

AC_MSG_CHECKING(for AIX)
AC_EGREP_CPP(yes,
[
#ifdef _AIX
  yes
#endif
],AC_MSG_RESULT(yes)
  aix=1
  AC_DEFINE(_ALL_SOURCE),
  AC_MSG_RESULT(no))

AC_PROG_LEX
AC_PROG_GCC_TRADITIONAL
AC_CHECK_LIB(sun, getpwnam)

AC_MSG_CHECKING(for qnx)
case "$(uname -s)" in
  QNX*)
    AC_MSG_RESULT(yes)
    LDFLAGS=-N64k                  dnl 64k of stack
    CFLAGS="-w4 -O -g -fi=unix.h"  dnl better compile options
  ;;
  *)
    AC_MSG_RESULT(no)
esac

AC_MSG_CHECKING(for solaris)
if /bin/sun 2> /dev/null
then
  uname=`uname -r`
  case "$uname" in
    4.*)
      AC_MSG_RESULT(no) 
      ;;
    5.*)
      AC_MSG_RESULT(yes)
      AC_DEFINE(__solaris__)
      AC_DEFINE(SVR4)
      svr4=1
      ;;
  esac
else
  AC_MSG_RESULT(no)
  AC_MSG_CHECKING(for SVR4)
  AC_EGREP_CPP(yes,
[#if defined(SVR4) || defined(__svr4__)
  yes
#endif
],svr4=1)
fi

if test -n "$svr4"
then
  AC_MSG_RESULT(yes)
  LIBS="-L/usr/ccs/lib $LIBS"
  AC_DEFINE(SVR4)
else
  AC_MSG_RESULT(no)
fi

dnl
dnl testing for svr3/wollengong tcp's /usr/netinclude
dnl

AC_MSG_CHECKING(for -I/usr/netinclude)
if test -d /usr/netinclude; then
  AC_MSG_RESULT(yes)
  CFLAGS="$CFLAGS -I/usr/netinclude"
else
  AC_MSG_RESULT(no)
fi
  
AC_CHECK_HEADERS(sys/un.h sys/select.h sys/fcntl.h sys/file.h sys/time.h sys/wait.h sys/twg_config.h sys/ptem.h)dnl sys/ ones
AC_CHECK_HEADERS(stdarg.h unistd.h fcntl.h string.h memory.h netdb.h limits.h)dnl non sys/ ones
AC_CHECK_FUNC(setsid, AC_DEFINE(HAVE_SETSID),)
AC_CHECK_FUNC(getpgid, AC_DEFINE(HAVE_GETPGID),)
AC_CHECK_FUNC(getsid, AC_DEFINE(HAVE_GETSID),)
AC_CHECK_FUNC(scandir, AC_DEFINE(HAVE_SCANDIR),)
AC_CHECK_FUNC(memmove, AC_DEFINE(HAVE_MEMMOVE),)
AC_CHECK_FUNC(uname, AC_DEFINE(HAVE_UNAME),)
AC_CHECK_FUNC(getcwd,, AC_DEFINE(NEED_GETCWD))
AC_CHECK_FUNC(fchmod,, AC_DEFINE(NEED_FCHMOD))
AC_CHECK_FUNC(strerror,, AC_DEFINE(NEED_STRERROR))
AC_HEADER_STDC
AC_HEADER_TIME
AC_HEADER_DIRENT
AC_TYPE_SIGNAL
AC_TYPE_MODE_T
AC_TYPE_PID_T
AC_TYPE_SIZE_T
AC_TYPE_UID_T

if test x$ac_cv_header_sys_twg_config_h = xyes
then
  AC_DEFINE(WINS)
fi

dnl
dnl check for hpux, and hpux version
dnl

AC_MSG_CHECKING(for hpux version)
if test -f /hp-ux; then
  AC_MSG_RESULT(yes)
  hpux=1
  uname=`uname -r` 2> /dev/null
  case $uname in
	A.09* | A.9* | a.9* | a.09* | 9* | 09*)
		;;
	A.08* | A.8* | a.8* | a.08* | 8* | 08*)
		AC_DEFINE(HPUX8)
		;;
	A.07* | A.B7* | A.7* | a.7* | a.07* | 7* | 07*)
		AC_DEFINE(HPUX7)
		;;
	*)
		AC_DEFINE(HPUXUNKNOWN)
		;;
  esac
else
  AC_MSG_RESULT(no)
fi

dnl
dnl do ultrix/posix stuff
dnl

AC_MSG_CHECKING(for ultrix)
AC_EGREP_CPP(yes,
[#if defined(ultrix) || defined(__ultrix) || defined(__ultrix)
  yes
#endif
], ultrix=1)

if test -n "$ultrix"; then
  AC_MSG_RESULT(yes)
  test -z "$GCC" && CC="$CC -YBSD"
else
  AC_MSG_RESULT(no)
  # POSIX termios is broken on Ultrix so don't look for it.
AC_MSG_CHECKING(for POSIX.1)
AC_EGREP_CPP(yes,
[#include <sys/types.h>
#include <unistd.h>
main () {
#ifdef _POSIX_VERSION
  yes
#endif
}
], AC_DEFINE(POSIX) AC_MSG_RESULT(yes); posix=1, AC_MSG_RESULT(no))
fi

dnl
dnl check for ptx
dnl

AC_MSG_CHECKING(for sequent/ptx)
AC_EGREP_CPP(yes,
[#ifdef _SEQUENT_
  yes
#endif
], LIBS="$LIBS -lseq" seqptx=1 AC_MSG_RESULT(yes), AC_MSG_RESULT(no))

dnl
dnl check for struct linger
dnl

AC_MSG_CHECKING(for struct linger)
AC_EGREP_HEADER([struct( |	)*linger], sys/socket.h, AC_MSG_RESULT(yes), AC_DEFINE(NO_STRUCT_LINGER) AC_MSG_RESULT(no, ugh.))

dnl
dnl grok process groups
dnl

if test x$ac_cv_func_getsid != xyes && test x$ac_cv_func_getpgid != xyes
then
  AC_MSG_CHECKING(if getpgrp takes an argument)
  AC_TRY_RUN([
main()
{
  int pid;
  int pgid;

  pid = fork();

  if (0 == pid)
  {
#ifdef HAVE_SETSID
    setsid();
#else
    setpgrp(0, getpid());
#endif /* HAVE_SETSID */
    sleep(10);
  }
  else
  {
    sleep(2);
    pgid = getpgrp(pid);
    kill(pid,9);
    if (pid != pgid)
      exit(1);
  }
  exit(0);
}
],
  AC_MSG_RESULT(yes),
  AC_MSG_RESULT(no your getpgrp is painful)
  AC_DEFINE(BROKEN_GETPGRP), :)
fi

dnl
dnl work out wait type..
dnl

if test x$posix != x1
then
AC_MSG_CHECKING(for bsd wait)
AC_TRY_LINK([
#include <sys/types.h>
#include <sys/wait.h>
],[
  union wait x;
  int y;
#ifdef WEXITSTATUS
  y = WEXITSTATUS(x);
#endif
],
  AC_DEFINE(BSDWAIT)
  bsdwait=1
  AC_MSG_RESULT(yes),
  AC_MSG_RESULT(no)
  AC_CHECK_FUNC(waitpid,,
    AC_DEFINE(NEED_WAITPID)))
fi

dnl
dnl checking for select()
dnl

olibs="$LIBS"
AC_CHECK_FUNC(select, ,
  AC_CHECK_LIB(socket, select, LIBS="$LIBS -lsocket",
    AC_CHECK_LIB(nsl, select, LIBS="$LIBS -lnsl",
      AC_CHECK_LIB(inet, select, LIBS="$LIBS -linet",
        AC_CHECK_LIB(cposix, select, LIBS="$LIBS -lcposix",
          AC_CHECK_LIB(net, select, LIBS="$LIBS -lnet",
            AC_MSG_WARN(i can not find select.  you might need to help me)))))))

dnl
dnl termcap or curses
dnl
if test x$hpux = x1 -o x$aix = x1
then
  LIBS="-lcurses $LIBS"
  AC_DEFINE(USING_CURSES)
else
  olibs="$LIBS"
  AC_CHECK_LIB(termcap, tgetent, LIBS="-ltermcap $olibs",
    AC_CHECK_LIB(termlib, tgetent, LIBS="-ltermlib $olibs",
      AC_CHECK_LIB(curses, tgetent, LIBS="-lcurses $olibs",
        AC_CHECK_LIB(xtermcap, tgetent, LIBS="-lxtermcap $olibs",
          AC_MSG_WARN(i can not find tgetent.  you might need to help me)))))
fi

dnl
dnl signal handling
dnl

AC_CHECKING(signal implimentation)
AC_CHECK_FUNC(sigaction, AC_DEFINE(USE_SIGACTION)
  echo using posix signals
  ,
  AC_CHECK_FUNC(sigset, AC_DEFINE(USE_SIGSET)
  echo using ok system v signals
  ,

echo checking for reliable signals
AC_TRY_RUN([
#include <sys/types.h>
#include <signal.h>

#ifndef SIGCHLD
# define SIGCHLD SIGCLD
#endif
#ifdef USE_SIGSET
# define signal sigset
#endif

int got;

#ifdef SIGVOID
void
#endif
hand()
{
  got++;
}

main()
{
  (void)signal(SIGCHLD, hand);
  kill(getpid(), SIGCHLD);
  kill(getpid(), SIGCHLD);
  if (got < 2)
    exit(1);
  exit(0);
}
], 
echo using bsd signals
, AC_DEFINE(SYSVSIGNALS)
echo using system v signals, you lose.
)))

if test x$bsdwait = x1
then
  AC_MSG_CHECKING(for wait3 declaration)
  AC_EGREP_CPP([wait3( |	|\()],[#include <sys/types.h> dnl )
#include <signal.h>
#include <sys/wait.h>
], AC_DEFINE(WAIT3_DECLARED) AC_MSG_RESULT(yes), AC_MSG_RESULT(no))
else
  AC_MSG_CHECKING(for waitpid declaration)
  AC_EGREP_CPP([waitpid( |	|\()],[#include <sys/types.h> dnl )
#include <signal.h>
#include <sys/wait.h>
], AC_DEFINE(WAITPID_DECLARED) AC_MSG_RESULT(yes), AC_MSG_RESULT(no))
fi

dnl
dnl check for sys_errlist declaration
dnl

AC_MSG_CHECKING(for sys_errlist declaration)
AC_TRY_RUN([
#include <sys/types.h>
#include <stdio.h>
#include <errno.h>
main()
{
  char *s = sys_errlist[0];
  exit(0);
}
],
  AC_MSG_RESULT(yes)
  AC_DEFINE(SYS_ERRLIST_DECLARED),
  AC_MSG_RESULT(no), :)

dnl
dnl need this for dcc stuff
dnl

AC_MSG_CHECKING(for a 32 bit integer)
AC_TRY_RUN([
main()
{
  if (4 == sizeof(unsigned long))
    exit(0);
  exit(1);
}
],
  AC_MSG_RESULT(unsigned long)
  AC_DEFINE(UNSIGNED_LONG32),
  AC_TRY_RUN([
main()
{
  if (4 == sizeof(unsigned int))
    exit(0);
  exit(1);
}
],
  AC_MSG_RESULT(unsigned int),
  AC_DEFINE(UNSIGNED_INT32),
  AC_MSG_RESULT(none, using unsigned long)
  AC_DEFINE(UNKNOWN_32INT)), :)

dnl
dnl libraries
dnl

dnl i think this was only needed for solaris with -lucb.
dnl AC_HAVE_LIBRARY(elf, LIBS="$LIBS -lelf",)
dnl AC_HAVE_LIBRARY(nls, libnls=1;AC_DEFINE(HAVE_LIB_NLS),)
if test ! -n "$libsocket"; then
	AC_CHECK_LIB(socket, socket, LIBS="$LIBS -lsocket",)
fi
dnl this is for isc.  need the nsl_s library as well.
if test ! -n "$libinet"; then
	AC_CHECK_LIB(inet, socket, libnsl=1; LIBS="$LIBS -linet -lnsl_s",)
fi
if test ! -n "$libnsl"; then
	AC_CHECK_LIB(nsl, gethostname, LIBS="$LIBS -lnsl",)
fi
AC_CHECK_LIB(dgc, inet_addr, LIBS="$LIBS -ldgc",)
AC_CHECK_LIB(resolv, gethostbyname,
  olibs=$LIBS
  LIBS="$LIBS -lresolv"
  AC_TRY_RUN([
#include <netdb.h>
main()
{
  struct hostent *hp;

  hp = gethostbyname("foo");
  exit(0);
}
],,LIBS=$olibs, :))
dnl AC_HAVE_LIBRARY(PW, LIBS="$LIBS -lPW",)

dnl this is all stolen from perl-4.036's Configure.  larry is god.
echo "generating a list of signal names..."
set X `cat /usr/include/signal.h /usr/include/sys/signal.h 2>&1 | awk '
$1 ~ /^#define$/ && $2 ~ /^SIG[A-Z0-9]*$/ && $3 ~ /^[1-9][0-9]*$/ {
  [sig[$3] = substr($2,4,20)]
  if (max < $3 && $3 < 60) {
	max = $3
  }
}

END {
  for (i=1; i<=max; i++) {
    [if (sig[i] == "")]
      printf "%d", i
    else
      [printf "%s", sig[i]]
    if (i < max)
      printf " "
  }
  printf "\n"
}
'`
shift
case $# in
0)
  set X `kill -l 2> /dev/null`
  shift
  case $# in
  0) set HUP INT QUIT ILL TRAP IOT EMT FPE KILL BUS SEGV SYS PIPE ALRM TERM
    ;;
  esac
  ;;
esac
sig_name="ZERO $*"
if test -f source/sig.inc; then
  /bin/rm -f source/sig.inc
fi
[echo $sig_name | sed -e 's/$/"};/' -e 's/ /", "/g' -e 's/^/char *signals[] = { "/' >> source/sig.inc]

dnl work out UNIX mail dir..

AC_MSG_CHECKING(for unix mail directory)

for foo in /var/spool/mail /usr/spool/mail /var/mail /usr/mail
do
  if test -d $foo; then
    mdir=$foo
    break
  fi
done

if test -n "$mdir"; then
  UNIX_MAIL=\"$mdir\"
else
  UNIX_MAIL=\"unknown\"
fi

AC_MSG_RESULT($mdir)

AC_DEFINE_UNQUOTED(UNIX_MAIL, "$mdir")

if test -z "$CFLAGS"; then CFLAGS=-O ; fi
if test -z "$LDFLAGS"; then LDFLAGS= ; fi
RM="rm -f"
LN="ln -s"

if test ! -n "$bindir";
then
	bindir=\${exec_prefix}/bin
fi

if test ! -n "$IRCLIB";
then
	IRCLIB=\${prefix}/lib/irc
fi

if test -n "$nextstep"; then
  LIBS=`echo $LIBS | sed -e 's/-lposix/-lsys_s -lposix/'`
fi

AC_SUBST(RM)
AC_SUBST(LN)
AC_SUBST(IRCLIB)
AC_SUBST(bindir)
AC_OUTPUT(Makefile source/Makefile)

echo
echo well there we are, you now might want to look in include/config.h
echo and see if there is anything you might want to tune, else you can
echo just run a make here..  good luck!
echo

DEFINE(HAVE_SCANDIR),)
AC_CHECK_FUNC(memmove, AC_DEFINE(HAVE_MEMMOVE),)
AC_CHECK_FUNC(uname, AC_DEFINE(HAVE_UNAME),)
AC_CHECK_FUNC(getcwd,, AC_DEFINE(NEED_GETCWD))
AC_CHECK_FUNC(fchmod,, AC_DEFINE(NEED_FCHMOD))
AC_CHECK_FUNC(strerror,, AC_DEFINE(NEED_STRERROR))
AC_HEADER_STDC
AC_HEADER_TIME
AC_HEADER_DIRENT
AC_TYPE_SIGNAL
AC_TYPE_MODE_T
AC_TYPE_PID_T
AC_TYPE_SIZE_T
AC_TYPE_UID_T

if test x$ac_cv_header_sys_twg_config_h = xyes
then
  AC_DEFINE(WINS)
fi

dnl
dnl check for hpux, and hpux version
dnl

ACDarkNET-1.08/ircii-2.8.H1/easyinst                                                                     755   21270   21270        26015  5667563276  11563                                                                                                                                                                                                                                                                                                                                                                      #!/bin/sh
#
# this script is a front end to `configure' which also asks a few
# other questions such as default server, help service, etc.
# $Id: easyinst,v 2.10 1994/12/02 09:19:58 mrg stable $
#
# $defserver
# $sysinstall (exists and is nonempty if system install)
# $prefix
# $bindir
# $libdir
# $help_service
#
# Eventually, if $HOME/.irc.easyinst.status defines no previous $libdir,
# and the environment variable $IRCLIB is set and non-nul,
# $libdir will default to that.
#

#
# Check if this is run through sh...
#
export PATH || \
(echo "This shell does not look like sh... buggy OS."; sh $0; kill $$)

#
# List of HELP SERVICES
#
help_services="NULL IrcIIhelp help_US help_UK help_AU help_EU"

#
# File to save configuration in...
#

# I guess root doesn't want a /.irc.easyinst.status file created
if test -w /; then
  savefile=/tmp/irc.easyinst.status
else
  savefile=$HOME/.irc.easyinst.status
fi

#
# The famous "no default" string
#
nodef="no default"

#
# Checking out how to suppress new lines...
#
if [ "`echo -n a`" = "a" ]; then
  n='-n'
  c=''
else
  n=''
  c='\c'
fi

#
# Set up ~user expansion
cat >.tildexp <<EOF
#!/bin/sh
case "\$1" in
~/*|~)
  echo \$1 | $sed "s|~|\${HOME-\$LOGDIR}|"
  ;;
~*)
  if test -f /bin/csh; then
    /bin/csh -f -c "glob \$1"
    failed=$?
    echo ""
    exit \$failed
  else
    name=\`$expr x\$1 : '..\([^/]*\)'\`
    dir=\`$sed -n -e "/^\${name}:/{s/^[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:\([^:]*\).*"'\$'"/\1/" -e p -e q -e '}' </etc/passwd\`
    if test ! -d "\$dir"; then
      me=\`basename \$0\`
      echo "\$me: can't locate home directory for: \$name" \>\&2
      exit 1
    fi
    case "\$1" in
    */*)
      echo \$dir/\`$expr x\$1 : '..[^/]*/\(.*\)'\`
      ;;
    *)
      echo \$dir
      ;;
    esac
  fi
  ;;
*)
  echo \$1
  ;;
esac
EOF
chmod a+x .tildexp

#
# Set up shell script to read input
#
myecho="case \"\$xxxm\" in
'') echo $n \"\$rp $c\" >&4;;
*)  case \"\$rp\" in
  '') echo $n \"[\$xxxm] $c\";;
  *)
    if test \`echo \"\$rp [\$xxxm]  \" | wc -c\` -ge ${COLUMNS-80}; then
      echo \"\$rp\" >&4
      echo $n \"[\$xxxm] $c\" >&4
    else
      echo $n \"\$rp [\$xxxm] $c\" >&4
    fi
    ;;
  esac;;
esac"
cat <<EOF > .myread
xxxm=\$dflt
$myecho
ans='!'
case "\$fastread" in
yes) case "\$dflt" in
  '') ;;
  *) ans='';
    case "\$silent-\$rp" in
    true-) ;;
    *) echo " " >&4;;
    esac;;
  esac;;
*) case "\$silent" in
  true) case "\$rp" in
    '') ans='';;
    esac;;
  esac;;
esac
while expr "X\$ans" : "X!" >/dev/null; do
  read answ
  set x \$xxxm
  shift
  aok=''; eval "ans=\"\$answ\"" && aok=y
  case  "\$answ" in
  "\$ans")
    case "\$ans" in
    "!")
      sh 1>&4
      echo " "
      $myecho
      ;;
    !*)
      set x \`expr "X\$ans" : "X!\(.*\)\$"\`
      shift
      sh 1>&4 -c "\$*"
      echo " "
      $myecho
      ;;
    esac;;
  *)
    case "\$aok" in
    y)
      echo "*** Substitution done -- please confirm."
      xxxm="\$ans"
      ans=\`echo $n "\$ans$c" | tr '\012' ' '\`
      xxxm="\$ans"
      ans=!
      ;;
    *)
      echo "*** Error -- try again."
      ans=!
      ;;
    esac
    $myecho
    ;;
  esac
  case "\$ans\$xxxm\$nostick" in
  '')
    ans=!
    $myecho
    ;;
  esac
done
case "\$ans" in
'') ans="\$xxxm";;
esac
EOF

trapdeletefiles=".myread .tildexp"

trap '{
  exitstat=$?
  rm -f $trapdeletefiles
  trap "" 0
  echo "Aborting... cleaning up." >&2
  exit $exitstat
}' 0 1 2 15

# Prepare redirection for "silent" mode (to be implemented :)
exec 4>&1

cat << EOF

Welcome to the easy install script.

I will ask you a few questions. Most of the time, a default value will
be printed, and you'll just need to hit the 'Return' key to confirm.
If you get stuck on a question, you may use a ! shell escape to start
a subshell or execute a !command.

Some questions asking for file or directory names allow the use of the ~user
construct to specify the login directory belonging to "user", even if you
don't have a shell which knows about that. They'll be marked "(~user ok)".

The prompter used in this script allows you to use shell variables and
backticks in your answers.  You may use \$1, \$2, etc...  to refer to the words
in the default answer, as if the default line was a set of arguments given to a
script shell.  This means you may also use \$@ to repeat the whole default line,
so you do not have to re-type everything to add something to the default.

Everytime there is a substitution, you will have to confirm.  If there is an
error (e.g. an unmatched backtick), the default answer will remain unchanged
and you will be prompted again.

If you are satisfied with your choices, I will then run a script for you
to work out some of the hairier parts of your system. Good luck!
EOF
dflt="Press 'Return' to go on"
. ./.myread

#
# Trick to load old easyinst values :)
#
if test -r "$savefile"; then
  echo "
I see a $savefile file."
  dflt="y"
  rp="Do you want to use it to set the defaults?"
  . ./.myread
  case "$ans" in
  n*|N*) echo "Ignoring $savefile." ;;
  *)
    echo "Loading previous easyinst choices..."
    trap "{
      rm -f $savefile
      echo 'Fatal error. Please restart easyinst.' >&2
    }" 0
    . $savefile || \
      (
        echo 'Fatal error. Please restart easyinst.' >&2
        rm -f $savefile
        kill $$ \$\$
      )
    ;;
  esac
  trap 0
fi

# Because the previous branch as squished the trap on exit
trap '{
  exitstat=$?
  rm -f $trapdeletefiles
  trap "" 0
  echo "Aborting... cleaning up." >&2
  exit $exitstat
}' 0 1 2 15

# we have to get this from the user:
#  default server, default help service, and where to install things.

# first we get the default server.

cat << EOF

I need to know the name of the irc server you intend to use as your
primary link.  You should have done a little research by this time to see
what servers are in your area. You should always pick the absolute closest
server to you.  You can use an IP address instead of a name as well.

EOF

if test "$defserver"; then
  dflt="$defserver"
else
  dflt="$nodef"
fi
rp="Please type the name of a server."

while true; do
  . ./.myread
  case "$ans" in
  "$nodef")
    continue
    ;;
  /*)
    if test -f "$ans"; then :; else
      echo "$ans doesn't seem to exist right now. You'll need to create it."
    fi
    ;;
  *)
    ;;
  esac
  break
done
defserver="$ans"

# got a default server, must be time to get the installation dir.

cat << EOF

Ok, we've got a default server now, next we have to choose where things
are going to go.  First i need to know if you are compiling ircii for
yourself, or for the system.

EOF
if test "$prefix"; then
  echo "Note: If you want to keep old directory values, just hit 'Return'.
"
  nostick=true
fi

dflt=""
rp="Do you want to install ircii for the system?"
. ./.myread
case "$ans" in
y*|Y*)
  sysinstall=nap
  prefix="/usr/local"
  bindir=
  libdir=
  ;;
n*|N*)
  sysinstall=
  prefix="${HOME}"
  bindir=
  libdir=
  ;;
*)
  prefix="${prefix-${HOME}}"
  ;;
esac
nostick=""

cat << EOF

We now need to find out the destination area of the installation.
Such a directory will probably have two subdirectories,
something like 'bin' for the binaries, and 'lib/irc' for the libraries.

Hit 'Return' to keep previously computed values.
EOF
dflt="$prefix"
rp='
What is the destination prefix of the installation? (~user ok)'
. ./.myread
ans=`./.tildexp "$ans"`

#
# If we have an answer, reset the other variables so that they get computed.
#
case "$ans" in
"$dflt") ;;
*)
  prefix="$ans"
  bindir=
  libdir=
  ;;
esac

if test -z "$bindir"; then
  bindir="${prefix}/bin"
fi

dflt="$bindir"
rp='
Where do you want to install the ircII binaries? (~user ok)'
. ./.myread
ans=`./.tildexp "$ans"`

if test "$ans"; then bindir="$ans"; fi

#
# Algorithm used:
# Check if directory ${prefix}/lib exists...
#   Yes -> install in ${prefix}/lib/irc
#    No -> install in ${prefix}/IRC
#

# If no $libdir is defined at this stage, but there's a $IRCLIB
# in the environment, default to this value.

if test -z "$libdir"; then
  if test "${IRCLIB}"; then
    libdir="${IRCLIB}"
  elif test -d "${prefix}/lib"; then
    libdir="${prefix}/lib/irc"
  else
    libdir="${prefix}/IRC"
  fi
fi

dflt="$libdir"
rp='
Where do you want to install the irc librairies? (~user ok)'
. ./.myread
ans=`./.tildexp "$ans"`

if test "$ans"; then libdir="$ans"; fi

# ok, we have places to put things now.

cat << EOF

Moving right along here.  Time to tell me which help service you'd
like to use.  Please enter the number of the one that is closest to you.
You can choose 0) if you don't know.

EOF

index=0
for a in $help_services; do
  echo "	$index) $a"
  index=`expr $index + 1`
done

index=`expr "$index" - 1`
echo ""
while true; do
  rp="Choice (0-$index)"
  dflt="${help_service-$nodef}"
  . ./.myread
  case "$ans" in
  "$nodef")
    continue
    ;;
  *)
    if test "$ans" -gt "$index" || test "$ans" -lt 0; then
      :
    else
      break
    fi
  esac
done

help_service="$ans"
sedbit='[^ ]*'
while test "$ans" -gt 0; do
  ans=`expr $ans - 1`
  sedfull="$sedbit $sedfull"
done

if test -n "$sedfull"; then
  defhelp=`echo $help_services | sed -e "s/$sedfull//" -e "s/ .*//"`
else
  defhelp=`echo $help_services | sed -e "s/ .*//"`
fi

cat << EOF

I will summarize below the various choices you've made.

                Default server: $defserver
                        Prefix: $prefix
    Directory for binary files: $bindir
       Directory for libraries: $libdir
                  Help service: $defhelp

EOF

rp='Do you want to save those values for future use and proceed?'
dflt='y'
. ./.myread
case "$ans" in
n*|N*)
  echo "Exiting without saving..."
  exit 1
  ;;
*)
  ;;
esac

{
  cat << EOF
#
# ${savefile}
# This file is automagically generated by the command 'easyinst'
# Please do not edit.
#
EOF
  echo '# $Id: easyinst,v 2.10 1994/12/02 09:19:58 mrg stable $'
  echo "# Created: `date`"
  echo '# '
  cat << EOF
defserver="${defserver}"
sysinstall="${sysinstall}"
prefix="${prefix}"
bindir="${bindir}"
libdir="${libdir}"
help_service="${help_service}"

EOF
} > ${savefile}

cat << EOF

I just saved for you the current configuration in
	$savefile

If you have made a typo, hit ^C now, edit this file and restart easyinst.

Now I will configure this version of ircii using the 'configure'
script provided.

This may take a few minutes, so sit back an enjoy the show...

EOF

# work out what arguments to call configure with.

echo "setting up config.h..."

IRCLIB="$libdir"

if test "$defserver" || test "$defhelp"; then
  rm -f include/config.h.old
  mv include/config.h include/config.h.old
  cp include/config.h.dist include/config.h
fi

if test "$defserver"; then
  sed -e "s@\(#define[ 	]*DEFAULT_SERVER[	 ]*\).*\$@\1 \"$defserver\"@" \
< include/config.h > include/config.h.new
  rm -f include/config.h
  mv -f include/config.h.new include/config.h
fi

if test "$defhelp"; then
  if test "$defhelp" = "NULL"; then
    defhelp="(char *) 0"
  else
    defhelp="\"$defhelp\""
  fi
  sed -e "s/\(#define[ 	]*DEFAULT_HELP_SERVICE[ 	]*\).*$/\1 $defhelp/" \
< include/config.h > include/config.h.new
  rm -f include/config.h
  mv -f include/config.h.new include/config.h
fi


rm -f $trapdeletefiles
trap 0 1 2 15

echo "calling configure..."
. ./configure

# End of script
exit 0

s, I will then run a script for you
to work out some of the hairier parts of your system. Good luck!
EOF
dflt="Press 'Return' to go on"
. ./.myread

#
# Trick to load old easyinst values :)
#
if test -r "$savefile"; then
  echo "
I see a $savefile file."
  dflt="y"
  rp="Do you want to use it to set the defaults?"
  . ./.myread
  case "$ans" in
  n*|N*) echo "Ignoring $savefile." ;;
  *)
    echo "Loading previous easyinst choices..."
    trap "{
      rm -f $savefile
      echo 'Fatal error. PDarkNET-1.08/ircii-2.8.H1/mkinstalldirs                                                                755   21270   21270         1311  5657052103  12531                                                                                                                                                                                                                                                                                                                                                                      #!/bin/sh
# mkinstalldirs --- make directory hierarchy
# Author: Noah Friedman <friedman@prep.ai.mit.edu>
# Created: 1993-05-16
# Last modified: 1994-03-25
# Public domain
# @(#)$Id: mkinstalldirs,v 2.1 1994/11/06 03:57:55 mrg stable $

errstatus=0

for file in ${1+"$@"} ; do 
   set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
   shift

   pathcomp=
   for d in ${1+"$@"} ; do
     pathcomp="$pathcomp$d"
     case "$pathcomp" in
       -* ) pathcomp=./$pathcomp ;;
     esac

     if test ! -d "$pathcomp"; then
        echo "mkdir $pathcomp" 1>&2
        mkdir "$pathcomp" || errstatus=$?
     fi

     pathcomp="$pathcomp/"
   done
done

exit $errstatus

# mkinstalldirs ends here
                                                                                                                                                                                                                                                                                                                       DarkNET-1.08/ircii-2.8.H1/todo                                                                         644   21270   21270         1266  5710725531  10626                                                                                                                                                                                                                                                                                                                                                                      $Id: todo,v 1.7 1995/01/23 13:12:57 mrg Exp $

mrg's list:

finish /stack.  make sure it works.  i don't think /stack % on <numeric> works.
fix eight bit mode, stty losing problems.
fix zcat stuff to grok .Z .z .gz, etc, all at once.
fix problem with /server not working, but /window server does.
fix aix /notify crashes when using aix cc.
scroll_forward is hosed.
find and fix rejoin lossage with trashed reconnect channels.
find and `fix' all lame uses of my_stricmp(), such as the one that is in who() -- do the tolower once and use strcmp()
fix the next `port'.

ian's list:

[ =Dae= <16:41> ] document index's ^ feature in the help file.
[ =Dae= <16:41> ] figure out /win new level snotes
                                                                                                                                                                                                                                                                                                                                          DarkNET-1.08/ircii-2.8.H1/include/                                                                     755   21270   21270            0  5742136325  11271                                                                                                                                                                                                                                                                                                                                                                      DarkNET-1.08/ircii-2.8.H1/include/config.h                                                             644   21270   21270        17402  5731670014  13014                                                                                                                                                                                                                                                                                                                                                                      /* 'new' config.h:
 *	A configuration file designed to make best use of the abilities
 *	of ircII, and trying to make things more intuitively understandable.
 *
 * Done by Carl v. Loesch <lynx@dm.unirm1.it>
 * Based on the 'classic' config.h by Michael Sandrof.
 * Copyright(c) 1991 - See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT 
 *
 * Warning!  You will most likely have to make changes to your .ircrc file to
 * use this version of IRCII!  Please read the INSTALL and New2.2 files
 * supplied with the distribution for details!
 *
 * @(#)$Id: config.h,v 1.2 1995/02/17 02:28:20 hellcat Exp $
 */

#ifndef __config_h_
#define __config_h_

/*
 * Set your favorite default server list here.  This list should be a
 * whitespace separated hostname:portnum:password list (with portnums and
 * passwords optional).  This IS NOT an optional definition. Please set this
 * to your nearest servers.  However if you use a seperate 'ircII.servers'
 * file and the ircII can find it, this setting is overridden.
 */
#define DEFAULT_SERVER	    "localhost"

/*
 * Uncomment the following if the gecos field of your /etc/passwd has other
 * information in it that you don't want as the user name (such as office
 * locations, phone numbers, etc).  The default delimiter is a comma, change
 * it if you need to. If commented out, the entire gecos field is used. 
 */
/*
#define GECOS_DELIMITER ','
*/

/*
 * Set the following to 1 if you wish for IRCII not to disturb the tty's flow
 * control characters as the default.  Normally, these are ^Q and ^S.  You
 * may have to rebind them in IRCII.  Set it to 0 for IRCII to take over the
 * tty's flow control.
 */
#define USE_FLOW_CONTROL 1

/*
 * Below you can set what type of mail your system uses and the path to the
 * appropriate mail file/directory.  Only one may be selected. 
 * You may also undefine both if you think mail checking in irc clients is
 * silly.
 */
/* AMS_MAIL is the Andrew Mail System mail format. */

#undef AMS_MAIL

/* UNIX_MAIL is the normal unix mail format.  */
#ifndef UNIX_MAIL
# define UNIX_MAIL "/usr/spool/mail"	/* */
#endif

/*
 * MAIL_DELIMITER specifies the unique text that separates one mail message
 * from another in the mail spool file when using UNIX_MAIL.
 */
#define MAIL_DELIMITER "From "

#ifdef AMS_MAIL
# define AMS_MAIL "Mailbox"
#endif /* AMS_MAIL */
/* Thanks to Allanon a very useful feature, when this is defined, ircII will
 * be able to read help files in compressed format (it will recognize the .Z)
 * If you undefine this you will spare some code, though, so better only
 * set if you are sure you are going to keep your help-files compressed.
 */
#define ZCAT "/bin/zcat"

/* Define ZSUFFIX in case we are using ZCAT */
#ifdef ZCAT
# define ZSUFFIX ".Z"
#endif

/* Make ^Z stop the irc process by default,
 * if undefined, ^Z will self-insert by default
 */
#define ALLOW_STOP_IRC /**/

/* And here is the port number for default client connections.  */
#define IRC_PORT 6667

/*
 * With this version IRCII help services are being regionalised, so you
 * will need to set that to your nearest help service (see below).
 * DEFAULT_HELP_SERVICE should never be commented out.
 */

/*
 * Help services are now regionalised.  Set DEFAULT_HELP_SERVICE to
 * one of the following, or to NULL, if you wish no have no default.
 *
 *	"IrcIIhelp"
 *	"help_AU"
 *	"help_US"
 *	"help_EU"
 *	"help_UK"
 */

#define	DEFAULT_HELP_SERVICE     "IrcIIhelp"

/*
 * Uncomment the following to make ircII read a list of irc servers from
 * the ircII.servers file in the ircII library. This file should be
 * whitespace separated hostname:portnum:password (with the portnum and
 * password being optional). This server list will supercede the
 * DEFAULT_SERVER. 
*/

#define SERVERS_FILE "ircII.servers"

/* Uncomment the following if you want ircII to display the file
 * ircII.motd in the ircII library at startup.
 */
#define MOTD_FILE "ircII.motd"
#define PAUSE_AFTER_MOTD 1

/*
 * set this is you want have debugging in the client... really pretty
 * boring..and mostly does nothing.
 */
#undef DEBUG

/*
 * define this if you are on a machine that dynamically changes ip
 * address, such as a floating slip machine.
 */

#undef DYNAMIC_SLIP

/*
 * Below are the IRCII variable defaults.  For boolean variables, use 1 for
 * ON and 0 for OFF.  You may set string variable to NULL if you wish them to
 * have no value.  None of these are optional.  You may *not* comment out or
 * remove them.  They are default values for variables and are required for
 * proper compilation.
 */
#define DEFAULT_ALWAYS_SPLIT_BIGGEST 1
#define DEFAULT_AUTO_UNMARK_AWAY 0
#define DEFAULT_AUTO_WHOWAS 0
#define DEFAULT_BEEP 1
#define DEFAULT_BEEP_MAX 3
#define DEFAULT_BEEP_ON_MSG "NONE"
#define DEFAULT_BEEP_WHEN_AWAY 0
#define DEFAULT_BOLD_VIDEO 1
#define DEFAULT_CHANNEL_NAME_WIDTH 10
#define DEFAULT_CLOCK 1
#define DEFAULT_CLOCK_24HOUR 1
#define DEFAULT_CLOCK_ALARM NULL
#define DEFAULT_CMDCHARS "/"
#define DEFAULT_COMMAND_MODE 0
#define DEFAULT_CONTINUED_LINE "+"
#define DEFAULT_DCC_BLOCK_SIZE 512
#define DEFAULT_DISPLAY 1
#define DEFAULT_EIGHT_BIT_CHARACTERS 1
#define DEFAULT_ENCRYPT_PROGRAM NULL
#define DEFAULT_EXEC_PROTECTION 1
#define DEFAULT_FLOOD_AFTER 3
#define DEFAULT_FLOOD_RATE 3
#define DEFAULT_FLOOD_USERS 3
#define DEFAULT_FLOOD_WARNING 0
#define DEFAULT_FULL_STATUS_LINE 1
#define DEFAULT_HELP_PAGER 1
#define DEFAULT_HELP_PROMPT 1
#define DEFAULT_HELP_WINDOW 0
#define DEFAULT_HIDE_PRIVATE_CHANNELS 1
#define DEFAULT_HIGHLIGHT_CHAR "INVERSE"
#define DEFAULT_HISTORY 30
#define DEFAULT_HISTORY_FILE NULL
#define DEFAULT_HOLD_MODE 0
#define DEFAULT_HOLD_MODE_MAX 0
#define DEFAULT_INDENT 0
#define DEFAULT_INPUT_ALIASES 0
#define DEFAULT_INPUT_PROMPT NULL
#define DEFAULT_INPUT_PROTECTION 1
#define DEFAULT_INSERT_MODE 1
#define DEFAULT_INVERSE_VIDEO 1
#define DEFAULT_LASTLOG 44
#define DEFAULT_LASTLOG_LEVEL "ALL -CRAP"
#define DEFAULT_LOG 0
#define DEFAULT_LOGFILE "IrcLog"
#define DEFAULT_MAIL 0
#define DEFAULT_MAX_RECURSIONS 10
#define DEFAULT_MINIMUM_SERVERS 0
#define DEFAULT_MINIMUM_USERS 0
#define DEFAULT_NO_CTCP_FLOOD 1
#define DEFAULT_NOTIFY_HANDLER "QUIET"
#define DEFAULT_NOTIFY_LEVEL "ALL DCC"
#define DEFAULT_NOTIFY_ON_TERMINATION 0
#define DEFAULT_SCROLL 1
#define DEFAULT_SCROLL_LINES 1
#define DEFAULT_SEND_IGNORE_MSG 0
#define DEFAULT_SHELL "/bin/sh"
#define DEFAULT_SHELL_FLAGS "-c"
#define DEFAULT_SHELL_LIMIT 0
#define DEFAULT_SHOW_AWAY_ONCE 1
#define DEFAULT_SHOW_CHANNEL_NAMES 0
#define DEFAULT_SHOW_END_OF_MSGS 0
#define DEFAULT_SHOW_NUMERICS 0
#define DEFAULT_SHOW_STATUS_ALL 0
#define DEFAULT_SHOW_WHO_HOPCOUNT 0
#define DEFAULT_STATUS_AWAY " (away)"
#define DEFAULT_STATUS_CHANNEL " on %C"
#define DEFAULT_STATUS_CHANOP "@"
#define DEFAULT_STATUS_CLOCK " %T"
#define DEFAULT_STATUS_FORMAT "[%R]%T %*%@%N%#%S%H%B%Q%A%C%+%I%O%M%F%U %W"
#define DEFAULT_STATUS_HOLD " --- more ---"
#define DEFAULT_STATUS_HOLD_LINES " (%B)"
#define DEFAULT_STATUS_INSERT ""
#define DEFAULT_STATUS_MODE " (+%+)"
#define DEFAULT_STATUS_MAIL " [Mail: %M]"
#define DEFAULT_STATUS_NOTIFY " [Activity: %F]"
#define DEFAULT_STATUS_OPER "*"
#define DEFAULT_STATUS_OVERWRITE "(overtype) "
#define DEFAULT_STATUS_QUERY " [Query: %Q]"
#define DEFAULT_STATUS_SERVER " via %S"
#define DEFAULT_STATUS_UMODE " (+%#)"
#define DEFAULT_STATUS_USER " * type /help for help "
#define DEFAULT_STATUS_USER1 ""
#define DEFAULT_STATUS_USER2 ""
#define DEFAULT_STATUS_USER3 ""
#define DEFAULT_STATUS_WINDOW "^^^^^^^^"
#define DEFAULT_SUPPRESS_SERVER_MOTD 0
#define DEFAULT_TAB 1
#define DEFAULT_TAB_MAX 8
#define DEFAULT_UNDERLINE_VIDEO 1
#define DEFAULT_USE_OLD_MSG 0
#define DEFAULT_USERINFO ""
#define DEFAULT_USER_WALLOPS 0
#define DEFAULT_VERBOSE_CTCP 0
#define DEFAULT_WARN_OF_IGNORES 0
#define DEFAULT_XTERM_OPTIONS NULL

/*
 * define this if you want to have the -l and -L command line
 * options.
 */

#undef COMMAND_LINE_L

#endif /* __config_h_ */
d list (with portnums and
 * passwords optional).  This IS NOT an optional definition. Please set this
 * to your nearest servers.  However if you use a seperate 'ircII.servers'
 * file and the ircII can find it, this setting is overridden.
 */
#define DDarkNET-1.08/ircii-2.8.H1/include/.cvsignore                                                           644   21270   21270           45  5704230437  13312                                                                                                                                                                                                                                                                                                                                                                      config.h
defs.h
vars.h
hook.h
keys.h
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           DarkNET-1.08/ircii-2.8.H1/include/alias.h                                                              444   21270   21270         2622  5721004062  12605                                                                                                                                                                                                                                                                                                                                                                      /*
 * alias.h: header for alias.c 
 *
 * Written By Michael Sandrof
 *
 * Copyright(c) 1990 
 *
 * See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT 
 *
 * @(#)$Id: alias.h,v 1.1 1995/02/17 02:21:38 hellcat Exp $
 */

#ifndef _ALIAS_H_
#define _ALIAS_H_

#define COMMAND_ALIAS 0
#define VAR_ALIAS 1

#define LEFT_BRACE '{'
#define RIGHT_BRACE '}'
#define LEFT_BRACKET '['
#define RIGHT_BRACKET ']'
#define LEFT_PAREN '('
#define RIGHT_PAREN ')'
#define DOUBLE_QUOTE '"'

extern	void	add_alias();
extern	char	*get_alias();
extern	char	*expand_alias();
extern	void	execute_alias();
extern	void	list_aliases();
extern	int	mark_alias();
extern	void	delete_alias();
extern	char	*inline_aliases();
extern	char	**match_alias();
extern	char	alias_illegals[];
extern	void	alias _((char *, char *, char *));
extern	char	*parse_inline();
extern	char	*MatchingBracket();
extern	void	save_aliases();
extern	int	word_count _((char *));

extern	char	command_line[];

struct	ArgPosTag
{
	char *ArgStart;
	int ArgLen;
	char *FirstComp;
};

typedef	struct ArgPosTag	ArgPos;

/* Alias: structure of each alias entry */
typedef	struct	AliasStru
{
	char	*name;			/* name of alias */
	char	*stuff;			/* what the alias is */
	int	mark;			/* used to prevent recursive aliasing */
	int	global;			/* set if loaded from `global' */
	struct	AliasStru *next;	/* pointer to next alias in list */
}	Alias;

#define MAX_CMD_ARGS 5

#endif /* _ALIAS_H_ */
                                                                                                              DarkNET-1.08/ircii-2.8.H1/include/config.h.dist                                                        444   21270   21270        17424  5721032217  13754                                                                                                                                                                                                                                                                                                                                                                      /* 'new' config.h:
 *	A configuration file designed to make best use of the abilities
 *	of ircII, and trying to make things more intuitively understandable.
 *
 * Done by Carl v. Loesch <lynx@dm.unirm1.it>
 * Based on the 'classic' config.h by Michael Sandrof.
 * Copyright(c) 1991 - See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT 
 *
 * Warning!  You will most likely have to make changes to your .ircrc file to
 * use this version of IRCII!  Please read the INSTALL and New2.2 files
 * supplied with the distribution for details!
 *
 * @(#)$Id: config.h.dist,v 1.2 1995/02/17 05:30:50 hellcat Exp $
 */

#ifndef __config_h_
#define __config_h_

/*
 * Set your favorite default server list here.  This list should be a
 * whitespace separated hostname:portnum:password list (with portnums and
 * passwords optional).  This IS NOT an optional definition. Please set this
 * to your nearest servers.  However if you use a seperate 'ircII.servers'
 * file and the ircII can find it, this setting is overridden.
 */
#define DEFAULT_SERVER	    "korea.slip.umd.edu"

/*
 * Uncomment the following if the gecos field of your /etc/passwd has other
 * information in it that you don't want as the user name (such as office
 * locations, phone numbers, etc).  The default delimiter is a comma, change
 * it if you need to. If commented out, the entire gecos field is used. 
 */
#define GECOS_DELIMITER ','

/*
 * Set the following to 1 if you wish for IRCII not to disturb the tty's flow
 * control characters as the default.  Normally, these are ^Q and ^S.  You
 * may have to rebind them in IRCII.  Set it to 0 for IRCII to take over the
 * tty's flow control.
 */
#define USE_FLOW_CONTROL 1

/*
 * Below you can set what type of mail your system uses and the path to the
 * appropriate mail file/directory.  Only one may be selected. 
 * You may also undefine both if you think mail checking in irc clients is
 * silly.
 */
/* AMS_MAIL is the Andrew Mail System mail format. */

#undef AMS_MAIL

/* UNIX_MAIL is the normal unix mail format.  */
#ifndef UNIX_MAIL
# define UNIX_MAIL "/usr/spool/mail"	/* */
#endif

/*
 * MAIL_DELIMITER specifies the unique text that separates one mail message
 * from another in the mail spool file when using UNIX_MAIL.
 */
#define MAIL_DELIMITER "From "

#ifdef AMS_MAIL
# define AMS_MAIL "Mailbox"
#endif /* AMS_MAIL */
/* Thanks to Allanon a very useful feature, when this is defined, ircII will
 * be able to read help files in compressed format (it will recognize the .Z)
 * If you undefine this you will spare some code, though, so better only
 * set if you are sure you are going to keep your help-files compressed.
 */
#define ZCAT "/usr/local/bin/zcat"

/* Define ZSUFFIX in case we are using ZCAT */
#ifdef ZCAT
# define ZSUFFIX ".Z"
#endif

/* Make ^Z stop the irc process by default,
 * if undefined, ^Z will self-insert by default
 */
#define ALLOW_STOP_IRC /**/

/* And here is the port number for default client connections.  */
#define IRC_PORT 6667

/*
 * With this version IRCII help services are being regionalised, so you
 * will need to set that to your nearest help service (see below).
 * DEFAULT_HELP_SERVICE should never be commented out.
 */

/*
 * Help services are now regionalised.  Set DEFAULT_HELP_SERVICE to
 * one of the following, or to NULL, if you wish no have no default.
 *
 *	"IrcIIhelp"
 *	"help_AU"
 *	"help_US"
 *	"help_EU"
 *	"help_UK"
 */

#define	DEFAULT_HELP_SERVICE     "IrcIIhelp"

/*
 * Uncomment the following to make ircII read a list of irc servers from
 * the ircII.servers file in the ircII library. This file should be
 * whitespace separated hostname:portnum:password (with the portnum and
 * password being optional). This server list will supercede the
 * DEFAULT_SERVER. 
*/

#define SERVERS_FILE "ircII.servers"

/* Uncomment the following if you want ircII to display the file
 * ircII.motd in the ircII library at startup.
 */
#define MOTD_FILE "ircII.motd"
#define PAUSE_AFTER_MOTD 1

/*
 * set this is you want have debugging in the client... really pretty
 * boring..and mostly does nothing.
 */
#undef DEBUG

/*
 * define this if you are on a machine that dynamically changes ip
 * address, such as a floating slip machine.
 */

#undef DYNAMIC_SLIP

/*
 * Below are the IRCII variable defaults.  For boolean variables, use 1 for
 * ON and 0 for OFF.  You may set string variable to NULL if you wish them to
 * have no value.  None of these are optional.  You may *not* comment out or
 * remove them.  They are default values for variables and are required for
 * proper compilation.
 */
#define DEFAULT_ALWAYS_SPLIT_BIGGEST 1
#define DEFAULT_AUTO_UNMARK_AWAY 0
#define DEFAULT_AUTO_WHOWAS 0
#define DEFAULT_BEEP 1
#define DEFAULT_BEEP_MAX 3
#define DEFAULT_BEEP_ON_MSG "NONE"
#define DEFAULT_BEEP_WHEN_AWAY 0
#define DEFAULT_BOLD_VIDEO 1
#define DEFAULT_CHANNEL_NAME_WIDTH 10
#define DEFAULT_CLOCK 1
#define DEFAULT_CLOCK_24HOUR 1
#define DEFAULT_CLOCK_ALARM NULL
#define DEFAULT_CMDCHARS "/"
#define DEFAULT_COMMAND_MODE 0
#define DEFAULT_CONTINUED_LINE "+"
#define DEFAULT_DCC_BLOCK_SIZE 512
#define DEFAULT_DISPLAY 1
#define DEFAULT_EIGHT_BIT_CHARACTERS 1
#define DEFAULT_ENCRYPT_PROGRAM NULL
#define DEFAULT_EXEC_PROTECTION 1
#define DEFAULT_FLOOD_AFTER 3
#define DEFAULT_FLOOD_RATE 3
#define DEFAULT_FLOOD_USERS 3
#define DEFAULT_FLOOD_WARNING 0
#define DEFAULT_FULL_STATUS_LINE 1
#define DEFAULT_HELP_PAGER 1
#define DEFAULT_HELP_PROMPT 1
#define DEFAULT_HELP_WINDOW 0
#define DEFAULT_HIDE_PRIVATE_CHANNELS 1
#define DEFAULT_HIGHLIGHT_CHAR "INVERSE"
#define DEFAULT_HISTORY 30
#define DEFAULT_HISTORY_FILE NULL
#define DEFAULT_HOLD_MODE 0
#define DEFAULT_HOLD_MODE_MAX 0
#define DEFAULT_INDENT 0
#define DEFAULT_INPUT_ALIASES 0
#define DEFAULT_INPUT_PROMPT NULL
#define DEFAULT_INPUT_PROTECTION 1
#define DEFAULT_INSERT_MODE 1
#define DEFAULT_INVERSE_VIDEO 1
#define DEFAULT_LASTLOG 44
#define DEFAULT_LASTLOG_LEVEL "ALL -CRAP"
#define DEFAULT_LOG 0
#define DEFAULT_LOGFILE "IrcLog"
#define DEFAULT_MAIL 0
#define DEFAULT_MAX_RECURSIONS 10
#define DEFAULT_MINIMUM_SERVERS 0
#define DEFAULT_MINIMUM_USERS 0
#define DEFAULT_NO_CTCP_FLOOD 1
#define DEFAULT_NOTIFY_HANDLER "QUIET"
#define DEFAULT_NOTIFY_LEVEL "ALL DCC"
#define DEFAULT_NOTIFY_ON_TERMINATION 0
#define DEFAULT_SCROLL 1
#define DEFAULT_SCROLL_LINES 1
#define DEFAULT_SEND_IGNORE_MSG 0
#define DEFAULT_SHELL "/bin/sh"
#define DEFAULT_SHELL_FLAGS "-c"
#define DEFAULT_SHELL_LIMIT 0
#define DEFAULT_SHOW_AWAY_ONCE 1
#define DEFAULT_SHOW_CHANNEL_NAMES 0
#define DEFAULT_SHOW_END_OF_MSGS 0
#define DEFAULT_SHOW_NUMERICS 0
#define DEFAULT_SHOW_STATUS_ALL 0
#define DEFAULT_SHOW_WHO_HOPCOUNT 0
#define DEFAULT_STATUS_AWAY " (away)"
#define DEFAULT_STATUS_CHANNEL " on %C"
#define DEFAULT_STATUS_CHANOP "@"
#define DEFAULT_STATUS_CLOCK " %T"
#define DEFAULT_STATUS_FORMAT "[%R]%T %*%@%N%#%S%H%B%Q%A%C%+%I%O%M%F%U %W"
#define DEFAULT_STATUS_HOLD " --- more ---"
#define DEFAULT_STATUS_HOLD_LINES " (%B)"
#define DEFAULT_STATUS_INSERT ""
#define DEFAULT_STATUS_MODE " (+%+)"
#define DEFAULT_STATUS_MAIL " [Mail: %M]"
#define DEFAULT_STATUS_NOTIFY " [Activity: %F]"
#define DEFAULT_STATUS_OPER "*"
#define DEFAULT_STATUS_OVERWRITE "(overtype) "
#define DEFAULT_STATUS_QUERY " [Query: %Q]"
#define DEFAULT_STATUS_SERVER " via %S"
#define DEFAULT_STATUS_UMODE " (+%#)"
#define DEFAULT_STATUS_USER " * type /help for help "
#define DEFAULT_STATUS_USER1 ""
#define DEFAULT_STATUS_USER2 ""
#define DEFAULT_STATUS_USER3 ""
#define DEFAULT_STATUS_WINDOW "^^^^^^^^"
#define DEFAULT_SUPPRESS_SERVER_MOTD 0
#define DEFAULT_TAB 1
#define DEFAULT_TAB_MAX 8
#define DEFAULT_UNDERLINE_VIDEO 1
#define DEFAULT_USE_OLD_MSG 0
#define DEFAULT_USERINFO ""
#define DEFAULT_USER_WALLOPS 0
#define DEFAULT_VERBOSE_CTCP 0
#define DEFAULT_WARN_OF_IGNORES 0
#define DEFAULT_XTERM_OPTIONS NULL

/*
 * define this if you want to have the -l and -L command line
 * options.
 */

#undef COMMAND_LINE_L

#endif /* __config_h_ */
                                                                                                                                                                                                                                            DarkNET-1.08/ircii-2.8.H1/include/config.h.lynx                                                        444   21270   21270        17256  5657044741  14023                                                                                                                                                                                                                                                                                                                                                                      /* 'new' config.h:
 *	A configuration file designed to make best use of the abilities
 *	of ircII, and trying to make things more intuitively understandable.
 *
 * Written by Carl v. Loesch <lynx@dm.unirm1.it>
 * Based on the 'classic' config.h by Michael Sandrof.
 * Copyright(c) 1991 - See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT 
 *
 * Warning!  You will most likely have to make changes to your .ircrc file to
 * use this version of IRCII!  Please read the NOTES file supplied with the
 * distribution for details!
 */

#ifndef _CONFIG_H_
#define _CONFIG_H_

/*
 * Set your favorite default server list here.  This list should be a
 * whitespace separated hostname:portnum:password list (with portnums and
 * passwords optional).  This IS NOT an optional definition. Please set this
 * to your nearest servers.  However if you use a seperate 'servers' file
 * and the ircII can find it, this setting is overridden.
 */
#define DEFAULT_SERVER "arbi"

/*
 * Uncomment the following if the gecos field of your /etc/passwd has other
 * information in it that you don't want as the user name (such as office
 * locations, phone numbers, etc).  The default delimiter is a comma, change
 * it if you need to. If commented out, the entire gecos field is used. 
 */
#define GECOS_DELIMITER ',' /**/

/*
 * Set the following to 1 if you wish for IRCII not to disturb the tty's flow
 * control characters as the default.  Normally, these are ^Q and ^S.  You
 * may have to rebind them in IRCII.  Set it to 0 for IRCII to take over the
 * tty's flow control.
 */
#define USE_FLOW_CONTROL 0

/*
 * Below you can set what type of mail your system uses and the path to the
 * appropriate mail file/directory.  Only one may be selected. 
 * You may also undefine both if you think mail checking in irc clients is
 * silly.
 */
/* UNIX_MAIL is the normal unix mail format.  */
#ifndef UNIX_MAIL
/* #define UNIX_MAIL "/usr/spool/mail"	/**/
#endif
/* AMS_MAIL is the Andrew Mail System mail format. */
/* #define AMS_MAIL "Mailbox"	/**/
/* MAIL_DELIMITER specifies the unique text that separates one mail message
 * from another in the mail spool file when using UNIX_MAIL. */
#define MAIL_DELIMITER "From "

/* Thanks to Allanon a very useful feature, when this is defined, ircII will
 * be able to read help files in compressed format (it will recognize the .Z)
 */
#define ZCAT "/usr/ucb/zcat"

/* Define ZSUFFIX in case we are using ZCAT */
#ifdef ZCAT
# define ZSUFFIX ".Z"
#endif

/* If you keep this disabled you spare some K of code. This feature is needed
 * for irciid installations or any other situation when you have 'guest'
 * users and you want to allow them to use ircII, but at the same time don't
 * want them to be able to use /exec and all the other 'unsecure' commands.
 * If ircII runs under the uid that you define herein as DAEMON_UID it will
 * not allow the 'daemon' user to do anything dangerous.
 */
/* #define DAEMON_UID 1 /**/

/* Make ^Z stop the irc process by default,
 * if undefined, ^Z will self-insert by default
 */
#define ALLOW_STOP_IRC /**/

/* And here is the port number for default client connections.  */
#define IRC_PORT 6667

/* DEFAULT_HELP_SERVICE should never be commented out.
 * It should contain the name of the topologically nearest
 * ircIIhelp-robot to you. Choices are: Help_US, Help_EU, HELP_AU...
 */
#define DEFAULT_HELP_SERVICE "Help_EU"

/*
 * Uncomment the following to make ircII read a list of irc servers from
 * the 'servers' file in the ircII library. This file should be
 * whitespace separated hostname:portnum:password (with the portnum and
 * password being optional). This server list will supercede the
 * DEFAULT_SERVER. 
*/
#define SERVERS_FILE "servers"

/* Uncomment the following if you want ircII to display the file
 * ircII.motd in the ircII library at startup.
 */
#define MOTD_FILE "ircII.motd"
#define PAUSE_AFTER_MOTD 1

/*
 * define this if you are on a machine that dynamically changes ip
 * address, such as a floating slip machine.
 */

#undef DYNAMIC_SLIP

/*
 * Below are the IRCII variable defaults.  For boolean variables, use 1 for
 * ON and 0 for OFF.  You may set string variable to NULL if you wish them to
 * have no value.  None of these are optional.  You may *not* comment out or
 * remove them.  They are default values for variables and are required for
 * proper compilation.
 */
#define DEFAULT_ALWAYS_SPLIT_BIGGEST 1
#define DEFAULT_AUTO_UNMARK_AWAY 0
#define DEFAULT_AUTO_WHOWAS 0
#define DEFAULT_BEEP 1
#define DEFAULT_BEEP_MAX 7
#define DEFAULT_BEEP_ON_MSG "NONE"
#define DEFAULT_BEEP_WHEN_AWAY 1
#define DEFAULT_BOLD_VIDEO 1
#define DEFAULT_CHANNEL_NAME_WIDTH 10
#define DEFAULT_CLOCK 1
#define DEFAULT_CLOCK_24HOUR 1
#define DEFAULT_CLOCK_ALARM NULL
#define DEFAULT_CMDCHARS "/"
#define DEFAULT_COMMAND_MODE 0
#define DEFAULT_CONTINUED_LINE "  "
#define DEFAULT_DCC_BLOCK_SIZE 512
#define DEFAULT_DISPLAY 1
#define DEFAULT_EIGHT_BIT_CHARACTERS 0
#define DEFAULT_ENCRYPT_PROGRAM NULL
#define DEFAULT_EXEC_PROTECTION 1
#define DEFAULT_FLOOD_AFTER 3
#define DEFAULT_FLOOD_RATE 3
#define DEFAULT_FLOOD_USERS 3
#define DEFAULT_FLOOD_WARNING 0
#define DEFAULT_FULL_STATUS_LINE 1
#define DEFAULT_HELP_PAGER 1
#define DEFAULT_HELP_PROMPT 1
#define DEFAULT_HELP_WINDOW 0
#define DEFAULT_HIDE_PRIVATE_CHANNELS 1
#define DEFAULT_HIGHLIGHT_CHAR "INVERSE"
#define DEFAULT_HISTORY 30
#define DEFAULT_HISTORY_FILE NULL
#define DEFAULT_HOLD_MODE 1
#define DEFAULT_HOLD_MODE_MAX 0
#define DEFAULT_INDENT 1
#define DEFAULT_INPUT_ALIASES 0
#define DEFAULT_INPUT_PROMPT NULL
#define DEFAULT_INPUT_PROTECTION 1
#define DEFAULT_INSERT_MODE 1
#define DEFAULT_INVERSE_VIDEO 1
#define DEFAULT_LASTLOG 44
#define DEFAULT_LASTLOG_LEVEL "ALL DCC -CRAP"
#define DEFAULT_LOG 0
#define DEFAULT_LOGFILE "IrcLog"
#define DEFAULT_MAIL 1
#define DEFAULT_MAX_RECURSIONS 9
#define DEFAULT_MINIMUM_SERVERS 0
#define DEFAULT_MINIMUM_USERS 0
#define DEFAULT_NO_CTCP_FLOOD 0
#define DEFAULT_NOTIFY_HANDLER "QUIET"
#define DEFAULT_NOTIFY_LEVEL
#define DEFAULT_NOTIFY_ON_TERMINATION 0
#define DEFAULT_SCROLL 1
#define DEFAULT_SCROLL_LINES 1
#define DEFAULT_SEND_IGNORE_MSG 1
#define DEFAULT_SHELL "/bin/sh"
#define DEFAULT_SHELL_FLAGS "-c"
#define DEFAULT_SHELL_LIMIT 0
#define DEFAULT_SHOW_AWAY_ONCE 1
#define DEFAULT_SHOW_CHANNEL_NAMES 1
#define DEFAULT_SHOW_END_OF_MSGS 0
#define DEFAULT_SHOW_NUMERICS 0
#define DEFAULT_SHOW_STATUS_ALL 1
#define DEFAULT_SHOW_WHO_HOPCOUNT 0
#define DEFAULT_STATUS_AWAY "(away) "
#define DEFAULT_STATUS_CHANNEL "on %C "
#define DEFAULT_STATUS_CHANOP "@"
#define DEFAULT_STATUS_CLOCK "%T "
#define DEFAULT_STATUS_FORMAT " %T[%R] %*%N%#%@ %S%H%Q%A%C%+%I%O%M%U %W"
#define DEFAULT_STATUS_HOLD "--- more --- "
#define DEFAULT_STATUS_HOLD_LINES "(%B) "
#define DEFAULT_STATUS_INSERT ""
#define DEFAULT_STATUS_MODE "(+%+) "
#define DEFAULT_STATUS_MAIL NULL /* "[Mail: %M] " */
#define DEFAULT_STATUS_NOTIFY "[Activity: %F]"
#define DEFAULT_STATUS_OPER "*"
#define DEFAULT_STATUS_OVERWRITE "(overtype) "
#define DEFAULT_STATUS_QUERY "[Query: %Q] "
#define DEFAULT_STATUS_SERVER "via %S "
#define DEFAULT_STATUS_USER "* type /help for help"
#define DEFAULT_STATUS_USER1 ""
#define DEFAULT_STATUS_USER2 ""
#define DEFAULT_STATUS_USER3 ""
#define DEFAULT_STATUS_UMODE "{%#}"
#define DEFAULT_STATUS_WINDOW "^"
#define DEFAULT_SUPPRESS_SERVER_MOTD 0
#define DEFAULT_TAB 1
#define DEFAULT_TAB_MAX 8
#define DEFAULT_UNDERLINE_VIDEO 1
#define DEFAULT_USE_OLD_MSG 0
#define DEFAULT_USERINFO "<none>"
#define DEFAULT_VERBOSE_CTCP 0 
#define DEFAULT_WARN_OF_IGNORES 1
#define DEFAULT_USER_WALLOPS 1 /* strange type of /ignore this one! */
#define DEFAULT_XTERM_OPTIONS NULL

/* These are the format strings for screen output of some events */
#define SHOW_ACTION "* %s %s"
#define SHOW_ACTION_OUT SHOW_ACTION
#define SHOW_ACTION_TO "* -> %s: %s %s"

#endif /* _CONFIG_H_ */
                                                                                                                                                                                                                                                                                                                                                  DarkNET-1.08/ircii-2.8.H1/include/config.h.old                                                         444   21270   21270        17373  5721004062  13567                                                                                                                                                                                                                                                                                                                                                                      /* 'new' config.h:
 *	A configuration file designed to make best use of the abilities
 *	of ircII, and trying to make things more intuitively understandable.
 *
 * Done by Carl v. Loesch <lynx@dm.unirm1.it>
 * Based on the 'classic' config.h by Michael Sandrof.
 * Copyright(c) 1991 - See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT 
 *
 * Warning!  You will most likely have to make changes to your .ircrc file to
 * use this version of IRCII!  Please read the INSTALL and New2.2 files
 * supplied with the distribution for details!
 *
 * $Id: config.h.old,v 1.1 1995/02/17 02:21:38 hellcat Exp $
 */

#ifndef __config_h_
#define __config_h_

/*
 * Set your favorite default server list here.  This list should be a
 * whitespace separated hostname:portnum:password list (with portnums and
 * passwords optional).  This IS NOT an optional definition. Please set this
 * to your nearest servers.  However if you use a seperate 'ircII.servers'
 * file and the ircII can find it, this setting is overridden.
 */
#define DEFAULT_SERVER	     "irc"

/*
 * Uncomment the following if the gecos field of your /etc/passwd has other
 * information in it that you don't want as the user name (such as office
 * locations, phone numbers, etc).  The default delimiter is a comma, change
 * it if you need to. If commented out, the entire gecos field is used. 
 */
#define GECOS_DELIMITER ','

/*
 * Set the following to 1 if you wish for IRCII not to disturb the tty's flow
 * control characters as the default.  Normally, these are ^Q and ^S.  You
 * may have to rebind them in IRCII.  Set it to 0 for IRCII to take over the
 * tty's flow control.
 */
#define USE_FLOW_CONTROL 1

/*
 * Below you can set what type of mail your system uses and the path to the
 * appropriate mail file/directory.  Only one may be selected. 
 * You may also undefine both if you think mail checking in irc clients is
 * silly.
 */
/* AMS_MAIL is the Andrew Mail System mail format. */

#undef AMS_MAIL

/* UNIX_MAIL is the normal unix mail format.  */
#ifndef UNIX_MAIL
# define UNIX_MAIL "/usr/spool/mail"	/* */
#endif

/*
 * MAIL_DELIMITER specifies the unique text that separates one mail message
 * from another in the mail spool file when using UNIX_MAIL.
 */
#define MAIL_DELIMITER "From "

#ifdef AMS_MAIL
# define AMS_MAIL "Mailbox"
#endif /* AMS_MAIL */
/* Thanks to Allanon a very useful feature, when this is defined, ircII will
 * be able to read help files in compressed format (it will recognize the .Z)
 * If you undefine this you will spare some code, though, so better only
 * set if you are sure you are going to keep your help-files compressed.
 */
#define ZCAT "/usr/ucb/zcat"

/* Define ZSUFFIX in case we are using ZCAT */
#ifdef ZCAT
# define ZSUFFIX ".Z"
#endif

/* Make ^Z stop the irc process by default,
 * if undefined, ^Z will self-insert by default
 */
#define ALLOW_STOP_IRC /**/

/* And here is the port number for default client connections.  */
#define IRC_PORT 6667

/*
 * With this version IRCII help services are being regionalised, so you
 * will need to set that to your nearest help service (see below).
 * DEFAULT_HELP_SERVICE should never be commented out.
 */

/*
 * Help services are now regionalised.  Set DEFAULT_HELP_SERVICE to
 * one of the following, or to NULL, if you wish no have no default.
 *
 *	"IrcIIhelp"
 *	"help_AU"
 *	"help_US"
 *	"help_EU"
 *	"help_UK"
 */

#define	DEFAULT_HELP_SERVICE      (char *) 0

/*
 * Uncomment the following to make ircII read a list of irc servers from
 * the ircII.servers file in the ircII library. This file should be
 * whitespace separated hostname:portnum:password (with the portnum and
 * password being optional). This server list will supercede the
 * DEFAULT_SERVER. 
*/

#define SERVERS_FILE "ircII.servers"

/* Uncomment the following if you want ircII to display the file
 * ircII.motd in the ircII library at startup.
 */
#define MOTD_FILE "ircII.motd"
#define PAUSE_AFTER_MOTD 1

/*
 * set this is you want have debugging in the client... really pretty
 * boring..and mostly does nothing.
 */
#undef DEBUG

/*
 * define this if you are on a machine that dynamically changes ip
 * address, such as a floating slip machine.
 */

#undef DYNAMIC_SLIP

/*
 * Below are the IRCII variable defaults.  For boolean variables, use 1 for
 * ON and 0 for OFF.  You may set string variable to NULL if you wish them to
 * have no value.  None of these are optional.  You may *not* comment out or
 * remove them.  They are default values for variables and are required for
 * proper compilation.
 */
#define DEFAULT_ALWAYS_SPLIT_BIGGEST 1
#define DEFAULT_AUTO_UNMARK_AWAY 0
#define DEFAULT_AUTO_WHOWAS 0
#define DEFAULT_BEEP 1
#define DEFAULT_BEEP_MAX 3
#define DEFAULT_BEEP_ON_MSG "NONE"
#define DEFAULT_BEEP_WHEN_AWAY 0
#define DEFAULT_BOLD_VIDEO 1
#define DEFAULT_CHANNEL_NAME_WIDTH 10
#define DEFAULT_CLOCK 1
#define DEFAULT_CLOCK_24HOUR 1
#define DEFAULT_CLOCK_ALARM NULL
#define DEFAULT_CMDCHARS "/"
#define DEFAULT_COMMAND_MODE 0
#define DEFAULT_CONTINUED_LINE "+"
#define DEFAULT_DCC_BLOCK_SIZE 512
#define DEFAULT_DISPLAY 1
#define DEFAULT_EIGHT_BIT_CHARACTERS 0
#define DEFAULT_ENCRYPT_PROGRAM NULL
#define DEFAULT_EXEC_PROTECTION 1
#define DEFAULT_FLOOD_AFTER 3
#define DEFAULT_FLOOD_RATE 3
#define DEFAULT_FLOOD_USERS 3
#define DEFAULT_FLOOD_WARNING 0
#define DEFAULT_FULL_STATUS_LINE 1
#define DEFAULT_HELP_PAGER 1
#define DEFAULT_HELP_PROMPT 1
#define DEFAULT_HELP_WINDOW 0
#define DEFAULT_HIDE_PRIVATE_CHANNELS 1
#define DEFAULT_HIGHLIGHT_CHAR "INVERSE"
#define DEFAULT_HISTORY 30
#define DEFAULT_HISTORY_FILE NULL
#define DEFAULT_HOLD_MODE 0
#define DEFAULT_HOLD_MODE_MAX 0
#define DEFAULT_INDENT 0
#define DEFAULT_INPUT_ALIASES 0
#define DEFAULT_INPUT_PROMPT NULL
#define DEFAULT_INPUT_PROTECTION 1
#define DEFAULT_INSERT_MODE 1
#define DEFAULT_INVERSE_VIDEO 1
#define DEFAULT_LASTLOG 44
#define DEFAULT_LASTLOG_LEVEL "ALL -CRAP"
#define DEFAULT_LOG 0
#define DEFAULT_LOGFILE "IrcLog"
#define DEFAULT_MAIL 1
#define DEFAULT_MAX_RECURSIONS 10
#define DEFAULT_MINIMUM_SERVERS 0
#define DEFAULT_MINIMUM_USERS 0
#define DEFAULT_NO_CTCP_FLOOD 1
#define DEFAULT_NOTIFY_HANDLER "QUIET"
#define DEFAULT_NOTIFY_LEVEL "ALL DCC"
#define DEFAULT_NOTIFY_ON_TERMINATION 0
#define DEFAULT_SCROLL 1
#define DEFAULT_SCROLL_LINES 1
#define DEFAULT_SEND_IGNORE_MSG 0
#define DEFAULT_SHELL "/bin/sh"
#define DEFAULT_SHELL_FLAGS "-c"
#define DEFAULT_SHELL_LIMIT 0
#define DEFAULT_SHOW_AWAY_ONCE 1
#define DEFAULT_SHOW_CHANNEL_NAMES 0
#define DEFAULT_SHOW_END_OF_MSGS 0
#define DEFAULT_SHOW_NUMERICS 0
#define DEFAULT_SHOW_STATUS_ALL 0
#define DEFAULT_SHOW_WHO_HOPCOUNT 0
#define DEFAULT_STATUS_AWAY " (away)"
#define DEFAULT_STATUS_CHANNEL " on %C"
#define DEFAULT_STATUS_CHANOP "@"
#define DEFAULT_STATUS_CLOCK " %T"
#define DEFAULT_STATUS_FORMAT "[%R]%T %*%@%N%#%S%H%B%Q%A%C%+%I%O%M%F%U %W"
#define DEFAULT_STATUS_HOLD " --- more ---"
#define DEFAULT_STATUS_HOLD_LINES " (%B)"
#define DEFAULT_STATUS_INSERT ""
#define DEFAULT_STATUS_MODE " (+%+)"
#define DEFAULT_STATUS_MAIL " [Mail: %M]"
#define DEFAULT_STATUS_NOTIFY " [Activity: %F]"
#define DEFAULT_STATUS_OPER "*"
#define DEFAULT_STATUS_OVERWRITE "(overtype) "
#define DEFAULT_STATUS_QUERY " [Query: %Q]"
#define DEFAULT_STATUS_SERVER " via %S"
#define DEFAULT_STATUS_UMODE " (+%#)"
#define DEFAULT_STATUS_USER " * type /help for help "
#define DEFAULT_STATUS_USER1 ""
#define DEFAULT_STATUS_USER2 ""
#define DEFAULT_STATUS_USER3 ""
#define DEFAULT_STATUS_WINDOW "^^^^^^^^"
#define DEFAULT_SUPPRESS_SERVER_MOTD 0
#define DEFAULT_TAB 1
#define DEFAULT_TAB_MAX 8
#define DEFAULT_UNDERLINE_VIDEO 1
#define DEFAULT_USE_OLD_MSG 0
#define DEFAULT_USERINFO ""
#define DEFAULT_USER_WALLOPS 0
#define DEFAULT_VERBOSE_CTCP 0
#define DEFAULT_WARN_OF_IGNORES 0
#define DEFAULT_XTERM_OPTIONS NULL

/*
 * define this if you want to have the -l and -L command line
 * options.
 */

#undef COMMAND_LINE_L

#endif /* __config_h_ */
                                                                                                                                                                                                                                                                     DarkNET-1.08/ircii-2.8.H1/include/config.h.phone                                                       444   21270   21270        17544  5721004062  14122                                                                                                                                                                                                                                                                                                                                                                      /* 'new' config.h:
 *	A configuration file designed to make best use of the abilities
 *	of ircII, and trying to make things more intuitively understandable.
 *
 * Done by Carl v. Loesch <lynx@dm.unirm1.it>
 * Based on the 'classic' config.h by Michael Sandrof.
 * Copyright(c) 1991 - See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT 
 *
 * Warning!  You will most likely have to make changes to your .ircrc file to
 * use this version of IRCII!  Please read the INSTALL and New2.2 files
 * supplied with the distribution for details!
 *
 * $Id: config.h.phone,v 1.1 1995/02/17 02:21:38 hellcat Exp $
 */

#ifndef __config_h_
#define __config_h_

/*
 * Set your favorite default server list here.  This list should be a
 * whitespace separated hostname:portnum:password list (with portnums and
 * passwords optional).  This IS NOT an optional definition. Please set this
 * to your nearest servers.  However if you use a seperate 'ircII.servers'
 * file and the ircII can find it, this setting is overridden.
 */
#define DEFAULT_SERVER	    "irc"

/*
 * Uncomment the following if the gecos field of your /etc/passwd has other
 * information in it that you don't want as the user name (such as office
 * locations, phone numbers, etc).  The default delimiter is a comma, change
 * it if you need to. If commented out, the entire gecos field is used. 
 */
#define GECOS_DELIMITER ',' /**/

/*
 * Set the following to 1 if you wish for IRCII not to disturb the tty's flow
 * control characters as the default.  Normally, these are ^Q and ^S.  You
 * may have to rebind them in IRCII.  Set it to 0 for IRCII to take over the
 * tty's flow control.
 */
#define USE_FLOW_CONTROL 1

/*
 * Below you can set what type of mail your system uses and the path to the
 * appropriate mail file/directory.  Only one may be selected. 
 * You may also undefine both if you think mail checking in irc clients is
 * silly.
 */
/* AMS_MAIL is the Andrew Mail System mail format. */
#undef AMS_MAIL

/* UNIX_MAIL is the normal unix mail format.  */
#ifndef UNIX_MAIL
#define UNIX_MAIL "/usr/spool/mail"	/* */
#endif

/*
 * MAIL_DELIMITER specifies the unique text that separates one mail message
 * from another in the mail spool file when using UNIX_MAIL.
 */
#define MAIL_DELIMITER "From "

#ifdef AMS_MAIL
# define AMS_MAIL "Mailbox"
#endif /* AMS_MAIL */
/* Thanks to Allanon a very useful feature, when this is defined, ircII will
 * be able to read help files in compressed format (it will recognize the .Z)
 * If you undefine this you will spare some code, though, so better only
 * set if you are sure you are going to keep your help-files compressed.
 */
#define ZCAT "/usr/bin/gzcat"

/* Define ZSUFFIX in case we are using ZCAT */
#ifdef ZCAT
# define ZSUFFIX ".gz"
#endif

/* Make ^Z stop the irc process by default,
 * if undefined, ^Z will self-insert by default
 */
#define ALLOW_STOP_IRC /**/

/* And here is the port number for default client connections.  */
#define IRC_PORT 6667

/*
 * With this version IRCII help services are being regionalised, so you
 * will need to set that to your nearest help service (see below).
 * DEFAULT_HELP_SERVICE should never be commented out.
 */

/*
 * Help services are now regionalised.  Set DEFAULT_HELP_SERVICE to
 * one of the following, or to NULL, if you wish no have no default.
 *
 *	"IrcIIhelp"
 *	"help_AU"
 *	"help_US"
 *	"help_EU"
 *	"help_UK"
 */

#define	DEFAULT_HELP_SERVICE     NULL

/*
 * Uncomment the following to make ircII read a list of irc servers from
 * the ircII.servers file in the ircII library. This file should be
 * whitespace separated hostname:portnum:password (with the portnum and
 * password being optional). This server list will supercede the
 * DEFAULT_SERVER. 
*/

#define SERVERS_FILE "ircII.servers"

/* Uncomment the following if you want ircII to display the file
 * ircII.motd in the ircII library at startup.
 */
#define MOTD_FILE "ircII.motd"
#define PAUSE_AFTER_MOTD 1

/*
 * set this is you want have debugging in the client... really pretty
 * boring..
 */
#define DEBUG

/*
 * define this if you are on a machine that dynamically changes ip
 * address, such as a floating slip machine.
 */

#undef DYNAMIC_SLIP

/*
 * Below are the IRCII variable defaults.  For boolean variables, use 1 for
 * ON and 0 for OFF.  You may set string variable to NULL if you wish them to
 * have no value.  None of these are optional.  You may *not* comment out or
 * remove them.  They are default values for variables and are required for
 * proper compilation.
 */
#define DEFAULT_ALWAYS_SPLIT_BIGGEST 1
#define DEFAULT_AUTO_UNMARK_AWAY 0
#define DEFAULT_AUTO_WHOWAS 0
#define DEFAULT_BEEP 1
#define DEFAULT_BEEP_MAX 3
#define DEFAULT_BEEP_ON_MSG "NONE"
#define DEFAULT_BEEP_WHEN_AWAY 0
#define DEFAULT_BOLD_VIDEO 1
#define DEFAULT_CHANNEL_NAME_WIDTH 10
#define DEFAULT_CLOCK 0
#define DEFAULT_CLOCK_24HOUR 1
#define DEFAULT_CLOCK_ALARM NULL
#define DEFAULT_CMDCHARS "/"
#define DEFAULT_COMMAND_MODE 0
#define DEFAULT_CONTINUED_LINE "  "
#define DEFAULT_DCC_BLOCK_SIZE 512
#define DEFAULT_DISPLAY 1
#define DEFAULT_EIGHT_BIT_CHARACTERS 0
#define DEFAULT_ENCRYPT_PROGRAM NULL
#define DEFAULT_EXEC_PROTECTION 1
#define DEFAULT_FLOOD_AFTER 3
#define DEFAULT_FLOOD_RATE 3
#define DEFAULT_FLOOD_USERS 3
#define DEFAULT_FLOOD_WARNING 1
#define DEFAULT_FULL_STATUS_LINE 1
#define DEFAULT_HELP_PAGER 1
#define DEFAULT_HELP_PROMPT 1
#define DEFAULT_HELP_WINDOW 0
#define DEFAULT_HIDE_PRIVATE_CHANNELS 1
#define DEFAULT_HIGHLIGHT_CHAR "INVERSE"
#define DEFAULT_HISTORY 100
#define DEFAULT_HISTORY_FILE NULL
#define DEFAULT_HOLD_MODE 0
#define DEFAULT_HOLD_MODE_MAX 0
#define DEFAULT_INDENT 0
#define DEFAULT_INPUT_ALIASES 0
#define DEFAULT_INPUT_PROMPT "$T> "
#define DEFAULT_INPUT_PROTECTION 1
#define DEFAULT_INSERT_MODE 1
#define DEFAULT_INVERSE_VIDEO 1
#define DEFAULT_LASTLOG 512
#define DEFAULT_LASTLOG_LEVEL "ALL DCC -CRAP,WALLOP"
#define DEFAULT_LOG 0
#define DEFAULT_LOGFILE "IrcLog"
#define DEFAULT_MAIL 1
#define DEFAULT_MAX_RECURSIONS 20
#define DEFAULT_MINIMUM_SERVERS 0
#define DEFAULT_MINIMUM_USERS 0
#define DEFAULT_NO_CTCP_FLOOD 1
#define DEFAULT_NOTIFY_HANDLER "QUIET"
#define DEFAULT_NOTIFY_LEVEL "ALL DCC"
#define DEFAULT_NOTIFY_ON_TERMINATION 0
#define DEFAULT_NOVICE 0
#define DEFAULT_SCROLL 1
#define DEFAULT_SCROLL_LINES 1
#define DEFAULT_SEND_IGNORE_MSG 0
#define DEFAULT_SHELL "/bin/csh"
#define DEFAULT_SHELL_FLAGS "-c"
#define DEFAULT_SHELL_LIMIT 0
#define DEFAULT_SHOW_AWAY_ONCE 1
#define DEFAULT_SHOW_CHANNEL_NAMES 1
#define DEFAULT_SHOW_END_OF_MSGS 0
#define DEFAULT_SHOW_NUMERICS 0
#define DEFAULT_SHOW_STATUS_ALL 0
#define DEFAULT_SHOW_WHO_HOPCOUNT 1
#define DEFAULT_STATUS_AWAY " (dead)"
#define DEFAULT_STATUS_CHANNEL " on %C"
#define DEFAULT_STATUS_CHANOP "@"
#define DEFAULT_STATUS_CLOCK " %T"
#define DEFAULT_STATUS_FORMAT "[%R]%T %*%@%N%#%S%H%B%Q%A%C%+%I%O%M%F%U %W"
#define DEFAULT_STATUS_HOLD " --- more ---"
#define DEFAULT_STATUS_HOLD_LINES " (%B)"
#define DEFAULT_STATUS_INSERT ""
#define DEFAULT_STATUS_MODE " (+%+)"
#define DEFAULT_STATUS_MAIL " [Mail: %M]"
#define DEFAULT_STATUS_NOTIFY " [Activity: %F]"
#define DEFAULT_STATUS_OPER "*"
#define DEFAULT_STATUS_OVERWRITE "(overtype) "
#define DEFAULT_STATUS_QUERY " [Query: %Q]"
#define DEFAULT_STATUS_SERVER " via %S"
#define DEFAULT_STATUS_UMODE " (+%#)"
#define DEFAULT_STATUS_USER ""
#define DEFAULT_STATUS_USER1 ""
#define DEFAULT_STATUS_USER2 ""
#define DEFAULT_STATUS_USER3 ""
#define DEFAULT_STATUS_WINDOW "~~~~"
#define DEFAULT_SUPPRESS_SERVER_MOTD 1
#define DEFAULT_TAB 1
#define DEFAULT_TAB_MAX 4
#define DEFAULT_UNDERLINE_VIDEO 1
#define DEFAULT_USE_OLD_MSG 0
#define DEFAULT_USERINFO "blahcrapblah"
#define DEFAULT_USER_WALLOPS 1
#define DEFAULT_VERBOSE_CTCP 0
#define DEFAULT_WARN_OF_IGNORES 1
#define DEFAULT_XTERM_OPTIONS NULL

/* define these if you want them included */
#undef COMMAND_LINE_B
#undef COMMAND_LINE_L

#endif /* __config_h_ */

#define PHONE
#define COMMAND_LINE_L
#define NO_QUIT_ON_OPERATOR_KILL
#define ON_KICK
#define INPUT_BUFFER_SIZE 500
                                                                                                                                                            DarkNET-1.08/ircii-2.8.H1/include/crypt.h                                                              444   21270   21270          675  5721004062  12643                                                                                                                                                                                                                                                                                                                                                                      /*
 * crypt.h: header for crypt.c 
 *
 * Written By Michael Sandrof
 *
 * Copyright(c) 1990 
 *
 * See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT 
 *
 * @(#)$Id: crypt.h,v 1.1 1995/02/17 02:21:38 hellcat Exp $
 */

#ifndef _CRYPT_H_
#define _CRYPT_H_

extern	char	*crypt_msg();
extern	void	encrypt_cmd _((char *, char *, char *));
extern	char	*is_crypted();

#define CRYPT_HEADER ""
#define CRYPT_HEADER_LEN 5

#endif /* _CRYPT_H_ */
                                                                   DarkNET-1.08/ircii-2.8.H1/include/ctcp.h                                                               444   21270   21270         3526  5721004062  12451                                                                                                                                                                                                                                                                                                                                                                      /*
 * ctcp.h: header file for ctcp.c
 *
 * Written By Michael Sandrof
 *
 * Copyright(c) 1990 
 *
 * See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT 
 *
 * @(#)$Id: ctcp.h,v 1.1 1995/02/17 02:21:38 hellcat Exp $
 */

#ifndef _CTCP_H_
#define _CTCP_H_

/*
 * ctcp_entry: the format for each ctcp function.   note that the function
 * described takes 4 parameters, a pointer to the ctcp entry, who the message
 * was from, who the message was to (nickname, channel, etc), and the rest of
 * the ctcp message.  it can return null, or it can return a malloced string
 * that will be inserted into the oringal message at the point of the ctcp.
 * if null is returned, nothing is added to the original message
 */
typedef	struct
{
	char	*name;                 /* name of ctcp datatag */
	char	*desc;                 /* description returned by ctcp clientinfo */
	int	flag;
	char	*(*func)();           /* function that does the dirty deed */
}	CtcpEntry;

#define CTCP_DELIM_CHAR '\001'
#define CTCP_DELIM_STR "\001"
#define CTCP_QUOTE_CHAR '\\'
#define CTCP_QUOTE_STR "\\"

#define CTCP_QUOTE_EM "\n\r\001\\"

#define CTCP_PRIVMSG 0
#define CTCP_NOTICE 1

#define	CTCP_SED 0
#define CTCP_VERSION 1
#define CTCP_CLIENTINFO 2
#define	CTCP_USERINFO 3
#define	CTCP_ERRMSG 4
#define	CTCP_FINGER 5
#define	CTCP_TIME 6
#define CTCP_ACTION 7
#define	CTCP_DCC_CHAT 8
#define	CTCP_UCT 9
#define CTCP_PING 10
#define CTCP_ECHO 11
#define	NUMBER_OF_CTCPS 12

extern	char	*ctcp_type[];
extern	int	sed;

extern	char	*do_ctcp();
extern	char	*ctcp_quote_it();
extern	char	*ctcp_unquote_it();
extern	char	*do_notice_ctcp();
extern	int	in_ctcp();
#ifdef USE_STDARG_H
extern        void    send_ctcp_reply(char *, char *, char *, ...);
extern        void    send_ctcp(char *, char *, char *, char *, ...);
#else
extern	void	send_ctcp_reply();
extern	void	send_ctcp();
#endif

#endif /* _CTCP_H_ */
                                                                                                                                                                          DarkNET-1.08/ircii-2.8.H1/include/dcc.h                                                                444   21270   21270         3475  5721004062  12254                                                                                                                                                                                                                                                                                                                                                                      /*
 * dcc.h: Things dealing client to client connections. 
 *
 * Written By Troy Rollo <troy@plod.cbme.unsw.oz.au> 
 *
 * Copyright(c) 1991 
 *
 * See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT 
 *
 * @(#)$Id: dcc.h,v 1.1 1995/02/17 02:21:38 hellcat Exp $
 */

/*
 * this file must be included after irc.h as i needed <sys/types.h>
 * <netinet/in.h> and <apra/inet.h>
 */

#ifndef _DCC_H_
#define _DCC_H_

#define DCC_CHAT	((unsigned) 0x0001)
#define DCC_FILEOFFER	((unsigned) 0x0002)
#define DCC_FILEREAD	((unsigned) 0x0003)
#define DCC_TALK	((unsigned) 0x0004)
#define DCC_SUMMON	((unsigned) 0x0005)
#define	DCC_RAW_LISTEN	((unsigned) 0x0006)
#define	DCC_RAW		((unsigned) 0x0007)
#define DCC_TYPES	((unsigned) 0x000f)

#define DCC_WAIT	((unsigned) 0x0010)
#define DCC_ACTIVE	((unsigned) 0x0020)
#define DCC_OFFER	((unsigned) 0x0040)
#define DCC_DELETE	((unsigned) 0x0080)
#define DCC_TWOCLIENTS	((unsigned) 0x0100)
#define DCC_STATES	((unsigned) 0xfff0)

typedef	struct	DCC_struct
{
	unsigned	flags;
	int	read;
	int	write;
	int	file;
	int	filesize;
	char	*description;
	char	*user;
	char	*othername;
	struct	DCC_struct	*next;
	struct	in_addr	remote;
	u_short	remport;
	long	bytes_read;
	time_t	bytes_sent;
	time_t	lasttime;
	time_t	starttime;
	char	*buffer;
	char	talkchars[3];
}	DCC_list;

#define DCC_TALK_CHECK 0
#define DCC_TALK_INVITE 1
#define DCC_TALK_ANNOUNCE 2
#define DCC_TALK_DELETE_LOCAL 3
#define DCC_TALK_DELETE_REMOTE 4
#define DCC_TALK_SUMMON 5
#define DCC_TALK_DELETE_SUMMON 6

extern	DCC_list	*dcc_searchlist();
extern	void	dcc_erase();
extern	void	register_dcc_offer();
extern	void	process_dcc();
extern	void	dcc_list();
extern	void	dcc_chat_transmit();
extern	void	dcc_message_transmit();
extern	int	send_talk_control();
extern	void	close_all_dcc();
extern	void	set_dcc_bits();
extern	void	dcc_check();

#endif /* _DCC_H_ */
                                                                                                                                                                                                   DarkNET-1.08/ircii-2.8.H1/include/debug.h                                                              444   21270   21270          714  5721004062  12562                                                                                                                                                                                                                                                                                                                                                                      /*
 * debug.h - header file for phone's debug routine..
 *
 * Copyright (C) 1993, Matthew Green.
 *
 * @(#)$Id: debug.h,v 1.1 1995/02/17 02:21:38 hellcat Exp $
 */

#ifndef _DEBUG_H_
# define _DEBUG_H_ 

#ifdef DEBUG
# define Debug(x) debug x

# ifdef USE_STDARG_H
extern  void    debug( int, char *, ... );
# else
extern        void    debug();
# endif

extern	int	debuglevel;
extern	int	setdlevel();

# else
# define Debug(x)
# endif

#endif /* _DEBUG_H_ */
                                                    DarkNET-1.08/ircii-2.8.H1/include/defs.h.in                                                            444   21270   21270        11457  5702474756  13114                                                                                                                                                                                                                                                                                                                                                                      /* include/defs.h.in.  Generated automatically from configure.in by autoheader.  */

/* Define if on AIX 3.
   System headers sometimes define this.
   We just want to avoid a redefinition error message.  */
#ifndef _ALL_SOURCE
#undef _ALL_SOURCE
#endif

/* Define to `int' if <sys/types.h> doesn't define.  */
#undef gid_t

/* Define if you have <sys/wait.h> that is POSIX.1 compatible.  */
#undef HAVE_SYS_WAIT_H

/* Define to `int' if <sys/types.h> doesn't define.  */
#undef mode_t

/* Define to `int' if <sys/types.h> doesn't define.  */
#undef pid_t

/* Define if the system does not provide POSIX.1 features except
   with this defined.  */
#undef _POSIX_1_SOURCE

/* Define if you need to in order for stat and other things to work.  */
#undef _POSIX_SOURCE

/* Define as the return type of signal handlers (int or void).  */
#undef RETSIGTYPE

/* Define to `unsigned' if <sys/types.h> doesn't define.  */
#undef size_t

/* Define if you have the ANSI C header files.  */
#undef STDC_HEADERS

/* Define on System V Release 4.  */
#undef SVR4

/* Define if you can safely include both <sys/time.h> and <time.h>.  */
#undef TIME_WITH_SYS_TIME

/* Define to `int' if <sys/types.h> doesn't define.  */
#undef uid_t

/* define if allow sys/time.h with time.h */
#undef TIME_WITH_SYS_TIME

/* define this if you are using BSD wait union thigs */
#undef BSDWAIT

/* define this if you are using -lcurses */
#undef USING_CURSES

/* define this if you are using sigaction() instead of signal() */
#undef USE_SIGACTION

/* define this if you are using sigset() instead of signal() */
#undef USE_SIGSET

/* define this if you are using system V (unreliable) signals */
#undef SYSVSIGNALS

/* define this if wait3() is declared */
#undef WAIT3_DECLARED

/* define this if waitpid() is declared */
#undef WAITPID_DECLARED

/* define this if waitpid() is unavailable */
#undef NEED_WAITPID

/* define this if you have scandir() */
#undef HAVE_SCANDIR

/* define this if you have memmove() */
#undef HAVE_MEMMOVE

/* define this if you have setsid() */
#undef HAVE_SETSID

/* define this if you have getsid() */
#undef HAVE_GETSID

/* define this if you have getpgid() */
#undef HAVE_GETPGID

/* define this if your getpgrp() doesn't take a pid argument */
#undef BROKEN_GETPGRP

/* define this if you need getcwd() */
#undef NEED_GETCWD 

/* define this if you have hpux version 7 */
#undef HPUX7

/* define this if you have hpux version 8 */
#undef HPUX8

/* define this if you have an unknown hpux version (pre ver 7) */
#undef HPUXUNKNOWN

/* define this if an unsigned long is 32 bits */
#undef UNSIGNED_LONG32

/* define this if an unsigned int is 32 bits */
#undef UNSIGNED_INT32

/* define this if you are unsure what is is 32 bits */
#undef UNKNOWN_32INT

/* define this if you are on a svr4 derivative */
#undef SVR4

/* define this if you are on solaris 2.x */
#undef __solaris__

/* define this if you don't have struct linger */
#undef NO_STRUCT_LINGER

/* define this if you are on svr3/twg */
#undef WINS

/* define this if you need fchmod */
#undef NEED_FCHMOD

/* define this to the location of normal unix mail */
#undef UNIX_MAIL

/* define this if your header files declare sys_errlist */
#undef SYS_ERRLIST_DECLARED

/* define this if you have uname(2) */
#undef HAVE_UNAME

/* define this if you need strerror(3) */
#undef NEED_STRERROR

/* Define if you have the <dirent.h> header file.  */
#undef HAVE_DIRENT_H

/* Define if you have the <fcntl.h> header file.  */
#undef HAVE_FCNTL_H

/* Define if you have the <limits.h> header file.  */
#undef HAVE_LIMITS_H

/* Define if you have the <memory.h> header file.  */
#undef HAVE_MEMORY_H

/* Define if you have the <ndir.h> header file.  */
#undef HAVE_NDIR_H

/* Define if you have the <netdb.h> header file.  */
#undef HAVE_NETDB_H

/* Define if you have the <stdarg.h> header file.  */
#undef HAVE_STDARG_H

/* Define if you have the <string.h> header file.  */
#undef HAVE_STRING_H

/* Define if you have the <sys/dir.h> header file.  */
#undef HAVE_SYS_DIR_H

/* Define if you have the <sys/fcntl.h> header file.  */
#undef HAVE_SYS_FCNTL_H

/* Define if you have the <sys/file.h> header file.  */
#undef HAVE_SYS_FILE_H

/* Define if you have the <sys/ndir.h> header file.  */
#undef HAVE_SYS_NDIR_H

/* Define if you have the <sys/ptem.h> header file.  */
#undef HAVE_SYS_PTEM_H

/* Define if you have the <sys/select.h> header file.  */
#undef HAVE_SYS_SELECT_H

/* Define if you have the <sys/time.h> header file.  */
#undef HAVE_SYS_TIME_H

/* Define if you have the <sys/twg_config.h> header file.  */
#undef HAVE_SYS_TWG_CONFIG_H

/* Define if you have the <sys/un.h> header file.  */
#undef HAVE_SYS_UN_H

/* Define if you have the <sys/wait.h> header file.  */
#undef HAVE_SYS_WAIT_H

/* Define if you have the <unistd.h> header file.  */
#undef HAVE_UNISTD_H

/* Define if you have the sun library (-lsun).  */
#undef HAVE_LIBSUN
you have hpux version 7 */
#undef HPUX7

/* define this if you have hpux version 8 */
#undef HPUX8

/* define this if you have an unknown hpux version (pre ver 7) */
#undef HPUXUNKNOWN

/* define this if an unDarkNET-1.08/ircii-2.8.H1/include/edit.h                                                               444   21270   21270         1670  5721004062  12443                                                                                                                                                                                                                                                                                                                                                                      /*
 * edit.h: header for edit.c 
 *
 * Written By Michael Sandrof
 *
 * Copyright(c) 1990 
 *
 * See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT 
 *
 * @(#)$Id: edit.h,v 1.1 1995/02/17 02:21:38 hellcat Exp $
 */

#ifndef _EDIT_H_
#define _EDIT_H_

extern	char	*sent_nick;
extern	char	*sent_body;
extern	char	*recv_nick;
extern	void	load _((char *, char *, char *));
extern	void	send_text();
extern	void	eval_inputlist();
extern	void	parse_command();
extern	void	parse_line();
extern	void	edit_char _((unsigned char));
extern	void	ExecuteTimers();
extern	void	ison_ison();
extern	void	query _((char *, char *, char *));

#define AWAY_ONE 0
#define AWAY_ALL 1

#define STACK_POP 0
#define STACK_PUSH 1
#define STACK_SWAP 2

/* a structure for the timer list */
typedef struct	timerlist_stru
{
	int	ref;
	int	in_on_who;
	time_t	time;
	char	*command;
	struct	timerlist_stru *next;
}	TimerList;

extern TimerList *PendingTimers;

#endif /* _EDIT_H_ */
                                                                        DarkNET-1.08/ircii-2.8.H1/include/exec.h                                                               444   21270   21270         3450  5721004062  12440                                                                                                                                                                                                                                                                                                                                                                      /*
 * exec.h: header for exec.c 
 *
 * Written By Michael Sandrof
 *
 * Copyright(c) 1990 
 *
 * See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT 
 *
 * @(#)$Id: exec.h,v 1.1 1995/02/17 02:21:38 hellcat Exp $
 */

#ifndef _EXEC_H_
#define _EXEC_H_

#include <sys/types.h>

#if defined(NeXT)		/* lameness for configure/NeXT -phone */
# if !defined(_POSIX_SOURCE) && !defined(BSDWAIT)
#  define BSDWAIT
# endif /* !_POSIX_SOURCE && !BSDWAIT */
#else /* !NeXT */
# ifndef WAITSTUFF_DECLARED
#  ifdef BSDWAIT
#   ifndef WAIT3_DECLARED
struct rusage;
union wait;
extern int   wait3 _((union wait *, int, struct rusage *));
#   endif /* WAIT3_DECLARED */
#  else /* BSDWAIT */
#   ifndef WAITPID_DECLARED
extern short waitpid _((int, int *, int));
#   endif /* WAITPID_DECLARED */
#  endif /* BSDWAIT */
# endif /* WAITSTUFF_DECLARED */
#endif /* NeXT */

#ifndef WTERMSIG
# ifndef BSDWAIT /* if wait is NOT a union: */
#  define WTERMSIG(status) ((status) & 0177)
# else
#  define WTERMSIG(status) status.w_T.w_Termsig
# endif
#endif

#ifndef WEXITSTATUS
# ifndef BSDWAIT
#  define WEXITSTATUS(status) ((status) & 0xff00) >> 8		/* dgux 5.4.1 */
# else
#  define WEXITSTATUS(status) status.w_T.w_Retcode
# endif
#endif

extern	int	get_child_exit _((int));
extern	int	check_wait_status _((int));
extern	void	check_process_list();
extern	void	check_process_limits();
extern	void	do_processes();
extern	void	set_process_bits();
extern	int	text_to_process();
extern	char	*signals[];
extern	void	clean_up_processes();
extern	int	is_process();
extern	int	get_process_index();
extern	void	exec_server_delete();
extern	int	is_process_running();
extern	void	add_process_wait();
extern	void	set_wait_process();
extern	void	close_all_exec();
extern	int	logical_to_index();
extern	void	execcmd _((char *, char *, char *));

#endif /* _EXEC_H_ */
                                                                                                                                                                                                                        DarkNET-1.08/ircii-2.8.H1/include/flood.h                                                              444   21270   21270          517  5721004062  12600                                                                                                                                                                                                                                                                                                                                                                      /*
 * flood.h: header file for flood.c
 *
 * @(#)$Id: flood.h,v 1.1 1995/02/17 02:21:38 hellcat Exp $
 */

#ifndef _FLOOD_H_
#define _FLOOD_H_

extern	int	check_flooding();

#define MSG_FLOOD 0
#define PUBLIC_FLOOD 1
#define NOTICE_FLOOD 2
#define WALL_FLOOD 3
#define WALLOP_FLOOD 4
#define NUMBER_OF_FLOODS 5

#endif /* _FLOOD_H_ */
                                                                                                                                                                                 DarkNET-1.08/ircii-2.8.H1/include/funny.h                                                              444   21270   21270         1416  5721004062  12653                                                                                                                                                                                                                                                                                                                                                                      /*
 * funny.h: header for funny.c
 *
 * written by michael sandrof
 *
 * copyright(c) 1990 
 *
 * see the copyright file, or do a help ircii copyright 
 *
 * @(#)$Id: funny.h,v 1.1 1995/02/17 02:21:38 hellcat Exp $
 */

#ifndef _FUNNY_H_
#define _FUNNY_H_

#define FUNNY_PUBLIC 1
#define FUNNY_PRIVATE 2
#define FUNNY_TOPIC  4
#define FUNNY_WIDE   8
#define FUNNY_USERS  16
#define FUNNY_NAME   32

extern	void	set_funny_flags();
extern	void	funny_match();
extern	void	reinstate_user_modes();
extern	void	funny_set_ignore_channel();
extern	void	funny_print_widelist();
extern	void	funny_list();
extern	void	funny_mode();
extern	void	funny_namreply();
extern	int	funny_is_ignore_channel();
extern	void	update_user_mode();
extern	void	funny_set_ignore_mode();

#endif /* _FUNNY_H_ */
                                                                                                                                                                                                                                                  DarkNET-1.08/ircii-2.8.H1/include/help.h                                                               444   21270   21270          456  5721004062  12427                                                                                                                                                                                                                                                                                                                                                                      /*
 * help.h: header for help.c
 *
 * copyright(c) 1994 matthew green
 *
 * See the copyright file, or do a help ircii copyright 
 *
 * @(#)$Id: help.h,v 1.1 1995/02/17 02:21:38 hellcat Exp $
 */

#ifndef __help_h
# define __help_h

extern	void	help _((char *, char *, char *));

#endif /* __help_h */
                                                                                                                                                                                                                  DarkNET-1.08/ircii-2.8.H1/include/history.h                                                            444   21270   21270         1057  5721004062  13216                                                                                                                                                                                                                                                                                                                                                                      /*
 * history.h: header for history.c 
 *
 * Written By Michael Sandrof
 *
 * Copyright(c) 1990 
 *
 * See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT 
 *
 * @(#)$Id: history.h,v 1.1 1995/02/17 02:21:38 hellcat Exp $
 */

#ifndef _HISTORY_H_
#define _HISTORY_H_

extern	void	set_history_size();
extern	void	set_history_file();
extern	void	add_to_history();
extern	char	*get_from_history();
extern	char	*do_history();
extern	void	history _((char *, char *, char *));

/* used by get_from_history */
#define NEXT 0
#define PREV 1

#endif /* _HISTORY_H_ */
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 DarkNET-1.08/ircii-2.8.H1/include/hold.h                                                               444   21270   21270         1210  5721004062  12432                                                                                                                                                                                                                                                                                                                                                                      /*
 * hold.h: header for hold.c
 *
 * Written By Michael Sandrof
 *
 * Copyright(c) 1990 
 *
 * See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT 
 *
 * @(#)$Id: hold.h,v 1.1 1995/02/17 02:21:38 hellcat Exp $
 */

#ifndef _HOLD_H_
#define _HOLD_H_

/* Hold: your general doubly-linked list type structure */

typedef struct HoldStru
{
	char	*str;
	struct	HoldStru	*next;
	struct	HoldStru	*prev;
	int	logged;
}	Hold;

extern	void	remove_from_hold_list();
extern	void	add_to_hold_list();
extern	void	hold_mode();
extern	int	hold_output();
extern	char	*hold_queue();
extern	void	reset_hold();
extern	int	hold_queue_logged();

#endif /* _HOLD_H_ */
                                                                                                                                                                                                                                                                                                                                                                                        DarkNET-1.08/ircii-2.8.H1/include/hook.h.proto                                                         444   21270   21270         7171  5721004062  13622                                                                                                                                                                                                                                                                                                                                                                      /*
 * hook.h.proto: header for hook.c
 * 
 * Generated from hook.h.proto by source/Makefile
 *
 * @(#)$Id: hook.h.proto,v 1.1 1995/02/17 02:21:38 hellcat Exp $
 */

#ifndef __hook_h_
# define __hook_h_

/* Hook: The structure of the entries of the hook functions lists */
typedef struct	hook_stru
{
	struct	hook_stru *next;	/* pointer to next element in list */
	char	*nick;			/* The Nickname */
	int	not;			/* If true, this entry should be
					 * ignored when matched, otherwise it
					 * is a normal entry */
	int	noisy;			/* flag indicating how much output
					 * should be given */
	int	server;			/* the server in which this hook
					 * applies. (-1 if none). If bit 0x1000
					 * is set, then no other hooks are
					 * tried in the given server if all the
					 * server specific ones fail
					 */
	int	sernum;			/* The serial number for this hook. This
					 * is used for hooks which will be
					 * concurrent with others of the same
					 * pattern. The default is 0, which
					 * means, of course, no special
					 * behaviour. If any 1 hook suppresses
					 * the * default output, output will be
					 * suppressed.
					 */
	char	*stuff;			/* The this that gets done */
	int	global;			/* set if loaded from `global' */
}	Hook;

/* HookFunc: A little structure to keep track of the various hook functions */
typedef struct
{
	char	*name;			/* name of the function */
	Hook	*list;			/* pointer to head of the list for this
					 * function */
	int	params;			/* number of parameters expected */
	int	mark;
	unsigned flags;
}	HookFunc;

/*
 * NumericList: a special list type to dynamically handle numeric hook
 * requests 
 */
typedef struct numericlist_stru
{
	struct	numericlist_stru *next;
	char	*name;
	Hook	*list;
}	NumericList;

#define	ACTION_LIST $
#define	CHANNEL_NICK_LIST $
#define CHANNEL_SIGNOFF_LIST $
#define CONNECT_LIST $
#define CTCP_LIST $
#define CTCP_REPLY_LIST $
#define	DCC_CHAT_LIST $
#define DCC_CONNECT_LIST $
#define DCC_ERROR_LIST $
#define DCC_LOST_LIST $
#define	DCC_RAW_LIST $
#define DCC_REQUEST_LIST $
#define DISCONNECT_LIST $
#define ENCRYPTED_NOTICE_LIST $
#define ENCRYPTED_PRIVMSG_LIST $
#define EXEC_LIST $
#define EXEC_ERRORS_LIST $
#define EXEC_EXIT_LIST $
#define EXEC_PROMPT_LIST $
#define EXIT_LIST $
#define FLOOD_LIST $
#define HELP_LIST $
#define	HOOK_LIST $
#define IDLE_LIST $
#define INPUT_LIST $
#define INVITE_LIST $
#define JOIN_LIST $
#define LEAVE_LIST $
#define LIST_LIST $
#define MAIL_LIST $
#define MODE_LIST $
#define MSG_LIST $
#define MSG_GROUP_LIST $
#define NAMES_LIST $
#define NICKNAME_LIST $
#define NOTE_LIST $
#define NOTICE_LIST $
#define NOTIFY_SIGNOFF_LIST $
#define NOTIFY_SIGNON_LIST $
#define PUBLIC_LIST $
#define PUBLIC_MSG_LIST $
#define PUBLIC_NOTICE_LIST $
#define PUBLIC_OTHER_LIST $
#define	RAW_IRC_LIST $
#define	SEND_ACTION_LIST $
#define	SEND_DCC_CHAT_LIST $
#define SEND_MSG_LIST $
#define SEND_NOTICE_LIST $
#define SEND_PUBLIC_LIST $
#define	SEND_TALK_LIST $
#define	SERVER_NOTICE_LIST $
#define SIGNOFF_LIST $
#define	TALK_LIST $
#define TIMER_LIST $
#define TOPIC_LIST $
#define WALL_LIST $
#define WALLOP_LIST $
#define WHO_LIST $
#define WIDELIST_LIST $
#define WINDOW_LIST $
#define WINDOW_KILL_LIST $
#define KICK_LIST $

#ifdef ON_KICK
# define NUMBER_OF_LISTS KICK_LIST + 1
#else
# define NUMBER_OF_LISTS WINDOW_KILL_LIST + 1
#endif 

#ifdef USE_STDARG_H
extern	int	do_hook(int, char *, ...);
#else
extern	int	do_hook();
#endif

extern	void	on _((char *, char *, char *));
extern	void	save_hooks();
extern	char	*hook_info;
extern	void	remove_hook();
extern	void	show_hook();

extern	NumericList *numeric_list;
extern	HookFunc hook_functions[];

extern	int	in_on_who;

#endif /* __hook_h_ */
	char	*stuff;			/* The this that gets done */
	int	global;			/* set if loaded from `global' */
}	Hook;

/* HookFunc: A little structure to keep track of the various hook functions */
typedef struct
{
	char	*name;			/* name of the function */
	Hook	*list;			/* pointer to head of the list for this
					 * function */
	int	params;			/* number of parameters expected */
	int	mark;
	unsigned flDarkNET-1.08/ircii-2.8.H1/include/if.h                                                                 444   21270   21270         1163  5721004062  12111                                                                                                                                                                                                                                                                                                                                                                      /*
 * if.h: header for if.c
 *
 * copyright(c) 1994 matthew green
 *
 * See the copyright file, or do a help ircii copyright 
 *
 * @(#)$Id: if.h,v 1.1 1995/02/17 02:21:38 hellcat Exp $
 */

#ifndef __if_h
# define __if_h

extern	char	*next_expr _((char **, char));
extern	void	ifcmd _((char *, char *, char *));
extern	void	whilecmd _((char *, char *, char *));
extern	void	foreach_handler _((char *, char *, char *));
extern	void	foreach _((char *, char *, char *));
extern	void	fe _((char *, char *, char *));
extern	void	forcmd _((char *, char *, char *));
extern	void	fec _((char *, char *, char *));

#endif /* __if_h */
                                                                                                                                                                                                                                                                                                                                                                                                             DarkNET-1.08/ircii-2.8.H1/include/ignore.h                                                             444   21270   21270         1767  5721004062  13010                                                                                                                                                                                                                                                                                                                                                                      /*
 * ignore.h: header for ignore.c 
 *
 * Written By Michael Sandrof
 *
 * Copyright(c) 1990 
 *
 * See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT 
 *
 * @(#)$Id: ignore.h,v 1.1 1995/02/17 02:21:38 hellcat Exp $
 */

#ifndef _IGNORE_H_
#define _IGNORE_H_

/* declared in ignore.c */
extern	int	ignore_usernames;
extern	int	is_ignored();
extern	char	highlight_char;
extern	int	ignore_combo();
extern	int	double_ignore();
extern	void	ignore _((char *, char *, char *));

/* Type of ignored nicks */
#define IGNORE_MSGS	0x0001
#define IGNORE_PUBLIC	0x0002
#define IGNORE_WALLS	0x0004
#define IGNORE_WALLOPS	0x0008
#define IGNORE_INVITES	0x0010
#define IGNORE_NOTICES	0x0020
#define IGNORE_NOTES	0x0040
#define IGNORE_CTCPS	0x0080
#define IGNORE_CRAP	0x0100
#define IGNORE_ALL (IGNORE_MSGS | IGNORE_PUBLIC | IGNORE_WALLS | \
	IGNORE_WALLOPS | IGNORE_INVITES | IGNORE_NOTICES | IGNORE_NOTES | \
	IGNORE_CTCPS | IGNORE_CRAP)

#define IGNORED 1
#define DONT_IGNORE 2
#define HIGHLIGHTED -1

#endif /* _IGNORE_H_ */
         DarkNET-1.08/ircii-2.8.H1/include/input.h                                                              444   21270   21270         1301  5721004062  12644                                                                                                                                                                                                                                                                                                                                                                      /*
 * input.h: header for input.c 
 *
 * Written By Michael Sandrof
 *
 * Copyright(c) 1990 
 *
 * See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT 
 *
 * @(#)$Id: input.h,v 1.1 1995/02/17 02:21:38 hellcat Exp $
 */

#ifndef _INPUT_H_
#define _INPUT_H_

extern	char	input_pause();
extern	void	set_input();
extern	void	set_input_prompt();
extern	char	*get_input_prompt();
extern	char	*get_input();
extern	void	update_input();
extern	void	init_input();
extern	void	input_move_cursor();
extern	void	change_input_prompt();
extern	void	cursor_to_input();

/* used by update_input */
#define NO_UPDATE 0
#define UPDATE_ALL 1
#define UPDATE_FROM_CURSOR 2
#define UPDATE_JUST_CURSOR 3

#endif /* _INPUT_H_ */
                                                                                                                                                                                                                                                                                                                               DarkNET-1.08/ircii-2.8.H1/include/irc.h                                                                644   21270   21270        15115  5731740551  12327                                                                                                                                                                                                                                                                                                                                                                      /*
 * irc.h: header file for all of ircII! 
 *
 * Written By Michael Sandrof
 * Copyright(c) 1990 
 *
 * See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT 
 *
 * @(#)$Id: irc.h,v 1.3 1995/02/17 05:28:48 hellcat Exp $
 */

#ifndef __irc_h
#define __irc_h

#define IRCII_COMMENT   "this is a bug free client.  honest"

#define IRCRC_NAME "/.ircrc"

/*
 * Here you can set the in-line quote character, normally backslash, to
 * whatever you want.  Note that we use two backslashes since a backslash is
 * also C's quote character.  You do not need two of any other character.
 */
#define QUOTE_CHAR '\\'

#if defined(ISC30)		/* for some reason it doesn't get defined */
# define _POSIX_SOURCE
#endif /* ISC30 */

#include "defs.h"
#include "config.h"
#include <stdio.h>
#include <ctype.h>
#include "myctype.h"		/* for hangul - DKIM */
#include <sys/types.h>
#include <sys/socket.h>
#ifndef WINS
#include <netinet/in.h>
#else
#include <sys/twg_config.h>
#include <sys/in.h>
#undef server
#endif
#include <arpa/inet.h>
#include <signal.h>
#include <sys/param.h>

#ifdef TIME_WITH_SYS_TIME
# include <sys/time.h>
# include <time.h>
#else
# ifdef HAVE_SYS_TIME_H
#  include <sys/time.h>
# else
#  include <time.h>
# endif /* HAVE_SYS_TIME_H */
#endif /* TIME_WITH_SYS_TIME */

#ifdef HAVE_SYS_FCNTL_H
# include <sys/fcntl.h>
#else
# ifdef HAVE_FCNTL_H
#  include <fcntl.h>
# endif /* HAVE_FCNTL_H */
#endif /* HAVE_SYS_FCNTL_H */

/* machines we don't want to use <unistd.h> on 'cause its broken */
#if defined(pyr) || defined(_SEQUENT_) || defined(IN_EXEC_C)
# undef HAVE_UNISTD_H
#endif

#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif

#ifdef HAVE_SYS_FILE_H
# include <sys/file.h>
#endif

#ifdef HAVE_NETDB_H
# include <netdb.h>
#endif

#if defined(__QNX__)
# include <sys/select.h>
# include <unix.h>
# define BROKEN_GETPGRP 1
# define USE_STDARG_H
#endif

#ifdef HAVE_STDARG_H
# include <stdarg.h>
#endif

#include "irc_std.h"
#include "debug.h"

/* these define what characters do, inverse, underline, bold and all off */
#define REV_TOG		'\026'		/* ^V */
#define UND_TOG		'\037'		/* ^_ */
#define BOLD_TOG	'\002'		/* ^B */
#define ALL_OFF		'\017'		/* ^O */

#define IRCD_BUFFER_SIZE	1024
#define BIG_BUFFER_SIZE		(IRCD_BUFFER_SIZE * 2)

#ifndef INPUT_BUFFER_SIZE
#define INPUT_BUFFER_SIZE	(IRCD_BUFFER_SIZE / 4)
#endif

#ifdef notdef
# define DAEMON_UID 1
#endif

#define NICKNAME_LEN 9
#define NAME_LEN 80
#define REALNAME_LEN 50
#define PATH_LEN 1024

#if defined(__hpux) || defined(hpux) || defined(_HPUX_SOURCE)
# undef HPUX
# define HPUX
# ifndef HPUX7
#  define killpg(pgrp,sig) kill(-pgrp,sig)
# endif
#endif

#if defined(__sgi)
# define USE_TERMIO
#endif /* __sgi */

#ifdef ultrix
# define USE_TERMIO
#endif

#ifdef DGUX
# define USE_TERMIO
# define inet_addr(x) inet_network(x)	/* dgux lossage */
#endif /* DGUX */

/*
 * Lame Linux doesn't define X_OK in a non-broken header file, so
 * we define it here.. 
 */
#if defined(linux) && !defined(X_OK)
# define X_OK  1
#endif /* linux */

#if __osf__
# define _BSD
#endif

#if defined(UNICOS) && !defined(USE_TERMIO)
# define USE_TERMIO
#endif /* UNICOS */

/* systems without getwd() can lose, if this dies */
#if defined(NEED_GETCWD)
# define getcwd(b, c)	getwd(b);
#endif

#if defined(ISC22) || defined(ISC30)
# define USE_TERMIO
# define ISC
#endif /* ISC22 || ISC30 */

#if defined(_AUX_SOURCE) && !defined(USE_TERMIO)
# define USE_TERMIO
#endif

#ifdef MAIL_DIR
# undef UNIX_MAIL
# define UNIX_MAIL MAIL_DIR
#endif

/* flags used by who() and whoreply() for who_mask */
#define WHO_OPS		0x0001
#define WHO_NAME	0x0002
#define WHO_ZERO	0x0004
#define WHO_CHOPS	0x0008
#define WHO_FILE	0x0010
#define WHO_HOST	0x0020
#define WHO_SERVER	0x0040
#define	WHO_HERE	0x0080
#define	WHO_AWAY	0x0100
#define	WHO_NICK	0x0200
#define	WHO_LUSERS	0x0400
#define	WHO_REAL	0x0800

/*
 (* Some defines in case we're using IRCII setuid->root, so that we can bind
 * to privileged ports. This will allow future IRC nets to verify the true
 * identity of users much more reliably.
 */
#ifdef PRIV_PORT
# define	open		ruid_open
# define	fopen		ruid_fopen
# define	system		ruid_system
# define	unlink		ruid_unlink
# define	stat_file	ruid_stat
#ifdef EOF	/* defined if stdio.h has been included */
extern FILE *ruid_fopen();
# endif /*EOF*/
extern	int	ruid_open();
extern	int	ruid_system();
extern	int	ruid_unlink();
#else
# define stat_file stat
#endif /*PRIV_PORT*/

/*
 * declared in irc.c 
 */
extern	char	*cut_buffer;
extern	char	oper_command;
extern	int	irc_port;
extern	int	send_text_flag;
extern	int	irc_io_loop;
extern	int	break_io_processing;
extern	int	use_flow_control;
extern	char	*joined_nick;
extern	char	*public_nick;
extern	char	empty_string[];

extern	char	irc_version[];
extern	char	internal_version[];
extern	char	buffer[];
extern	char	nickname[];
extern	char	*ircrc_file;
extern	char	hostname[];
extern	char	realname[];
extern	char	username[];
extern	char	*send_umode;
extern	char	*last_notify_nick;
extern	int	away_set;
extern	int	background;
extern	char	*my_path;
extern	char	*irc_path;
extern	char	*irc_lib;
extern	char	*args_str;
extern	char	*invite_channel;
extern	int	who_mask;
extern	char	*who_name;
extern	char	*who_host;
extern	char	*who_server;
extern	char	*who_file;
extern	char	*who_nick;
extern	char	*who_real;
extern	char	*cannot_open;
extern	char	global_all_off[];
extern	int	dumb;
extern	int	use_input;
extern	time_t	idle_time;
extern	int	waiting;
extern	char	wait_nick[];
extern	char	whois_nick[];
extern	char	lame_wait_nick[];
extern	char	**environ;
extern	int	current_numeric;
extern	int	new_select();
extern	int	quick_startup;

extern	struct	in_addr	local_ip_address;
extern	int	irc_io();
extern	int	dgets();
extern	time_t	dgets_timeout();
extern	char	*current_channel();
extern	void	new_stty();
extern	int	wild_match();
extern	char	*new_malloc();
extern	void	do_server();
extern	char	*get_server_nickname();
extern  int     connect_by_number();
extern	int	is_channel();
extern	void	irc_exit();
extern	void	new_close();
extern	void	beep_em();
extern	void	set_socket_options _((int));

typedef	struct	WhoisStuffStru
{
	char	*nick;
	char	*user;
	char	*host;
	char	*channel;
	char	*channels;
	char	*name;
	char	*server;
	char	*server_stuff;
	char	*away;
	int	oper;
	int	chop;
	int	not_on;
}	WhoisStuff;

/* Moved into here, because some weird CC's can't do (void *) */
typedef	struct	WhoisQueueStru
{
	char	*nick;			/* nickname of whois'ed person(s) */
	char	*text;			/* additional text */
	int	type;			/* Type of WHOIS queue entry */
	/*
	 * called with func((WhoisStuff *)stuff,(char *) nick, (char *) text) 
	 */
	void	(*func)();
	struct	WhoisQueueStru	*next;/* next element in queue */
}	WhoisQueue;

extern	char	*getenv();

#endif /* __irc_h */
                                                                                                                                                                                                                                                                                                                                                                                                                                                   DarkNET-1.08/ircii-2.8.H1/include/irc_std.h                                                            444   21270   21270         6317  5721004062  13150                                                                                                                                                                                                                                                                                                                                                                      /*
 * irc_std.h: header to define things used in all the programs ircii
 * comes with
 *
 * hacked together from various other files by matthew green
 * copyright(c) 1993 
 *
 * See the copyright file, or do a help ircii copyright 
 *
 * @(#)$Id: irc_std.h,v 1.1 1995/02/17 02:21:38 hellcat Exp $
 */

#ifndef __irc_std_h
#define __irc_std_h

#undef _
#if defined(__STDC__)
# define _(a) a
#else
# define _(a) ()
# define const
#endif

#ifdef _IBMR2
# include <sys/errno.h>
# include <sys/select.h>
#else
# include <errno.h>
extern	int	errno;
#endif /* _IBMR2 */

#ifdef TRUE
# define TRUE 1
#endif /* TRUE */

#ifndef FALSE
# define FALSE !TRUE
#endif /* FALSE */

#ifndef NBBY
# define NBBY	8		/* number of bits in a byte */
#endif /* NBBY */

#ifndef NFDBITS
# define NFDBITS	(sizeof(long) * NBBY)	/* bits per mask */
#endif /* NFDBITS */

#ifndef FD_SET
# define FD_SET(n, p)	((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
#endif /* FD_SET */

#ifndef FD_CLR
# define FD_CLR(n, p)	((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
#endif /* FD_CLR */

#ifndef FD_ISSET
# define FD_ISSET(n, p)	((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
#endif /* FD_ISSET */

#ifndef FD_ZERO
# define FD_ZERO(p)	bzero((char *)(p), sizeof(*(p)))
#endif /* FD_ZERO */

#ifndef	FD_SETSIZE
# define FD_SETSIZE	32
#endif

#ifdef USE_SIGACTION

typedef RETSIGTYPE sigfunc _((int));
sigfunc *my_signal _((int, sigfunc *, int));

# define MY_SIGNAL(s_n, s_h, m_f) my_signal(s_n, s_h, m_f)
#else
# if USE_SIGSET
#  define MY_SIGNAL(s_n, s_h, m_f) sigset(s_n, s_h)
# else
#  define MY_SIGNAL(s_n, s_h, m_f) signal(s_n, s_h)
# endif /* USE_SIGSET */
#endif /* USE_SIGACTION */

#if defined(USE_SIGACTION) || defined(USE_SIGSET)
# undef SYSVSIGNALS
#endif

#if defined(__svr4__) && !defined(SVR4)
# define SVR4
#else
# if defined(SVR4) && !defined(__svr4__)
#  define __svr4__
# endif
#endif

#ifdef _SEQUENT_
# define	u_short	ushort
# define	u_char	unchar
# define	u_long	ulong
# define	u_int	uint
# define	USE_TERMIO
# ifndef POSIX
#  define POSIX
# endif
#endif /* _SEQUENT_ */

#ifndef NeXT
# if defined(STDC_HEADERS) || defined(HAVE_STRING_H)
#  include <string.h>
#  include <stdlib.h>
#  if defined(HAVE_MEMORY_H)
#   include <memory.h>
#  endif /* HAVE_MEMORY_H */
#  undef index
#  undef rindex
#  undef bcopy
#  undef bzero
#  undef bcmp
#  define index strchr
#  define rindex strrchr
#  ifdef HAVE_MEMMOVE
#   define bcopy(s, d, n) memmove((d), (s), (n))
#  else
#   define bcopy(s, d, n) memcpy ((d), (s), (n))
#  endif
#  define bcmp(s, t, n) memcmp ((s), (t), (n))
#  define bzero(s, n) memset ((s), 0, (n))
# else /* STDC_HEADERS || HAVE_STRING_H */
#  include <strings.h>
# endif /* STDC_HEADERS || HAVE_STRING_H */
#endif /* !NeXT */

#ifndef SYS_ERRLIST_DECLARED
extern	char	*sys_errlist[];
extern	int	sys_nerr;
#endif

#ifdef NEED_STRERROR
# undef strerror
# define strerror(e) ((e) < 0 || (e) >= sys_nerr ? "(unknown)" : sys_errlist[e])
#endif

/* we need an unsigned 32 bit integer for dcc, how lame */

#ifdef UNSIGNED_LONG32

typedef		unsigned long		u_32int_t;

#else
# ifdef UNSIGNED_INT32

typedef		unsigned int		u_32int_t;

# else

typedef		unsigned long		u_32int_t;

# endif /* UNSIGNED_INT32 */
#endif /* UNSIGNED_LONG32 */

#endif /* __irc_std_h */
char *)(p), sizeof(*(p)))
#endif /* FD_ZERO */

#ifndef	FD_SETSIZE
# define FD_SETSIZE	32
#endif

#ifdef USE_SIGACTION

typedef RETSIGTYPE sigfunc _((int));
sigfunc *my_signal _((int, sigfunc *, int));

# define MY_SIGNAL(s_n, s_h, m_f) my_signal(s_n, s_h, m_f)
#else
# if USE_SIGSET
#  define MY_SIGNAL(sDarkNET-1.08/ircii-2.8.H1/include/ircaux.h                                                             444   21270   21270         1712  5721004063  13007                                                                                                                                                                                                                                                                                                                                                                      /*
 * ircaux.h: header file for ircaux.c 
 *
 * Written By Michael Sandrof
 *
 * Copyright(c) 1990 
 *
 * See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT 
 *
 * @(#)$Id: ircaux.h,v 1.1 1995/02/17 02:21:38 hellcat Exp $
 */

#ifndef _IRCAUX_H_
#define _IRCAUX_H_

#include <stdio.h>

extern	char	*check_nickname();
extern	char	*next_arg();
extern	char	*new_next_arg();
extern	char	*expand_twiddle();
extern	char	*upper();
extern	char	*sindex();
extern	char	*rfgets();
extern	char	*path_search();
extern	char	*double_quote();
extern	char	*new_malloc();
extern	char	*new_realloc();
extern	void	malloc_strcpy();
extern	void	malloc_strcat();
extern	void	new_free();
extern	void	wait_new_free();
extern	FILE	*zcat();
extern	int	is_number();
extern	int	my_stricmp _((char *, char *));
extern	int	my_strnicmp _((char *, char *, int));
extern	int	scanstr _((char *, char *));
extern	void	really_free();
extern	void	strmcpy();
extern	void	strmcat();

#endif /* _IRCAUX_H_ */
                                                      DarkNET-1.08/ircii-2.8.H1/include/keys.h.proto                                                         444   21270   21270         4370  5721004063  13634                                                                                                                                                                                                                                                                                                                                                                      /*
 * keys.h: header for keys.c 
 *
 * Written By Michael Sandrof
 *
 * Copyright(c) 1990 
 *
 * See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT 
 *
 * This file is automatically created by keys.h.proto.
 *
 * @(#)$Id: keys.h.proto,v 1.1 1995/02/17 02:21:38 hellcat Exp $
 */

#ifndef __keys_h
#define __keys_h

#define BACKSPACE $
#define BACKWARD_CHARACTER $
#define BACKWARD_HISTORY $
#define BACKWARD_WORD $
#define BEGINNING_OF_LINE $
#define CLEAR_SCREEN $
#define COMMAND_COMPLETION $
#define DELETE_CHARACTER $
#define DELETE_NEXT_WORD $
#define DELETE_PREVIOUS_WORD $
#define END_OF_LINE $
#define ENTER_DIGRAPH $
#define	ENTER_MENU $
#define ERASE_LINE $
#define ERASE_TO_BEG_OF_LINE $
#define ERASE_TO_END_OF_LINE $
#define FORWARD_CHARACTER $
#define FORWARD_HISTORY $
#define FORWARD_WORD $
#define META1_CHARACTER $
#define META2_CHARACTER $
#define META3_CHARACTER $
#define META4_CHARACTER $
#define NEXT_WINDOW $
#define NOTHING $
#define PARSE_COMMAND $
#define PREVIOUS_WINDOW $
#define QUIT_IRC $
#define QUOTE_CHARACTER $
#define REFRESH_INPUTLINE $
#define REFRESH_SCREEN $
#define	SCROLL_BACKWARD $
#define	SCROLL_END $
#define SCROLL_FORWARD $
#define SCROLL_START $
#define SELF_INSERT $
#define SEND_LINE $
#define STOP_IRC $
#define SWAP_LAST_WINDOW $
#define SWAP_NEXT_WINDOW $
#define SWAP_PREVIOUS_WINDOW $
#define SWITCH_CHANNELS $
#define TOGGLE_INSERT_MODE $
#define TOGGLE_STOP_SCREEN $
#define TRANSPOSE_CHARACTERS $
#define TYPE_TEXT $
#define UNSTOP_ALL_WINDOWS $
#define YANK_FROM_CUTBUFFER $
#define NUMBER_OF_FUNCTIONS $

/* KeyMap: the structure of the irc keymaps */
typedef struct
{
	int	index;
	char	changed;
	int	global;
	char	*stuff;
}	KeyMap;

/* KeyMapNames: the structure of the keymap to realname array */
typedef struct
{
	char	*name;
	void	(*func) ();
}	KeyMapNames;

extern	KeyMap	keys[],
		meta1_keys[],
		meta2_keys[],
		meta3_keys[],
		meta4_keys[];
extern	KeyMapNames key_names[];

extern	void	(* get_send_line())();
extern	void	save_bindings();
extern	void	input_add_character();
extern	void	change_send_line();
extern	void	bindcmd _((char *, char *, char *));
extern	void	rbindcmd _((char *, char *, char *));
extern	void	parsekeycmd _((char *, char *, char *));
extern	void	type _((char *, char *, char *));

#endif /* __keys_h */
                                                                                                                                                                                                                                                                        DarkNET-1.08/ircii-2.8.H1/include/lastlog.h                                                            444   21270   21270         2615  5721004063  13164                                                                                                                                                                                                                                                                                                                                                                      /*
 * lastlog.h: header for lastlog.c 
 *
 * Written By Michael Sandrof
 *
 * Copyright(c) 1990 
 *
 * See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT 
 *
 * @(#)$Id: lastlog.h,v 1.1 1995/02/17 02:21:38 hellcat Exp $
 */

#ifndef __lastlog_h_
#define __lastlog_h_

typedef struct	lastlog_stru
{
	int	level;
	char	*msg;
	struct	lastlog_stru	*next;
	struct	lastlog_stru	*prev;
}	Lastlog;

#define LOG_NONE	0x000000
#define LOG_CURRENT	0x000000
#define LOG_CRAP	0x000001
#define LOG_PUBLIC	0x000002
#define LOG_MSG		0x000004
#define LOG_NOTICE	0x000008
#define LOG_WALL	0x000010
#define LOG_WALLOP	0x000020
#define LOG_NOTES	0x000040
#define LOG_OPNOTE	0x000080
#define	LOG_SNOTE	0x000100
#define	LOG_ACTION	0x000200
#define	LOG_DCC		0x000400
#define LOG_CTCP	0x000800
#define	LOG_USER1	0x001000
#define LOG_USER2	0x002000
#define LOG_USER3	0x004000
#define LOG_USER4	0x008000

#define LOG_ALL (LOG_CRAP | LOG_PUBLIC | LOG_MSG | LOG_NOTICE | LOG_WALL | \
		LOG_WALLOP | LOG_NOTES | LOG_OPNOTE | LOG_SNOTE | LOG_ACTION | \
		LOG_CTCP | LOG_DCC )

extern	void	set_lastlog_level();
extern	int	set_lastlog_msg_level();
extern	void	set_lastlog_size();
extern	void	set_notify_level();
extern	void	lastlog();
extern	void	add_to_lastlog();
extern	char	*bits_to_lastlog_level();
extern	int	real_lastlog_level();
extern	int	real_notify_level();
extern	int	parse_lastlog_level();
extern	int	islogged();

#endif /* __lastlog_h_ */
                                                                                                                   DarkNET-1.08/ircii-2.8.H1/include/list.h                                                               444   21270   21270         1153  5721004063  12466                                                                                                                                                                                                                                                                                                                                                                      /*
 * list.h: header for list.c 
 *
 * Written By Michael Sandrof
 *
 * Copyright(c) 1990 
 *
 * See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT 
 *
 * @(#)$Id: list.h,v 1.1 1995/02/17 02:21:38 hellcat Exp $
 */

#ifndef _LIST_H_
#define _LIST_H_

typedef	struct	list_stru
{
	struct	list_stru	*next;
	char	*name;
}	List;

extern	void	add_to_list();
extern	List	*find_in_list();
extern	List	*remove_from_list();
extern	List	*list_lookup();
extern	List	*remove_from_list_ext();
extern	void	add_to_list_ext();
extern	List	*find_in_list_ext();

#define REMOVE_FROM_LIST 1
#define USE_WILDCARDS 1

#endif /* _LIST_H */
                                                                                                                                                                                                                                                                                                                                                                                                                     DarkNET-1.08/ircii-2.8.H1/include/log.h                                                                444   21270   21270          561  5721004063  12256                                                                                                                                                                                                                                                                                                                                                                      /*
 * log.h: header for log.c 
 *
 * Written By Michael Sandrof
 *
 * Copyright(c) 1990 
 *
 * See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT 
 *
 * @(#)$Id: log.h,v 1.1 1995/02/17 02:21:38 hellcat Exp $
 */

#ifndef _LOG_H_
#define _LOG_H_

extern	FILE	*do_log();
extern	void	logger();
extern	void	set_log_file();
extern	void	add_to_log();

#endif /* _LOG_H_ */
                                                                                                                                               DarkNET-1.08/ircii-2.8.H1/include/mail.h                                                               444   21270   21270          516  5721004063  12417                                                                                                                                                                                                                                                                                                                                                                      /*
 * mail.h: header for mail.c
 *
 * Written By Michael Sandrof
 *
 * Copyright(c) 1990 
 *
 * See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT 
 *
 * @(#)$Id: mail.h,v 1.1 1995/02/17 02:21:38 hellcat Exp $
 */

#ifndef _MAIL_H_
#define _MAIL_H_

extern	char	*check_mail();
extern	int	check_mail_status();

#endif /* _MAIL_H_ */
                                                                                                                                                                                  DarkNET-1.08/ircii-2.8.H1/include/menu.h                                                               444   21270   21270         1700  5721004063  12455                                                                                                                                                                                                                                                                                                                                                                      /*
 * Here we define how our menus are held
 *
 * @(#)$Id: menu.h,v 1.1 1995/02/17 02:21:38 hellcat Exp $
 */

#ifndef _MENU_H_
#define _MENU_H_

#define IRCII_MENU_H

#define	SMF_ERASE	0x0001
#define	SMF_NOCURSOR	0x0002
#define	SMF_CURSONLY	0x0004
#define	SMF_CALCONLY	0x0008

struct	MenuOptionTag
{
	char	*Name;
	char	*Arguments;
	void	(*Func)();
};

typedef	struct	MenuOptionTag	MenuOption;

struct	MenuTag
{
	struct	MenuTag	*next;
	char	*Name;
	int	TotalOptions;
	MenuOption	**Options;
};

typedef struct MenuTag Menu;

/* Below are our known menu functions */
extern	void	menu_previous();	/* Go to previous menu */
extern	void	menu_submenu();		/* Invoke a submenu */
extern	void	menu_exit();		/* Exit the menu */
extern	void	menu_channels();	/* List of channels menu */
extern	void	menu_command();		/* Invoke an IRCII command */
extern	void	menu_key();
extern	void	load_menu();
extern	int	ShowMenu();
extern	int	ShowMenuByWindow();

#endif /* _MENU_H_ */
                                                                DarkNET-1.08/ircii-2.8.H1/include/names.h                                                              444   21270   21270         4317  5721004063  12623                                                                                                                                                                                                                                                                                                                                                                      /*
 * names.h: Header for names.c
 *
 * Written By Michael Sandrof
 *
 * Copyright(c) 1990 
 *
 * See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT 
 *
 * @(#)$Id: names.h,v 1.1 1995/02/17 02:21:38 hellcat Exp $
 */

#ifndef _NAMES_H_
#define _NAMES_H_

#include "window.h"
#include "irc.h"

/* from names.c - "iklmnpst" */
#define MODE_INVITE	((u_long) 0x0001)
#define MODE_KEY	((u_long) 0x0002)
#define MODE_LIMIT	((u_long) 0x0004)
#define MODE_MODERATED	((u_long) 0x0008)
#define MODE_MSGS	((u_long) 0x0010)
#define MODE_PRIVATE	((u_long) 0x0020)
#define MODE_SECRET	((u_long) 0x0040)
#define MODE_TOPIC	((u_long) 0x0080)

/* ChannelList: structure for the list of channels you are current on */
typedef	struct	channel_stru
{
	struct	channel_stru	*next;	/* pointer to next channel entry */
	char	*channel;		/* channel name */
	int	server;			/* server index for this channel */
	u_long	mode;			/* Current mode settings for channel */
	u_long	i_mode;			/* channel mode for cached string */
	char	*s_mode;		/* cached string version of modes */
	int	limit;			/* max users for the channel */
	char	*key;			/* key for this channel */
	char	chop;			/* true if you are chop */
	Window	*window;		/* the window that the channel is "on" */
	NickList	*nicks;		/* pointer to list of nicks on channel */
}	ChannelList;

extern	int	is_channel_mode();
extern	int	is_chanop();
extern	ChannelList	*lookup_channel();
extern	char	*get_channel_mode();
extern	void	add_channel();
extern	void	add_to_channel _((char *, char *, int, int, int));
extern	void	remove_channel();
extern	void	remove_from_channel();
extern	int	is_on_channel();
extern	void	list_channels();
extern	void	reconnect_all_channels();
extern	void	switch_channels();
extern	char	*what_channel();
extern	char	*walk_channels();
extern	char	*real_channel();
extern	char	*old_current_channel();
extern	void	rename_nick();
extern	void	update_channel_mode();
extern	void	set_channel_window();
extern	char	*create_channel_list();
extern	int	get_channel_oper();
extern	void	channel_server_delete();
extern	void	change_server_channels();
extern	void	clear_channel_list();
extern	char	*channel_key();
extern	void	set_waiting_channel _((int));
extern	void	remove_from_mode_list _((char *));

#endif /* _NAMES_H_ */
                                                                                                                                                                                                                                                                                                                 DarkNET-1.08/ircii-2.8.H1/include/notify.h                                                             444   21270   21270          736  5721004063  13011                                                                                                                                                                                                                                                                                                                                                                      /*
 * notify.h: header for notify.c
 *
 * Written By Michael Sandrof
 *
 * Copyright(c) 1990 
 *
 * See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT 
 *
 * @(#)$Id: notify.h,v 1.1 1995/02/17 02:21:38 hellcat Exp $
 */

#ifndef _NOTIFY_H_
#define _NOTIFY_H_

extern	void	notify _((char *, char *, char *));
extern	void	do_notify();
extern	void	notify_mark _((char *, int, int));
extern	void	save_notify();
extern	void	set_notify_handler _((char *));

#endif /* _NOTIFY_H_ */
                                  DarkNET-1.08/ircii-2.8.H1/include/numbers.h                                                            444   21270   21270          577  5721004063  13157                                                                                                                                                                                                                                                                                                                                                                      /*
 * numbers.h: header for numbers.c
 *
 * written by michael sandrof
 *
 * copyright(c) 1990 
 *
 *
 * @(#)$Id: numbers.h,v 1.1 1995/02/17 02:21:38 hellcat Exp $
 * see the copyright file, or do a help ircii copyright 
 */

#ifndef _NUMBERS_H_
#define _NUMBERS_H_

extern	char	*numeric_banner();
extern	void	display_msg();
extern	void	numbered_command();

#endif /* _NUMBERS_H_ */
                                                                                                                                 DarkNET-1.08/ircii-2.8.H1/include/output.h                                                             444   21270   21270         1401  5721004063  13047                                                                                                                                                                                                                                                                                                                                                                      /*
 * output.h: header for output.c 
 *
 * Written By Michael Sandrof
 *
 * Copyright(c) 1990 
 *
 * See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT 
 *
 * @(#)$Id: output.h,v 1.1 1995/02/17 02:21:38 hellcat Exp $
 */

#ifndef _OUTPUT_H_
#define _OUTPUT_H_

# ifdef USE_STDARG_H
extern	void	put_it(char *, ...);
extern	void	send_to_server(char *, ...);
extern	void	say(char *, ...);
extern	void	yell(char *, ...);
extern	void	help_put_it(char *, char *, ...);
# else
extern	void	put_it();
extern	void	send_to_server();
extern	void	say();
extern	void	yell();
extern	void	help_put_it();
# endif

extern	RETSIGTYPE	refresh_screen();
extern	void	init_screen();
extern	void	set_continued_line();
extern	FILE	*irclog_fp;
extern	void	put_file();

#endif /* _OUTPUT_H_ */
                                                                                                                                                                                                                                                               DarkNET-1.08/ircii-2.8.H1/include/parse.h                                                              444   21270   21270          477  5721004063  12615                                                                                                                                                                                                                                                                                                                                                                      /*
 * parse.h
 *
 * written by matthew green
 * copyright (c) 1993
 *
 * @(#)$Id: parse.h,v 1.1 1995/02/17 02:21:38 hellcat Exp $
 */

#ifndef __parse_h_
# define __parse_h_

extern	char	*PasteArgs();
extern	void	parse_server _((char *));

extern	char	*FromUserHost;

extern	int	doing_privmsg;

#endif /* __parse_h_ */
                                                                                                                                                                                                 DarkNET-1.08/ircii-2.8.H1/include/queue.h                                                              444   21270   21270          470  5721004063  12620                                                                                                                                                                                                                                                                                                                                                                      /*
 * queue.h: header for queue.c
 *
 * copyright(c) 1994 matthew green
 *
 * See the copyright file, or do a help ircii copyright 
 *
 * @(#)$Id: queue.h,v 1.1 1995/02/17 02:21:38 hellcat Exp $
 */

#ifndef __queue_h
# define __queue_h

extern	void	queuecmd _((char *, char *, char *));

#endif /* __queue_h */
                                                                                                                                                                                                        DarkNET-1.08/ircii-2.8.H1/include/screen.h                                                             444   21270   21270         6062  5721004063  12776                                                                                                                                                                                                                                                                                                                                                                      /*
 * screen.h: header for screen.c
 *
 * written by matthew green.
 *
 * copyright (c) 1993, 1994.
 *
 * see the copyright file, or type help ircii copyright
 *
 * @(#)$Id: screen.h,v 1.1 1995/02/17 02:21:38 hellcat Exp $
 */

#ifndef _SCREEN_H_
#define _SCREEN_H_

#include "window.h"

#define WAIT_PROMPT_LINE        0x01
#define WAIT_PROMPT_KEY         0x02

typedef struct PromptStru
{
	char	*prompt;
	char	*data;
	int	type;
	void	(*func)();
	struct	PromptStru	*next;
}	WaitPrompt;


typedef	struct	ScreenStru
{
	int	screennum;
	Window	*current_window;
	unsigned int	last_window_refnum;	/* reference number of the
						 * window that was last
						 * the current_window */
	Window	*window_list;			/* List of all visible
						 * windows */
	Window	*window_list_end;		/* end of visible window
						 * list */
	Window	*cursor_window;			/* Last window to have
						 * something written to it */
	int	visible_windows;		/* total number of windows */
	WindowStack	*window_stack;		/* the windows here */

	int	meta1_hit;			/* if meta1 is hit in this
						 * screen or not */
	int	meta2_hit;			/* above, for meta2 */
	int	meta3_hit;			/* above, for meta3 */
	int	meta4_hit;			/* above, for meta4 */
	int	quote_hit;			/* true if a key bound to
						 * QUOTE_CHARACTER has been
						 * hit. */
	int	digraph_hit;			/* A digraph key has been hit */
	int	inside_menu;			/* what it says. */

	unsigned char	digraph_first;

	struct	ScreenStru *prev;		/* These are the Screen list */
	struct	ScreenStru *next;		/* pointers */

	FILE	*fpin;				/* These are the file pointers */
	int	fdin;				/* and descriptions for the */
	FILE	*fpout;				/* screen's input/output */
	int	fdout;

	char	input_buffer[INPUT_BUFFER_SIZE+1];	/* the input buffer */
	int	buffer_pos;			/* and the positions for the */
	int	buffer_min_pos;			/* screen */

	char	saved_input_buffer[INPUT_BUFFER_SIZE+1];
	int	saved_buffer_pos;
	int	saved_min_buffer_pos;

	WaitPrompt	*promptlist;

	char	*redirect_name;
	char	*redirect_token;
	int	redirect_server;

	char	*tty_name;
	int	co;
	int	li;

	int	alive;
}	Screen;

/* Stuff for the screen/xterm junk */

#define ST_NOTHING      -1
#define ST_SCREEN       0
#define ST_XTERM        1

/* This is here because it happens in so many places */
#define curr_scr_win	current_screen->current_window

extern	void	scrollback_forwards();
extern	void	scrollback_end();
extern	void	clear_window();
extern	void	recalculate_window_positions();
extern	int	output_line();
extern	void	recalculate_windows();
extern	void	scrollback_backwards();
extern	Window	*create_additional_screen();
extern	void	scroll_window();
extern	Window	*new_window();
extern	void	update_all_windows();
extern	void	add_wait_prompt();
extern	void	clear_all_windows();
extern	void	cursor_in_display();
extern	int	is_cursor_in_display();
extern	void	cursor_not_in_display();
extern	void	set_current_screen();
extern	void	redraw_resized();
extern	void	close_all_screen _((void));

extern	Window	*to_window;
extern	Screen	*current_screen;
extern	Screen	*main_screen;
extern	Screen	*last_input_screen;
extern	Screen	*screen_list;

#endif /* _SCREEN_H_ */
 */
	int	meta2_hit;			/* above, for meta2 */
	int	meta3_hit;			/* above, for meta3 */
	int	meta4_hit;			/* above, for meta4 */
	int	quote_hit;			/* true if a key bound to
						 * QUOTE_CHARACTER has been
						 * hit. */
	int	digraph_hit;			/* A digraph key has been hit */
	int	inside_menu;			/* what it says. */

	unsigned char	digraph_first;

	struct	ScreenStru *prev;		/* These are the Screen list */
	struct	ScreenStru *next;		/* pointers */

	FILE	*fpin;	DarkNET-1.08/ircii-2.8.H1/include/server.h                                                             644   21270   21270         7644  5731746600  13051                                                                                                                                                                                                                                                                                                                                                                      /*
 * server.h: header for server.c 
 *
 * Written By Michael Sandrof
 *
 * Copyright(c) 1990 
 *
 * See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT 
 *
 * @(#)$Id: server.h,v 1.1 1995/02/17 02:21:38 hellcat Exp $
 */

#ifndef _SERVER_H_
#define _SERVER_H_
  
/*
 * type definition to distinguish different
 * server versions
 */
#define Server2_5	0
#define Server2_6	1
#define Server2_7	2
#define Server2_8	3
#define Server2_9	4
#define Server2_10	5

/* Server: a structure for the server_list */
typedef	struct
{
	char	*name;			/* the name of the server */
	char	*itsname;		/* the server's idea of its name */
	char	*password;		/* password for that server */
	int	port;			/* port number on that server */
	char	*nickname;		/* nickname for this server */
	char	*away;			/* away message for this server */
	int	operator;		/* true if operator */
	int	version;		/* the version of the server -
					 * defined above */
	char	*version_string;	/* what is says */
	int	whois;			/* true if server sends numeric 318 */
	int	flags;			/* Various flags */
	int	connected;		/* true if connection is assured */
	int	write;			/* write descriptor */
	int	read;			/* read descriptior */
	pid_t	pid;			/* process id of server */
	int	eof;			/* eof flag for server */
	int	motd;			/* motd flag (used in notice.c) */
	int	sent;			/* set if something has been sent,
					 * used for redirect */
	char	*buffer;		/* buffer of what dgets() doesn't get */
	WhoisQueue	*WQ_head;	/* WHOIS Queue head */
	WhoisQueue	*WQ_tail;	/* WHOIS Queue tail */
	WhoisStuff	whois_stuff;	/* Whois Queue current collection buffer */
	struct in_addr local_addr;	/* ip address of this connection */
}	Server;

typedef	unsigned	short	ServerType;

extern	void	add_to_server_list();
extern	void	build_server_list();
extern	int	connect_to_server();
extern	void	get_connected();
extern	int	read_server_file();
extern	void	display_server_list();
extern	char	*current_server_password();
extern	int	server_list_size();
# ifdef USE_STDARG_H
extern	void	send_to_server(char *, ...);
# else
extern	void	send_to_server(char*, char*, char*, char*,
		char*, char*, char*, char*, char*, char*, char*);
# endif
extern	int	get_server_whois _((int));

extern	WhoisStuff	*get_server_whois_stuff();
extern	WhoisQueue	*get_server_qhead();
extern	WhoisQueue	*get_server_qtail();

extern	int	attempting_to_connect;
extern	int	number_of_servers;
extern	int	connected_to_server;
extern	int	never_connected;
extern	int	using_server_process;
extern	int	primary_server;
extern	int	from_server;
extern	char	*connect_next_nick;
extern	int	parsing_server_index;

extern	void	server _((char *, char *, char *));
extern	char	*get_server_nickname();
extern	char	*get_server_name();
extern	char	*get_server_itsname();
extern	void	set_server_flag();
extern	int	find_in_server_list();
extern	char	*create_server_list();
extern	void	set_server_motd();
extern	int	get_server_motd();
extern	int	get_server_operator();
extern	int	get_server_2_6_2();
extern	int	get_server_version();
extern	void	close_server();
extern	void	MarkAllAway();
extern	int	is_server_connected();
extern	void	flush_server();
extern	int	get_server_flag();
extern	void	set_server_operator();
extern	void	server_is_connected();
extern	int	parse_server_index();
extern	void	parse_server_info();
extern	void	set_server_bits();
extern	void	set_server_itsname();
extern	void	set_server_version();
extern	int	is_server_open();
extern	int	get_server_port();
extern	char	*set_server_password();
extern	void	set_server_nickname();
extern	void	set_server_2_6_2();
extern	void	set_server_qhead();
extern	void	set_server_qtail();
extern	void	set_server_whois();
extern	void	close_all_server _((void));
extern	void	disconnectcmd _((char *, char *, char *));

/* server_list: the list of servers that the user can connect to,etc */
extern	Server	*server_list;

#define	SERVER_2_6_2	0x0001
#define	USER_MODE_I	0x0002
#define	USER_MODE_W	0x0004
#define	USER_MODE_S	0x0008
#define CLOSING_SERVER	0x0010

#endif /* _SERVER_H_ */
                                                                                            DarkNET-1.08/ircii-2.8.H1/include/stack.h                                                              444   21270   21270         1366  5721004063  12626                                                                                                                                                                                                                                                                                                                                                                      /*
 * stack.h - header for stack.c
 *
 * written by matthew green
 *
 * copyright (c) 1993, 1994.
 *
 * @(#)$Id: stack.h,v 1.1 1995/02/17 02:21:38 hellcat Exp $
 */

#ifndef __stack_h_
# define __stack_h_

#include "hook.h"
#include "alias.h"

extern	void	stackcmd  _((char *, char *, char *));

#define STACK_POP 0
#define STACK_PUSH 1
#define STACK_SWAP 2
#define STACK_LIST 3

#define STACK_DO_ALIAS	0x0001
#define STACK_DO_ASSIGN	0x0002

typedef	struct	setstacklist
{
	int	which;
	Hook	*list;
	struct setstacklist *next;
}	SetStack;

typedef	struct	aliasstacklist
{
	int	which;
	Alias	*list;
	struct aliasstacklist *next;
}	AliasStack;

typedef	struct	onstacklist
{
	int	which;
	Hook	*list;
	struct onstacklist *next;
}	OnStack;

#endif /* __stack_h_ */
                                                                                                                                                                                                                                                                          DarkNET-1.08/ircii-2.8.H1/include/status.h                                                             444   21270   21270         1013  5721004063  13031                                                                                                                                                                                                                                                                                                                                                                      /*
 * status.h: header for status.c
 *
 * Written By Michael Sandrof
 *
 * Copyright(c) 1990 
 *
 * See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT 
 *
 * @(#)$Id: status.h,v 1.1 1995/02/17 02:21:38 hellcat Exp $
 */

#ifndef _STATUS_H_
#define _STATUS_H_

extern	void	make_status();
extern	void	refresh_status();
extern	void	set_alarm();
extern	char	*update_clock();
extern	void	reset_clock();
extern	void	build_status();
extern	void	status_update();

#define GET_TIME 1
#define RESET_TIME 2

#endif /* _STATUS_H_ */
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     DarkNET-1.08/ircii-2.8.H1/include/talkd.h                                                              444   21270   21270         6435  5721004063  12622                                                                                                                                                                                                                                                                                                                                                                      /*
 * Copyright (c) 1983 Regents of the University of California.
 * All rights reserved.  The Berkeley software License Agreement
 * specifies the terms and conditions for redistribution.
 *
 *	@(#)talkd.h	5.2 (Berkeley) 3/13/86
 *
 * $Id: talkd.h,v 1.1 1995/02/17 02:21:38 hellcat Exp $
 */

#ifndef _TALKD_H_
#define _TALKD_H_

#include <sys/types.h>
#ifdef notdef
#include <sys/socket.h>		/* this taken out because ultrix is lame */
#endif
/*
 * This describes the protocol used by the talk server and clients.
 *
 * The talk server acts a repository of invitations, responding to
 * requests by clients wishing to rendezvous for the purpose of
 * holding a conversation.  In normal operation, a client, the caller,
 * initiates a rendezvous by sending a CTL_MSG to the server of
 * type LOOK_UP.  This causes the server to search its invitation
 * tables to check if an invitation currently exists for the caller
 * (to speak to the callee specified in the message).  If the lookup
 * fails, the caller then sends an ANNOUNCE message causing the server
 * to broadcast an announcement on the callee's login ports requesting
 * contact.  When the callee responds, the local server uses the
 * recorded invitation to respond with the appropriate rendezvous
 * address and the caller and callee client programs establish a
 * stream connection through which the conversation takes place.
 */

/*
 * Client->server request message format.
 */
typedef struct {
	u_char	vers;		/* protocol version */
	u_char	type;		/* request type, see below */
	u_char	answer;		/* not used */
	u_char	pad;
	u_long	id_num;		/* message id */
	struct	sockaddr addr;
	struct	sockaddr ctl_addr;
	long	pid;		/* caller's process id */
#define	NAME_SIZE	12
	char	l_name[NAME_SIZE];/* caller's name */
	char	r_name[NAME_SIZE];/* callee's name */
#define	TTY_SIZE	16
	char	r_tty[TTY_SIZE];/* callee's tty name */
} CTL_MSG;

/*
 * Server->client response message format.
 */
typedef struct {
	u_char	vers;		/* protocol version */
	u_char	type;		/* type of request message, see below */
	u_char	answer;		/* respose to request message, see below */
	u_char	pad;
	u_long	id_num;		/* message id */
	struct	sockaddr addr;	/* address for establishing conversation */
} CTL_RESPONSE;

#define	TALK_VERSION	1		/* protocol version */

/* message type values */
#define LEAVE_INVITE	0	/* leave invitation with server */
#define LOOK_UP		1	/* check for invitation by callee */
#define DELETE		2	/* delete invitation by caller */
#define ANNOUNCE	3	/* announce invitation by caller */

/* answer values */
#define SUCCESS		0	/* operation completed properly */
#define NOT_HERE	1	/* callee not logged in */
#define FAILED		2	/* operation failed for unexplained reason */
#define MACHINE_UNKNOWN	3	/* caller's machine name unknown */
#define PERMISSION_DENIED 4	/* callee's tty doesn't permit announce */
#define UNKNOWN_REQUEST	5	/* request has invalid type value */
#define	BADVERSION	6	/* request has invalid protocol version */
#define	BADADDR		7	/* request has invalid addr value */
#define	BADCTLADDR	8	/* request has invalid ctl_addr value */

/*
 * Operational parameters.
 */
#define MAX_LIFE	60	/* max time daemon saves invitations */
/* RING_WAIT should be 10's of seconds less than MAX_LIFE */
#define RING_WAIT	30	/* time to wait before resending invitation */

#endif /* _TALKD_H_ */
                                                                                                                                                                                                                                   DarkNET-1.08/ircii-2.8.H1/include/term.h                                                               444   21270   21270         6204  5721004063  12464                                                                                                                                                                                                                                                                                                                                                                      /*
 * term.h: header file for term.c 
 *
 * Written By Michael Sandrof
 *
 * Copyright(c) 1990 
 *
 * See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT 
 *
 * @(#)$Id: term.h,v 1.1 1995/02/17 02:21:38 hellcat Exp $
 */

#ifndef _TERM_H_
# define _TERM_H_

#ifdef MUNIX
# include <sys/ttold.h>
#endif

extern	int	term_reset_flag;
extern	char	*CM,
		*DO,
		*CE,
		*CL,
		*CR,
		*NL,
		*SO,
		*SE,
		*US,
		*UE,
		*MD,
		*ME,
		*BL;
extern	int	CO,
		LI,
		SG;

extern	void	putchar_x();
#define tputs_x(s)		(tputs(s, 0, putchar_x))

#define term_underline_on()	(tputs_x(US))
#define term_underline_off()	(tputs_x(UE))
#define term_standout_on()	(tputs_x(SO))
#define term_standout_off()	(tputs_x(SE))
#define term_clear_screen()	(tputs_x(CL))
#define term_move_cursor(c, r)	(tputs_x(tgoto(CM, (c), (r))))
#define term_cr()		(tputs_x(CR))
#define term_newline()		(tputs_x(NL))
#define term_beep()		(tputs_x(BL),fflush(current_screen ? \
					current_screen->fpout : stdout))
#define	term_bold_on()		(tputs_x(MD))
#define	term_bold_off()		(tputs_x(ME))

extern	RETSIGTYPE	term_cont();
extern	int	term_echo();
extern	void	term_init();
extern	int	term_resize();
extern	void	term_pause();
extern	void	term_putchar();
extern	int	term_puts();
extern	void	term_flush();
extern	int	(*term_scroll)();
extern	int	(*term_insert)();
extern	int	(*term_delete)();
extern	int	(*term_cursor_right)();
extern	int	(*term_cursor_left)();
extern	int	(*term_clear_to_eol)();
extern	void	term_space_erase();
extern	void	term_reset();

extern  void    copy_window_size();
extern	int	term_eight_bit();
extern	void	set_term_eight_bit _((int));

#if defined(ISC22) || defined(MUNIX)
/* Structure for terminal special characters */
struct	tchars
{
	char	t_intrc;	/* Interrupt			*/
	char	t_quitc;	/* Quit 			*/
	char	t_startc;	/* Start output 		*/
	char	t_stopc;	/* Stop output			*/
	char	t_eofc;		/* End-of-file (EOF)		*/
	char	t_brkc;		/* Input delimiter (like nl)	*/
}

struct ltchars
{
	char	t_suspc;	/* stop process signal		*/
	char	t_dsuspc;	/* delayed stop process signal	*/
	char	t_rprntc;	/* reprint line			*/
	char	t_flushc;	/* flush output (toggles)	*/
	char	t_werasc;	/* word erase			*/
	char	t_lnextc;	/* literal next character	*/
};
#endif /* ISC22 || MUNIX */

#if defined(_HPUX_SOURCE)

#ifndef _TTY_CHARS_ST_
#define _TTY_CHARS_ST_

/* Structure for terminal special characters */
struct tchars
{
	char	t_intrc;	/* Interrupt			*/
	char	t_quitc;	/* Quit 			*/
	char	t_startc;	/* Start output 		*/
	char	t_stopc;	/* Stop output			*/
	char	t_eofc;		/* End-of-file (EOF)		*/
	char	t_brkc;		/* Input delimiter (like nl)	*/
};

#endif /* _TTY_CHARS_ST_ */

#ifndef TIOCSETC
# define TIOCSETC	_IOW('t', 17, struct tchars)	/* set special chars */
#endif /* TIOCSETC */

#ifndef TIOCGETC
# define TIOCGETC	_IOR('t', 18, struct tchars)	/* get special chars */
#endif /* TIOCGETC */

#ifndef CBREAK
# define CBREAK		0x02	/* Half-cooked mode */
#endif /* CBREAK */

#ifndef SIGWINCH
# define    SIGWINCH    SIGWINDOW
#endif /* SIGWINCH */

#endif /* _HPUX_SOURCE */

/* well, it works */
#ifdef mips
# define fputc(c,f) write(1,&(c),1)
# define fwrite(buffer,len,cnt,f) write(1,buffer,len)
#endif /*mips*/

#endif /* _TERM_H_ */
(tputs_x(SO))
#define term_standout_off()	(tputs_x(SE))
#define term_clear_screen()	(tputs_x(CL))
#define term_move_cursor(c, r)	(tputs_x(tgoto(CM, (c), (r))))
#define term_cr()		(tputs_x(CR))
#define term_newline()		(tputs_x(NL))
#define term_beep()		(tputs_x(BL),fflush(current_screen ? \
					current_screen->fpout : stdout))
#define	term_bold_on()		(tputs_x(MD))
#define	term_DarkNET-1.08/ircii-2.8.H1/include/translat.h                                                           444   21270   21270         1505  5721004063  13344                                                                                                                                                                                                                                                                                                                                                                      /*
 * Global stuff for translation tables.
 *
 * Tomten, tomten@solace.hsh.se / tomten@lysator.liu.se
 *
 * @(#)$Id: translat.h,v 1.1 1995/02/17 02:21:38 hellcat Exp $
 */

#ifndef __translat_h_
# define __translat_h_

extern	void	set_translation _((char *));
extern	void	enter_digraph _((unsigned char, char *));
extern	unsigned char	get_digraph _((unsigned char));
extern	void	digraph _((char *, char *, char *));
extern	void	save_digraphs _((FILE *));

extern	unsigned char	transToClient[256];
extern	unsigned char	transFromClient[256];
extern	char	translation;

# define DIG_TABLE_SIZE 256
extern	unsigned char	dig_table_lo[DIG_TABLE_SIZE];
extern	unsigned char	dig_table_hi[DIG_TABLE_SIZE];
extern	unsigned char	dig_table_di[DIG_TABLE_SIZE];

extern	char	digraph_hit;
extern	unsigned char	digraph_first;

#endif /* __translat_h_ */
                                                                                                                                                                                           DarkNET-1.08/ircii-2.8.H1/include/vars.h.proto                                                         644   21270   21270         7236  5725536716  13665                                                                                                                                                                                                                                                                                                                                                                      /*
 * vars.h: header for vars.c
 *
 * Generated from vars.h.proto automatically from the Makefile
 *
 * @(#)$Id: vars.h.proto,v 1.1 1995/02/17 02:21:38 hellcat Exp $
 */

#ifndef _VARS_H_
#define _VARS_H_

extern	int	do_boolean();
extern	void	set_variable _((char *, char *, char *));
extern	int	get_int_var();
extern	char	*get_string_var();
extern	void	set_int_var();
extern	void	set_string_var();
extern	char	*get_string_var();
extern	void	init_variables();
extern	char	*var_settings[];
extern	char	*make_string_var();
extern	void	set_highlight_char();
extern	int	charset_size();
extern	void	save_variables();
extern	void	set_var_value();

extern	int	loading_global;

/* var_settings indexes ... also used in display.c for highlights */
#define OFF 0
#define ON 1
#define TOGGLE 2

#define	DEBUG_COMMANDS		0x0001
#define	DEBUG_EXPANSIONS	0x0002
#define DEBUG_FUNCTIONS		0x0004

/* indexes for the irc_variable array */
#define ALWAYS_SPLIT_BIGGEST_VAR $
#define AUTO_UNMARK_AWAY_VAR $
#define AUTO_WHOWAS_VAR  $
#define BEEP_VAR $
#define BEEP_MAX_VAR $
#define BEEP_ON_MSG_VAR $
#define BEEP_WHEN_AWAY_VAR $
#define	BOLD_VIDEO_VAR $
#define CHANNEL_NAME_WIDTH_VAR $
#define CLIENTINFO_VAR $
#define CLOCK_VAR $
#define CLOCK_24HOUR_VAR $
#define CLOCK_ALARM_VAR $
#define CMDCHARS_VAR $
#define COMMAND_MODE_VAR $
#define CONTINUED_LINE_VAR $
#define DCC_BLOCK_SIZE_VAR $
#define	DEBUG_VAR $
#define DISPLAY_VAR $
#define EIGHT_BIT_CHARACTERS_VAR $
#define ENCRYPT_PROGRAM_VAR $
#define EXEC_PROTECTION_VAR $
#define FLOOD_AFTER_VAR $
#define FLOOD_RATE_VAR $
#define FLOOD_USERS_VAR $
#define FLOOD_WARNING_VAR $
#define FULL_STATUS_LINE_VAR $
#define HELP_PAGER_VAR $
#define HELP_PATH_VAR $
#define HELP_PROMPT_VAR $
#define HELP_SERVICE_VAR $
#define HELP_WINDOW_VAR $
#define HIDE_PRIVATE_CHANNELS_VAR $
#define HIGHLIGHT_CHAR_VAR $
#define HISTORY_VAR $
#define HISTORY_FILE_VAR $
#define HOLD_MODE_VAR $
#define HOLD_MODE_MAX_VAR $
#define INDENT_VAR $
#define INPUT_ALIASES_VAR $
#define INPUT_PROMPT_VAR $
#define INPUT_PROTECTION_VAR $
#define INSERT_MODE_VAR $
#define INVERSE_VIDEO_VAR $
#define LASTLOG_VAR $
#define LASTLOG_LEVEL_VAR $
#define	LOAD_PATH_VAR $
#define MAX_RECURSIONS_VAR $
#define	MENU_VAR $
#define MINIMUM_SERVERS_VAR $
#define MINIMUM_USERS_VAR $
#define NO_CTCP_FLOOD_VAR $
#define NOTIFY_HANDLER_VAR $
#define NOTIFY_LEVEL_VAR $
#define NOTIFY_ON_TERMINATION_VAR $
#define NOVICE_VAR $
#define REALNAME_VAR $
#define SCREEN_OPTIONS_VAR $
#define SCROLL_VAR $
#define SCROLL_LINES_VAR $
#define SEND_IGNORE_MSG_VAR $
#define SHELL_VAR $
#define SHELL_FLAGS_VAR $
#define SHELL_LIMIT_VAR $
#define SHOW_AWAY_ONCE_VAR $
#define SHOW_CHANNEL_NAMES_VAR $
#define SHOW_END_OF_MSGS_VAR $
#define SHOW_NUMERICS_VAR $
#define SHOW_STATUS_ALL_VAR $
#define SHOW_WHO_HOPCOUNT_VAR $
#define STATUS_AWAY_VAR $
#define STATUS_CHANNEL_VAR $
#define	STATUS_CHANOP_VAR $
#define STATUS_CLOCK_VAR $
#define STATUS_FORMAT_VAR $
#define STATUS_HOLD_VAR $
#define STATUS_HOLD_LINES_VAR $
#define STATUS_INSERT_VAR $
#define STATUS_MODE_VAR $
#define STATUS_NOTIFY_VAR $
#define STATUS_OPER_VAR $
#define STATUS_OVERWRITE_VAR $
#define STATUS_QUERY_VAR $
#define STATUS_SERVER_VAR $
#define	STATUS_UMODE_VAR $
#define STATUS_USER_VAR $
#define STATUS_USER1_VAR $
#define STATUS_USER2_VAR $
#define STATUS_USER3_VAR $
#define STATUS_WINDOW_VAR $
#define SUPPRESS_SERVER_MOTD_VAR $
#define TAB_VAR $
#define	TAB_MAX_VAR $
#define TRANSLATION_VAR $
#define UNDERLINE_VIDEO_VAR $
#define USE_OLD_MSG_VAR $
#define USER_INFO_VAR $
#define	USERINFO_VAR USER_INFO_VAR
#define	USER_WALLOPS_VAR $
#define VERBOSE_CTCP_VAR $
#define WARN_OF_IGNORES_VAR $
#define XTERM_OPTIONS_VAR $
#define NUMBER_OF_VARIABLES $

#endif /* _VARS_H_ */
                                                                                                                                                                                                                                                                                                                                                                  DarkNET-1.08/ircii-2.8.H1/include/whois.h                                                              444   21270   21270         2604  5721004063  12646                                                                                                                                                                                                                                                                                                                                                                      /*
 * whois.h: header for whois.c 
 *
 * Written By Michael Sandrof
 *
 * Copyright(c) 1990 
 *
 * See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT 
 *
 * @(#)$Id: whois.h,v 1.1 1995/02/17 02:21:38 hellcat Exp $
 */

#ifndef __whois_h_
# define __whois_h_

# ifdef USE_STDARG_H
extern	void	add_to_whois_queue(char *, void (*)(), char *, ...);
# else
extern	void	add_to_whois_queue();
# endif
extern	void	add_ison_to_whois();
extern	void	whois_name();
extern	void	whowas_name();
extern	void	whois_channels();
extern	void	whois_server();
extern	void	whois_oper();
extern	void	whois_lastcom();
extern	void	whois_nickname();
extern	void	whois_ignore_msgs();
extern	void	whois_ignore_notices();
extern	void	whois_ignore_walls();
extern	void	whois_ignore_invites();
extern	void	whois_join();
extern	void	whois_privmsg();
extern	void	whois_notify();
extern	void	whois_new_wallops();
extern	void	clean_whois_queue();
extern	void	set_beep_on_msg();
extern	int	beep_on_level;
extern  void    userhost_cmd_returned();
extern	void	user_is_away();
extern	void	userhost_returned();
extern	void	ison_returned();
extern	void	whois_chop();
extern	void	end_of_whois();
extern	void	whoreply();
extern	void	convert_to_whois();
extern	void	no_such_nickname();

extern	char	*redirect_format;

#define	WHOIS_WHOIS	0
#define	WHOIS_ISON	1
#define	WHOIS_USERHOST	2

#define	USERHOST_USERHOST ((void (*)()) 1)

#endif /* __whois_h_ */
                                                                                                                            DarkNET-1.08/ircii-2.8.H1/include/window.h                                                             444   21270   21270        17067  5721004063  13055                                                                                                                                                                                                                                                                                                                                                                      /*
 * window.h: header file for window.c 
 *
 * Written By Michael Sandrof
 *
 * Copyright(c) 1990 
 *
 * See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT 
 *
 * @(#)$Id: window.h,v 1.1 1995/02/17 02:21:38 hellcat Exp $
 */

#ifndef _WINDOW_H_
#define _WINDOW_H_

/*
 * Define this if you want to play with the new window feature, 
 * CREATE, that allows you to start new iscreen or xterm windows
 * connected to the ircII client.
 */
#define	WINDOW_CREATE

#ifdef M_UNIX
#undef WINDOW_CREATE
#endif /* M_UNIX */

/*
 * Define this if you want ircII to scroll after printing a line,
 * like it used to (2.1.5 and back era), not before printing the
 * line.   Its a waste of a line to me, but what ever people want.
 * Thanks to Veggen for telling me what to do for this.
 */
#undef SCROLL_AFTER_DISPLAY

#include "hold.h"
#include "lastlog.h"
#include "edit.h"
#include "menu.h"

/* used by the update flag to determine what needs updating */
#define REDRAW_DISPLAY_FULL 1
#define REDRAW_DISPLAY_FAST 2
#define UPDATE_STATUS 4
#define REDRAW_STATUS 8

struct	WindowMenuTag
{
	Menu	*menu;
	int	lines;
	int	items_per_line;
	int	cursor;
};

typedef	struct	WindowMenuTag	WindowMenu;

/* NickList: structure for the list of nicknames of people on a channel */
typedef struct nick_stru
{
	struct	nick_stru	*next;	/* pointer to next nickname entry */
	char	*nick;			/* nickname of person on channel */
	int	chanop;			/* True if the given nick has chanop */
}	NickList;

typedef	struct	DisplayStru
{
	char	*line;
	int	linetype;
	struct	DisplayStru	*next;
}	Display;

#define	LT_UNLOGGED	0
#define	LT_LOGHEAD	1
#define	LT_LOGTAIL	2

struct	ScreenStru;	/* ooh! */

typedef	struct	WindowStru
{
	unsigned int	refnum;		/* the unique reference number,
					 * assigned by IRCII */
	char	*name;			/* window's logical name */
	int	server;			/* server index */
	int	top;			/* The top line of the window, screen
					 * coordinates */
	int	bottom;			/* The botton line of the window, screen
					 * coordinates */
	int	cursor;			/* The cursor position in the window, window
					 * relative coordinates */
	int	line_cnt;		/* counter of number of lines displayed in
					 * window */
	int	scroll;			/* true, window scrolls... false window wraps */
	int	display_size;		/* number of lines of window - menu lines */
	int	old_size;		/* if new_size != display_size,
					 * resize_display is called */
	int	visible;		/* true, window is drawn... false window is
					 * hidden */
	int	update;			/* window needs updating flag */
	unsigned miscflags;		/* Miscellaneous flags. */

	char	*prompt;		/* A prompt string, usually set by EXEC'd process */
	char	*status_line;		/* The status line string */

	Display	*top_of_display,	/* Pointer to first line of display structure */
		*display_ip;		/* Pointer to insertiong point of display
					 * structure */

	char	*current_channel;	/* Window's current channel */
	char	*waiting_channel;	/* The channel that you _want_ to be on
					 * this window .. derived from a real
					 * fix for the phone bug */
	char	*bind_channel;		/* the window's bound channel */
	char	*query_nick;		/* User being QUERY'ied in this window */
	NickList	*nicks;		/* List of nicks that will go to window */
	int	window_level;		/* The LEVEL of the window, determines what
					 * messages go to it */

	/* hold stuff */
	int	hold_mode;		/* true, hold mode is on for window...
					 * false it isn't */
	int	hold_on_next_rite;	/* true, the next call to rite() will
					 * activate a hold */
	int	held;			/* true, the window is currently being
					 * held */
	int	last_held;		/* Previous value of hold flag.  Used
					 * for various updating needs */
	Hold	*hold_head,		/* Pointer to first entry in hold
					 * list */
		*hold_tail;		/* Pointer to last entry in hold list */
	int	held_lines;		/* number of lines being held */
	int	scrolled_lines;		/* number of lines scrolled back */
	int	new_scrolled_lines;	/* number of lines since scroll back
					 * keys where pressed */
	WindowMenu	menu;		/* The menu (if any) */

	/* lastlog stuff */
	Lastlog	*lastlog_head;		/* pointer to top of lastlog list */
	Lastlog	*lastlog_tail;		/* pointer to bottom of lastlog list */
	int	lastlog_level;		/* The LASTLOG_LEVEL, determines what
					 * messages go to lastlog */
	int	lastlog_size;		/* Max number of messages for the window
					 * lastlog */

	int	notify_level;		/* the notify level.. */

	char	*logfile;		/* window's logfile name */
	/* window log stuff */
	int	log;			/* true, file logging for window is on */
	FILE	*log_fp;		/* file pointer for the log file */

	struct	ScreenStru	*screen;

	struct	WindowStru	*next;	/* pointer to next entry in window list (null
					 * is end) */
	struct	WindowStru	*prev;	/* pointer to previous entry in window list
					 * (null is end) */
}	Window;

/*
 * WindowStack: The structure for the POP, PUSH, and STACK functions. A
 * simple linked list with window refnums as the data 
 */
typedef	struct	window_stack_stru
{
	unsigned int	refnum;
	struct	window_stack_stru	*next;
}	WindowStack;

extern	Window	*to_window;

extern	Window	*invisible_list;
extern	char	underline;
extern	int	who_level;
extern	char	*who_from;
extern	int	in_window_command;

typedef	struct
{
	int	top;
	int	bottom;
	int	position;
}	ShrinkInfo;

extern	void	set_scroll_lines();
extern	void	set_scroll();
extern	void	reset_line_cnt();
extern	void	set_continued_line();
extern	void	set_underline_video();
extern	int	rite();
extern	void	erase_display();
extern	ShrinkInfo	resize_display();
extern	void	redraw_all_windows();
extern	void	add_to_screen();
extern	void	init_windows();
extern	int	unhold_windows();
extern	Window	*traverse_all_windows();
extern	void	add_to_invisible_list();
extern	void	delete_window _((Window *));

/* var_settings indexes */
#define OFF 0
#define ON 1
#define TOGGLE 2

extern	Window	*add_to_window_list();
extern	void	erase_display();
extern	void	redraw_display();
extern	void	add_to_display();
extern	void	set_scroll();
extern	void	set_menu();
extern	void	set_scroll_lines();
extern	int	display_hold();
extern	void	update_all_status();
extern	void	set_query_nick();
extern	char	*query_nick();
extern	void	set_current_dcc();
extern	char	*current_dcc();
extern	void	update_window_status();
extern	void	window _((char *, char *, char *));
extern	void	redraw_window();
extern	void	redraw_all_windows();
extern	void	next_window();
extern	void	swap_last_window();
extern	void	swap_next_window();
extern	void	previous_window();
extern	void	swap_previous_window();
extern	void	back_window();
extern	void	window_kill_swap();
extern	int	is_current_channel();
extern	void	redraw_all_status();
extern	void	message_to();
extern	void	message_from();
extern	void	unstop_all_windows();
extern	void	set_display();
extern	unsigned int	window_display;

extern	int	is_main_screen();
extern	void	kill_screen();

extern	void	set_prompt_by_refnum();
extern	int	number_of_windows();
extern	void	clear_window_by_refnum();
extern	unsigned int	current_refnum();
extern	Window	*get_window_by_refnum();
extern	char	*get_target_by_refnum();
extern	char	*get_prompt_by_refnum();
extern	char	*set_channel_by_refnum();
extern	char	*get_channel_by_refnum();
extern	void	set_window_server();
extern	Window	*get_window_by_name();
extern	void	window_redirect();
extern	int	get_window_server();
extern	int	message_from_level();
extern	void	restore_message_from();
extern	void	save_message_from();
extern	void	window_check_servers();
extern	void	set_current_window();
extern	void	set_level_by_refnum();
extern	int	is_bound _((char *));
extern	void	unbind_channel _((char *));
extern	char	*get_bound_channel _((Window *));

#define WINDOW_NOTIFY	((unsigned) 0x0001)
#define WINDOW_NOTIFIED	((unsigned) 0x0002)

#endif /* _WINDOW_H_ */
	Menu	*menu;
	int	lines;
	int	items_per_line;
	int	cursor;
};

typedef	struct	WindowMenuTag	WindowMenu;

/* NickList: structure for the list of nicknames of people on a channel */
typedef struct nick_stru
{
	struct	nick_stru	*next;	/* pointer to next nickname entry */
	char	*nick;			/* nickname of person on channel */
	int	chanop;			/* True if the given nick has chanop */
}	NickList;

typedef	struct	DisplayStru
{
	char	*line;
	int	linetype;
	struct	DispDarkNET-1.08/ircii-2.8.H1/include/config.hh                                                            444   21270   21270        17407  5721004410  13155                                                                                                                                                                                                                                                                                                                                                                      /* 'new' config.h:
 *	A configuration file designed to make best use of the abilities
 *	of ircII, and trying to make things more intuitively understandable.
 *
 * Done by Carl v. Loesch <lynx@dm.unirm1.it>
 * Based on the 'classic' config.h by Michael Sandrof.
 * Copyright(c) 1991 - See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT 
 *
 * Warning!  You will most likely have to make changes to your .ircrc file to
 * use this version of IRCII!  Please read the INSTALL and New2.2 files
 * supplied with the distribution for details!
 *
 * @(#)$Id: config.h,v 1.1 1995/02/17 02:21:38 hellcat Exp $
 */

#ifndef __config_h_
#define __config_h_

/*
 * Set your favorite default server list here.  This list should be a
 * whitespace separated hostname:portnum:password list (with portnums and
 * passwords optional).  This IS NOT an optional definition. Please set this
 * to your nearest servers.  However if you use a seperate 'ircII.servers'
 * file and the ircII can find it, this setting is overridden.
 */
#define DEFAULT_SERVER	    "change.this.to.a.server"

/*
 * Uncomment the following if the gecos field of your /etc/passwd has other
 * information in it that you don't want as the user name (such as office
 * locations, phone numbers, etc).  The default delimiter is a comma, change
 * it if you need to. If commented out, the entire gecos field is used. 
 */
#define GECOS_DELIMITER ','

/*
 * Set the following to 1 if you wish for IRCII not to disturb the tty's flow
 * control characters as the default.  Normally, these are ^Q and ^S.  You
 * may have to rebind them in IRCII.  Set it to 0 for IRCII to take over the
 * tty's flow control.
 */
#define USE_FLOW_CONTROL 1

/*
 * Below you can set what type of mail your system uses and the path to the
 * appropriate mail file/directory.  Only one may be selected. 
 * You may also undefine both if you think mail checking in irc clients is
 * silly.
 */
/* AMS_MAIL is the Andrew Mail System mail format. */

#undef AMS_MAIL

/* UNIX_MAIL is the normal unix mail format.  */
#ifndef UNIX_MAIL
# define UNIX_MAIL "/usr/spool/mail"	/* */
#endif

/*
 * MAIL_DELIMITER specifies the unique text that separates one mail message
 * from another in the mail spool file when using UNIX_MAIL.
 */
#define MAIL_DELIMITER "