[alt.sources] Internet Relay Chat

bleckmd@jacobs.cs.orst.edu (david bleckmann) (06/20/89)

Here is Internet Relay Chat, or IRC.  It is one of a few multi person
chat programs that have recently come about which use internet sockets
to form a large network of servers and clients that span the US and
Europe  (the author is Finnish and there is a large network tree in
that country).


IRC has been hacked on for more than a year now, and the author
(jto@tolsun.oulu.fi) would like to come out with its "final" version
soon.  This final version will be posted to comp.sources.unix when
people decide exactly just what it is going to be.  One of the newest
improvements is an emacs style front end.

This source and all new versions (including the emacs one, irc.el)
are available by anonymous ftp to tolsun.oulu.fi [128.214.5.6], in
the directory irc.

If you get things set up, you will need an host to connect to.  This
should be the site closest (usually geographicly) to you in the irc network.
You will need to get their permission to use their server.  When is doubt,
write to irclist@tolsun.oulu.fi for the server nearest you.

Good luck!

David Bleckmann
UUCP: {tektronix,hp-pcd}!orstcs!jacobs.cs.orst.edu!bleckmd
Internet/CSNet: bleckmd@jacobs.cs.orst.edu
  or:bleckmd%jacobs.cs.orst.edu@orstcs.cs.orst.edu
US Mail: 861 SW Adams #3
	 Corvallis, OR  97333

---- Cut Here and unpack ----
#!/bin/sh
# shar:	Shell Archiver  (v1.22)
#	Packed Mon Jun 19 19:28:32 PDT 1989 by jacobs.CS.ORST.EDU!bleckmd
#	from directory /u1/bleckmd/net/irc.6
#
# This is part 1 of a multipart archive                                    
# do not concatenate these parts, unpack them in order with /bin/sh        
#
#	Run the following text with /bin/sh to create:
#	  ADVERTISEMENT
#	  COPYRIGHT
#	  Comms
#	  INSTALL
#	  MANUAL
#	  Makefile
#	  README
#	  bsd.c
#	  bsd.h
#	  c_bsd.c
#	  c_msg.c
#	  c_sysv.c
#	  card.c
#	  card.h
#	  channel.c
#	  conf.c
#	  date.c
#	  debug.c
#	  deck.c
#	  edit.c
#	  example.conf
#	  help.c
#	  help.h
#	  ignore.c
#	  irc.1
#	  irc.c
#	  ircd.8
#	  ircd.c
#	  list.c
#	  main.c
#	  msg.h
#	  packet.c
#	  parse.c
#	  r_bsd.c
#	  r_msg.c
#	  s_bsd.c
#	  s_msg.c
#	  s_sysv.c
#	  screen.c
#	  send.c
#	  sock.h
#	  str.c
#	  struct.h
#	  swear.c
#	  sys.h
#	  sysv.c
#	  sysv.h
#
if test -r s2_seq_.tmp
then echo "Must unpack archives in sequence!"
     next=`cat s2_seq_.tmp`; echo "Please unpack part $next next"
     exit 1; fi
echo "x - extracting ADVERTISEMENT (Text)"
sed 's/^X//' << 'SHAR_EOF' > ADVERTISEMENT &&
X                                                Author: Jeff Trim
X                                                        jtrim@orion.cair.du.edu
X                                                  Date: 04 Apr 1989
X                                     Last modification: 04 Apr 1989
X
X                 The Internet Relay Chat Program  -  IRC
X
XHave you ever wanted to talk with other computer users in other parts of
Xthe world?  Well guess what?  You can!  The program is called IRC and
Xit is networked over much of the United States, Finland, Sweden and very
Xsoon I think it's going to appear in the United Kingdom.  This program
Xis a substitution for talk(1), chat(1), vco(1) and many other multiple
Xtalk programs you might have read about.  When you are talking in IRC, 
Xeverything you type will instantly be transmitted around the world to
Xother users that might be watching their terminals at the time - they can
Xthen type something and RESPOND to your messages - and vise versa.  I will
Xtell you that the program can be very addictive once you begin to make
Xfriends and contacts on IRC ;)  .. and the Finnish people are as curious
Xabout Amercians as we are about them - so the topics can become very 
Xinteresting sometimes.  I think I have talked about everything from Politics
Xto Living expenses in the United States - in return they have told me about
Xlife in Finnland (which is quite interesting!) - I even know a few Finnish
Xcurse words - but we won't go into those ;)
X
XThe first step to beginning to getting aquinted to IRC is to throw off the
Xfear of embarrising yourself -- the fact of the matter is that the people
Xon the other end of the terminal are as scared as you are.  The Finnish
Xpeople speak VERY GOOD english, so you can feel comfortable speaking to
Xthem in english.  (I will add, however, that it's also interesting to see
Xhow they communicate in Finnish - some of their words can be 25 characters
Xlong - and I am talking just one word!)  When you /join a conference and 
Xthey recognize that you are an english speaking person they always nicely
Xswitch immediately into english - they are very cordial about that.  But
Xbe aware that finnish is their native language so they might stumble a bit
Xon some of our english counter parts  (especially english SLANG words).
XAlso you might need to give them a second or too to make the switch into
Xenglish because there might be a heated argument going on when you /join 
Xthe conference and they need time to finish what they are saying.
X
XBeyond the Finnish there are users from Oregon State University, Ohio State
XUniversity, MIT, Northwestern State University and we even picked up a
Xsite from NASA about a week ago.  At my last count there were 22 servers
Xrunning 24 hours aday all over the US/Finland - so you can loggin just
Xabout any time of day and find people talking on IRC (as a side note - the
XFinnish are 9 Hours ahead of us -- meaning when it's 11:00pm at night in Denver
Xit's 8:00am THE NEXT DAY in Finland!)  You should note that late afternoon
Xin Denver is EARLY in the morning for the Finnish ;)  But the US users
Xshould keep the same time schedual you have (keeping in mind Mountain Time,
XCentral Time, Pacific Time, ...etc).  
X
XWHAT DO I TALK ABOUT?
X
XThat is the most common question I get so I will answer it now.  Sometimes
Xyou'll notice that all conversation STOPS and you know everyone is waiting
Xon everyone else to say something - so this is a good time to talk about
XNews, weather or whatever -- best thing is to ask a question - like "How's
Xthe weather in finland?", "What's TV like in Finland?", "Did you know that
Xan Oil Tanker just spilt oil all over the Alaskan sea-shore?".  If things
Xget real desperate say something like "well why don't we choose a topic?"
X..then you should also try to think up something, maybe a good topic over
Xyour favoite beer, Broncos mainia (I haven't explained that to the Finnish
Xyet (I still don't get it) ;), Denver, skiing, computers, people, vacation
Xspots, travel, cars, housing, whatever you can think of.  ..but be assertive.
X
X
XA finally note is about IRC protocol.  Try not to CUSS out the other users
X(meaning use your best english - keep your laungauge printable ;), and
Xwhen you are going to LEAVE IRC - say "goodbye" and give the other users
Xabout 30 seconds to in turn say their goodbye's.  Never just /signoff 
Xbecause it makes the other users think you didn't like what they were
Xsaying - so try to leave on a good note.  A finally you should be aware
Xthat the program does allow <CTRL>G's (The ASCII BELL character).  They
Xare used only when absolutely necessary - and usually in PRIVATE messages
Xonly - so please restrict them to that.  If you need to wake up a sleeping
Xuser (IE one that's away from his terminal for awhile) then send him a few
X^G's (like 2) and wake him up in private message.  Don't post ^G's in
Xpublic messages.
X
X
XRUNNING THE PROGRAM:
X
XI have it set up currently on the 3 academic UNIXES - on EOS/TYCHE/ORION
Xtype: "irc".  I am Posting the IRC User Manual in the next posting so 
Xplease read that to get familiar with IRC and the various commands.  if
Xyou want help in the program type "/help".  If you see a topic you want to
Xread about then type "/help <topic>", like "/help who".  But anyway to
Xrun the program type:
X
X      irc
X
XIf you have any questions at all feel free to write me a note.  I am the
Xcurrent IRC Adminestrator for The University of Denver so I can answer 
Xall of your questions.  I am "jtrim@orion.cair.du.edu".
X
XThe program was written by "Jarkko Oikarinen" - and in IRC you can usually
Xfind him as NICKNAME "Wiz".
SHAR_EOF
chmod 0600 ADVERTISEMENT || echo "restore of ADVERTISEMENT fails"
set `wc -c ADVERTISEMENT`;Sum=$1
if test "$Sum" != "5597"
then echo original size 5597, current size $Sum;fi
echo "x - extracting COPYRIGHT (Text)"
sed 's/^X//' << 'SHAR_EOF' > COPYRIGHT &&
X/*****************************************************************************
X **
X ** IRC - Internet Relay Chat 
X **
X ** Author:          Jarkko Oikarinen
X **        Internet: jto@tolsun.oulu.fi
X **            UUCP: ...!mcvax!tut!oulu!jto
X **          BITNET: toljto at finou
X **
X ** Copyright 1988, 1989 by University of Oulu, Computing Center
X **
X ** All rights reserved
X **
X ** Permission is hereby granted to use and distribute this program freely.
X ** Permission to use this program for commercial purposes and in
X ** commercial Bulletin Board or similar systems is not given.
X ** Permission to modify this program and distribute modified version is
X ** not given. This copyright notice may not be modified or removed.
X **
X ** IRC is provided 'as is', without warranty of any kind, either
X ** expressed or implied, including, but not limited to, the implied
X ** merchantability and fitness for a particular purpose. The entire
X ** risk as to the quality and performance of the program is with you.
X ** Should the IRC program prove defective, you assume the cost of all
X ** necessary servicing, repair or correction.
X **
X ** All bug reports and suggestions for improvements etc. are welcome.
X **
X ****************************************************************************/
SHAR_EOF
chmod 0600 COPYRIGHT || echo "restore of COPYRIGHT fails"
set `wc -c COPYRIGHT`;Sum=$1
if test "$Sum" != "1280"
then echo original size 1280, current size $Sum;fi
echo "x - extracting Comms (Text)"
sed 's/^X//' << 'SHAR_EOF' > Comms &&
X					 	   Author: Jarkko Oikarinen
X						     Date: 3 Sep 1988
X					Last modification: 16 Mar 1989
X
X		     Internet Relay Chat Protocol
X
X1. Introduction
X
XThis document defines the protocol how IRC messages are transmitted
Xover Internet. IRC is a teleconferencing system which can run on
Xmany different hosts.
X
X1.1. Servers
X
XIRC consists of several servers, of which there should be only one
Xon each host (It is not recommended to use several servers, it is
Xpossible anyway). Servers are connected with each other so that they
Xform a tree-like net. [See Fig. 1]. This protocol defines no limit
Xhow many servers (or clients) one server can handle, it is machine
Xand server dependent. The name of the server is the same as the
Xname of the host where server is running.
X
X			     [ Server 1 ]
X			      /        \
X			     /          \
X                  [ Server 2 ]           [ Server 3 ]
X                    /       \                      \
X                   /         \                      \
X           [ Server 4 ]    [ Server 5 ]         [ Server 6 ]
X            /    |    \                           /      \
X           /     |     \                         /        \
X          /      |      \____                   /          \
X         /       |           \                 /            \
X[ Server 7 ] [ Server 8 ] [ Server 9 ]   [ Server 10 ] [ Server 11 ]
X                                 
X				  :
X			       [ etc. ]
X				  :
X			
X                 [ Fig. 1. Format of IRC Server net ]
X
X1.2. Clients
X
XIn this paper every conference attendant is referred to as client.
XEach client is distinguished from others with a nickname having
Xmaximum length of eight (8) characters. The following characters
Xmay be used in a nickname: all digits ('0' - '9'), lowercase letters
X('a' - 'z'), uppercase letters ('A' - 'Z'). In addition to nickname
Xservers should have following information on clients: Real name,
Xname of the host client is logged on, client's username on that host
Xand name of the server to which client is connected.
X
X
X1.3. Channels
X
XChannels are the way several (more that two) clients can communicate
Xwith each other. Every channel has a name with which it can be
Xunambiguously distinguished from other channels. Channel name is an
X32-bit integer number. Channels are divided into three groups:
XChannels with negative name are secret channels, and users on those
Xchannels are not shown to other users unless they are on same channel.
XChannels with name in between 1-999 are public channels, and users
Xand their channel names are shown to everyone. Channels 1000 - are
Xprivate channels, and users on these channels may be seen, but not
Xthe number of the channel. This system is not perfectly secure (nor
Xit is meant to be like that) because channel name can always be guessed.
X
X1.4. Services
X
XServices are used to allow servers and clients use certain databases
Xover IRCnet. These databases are mainly used to maintain access lists
Xfor servers and clients; that is, servers can query service and get
Xa list of other servers and clients that should be allowed to connect.
XThere may be several (even similar) services connected to net at the
Xsame time.
X
X2. The IRC Specification
X
X2.1. Overview
X
XThis protocol is only an interface between server and client programs.
XIt does not perform any user interaction, messages may have quite cryptic
Xformat. Client and service programs should perform all 'user-friendly'
Xfunctions.
X
X2.2. Character codes
X
XCommands are composed of characters from the ASCII character set.
XWhen the transport service provides an 8-bit byte (octet) transmission
Xchannel, each 7-bit character is transmitted right justified in an
Xoctet with the high order bit cleared to zero.
X
X2.3. Messages
X
XDaemons and Clients send each other messages which may or may not
Xgenerate a reply. Daemons normally should generate a reply for each message,
Xbut clients should not trust on it and await forever.
X
XMessages consist of prefix, a command, and parameters. Prefix
Xand parameters may be optional. Parameters are separated from
Xeach other with one space character. Prefix is separated from
Xcommand with space. Prefix is only used messages from servers to
Xidentify the original sender of the message. Client programs should
Xnever use prefixes. Command lines must be complete with all required
Xparameters, and may not contain more than one command. Commands,
Xprefixes and parameters are not case sensitive. The prefix is preceded
Xby a colon. 
X
XIRC Messages are always lines of characters terminated with CR-LF
X(Carriage Return - Line Feed) pair, and these messages shall not
Xexceed 512 characters in length, counting all characters, including
Xthe trailing CR-LF (thus there are 510 characters maximum allowed
Xfor the command and its parameters). There is no provision for
Xcontinuation message lines.
X
X2.4. Replies
X
XMost messages sent to daemon generate normally a reply. Reply consists
Xof three digits, space, comment and CR-LF combination. List of different
Xreplies will be on chapter 6. Replies are not yet implemented.
X
X3. Message details
X
XOn the following pages are descriptions of each message recognized
Xby the IRC server and client. All commands not explicitly marked as
Xoptional must be implemented by all IRC servers. The concept of
Xcurrent channel is used there several times and it is the channel
Xmessage sender is currently joined.
X
X3.1. User message
X
X   Command: USER
XParameters: <username> <hostname> <servername> <realname>
X
XUser message is used in the beginning of connection to specify username,
Xhostname, servername and realname of new user. It also used in
Xcommunication between servers to indicate new user arriving IRC.
X
XIt must be noted that Realname parameter must be the last parameter,
Xbecause it may contain space characters.
X
XExamples:
X
XMessage to identify client (note that hostname parameter is not needed,
Xbecause server always knows where user is from):
X USER guest tolmoon tolsun Ronnie Reagan
X 
X3.2. Server message
X
X   Command: SERVER
XParameters: <hostname> [<server> | <password>]
X
XServer message is used to tell server that on the other end of connection
Xresides a server. This message is also used to pass server data over
Xwhole net. Always when a new server is connected to net, info about
Xit should go through whole network.
X
XExample:
X  SERVER testhost                ; tells server I am testhost
X  SERVER tolmoon tolsun          ; tells server that behind me
X                                 ; resides a server tolmoon who is
X                                 ; connected to server at tolsun
X
X3.3. Oper message
X
X   Command: OPER
XParameters: <user> <password>
X
XOper message is used by normal user to obtain operator privileges.
X
X3.4. Password message
X
X   Command: PASS
XParameters: <password>
X
XPassword message is used to give password if secure version of irc is used.
X
X3.5. Nick message
X
X   Command: NICK
XParameters: <nickname>
X
XNICK message is used to give user a nickname.
X
X3.6. Quit message
X
X   Command: QUIT
XParameters: none
X
XThe session is finished with a quit message.
X
X3.7. Squit message
X
X   Command: SQUIT
XParameters: <server>
X
XSquit message is needed to tell about quitting or died servers.
X
X3.8. Text message
X
X   Command: MSG
XParameters: <text to be sent to channel>
X
XText message is needed to send message to all users on current channel.
X
XExamples:
X :Wiz MSG This is text message to the channel Wiz is logged on.
X MSG Another message to be sent to current channel !
X
X3.9. Private message
X
X   Command: PRIVMSG
XParameters: <receiver> <text to be sent>
X
XPrivate message is used to send private messages between users.
X<receiver> is the nickname of the receiver of the message.
X
XExamples:
X :Angel PRIVMSG Wiz Hello, are you receiving this message ?
X PRIVMSG Angel yes, I'm receiving !
X PRIVMSG jto@tolsun.oulu.fi Hello!
X
X3.10. Who message
X
X   Command: WHO
XParameters: [<channel>]
X
XWho message is used to query all users on IRC net. Server will answer
Xthis message with series of WHOREPLY messages. However it must be noted
Xthat the response may not come at once, and client must be able to accept
Xother messages before receiving user message. Channel is the number of
Xthe channel or an asterisk '*' to specify current channel. If <channel>
Xis omitted, all users (not the ones on secret channels) are shown.
X
XExamples:
X WHO
X
X3.11. Whois message
X
X   Command: WHOIS
XParameters: <nickname>
X
XThis message is used to query information about particular user. Server
Xwill answer this message with two text messages.
X
XExamples:
X WHOIS wiz
X WHOIS jto@tolsun.oulu.fi
X
X3.12. List message
X
X   Command: LIST
XParameters: [<channel>]
X
XList message is used to list channels and their topics. If <channel>
Xparameter is used, only status of that channel is displayed. Negative
Xchannels do not have topics, so negative channel is not allowed here.
X
XExamples:
X LIST                              ; List all channels
X LIST 7                            ; List channel 7
X LIST *                            ; List current channel
X
X3.13. Topic message
X
X   Command: TOPIC
XParameters: <topic>
X
XTopic message is used to change topic of current channel.
X
XExamples:
X :Wiz TOPIC New topic
X TOPIC Another topic
X
X3.14. Invite message
X        
X   Command: INVITE
XParameters: <nickname> [<channel>]
X
XInvite message is used to invite users on channel. Parameter
X<nickname> is the nickname of the person to be invited, or his/hers
XUserID. E.g. jto@tolsun.oulu.fi is a syntactically valid UserID. Channel
Xparameter is optional in messages from clients, but necessary
Xin messages from servers.
X
XExamples:
X :Angel INVITE Wiz 7
X INVITE Wiz -13
X
X3.15. Channel message
X
X   Command: CHANNEL
XParameters: <channel> [<flag>]
X
XChannel message is the way to change channel in IRC. There are three types
Xof channels: Channel numbers from 1 to 999 are public channels, ie: everyone
Xsees who are in there. Channel numbers > 1000 are secret channels, so
Xif somebody is on channel > 1000, you can see that he is in there, but
Xyou cannot see the channel number. Channels < 1000 are hidden channels,
Xyou cannot see users in there (and of course channel number either).
X
XExamples:
X :Wiz CHANNEL -13
X CHANNEL 7
X
X3.16. Version message
X
X   Command: VERSION
XParameters: [<server>]
X
XVersion message is used to query version of the server program.
XOptional parameter <server> is used to query version of the server
Xprogram on another host.
X
X3.17. Kill message
X
X   Command: KILL
XParameters: <nickname>
X
XOnly Operators may kill other users with kill message. 
X
X3.18. Stats message
X
X   Command: STATS
XParamaters: [<server>]
X
XStats message is used to query statistics of certain server. If <server>
Xparameter is omitted, current server processes this message.
X
X3.19. Service message
X
X   Command: SERVICE
XParamaters: <name>
X
XService command is used by a service to identify himself to server.
XName is the name of the service. Service which knows about IRCnet
Xtopology and connections between servers is called 'IRC' and servers
Xshould query their data from that service from time to time.
X
X3.20. Query message
X
X   Command: QUERY
XParamaters: <server> <service> <parameters>
X
XQuery message is used to send messages to services. Service responds
Xto queries by REPLY command. IRC service should be specifically noted
Xas that service which spreads access lists to each server in IRCnet.
X<server> parameter specifies the name of that server who sent that query,
X<service> is the name of the service and <parameters> may have a different
Xsyntax depending on which service the query is directed to.
X
X3.21. Links message
X
X   Command: LINKS
XParamaters: none
X
XWith links message user can list all servers and their connections on
XIRC net. LINKS message is replied by LINREPLY message by the server.
X
X3.22. Summon message
X
X   Command: SUMMON
XParameters: <user>
X
XSummon command is used to invite users not in IRC. <user> parameter
Xconsists of username and host separated with '@' sign, eg. jto@tolsun
X
X3.23. Users message
X
X   Command: USERS
XParameters: <host>
X
XWith USERS command it is possible to query users on another host.
X
X3.24. Notice message
X
X   Command: NOTICE
XParameters: <nickname> <text>
X
XNOTICE message is used similarly to PRIVMSG. The difference between NOTICE
Xand PRIVMSG is that automatic replies, etc. may NEVER reply to notice
Xmessage. Notice messages are generally used only by servers, but may
Xalso be used by client. Not yet implemented.
X
X3.25. Connect message
X
X   Command: CONNECT
XParameters: <host> <port>
X
XCONNECT message can be used to force a server to try to establish a new
Xconnection to another server immediately. CONNECT message is privileged
Xmessage and should be available only to ircd administrator(s).
X
X3.26. Ping message
X
X   Command: PING
XParameters: <daemon1> [<daemon2>]
X
XPING message must be always replied with PONG message as fast as possible.
XIf parameter <daemon2> is specified, ping gets forwarded there. <daemon1>
Xparameter specifies the querying daemon.
X
X3.27. Pong message
X
X   Command: PONG
XParameters: <daemon> [<daemon2>]
X
XPONG message is a reply to ping message. If paramater <daemon2> is given,
Xthis message must be forwarded to given daemon. <daemon> parameter is
Xthe name of the daemon who has responded to PING message and generated this
Xmessage.
X
X3.28. Reply message
X
X   Command: REPLY
XParameters: <service> <recipient> <parameters>
X
X3.29. Wall message
X
X   Command: WALL
XParameters: <msg>
X
XWALL message is used to send a broadcast message to everyone
Xconnected to IRCnet.
X
X3.30. Trace command
X
X   Command: TRACE
XParameters: [<server>]
X
XTRACE command is used to find out the route to specific server.
XEach server should process this message, tell the sender about it
Xand then send it to next server until given server is reached.
XIf <server> parameter is omitted, it is recommended that TRACE command
Xcould send a message to user telling to which servers current server
Xhas direct connection (and maybe the delay time to that server, too).
X
X3.31. Route command
X
X   Command: ROUTE
XParameters: <server1> <server2> <distance>
X
XROUTE message is sent to irc network when a connection between some
Xservers has been set up correctly. Distance tells the time delay between
Xservers so that other servers could optimize IRC network to be as fast
Xas possible and possibly alter the topology of IRC network.
X
X3.32. Linreply command
X
X   Command: LINREPLY
XParameters: <server> <location>
X
XLINKS command is replied by series of LINREPLY commands. Each LINSERVER
Xreply describes one server entry in IRC network.
X
X4. Optional messages
X
XOptional messages are described next. This means that valid and
Xworking server does not need to understand there messages. 
X
X4.1. Debug message
X
X   Command: DEBUG
X
XDebug command is reserved for testing purposes. Parameters and replies
Xare implementation specific and they are not listed here.
X
X4.2. Hide message
X
X   Command: HIDE 
XParameters: [nickname|id@host]
X
XMessages from specific nickname/id will not be displayed.
XHide without parameters hides all messages.
X
X4.3. Reset message
X
X   Command: RESET
XParameters: [nickname|id@host]
X
XResets messages from specific nickname/id to normal state, ie.
Xif HIDE or command has been issued, this removes it's effect.
XReset without any parameters undoes all previous hide messages.
X
X4.4. Status message
X
X   Command: STATUS
XParameters: [nickname|id@host]
X
XReturns status of given nickname/id. Ie. if messages are ignored
X(with HIDE command), status is HIDE. Status without parameters
Xreturns status of all changed nickname/id entries.
X
X4.5. Away message
X
X   Command: AWAY
XParameters: [message]
X
XWith away message you can set an automatic reply for messages.
XAway with parameter sets this mode on, and without parameter
Xresets modes. If away is on and somebody sends you a message,
Xresponse message is sent out automatically. Note that you cannot send
Xany messages while in away mode.
X
X4.6. Alias message
X
X   Command: ALIAS
XParameters: [nick [nick|id@host]]
X
XAlias message is used to set up aliases for some user. If you g.e.
Xspecify alias 'ALIAS Wiz jto@tolsun', all messages you send to
Xnickname Wiz are redirected to user jto@tolsun. If there already
Xexists nickname Wiz, then you cannot send messages to him/her
Xwithout first turning alias off (ALIAS Wiz). Alias without parameters
Xdisplays all current aliases.
X
X4.7. Expand message
X
X   Command: EXPAND
XParameters: [1|0]
X
XExpand message is used to switch on/off expand mode, ie. if expand mode
Xis on, then ids and hosts of message senders are given instead of bare
Xnickname. Expand mode is switched on with parameter 1 and off with
Xparameter 0. Expand called without parameters sets expand off.
X
X4.8. Die message
X
X   Command: DIE
XParameters: None
X
XDie message can be used to kill a certain server. That might be needed
Xin certain error conditions, hopefully never. Die should not be available
Xto normal users, only to ones with special privileges.
X
X4.9. Zkey message
X
X   Command: ZKEY
XParameters: <public encryption key>
X
XZkey message is used by the clients to give away their public encryption
Xkey which can then be used to encrypt private messages sent to the clients.
XThe encryption method is yet to be defined. See also ZMSG command.
X
X4.10. Zmsg message
X
X   Command: ZMSG
XParameters: <receiver> <encrypted text to be sent>
X
XZmsg message is used to send encrypted messages to users. Encryption key
Xis given with ZKEY command. Server knows that clients which have sent
Xtheir public key do accept encrypted messages, clients which have not
Xtold specifically with ZKEY that they want to have encrypted messages
Xshould never be sent them, because they probably wouldn't understand
Xthem.
X
X4.11. Time message
X
X   Command: TIME
XParameters: [<daemon>]
X
XTime message is used to query local time from given daemon. Default
Xdaemon is current daemon. Daemon should reply to this message with
XPRIVMSG or NOTICE command. (PRIVMSG as long as NOTICE is not
Ximplemented on current ircd's).
X
X4.12. Rehash message
X
X   Command: REHASH
XParameters: None
X
XRehash message can be used by the operator to force server reread
Xits irc.conf file.
X
X4.13. Names message
X
X   Command: NAMES
XParameters: [<channel>]
X
XWith names parameter you can list all nicknames on specified channel or,
Xif <channel> parameter is omitted, on all channels. If '*' is used
Xinstead of channel name, nicknames on current channel are listed.
XNAMES command is always replied by one or more NAMREPLY commands
Xcontaining channel types, names and users on channels.
X
X4.14. Namreply message
X
X   Command: NAMREPLY
XParameters: <type> <channel> {<nickname>}
X
XNAMREPLY command is a reply to NAMES command. <type> parameter is
X'*' for private channels, '=' for public channels and '?' for secret
Xchannels. <channel> is channels name. Usually NAMES query will be
Xresponded with several NAMREPLY commands, one for each public channel,
Xone for private/secret channel querying user is possibly a member and
Xthen all users on other private channels are marked as being on one
Xprivate channel, who's name is '*'.
X
XExample:
X
XNAMREPLY = 7 Angel Kilroy
XNAMREPLY * 1234 Jeff WiZ
XNAMREPLY * * Lars Karl Jim
X
XLast line indicates that Lars, Karl and Jim are on some private channel
Xor on NULL channel, they are not necessarily on same channel with each
Xother.
X
X4.15. Admin command
X
X   Command: ADMIN
XParameters: [<server>]
X
XAdmin message is used to tell the name of the administrator of given
Xserver (current server if <server> parameter is omitted). Each server
Xshould have the ability to forward ADMIN messages to other servers.
X
X5.0. Messages implemented in clients
X
XFollowing is a recommendation of messages that should be implemented in
Xclients. These messages do not actually belong to Internet Relay Chat
XProtocol, and should be used as guidelines and advices.
X
X5.1. Send message
X
X   Command: SEND
XParameters: filename
X	
XSend specified filenames contents to irc as normal messages.
XSend should not be implemented in server, but only on client.
X
X5.2. Beep message
X
X   Command: BEEP
XParameters: [2|1|0]
X
XBeep command is used to tell client that it should beep after
Xeach received line. BEEP can be set off by using '1' as a parameter
Xof calling BEEP without any parameters at all. Calling BEEP with
Xparameter 2 disables the use of BELL ('\007') completely, even
Xmessages containing BELLs are stripped from BELLs.
XBeep should not be implemented in server, but only on client.
X
X5.3. Cmdchar message
X
X   Command: CMDCH
XParameters: [char]
X
XWith this command you can set/reset the command character that
Xtells client this line is a command and not a simple message.
XCMD without parameter resets command character to '/'.
XCmd should as well be implemented only in clients.
X
X5.4. Query message
X  
X   Command: QUERY
XParameters: [user|id@host]
X
XQuery message is used specify that all folowing lines should be
Xsent to specific user as private messages. Query should be
Ximplemented in client, but may be used on servers as well.
XQuery without parameters stops sending messages as private ones
Xto some user, and sends them to current channel. QRY is only an
Xalias for QUERY.
X
X6. Replies
X
XNot implemented yet. Under construction.
X
X7. User and server authentication
X
XPasswords and host names. See the documentation for irc.conf.
SHAR_EOF
chmod 0600 Comms || echo "restore of Comms fails"
set `wc -c Comms`;Sum=$1
if test "$Sum" != "21088"
then echo original size 21088, current size $Sum;fi
echo "x - extracting INSTALL (Text)"
sed 's/^X//' << 'SHAR_EOF' > INSTALL &&
X[ Obsolete Installation file. Read README for new (and far better) document]
X
XNOTE: *READ* this file before installing ircd. 
X
XHow to INSTALL irc:
X
X1)  Scan through struct.h for machine dependent parameters and, only
X    if absolutely necessary, change the default port to a new one.
X
X2)  Check system type in Makefile
X
X3)  Run make
X
X4)  Read through example irc.conf file and set up your file.
X    You can at first just remove all links to other daemons and
X    add them when you've tested irc works ok.
X
X5)  Install irc, ircd, irc.conf, irc.1 and ircd.8 in their appropriate places.
X    Remember to install ircd as setuid program to a user who can read
X    irc.conf-file. irc.conf-file should NOT be readable by everyone.
X    If you have set up passwords for irc-client, then you should install
X    irc as a setuid program, too.
X
X6)  Check if everything seems to work:
X    Start ircd without parameters.
X    Start irc
X    Now you should be in normal irc-screen, and that means irc and ircd
X    have compiled successfully.
X
X7)  If in internet, ask from some (preferably nearest) irc-administrator
X    where you should connect your ircd to be able to chat with other hosts
X    You should get your authoritative host's domain-name and/or
X    internet address. If you do not know any irc-administrator, mail
X    a query to irc@tolsun.oulu.fi or irc%tolsun.oulu.fi@tut.fi.
X    If you're from states, you can send your queries to
X    vijay@lll-winken.llnl.gov
X
X    Then you should get an internet address and port where to connect your
X    daemon (in some cases you might get several of them) and two passwords,
X    one for other daemon to be able to log into your system and the other
X    for your daemon to be able to connect other daemon. Note that you
X    always need two passwords, both ends must have a password before
X    connection is established ok.
X
X8)  After you have got permission to connect to some other ircd,
X    start your ircd. (Remember to kill the previous one if it still is alive).
X    You should set irc so that it starts when rc.local is executed, if you
X    want to have irc running there all the time. That is; you may want to
X    add the following lines to /etc/rc.local (or some equivalent file that
X    is executed at system boot time):
X
X    if [ -f /usr/local/bin/ircd ]; then
X      /usr/local/bin/ircd & (echo -n ' ircd ') >/dev/console
X    fi
X
X    This requires of course that ircd is installed in directory
X    /usr/local/bin. 
X
X8)  Check if irc works:
X    irc
X    When irc-screen appears in front of you, type /links and see, if there
X    are other links up. If not, either irc has been started/installed
X    unsuccessfully or authoritative host/ircd is down. It is also known
X    that daemons may disconnect their links sometimes, so to be sure
X    try irc again after a half an hour or so, if it still doesn't show
X    other hosts, something is wrong somewhere... 
X
X9)  As a 'normal user' you should know about a couple of things which
X    simplify the use of irc a little bit. You can specify an environment
X    variable IRCNICK and that will become automatically your nickname
X    in irc. Also you can specify environment variable IRCSERVER and that
X    is the name of server you want to connect to. Note that these
X    variables apply only to clients, they have nothing to do when
X    starting ircdaemon (ircd).
X
XIf you encounter any bugs or other problems (you sure will have them !),
Xmail your suggestions and bug reports to me.
X
XJarkko Oikarinen            OuluBox: WIZARD     UUCP:...!mcvax!tut!oulu!jto
XInstitute of Information Processing Science    INTERNET: jto@tolsun.oulu.fi
XUniversity of Oulu, Finland                    EARN/BITNET: toljto at finou
X
SHAR_EOF
chmod 0600 INSTALL || echo "restore of INSTALL fails"
set `wc -c INSTALL`;Sum=$1
if test "$Sum" != "3696"
then echo original size 3696, current size $Sum;fi
echo "x - extracting MANUAL (Text)"
sed 's/^X//' << 'SHAR_EOF' > MANUAL &&
X                                              Author: Karl Kleinpaste
X                                                      karl@cis.ohio-state.edu
X                                                Date: 04 Apr 1989
X                                   Last modification: 04 Apr 1989
X
X			 INTERNET RELAY CHAT
X		  a real-time conversational system
X
X
X* 1: Irc - replacement for talk(1)
X
XIrc is a functional replacement for and improvement to talk(1).  Talk
Xis an old, primitive, atrocious, minimalist sort of keyboard/screen
Xconversation tool, using a grotesque, machine-dependent protocol.
XIrc does everything talk does, but with a better protocol, allowing
Xmore than 2 users to talk at once, with access across the aggregate
XInternet, and providing a whole raft of other useful features.
X
X* 2: Entering Internet Relay Chat
X
XType `irc'.  If one wishes to be known by a nickname which is not
Xone's login name, type `irc chosen-nickname' instead.
X
X* 3: How much can be seen from here
X
XThe universe - seriously.
X
XThis is most formally called Internet Relay Chat.  Server hosts are
Xconnected via a tree structure.  The various servers relay control and
Xmessage data among themselves to advertise the existence of other
Xservers, users, and the channels and other resources being occupied by
Xthose users.
X
X* 4: Structure
X
XThere is quite a lot of structure to the operation of irc, as
Xcompared to crufty old talk(1).  Since so little could be done with
Xtalk(1), it needed little structure.  But to keep track of people
Xspread literally around the world (the system was written by Jarkko
XOikarinen of Finland, usually seen on the system as `Wiz'), the
Xstructure is useful so that one can speak to exactly those people with
Xwhom one wishes to speak.
X
X** 4.1: Nicknames
X
XAll users of irc are known to the system by a `nickname.'  By
Xdefault, one's nickname is one's login name.  Nickname clashes are not
Xallowed; this is enforced by the servers.  If one's intended nickname
Xclashes with someone else as one enters chat, one will not be able to
Xcomplete entry to irc until one changes one's nickname to something
Xelse.
X
X** 4.2: Presence on a channel
X
XFundamental to the operation of irc is the concept of a channel.  All
Xusers are `on a channel' while inside irc.  One enters the `null
Xchannel,' channel 0, first.  One cannot send any messages while in
Xchannel 0 unless one has set up a private conversation in some way.
XThe number of channels is essentially unlimited - whatever will fit in
Xa 32-bit integer.
X
X** 4.3: Types of channels
X
XThere are 3 channel types, with increasing levels of privacy afforded
Xthem.
X
X*** 4.3.1: Public channels
X
XPublic channels are channels 1-999.  If one is on one of these
Xchannels, one can be seen by all other users.  Anyone can notice users
Xon a public channel and join such a channel's conversation.
X
X*** 4.3.2: Secret channels
X
XChannels 1000-up are called `secret.'  This means that, although
Xanyone can see that one is using chat, no one can tell what channel
Xone is using unless one is already on that channel with oneself.
XSince the number of potential channels is in the billions, this is
Xquite some security - all one gives away is the acknowledgement that
Xone is using chat.
X
X*** 4.3.3: Hidden channels
X
XNegative channel numbers are called `hidden.'  While one is on a
Xhidden channel, no one who is not on one's channel with oneself can
Xeven see that one is there.  One's name does not show up in a list of
Xactive users.  The only indication of one's presence is that, when
Xentering chat, all new users are told that there are "N users on P
Xservers."  If one checks on all users and finds less than N of them,
Xone knows that others are hiding on negative channels.  But a hidden
Xchannel user still cannot be found except by brute-force checking
Xthrough all channels, a hopeless proposition in the face of 10-digit
Xchannel numbers.  Security through obscurity finally means something.
X
X** 4.4: Channel limits
X
XMost channels are limited by server design to accommodate 10 users
Xeach.  The exceptions to this are channels 1-9, where no limits on
Xuser population are enforced.  But keeping track of conversations
Xamong more than 10 people is, shall we say, troublesome at best.
XUsers experienced in CompuServe's CB service, a fairly close
Xconceptual equivalent to chat, should understand this if they think
Xabout CB channel 1 on a Friday night.
X
X** 4.5: Conversations not using channels
X
XIt is possible to conduct conversations with others without using the
Xformalized channel structure.  Doing so requires that two people set
Xthemselves up for private conversation using special commands; see
XUser Commands below.
X
X* 5: Screen/keyboard structure
X
XChat is a full-screen utility.  It takes over the screen, with the
Xbulk of activity happening in the top N-2 lines, a modeline (vaguely
Xemacs-like) on the next to last line, and one's input being entered on
Xthe last line.  The rightmost position of the modeline indicates
Xeither OWR, meaning overwrite mode on input, or INS, meaning insert
Xmode.  Default is OWR.
X
X** 5.1: Keyboard input
X
XWhen typing commands at irc, one has a minimalist line-editing
Xfacility in an emacs style.  That is, ^A moves the cursor to the
Xbeginning of the line, ^E goes to the end, ^D deletes the character
Xunder the cursor, ^K kills from the cursor to the end, and so on.  If
Xone is in overwrite mode, then typing occurs on top of any characters
Xalready present in the input line.  If insert mode is active, then
Xcharacters in front of the cursor are pushed farther out as one types.
X
X** 5.2: Screen activity
X
XAlmost everything happens in the upper bulk of the screen.  This
Xincludes both messages from other users, as well as the output of the
Xcontrol commands.
X
XNormal messages from other users appear with the originating nickname
Xin <angle brackets>.  Private messages arrive with the originating
Xnickname in *asterisks*.  Messages which one sends to everyone appear
Xwith a preceding "> " whereas messages which one sends privately to
Xone other user appear with "-> *nickname*."
X
XOther output (e.g., /who commands, invitations from other users to
Xjoin channels, and so forth) appears interspersed with other activity
Xon the screen.
X
X* 6: Command structure
X
XOrdinary text typed at irc is sent as one's messages to everyone else
Xon the same channel, modulo personal choices for private messages and
Xthe like.  Commands to irc itself all begin with a command character,
Xwhich is initially `/' but may be changed to any other character
Xdesired.
X
XCommands may in general be abbreviated to a unique prefix.
X
X** 6.1: Leaving irc
X
XThe way to get out of irc is to enter the /signoff command.  "/si" is
Xsufficient.  Also equivalent are "/exit," "/bye," and perhaps "quit."
X
X** 6.2: Getting help
X
XType "/help."  Follow the instructions.
X
X** 6.3: User commands
X
XOther commands supported by irc are:
X
X      help   signoff       who     whois
X      list     topic      join   channel
X     links       msg    invite    summon
X     users     stats      nick      away
X      info     clear     query     cmdch
X      date
X
X*** 6.3.1: help
X
XInformation on how to use the rest of the system is available via
X/help.  The modeline says so as well.
X
X*** 6.3.2: signoff
X
X/signoff exits chat.
X
X*** 6.3.3: who
X
X/who returns information on who is using chat.  /who without arguments
Xprints info on all users that can be seen.  Users of public channels
Xshow up with their channel identified.  Users of secret channels
Xappear, but they are specified as being on a private, unspecified
Xchannel.  Users of hidden channels do not appear at all.
X
XGiving a numeric argument to /who returns only those users of the
Xspecified channel.  This still doesn't show users of secret or hidden
Xchannels unless one is actually on that channel.
X
X*** 6.3.4: whois
X
XThis returns information about individual users.  Say "/whois
Xnickname" to get information on the login name and host from which the
Xnicknamed user comes.
X
X*** 6.3.5: topic
X
XChannels can be given off-the-cuff "topics."  Saying "/topic some
Xstring of text" will associate that topic with the current channel.
X
X*** 6.3.6: list
X
X/list will give lists of active channels, the number of users of each,
Xand the topics therewith associated.  Again, secret and hidden
Xchannels do not appear.
X
X*** 6.3.7: join & channel
X
X/join or /channel are the means to enter a channel.  Give a numeric
Xargument for the channel one wishes to enter.  If this is a secret or
Xhidden channel, /who commands will show oneself and any other users of
Xone's channel.
X
XOne's arrival on a channel is announced to the rest of the users
Xalready on that channel.  Silent, anonymous "lurking" is not
Xsupported.
X
X*** 6.3.8: links
X
X/links lists the currently-active set of chat servers.  Beware: this
Xlist can be quite long, and will undoubtedly get longer as chat gains
Xwider use.  As of 22 March 1989, about 15-20 servers is typical.
X
X*** 6.3.9: msg
X
XA single message can be sent privately to a certain user with /msg.
XType /msg nickname and the text to be sent.  It will be sent privately
Xto the indicated nickname.
X
X*** 6.3.10: invite
X
XIf there is a user online to whom one wishes to speak, one may invite
Xthat user to join oneself on a certain channel.  One types "/invite
Xnickname" with an optional channel number.  The receiving user gets a
Xone-line message indicating the sender and the invitation.  The
Xreceiving user is free to ignore the invitation, of course.
X
X*** 6.3.11: summon
X
XAn extreme form of /invite is /summon.  "/summon user@host" will
Xrequest the user on the specified host to enter the chat system.  Do
Xnot do this unless one is fairly sure that one's request will be
Xwelcome - it can be a fairly disturbing and sometimes irritating
Xintrusion.  In order for /summon to work, the specified host must be a
Xconnected chat server - one can't summon random people from around the
XInternet.
X
X*** 6.3.12: users
X
X/users will return a list of the users logged into one's system.  With
Xan optional hostname identifying a chat server host, the users logged
Xinto that system will be listed.
X
X*** 6.3.13: stats
X
XThis command returns counts of various protocol operations of one's
Xchat server.  It is neither particularly useful nor interesting; it
Xwas, at one time, a debugging aid.
X
X*** 6.3.14: nick
X
XOne can change nicknames by issuing "/nick new-nickname."  All users
Xon one's channel will be advised of the change.  NOTE: If one enters
Xchat with a nickname clash (e.g., one's login name is the same as
Xsomeone else's, and the other user got there first), the system will
Xnot let one enter until one issues a /nick command with a unique
Xnickname.
X
X*** 6.3.15: away
X
XSometimes, one wishes to remain connected to the chat system, but one
Xmust be elsewhere for a while.  One can issue an /away command with
Xarbitrary text as argument, which will mark oneself as being away.  If
Xsomeone sends an away'd user a private message (via /msg or in a
Xprivate session set up via /query; see below), the sender will get a
Xmessage back from the server indicating the away-ness and the message
Xwhich was set.
X
X*** 6.3.16: info
X
X/info returns information regarding the author and copyright of the
Xchat system.
X
X*** 6.3.17: clear
X
XAt times, one wishes that one's screen weren't so cluttered.  /clear
Xmakes it so.
X
X*** 6.3.18: query
X
XThis command is used to set up private communications `outside' the
Xnormal channel system.
X
XWhen one enters "/query nickname," the indicated nickname is set up as
Xthe sole recipient of anything which one types thereafter.  Thus, if
Xuser A executes "/query B" and user B executes "/query A," they have
Xset up a private communication between themselves.  Significantly, it
Xremains possible for them to stay on their respective channels, which
Xneed not be the same, and listen to whatever conversation is going on
Xaround them as well, though they cannot respond to that ambient
Xconversation without leaving the private conversation they have set up.
X
XOne leaves this private mode by issuing /query without arguments.
X
X*** 6.3.19: cmdch
X
XThe `/' character may not be best for some people to use as their
Xcommand character.  It can be changed with "/cmdch <character>."
X
X** 6.4: Operator commands
X
XThe chat system administrators on each host have additional
Xresponsibilities and power over the configuration and operation of the
Xservers.  The commands to do so are delineated below.
X
X*** 6.4.1: oper
X
XUsers who have the potential for operator privileges initially invoke
Xthose privileges by "/oper nickname password," where nickname is the
Xnickname under which operation is intended, and password is the
Xpassword known to the chat system for that nickname.
X
X*** 6.4.2: kill
X
XObnoxious users had best beware the operator who's fast on the /kill
Xcommand.  "/kill nickname" blows any given nickname completely out of
Xthe chat system.
X
XObnoxiousness is not to be tolerated.  But operators do not use /kill
Xlightly.
X
X*** 6.4.3: quote
X
XRaw access to the underlying server protocol is possible through the
Xuser of the /quote command.  "/quote any text at all" is used to send
Xdirect, unmodified commands to the servers.  This has a wide variety
Xof uses, such as deliberately killing a local or remote chat daemon,
Xinvoking operator privileges for otherwise-operator-priv-forbidden
Xusers, and related tasks.  It is, again, a very powerful operation,
Xand not to be used lightly.
X
X* 7: Questions, problems, troubles?
X
XWrite mail to local irc coordinator.
SHAR_EOF
chmod 0600 MANUAL || echo "restore of MANUAL fails"
set `wc -c MANUAL`;Sum=$1
if test "$Sum" != "13403"
then echo original size 13403, current size $Sum;fi
echo "x - extracting Makefile (Text)"
sed 's/^X//' << 'SHAR_EOF' > Makefile &&
X#
X# See struct.h for machine dependent parameters    --Jto
X#
X# Format of command lines:
X# ircd {<hostname> <portnum>}
X# irc [<nickname> [<hostname>]]
X# Some options are available too. See manual pages.
X#
X# Thanx to mta@tut.fi for creating emacs-like interface in irc.
X#
X# Thanx to kim@kannel.lut.fi for creating hpux-version.
X#
X# Thanx to jtrim@orion.cair.du.edu for some enchantments and
X#   lotsa good advice and suggestions.
X#
X# Thanx to vijay@lll-winken.llnl.gov for lotsa advice and
X#   telling many people about irc.
X#
X# Thanx to karl@cis.ohio-state.edu for user's manual.
X#
X# Thanx to gl8f@astsun3.astro.virginia.edu for pointing out several
X#   FEATURES ;-) in irc...
X#
X# Thanx to all others who have given good advice, opinions and written
X# code for irc.
X#
X# Author:      Jarkko Oikarinen,
X# Internet:    jto@tolsun.oulu.fi
X# UUCP:        ...!mcvax!tut!oulu!jto
X# BITNET:      toljto at finou
X#
X# SYS = sysv   SysV NOT working... under construction...
X# Use bsd for HPUX, SUNs, ULTRIX, ...
XSYS = bsd
X
XDOBJS= ircd.o debug.o s_msg.o parse.o packet.o send.o list.o s_sys.o sys.o\
X       s_conf.o date.o channel.o
XCOBJS= irc.o parse.o packet.o send.o c_msg.o debug.o str.o edit.o screen.o\
X       c_sys.o sys.o c_conf.o help.o ignore.o
XROBJS= card.o parse.o packet.o send.o r_msg.o debug.o str.o r_sys.o sys.o\
X       c_conf.o deck.o
X
XCFLAGS = -g
X#CFLAGS = -O
X
X# At least HPUX needs only curses library, not termcap...
X#TLIBS = -lcurses
X
XTLIBS = -lcurses -ltermcap
SHAR_EOF
echo "End of part 1"
echo "File Makefile is continued in part 2"
echo "2" > s2_seq_.tmp
exit 0

bleckmd@jacobs.cs.orst.edu (david bleckmann) (06/20/89)

---- Cut Here and unpack ----
#!/bin/sh
# this is part 2 of a multipart archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file Makefile continued
#
CurArch=2
if test ! -r s2_seq_.tmp
then echo "Please unpack part 1 first!"
     exit 1; fi
( read Scheck
  if test "$Scheck" != $CurArch
  then echo "Please unpack part $Scheck next!"
       exit 1;
  else exit 0; fi
) < s2_seq_.tmp || exit 1
echo "x - Continuing file Makefile"
sed 's/^X//' << 'SHAR_EOF' >> Makefile
X
X# Libraries needed for ircd
X
XDLIBS =
X
XCC=/bin/cc
X
Xall: irc ircd
X
Xirc.tar.Z: irc.tar
X	compress irc.tar
X
Xirc.tar: irc ircd irc.1 ircd.8 Comms Makefile COPYRIGHT INSTALL README ADVERTISEMENT MANUAL
X	tar -cfv irc.tar Comms Makefile COPYRIGHT *.c *.h irc.1 ircd.8 INSTALL example.conf README ADVERTISEMENT MANUAL
X
Xirc.shar: irc ircd irc.1 ircd.8 Comms Makefile COPYRIGHT INSTALL README ADVERTISEMENT MANUAL
X	shar Comms Makefile COPYRIGHT *.c *.h irc.1 ircd.8 INSTALL example.conf README ADVERTISEMENT MANUAL >irc.shar
X
Xirc: $(COBJS)
X	$(CC) $(COBJS) -o irc $(TLIBS)
X	chmod 711 irc
X
Xircd: $(DOBJS)
X	$(CC) $(DOBJS) -o ircd $(DLIBS)
X	chmod 4711 ircd
X
Xcard: $(ROBJS)
X	$(CC) $(ROBJS) -o card
X	chmod 711 card
X
Xircd.o: ircd.c struct.h
X
Xignore.o: ignore.c struct.h
X
Xsys.o: $(SYS).c struct.h sock.h Makefile sys.h
X	$(CC) $(CFLAGS) -c $(SYS).c
X	mv $(SYS).o sys.o
X
Xc_sys.o: c_$(SYS).c struct.h sock.h Makefile sys.h
X	$(CC) $(CFLAGS) -c c_$(SYS).c
X	mv c_$(SYS).o c_sys.o
X
Xs_sys.o: s_$(SYS).c struct.h sock.h Makefile sys.h
X	$(CC) $(CFLAGS) -c s_$(SYS).c
X	mv s_$(SYS).o s_sys.o
X
Xr_sys.o: r_$(SYS).c struct.h sock.h Makefile sys.h
X	$(CC) $(CFLAGS) -c r_$(SYS).c
X	mv r_$(SYS).o r_sys.o
X
Xs_conf.o: conf.c struct.h
X	$(CC) $(CFLAGS) -DSERVER -c conf.c
X	mv conf.o s_conf.o
X
Xc_conf.o: conf.c struct.h
X	$(CC) $(CFLAGS) -DCLIENT -c conf.c
X	mv conf.o c_conf.o
X
Xdeck.o: deck.c r_cmd.h
X
Xdate.o: date.c
X
Xchannel.o: channel.c struct.h
X
Xsend.o: send.c struct.h
X
Xdebug.o: debug.c struct.h
X
Xhelp.o: help.c struct.h help.h
X
Xs_msg.o: s_msg.c msg.h struct.h sys.h
X
Xparse.o: parse.c msg.h struct.h sys.h
X
Xpacket.o: packet.c struct.h msg.h
X
Xstr.o: str.c sys.h
X
Xirc.o: irc.c struct.h msg.h sys.h
X
Xc_msg.o: c_msg.c struct.h msg.h
X
Xr_msg.o: r_msg.c struct.h msg.h
X
Xlist.o: list.c struct.h
X
Xedit.o: edit.c
X
Xscreen.o: screen.c
X
Xsys.h: $(SYS).h Makefile
X	cp $(SYS).h sys.h
SHAR_EOF
echo "File Makefile is complete"
chmod 0600 Makefile || echo "restore of Makefile fails"
set `wc -c Makefile`;Sum=$1
if test "$Sum" != "3298"
then echo original size 3298, current size $Sum;fi
echo "x - extracting README (Text)"
sed 's/^X//' << 'SHAR_EOF' > README &&
X                                                Author: Jeff Trim
X                                                        jtrim@orion.cair.du.edu
X                                                  Date: 04 Apr 1989
X                                     Last modification: 04 Apr 1989
X
X            Installing IRC - The Internet Relay Chat Program
X
X                        by Jarkko Oikarinen
X
X
XSystem Requirements:
XTCP/IP Sockets
XBSD 4.3 Unix, SUN Unix, HP Unix, Dec Ultrix, System V (w/sockets)
XKnowledge of UNIX/C Programming, helps ;-)
X
X....if you don't have sockets (and a good way to know is if the UNIX TELNET(1)
Xand FTP(1) programs don't work at all) then you can't run IRC! ;-( DRAT!
XWouldn't it be great if all UNIX destributions had SOCKETS?
X
X
X                        -=> To Install IRC <=-
X
XThis manual attempts to give you the ENTIRE installation procedure for IRC,
Xand I have made it so that you can skip over the parts you don't want to read
Xby looking at the NUMBERS located on the right side of the screen.  Here are
Xthe CHAPTERS contained in this DOCUMENT:
X
X  1) FTP - Getting the program files from "tolsun.oulu.fi" in Finland
X  2) EDITING THE "struct.h" FILE - and what the various #define's do
X  3) EDITING THE "Makefile" 
X  4) HOW TO COMPILE AND INITIALIZE THE SOURCE FILES
X  5) OVERVIEW - of the "irc.conf" file - an introduction to networking
X  6) A TOUR OF THE /etc/hosts DATABASE - Brief description what it does
X  7) SERVER CONNECTIONS - How to set up the "irc.conf" file for SERVERS
X  8) DEFINING YOUR LOCAL HOST INFORMATION - and placing it in "irc.conf"
X  9) CLIENT CONNECTIONS - How to allow Clients to connect to Servers
X 10) OPERATOR PRIVILEDGES - How to make yourself an IRC Adminestrator
X 11) AN EXAMPLE "irc.conf" FILE - Shows you what one REALLY looks like!
X 12) UPDATES TO THE PROGRAM:   - That effect the "irc.conf" file
X
X     A) ADDING SUBNETS: - Adding Multiple Unix Sites (V2.01.5+)
X    
X
XIf you want to just view over a curtain chapter, take this file into VI and
Xuse the VI SEARCH command to search for the NUMBER of your choice, like
X"1)", "2)" and so forth - those numbers are unique to this table of contents
Xand the CHAPTER headings themselves.
X
XBecause we have provided you with this nice manual, DON'T BOTHER ME OR
XANYONE ELSE UNTIL YOU HAVE PERSONALLY WORKED ATLEAST 40 HOURS ON THE
XPROGRAM YOURSELF.  That way when you do ask questions they'll be
Xintelligent questions ;-)
X
X----------===========>>>>>>>> Begin Manual <<<<<<<==========-------------
X
X
X1) FTP: Getting the program files and Unarchiveing them:
X
X   First grab a copy of the program files from the anonymous FTP area of
X   "tolsun.oulu.fi".  The files are usually COMPRESS(ed) and TAR(ed) into
X   an ARCHIVE format so you will need to unarchive them.  To do this, first
X   transfer the archive file on to your UNIX and make a SUBDRIECTORY to
X   hold the files in -- usually "mkdir IRC".  Then place the IRC ARCHIVE into
X   this new sub-directory.
X
X   To uncompress the ARCHIVE type: "uncompress <archive_file>"
X                      For example: "uncompress irc.v2.01.03.tar.Z"
X
X   To UNARCHIVE the program files type: "tar -xf <archive_file>"
X                           For example: "tar -xf irc.v2.01.03.tar"
X
X
X2) EDIT: The "struct.h" file and make changes to the various #DEFINE's:
X   
X   a) Define what type of UNIX OPERATING SYSTEM your machine uses. IRC currently
X      supports, BSD42, BSD43, APOLLO, SYSV.  To select the one you want, 
X      replace the "0" with a "1" next to the choice you want.  All the other
X      UNIX OPERATING SYSTEM DEFINES should be set to "0".
X
X   b) Define DOMAINNAME, if your systems supports the "getdomainname()" system
X      call.  You can check this by typing "domainname" at the UNIX prompt and
X      seeing if anything appears.  IRC will attempt to add your UNIX Internet
X      System Domain to your hostname if it is not currently present on your
X      "hostname()".  You should define this if you do support getdomainame(). 
X      
X   c) Define NOTTY if you want the IRCD to run as a DEAMON.  As a Deamon it
X      will sit in Unix Background and run independant of any Terminal or TTY.
X      If you want to run IRCD in FOREGROUND and attached to a TTY, undefine
X      this option.  NORMALLY you will want to DEFINE this option and run IRCD
X      in Unix Background. 
X
X   d) Define MYNAME to be the Unix Directory path (pwd) to the "ircd"   
X
X   e) Define CONFIGFILE to the Unix Directory path to the "irc.conf"
X      password file.  The Format of this file will be discussed later.
X
X   f) Define PORTNUM alters the Internet Socket Port for IRC.  IRC will use 
X      this port to accept connections from other IRCD Servers and IRC Clients.
X      The current ports being used for IRC are Internet Ports "6667" and "6666"
X      although these are not OFFICIALLY reserved for IRC, they are the ports
X      we have unofficially claimed for the program.  I recommend you set your
X      program to use port "6667".
X
X   g) Define LOGFILE should be set to "/dev/null" unless you plan to DEBUG
X      the program.  You should be aware that the logfile grows very quickly
X      so unless you really need a LOGFILE it should be set to "/dev/null".
X
X   h) Define TIMESEC to be the amount of IDLE time you will allow your server
X      to WAIT before attempting to request status of your neighboring server.
X      If no messages are recieved by your server in TIMESEC seconds your server
X      will send a PING messages to your neighboring site and will expect the
X      other server to reply with a PONG message.  The PONG message tells your 
X      server that the other server is alright and functioning properly.  Your
X      server will wait for PINGFREQUENCY * 2 seconds for the other server to
X      reply to the PING message, and if no reply is given to the PING your
X      server will hangup the current SOCKET between the hosts and attempt to
X      RECONNECT to it again after CONNECTFREQUENCY seconds have passed.  As you
X      can see these 3 commands are interrealted to each other.
X
X   i) Define PINGFREQUENCY - (see "h" above)
X
X   j) Define CONNECTFREQUENCY - will define the number of SECONDS for your
X      server to wait before it attempts reconnection at it's neighboring
X      IRC hosts.  The defualt value is 20 minutes (1200 seconds) and that
X      is generally pretty good for RECONNECTION time.  You should probably
X      not change this Define.
X
X   k) Define MAXUSERSPERCHANNEL - Defines the maximum allowed users per 
X      channel in IRC.  This effects the number of users that can all talk
X      at once in a given channel and it should be left at 10 unless you 
X      have at first consulted with an authorized IRC Adminestrator about
X      it.  DO NOT CHANGE THIS DEFINE UNLESS YOU HAVE PERMISSION TO DO SO.
X      It should be defined to "10" users.
X
X   l) Define WRITEDELAY effects the UNIX Socket command WRITE() which is used
X      to write socket information to the IRCD socket.. and beyond!  Sometimes
X      a socket can become very crowded (if say 10-20 people were using IRC)
X      and it will lock up the users keyboard until it can get a return value
X      from the socket, which tells  IRC some information about the WRITE() call.
X      To BREAK this lockup, you need to specify the number of seconds you'll
X      allow the SOCKET to stay locked up before you'll BREAK the lock - this
X      typically is 15 seconds and that is a pretty good number for it.  I
X      recommend you leave it DEFUALT value.
X
X           --> Shouldn't have to change anything else! < --
X
X3) EDIT Makefile:
X
X   Take the file "Makefile" into a text editor and DEFINE (IE remove the "#"
X   from the Machine type that is yours.  Currently the Makefile supports
X   Berkeley Unix 4.2/4.3, System V and Hewlett Packard Unix.  The following
X   example shows the Makefile defined for Berkley Unix:
X
X       #            
X       # SYS = sysv
X       # SYS = hpux
X       SYS = bsd
X
X   .. all the other machine types chould be UNCOMMENTED (IE should have "#"
X   in front of them).
X
X4) MAKE and Initial CHMOD commands:
X  
X   To compile everything type "make".  Make will compile all of the program
X   files and produce two files for you:  "irc" and "ircd".  You will need to
X   make sure that the "ircd" has the SETUID bit set on in so that OTHER users
X   besides you can boot server if it goes down and you aren't around to boot
X   it yourself.  This will allow them to BOOT the server but it will run under
X   *YOUR* UID so that you can kill it later if you need to.  To turn on the 
X   SETUID bit for IRCD type:
X
X        % chmod 4111 ircd
X
X   then your directory files should look something like this:
X
X       -rwx--x--x  1 wiz        142336 Mar 16 14:17 irc
X       -rwx------  1 wiz           707 Mar 16 02:42 irc.conf
X       -rws--x--x  1 wiz        110592 Mar 16 14:20 ircd
X          ^
X          |
X   the SETUID also allows the "IRCD" to read the "irc.conf" file, because it
X   would be accessed as USER instead of GROUP or OTHER.  You want to keep the
X   "irc.conf" file PROTECTED because there are PASSWORD in it.   Keep your
X   protection up on this file.
X
X
X+--------------------------------------------------------------------------+
X+      M A K I N G   T H E   I R C . C O N F    F I L E                    +
X+--------------------------------------------------------------------------+
X
XWhen you first look at the file it can be a bit confusing, so you should pay
Xclose attention to the following.  I get a lot of messages from people telling
Xme hos confusing this is so PLEASE - really read this:
X
X5) OVERVIEW:   (difference bewtween NAME and NUMERIC Addresses)
X
X   There are 2 different types of INETERNET addresses, NAMED addresses and
X   NUMERIC addresses.  NAMED addresses look like ENGLISH words (and indeed
X   they are ENGLISH words that refer to a given host).  A NAME address looks
X   like "tolsun.oulu.fi" - and that particular address refers to the UNIX
X   named TOLSUN in Finland.  It is a UNIQUE address because no other UNIX in
X   the world has its NAMED address the same as "tolsun.oulu.edu".  Anytime
X   you say "telnet tolsun.oulu.fi" - you would always connect to TOLSUN in
X   Finland.  NUMERIC addresses refer to those addresses that are made up of
X   NUMBERS for example "128.214.5.6" is the NUMERIC address for TOLSUN.  This
X   address is also UNIQUE in that no other UNIX in the would should be using 
X   those NUMERIC numbers.  The NUMERIC address is sometimes more reliable than
X   the NAME address because not all sites can recognize and transleate the
X   NAME address into it's numeric counterpart.  NUMERIC always seems to work
X   best, but use a NAME address when you can because it is easier to tell
X   what host you are connected to.
X
X6) The /ect/hosts Database:  The 0.25 Cent Tour ;-)
X
X   Every UNIX has a file called "/etc/hosts" on it and this file contains 
X   NAME and NUMERIC addresses in it.  When you supply IRC with a NAME address
X   it will at first try to look it up in /ect/hosts, and then (if it's 
X   really smart), use the Local Network File Server (NFS) to find the NUMERIC
X   address for the host you want to connect to.  Thus if you plan to use NAME
X   address keep in mind that on SOME sites that entry for the TARGET UNIX must 
X   be found in /etc/hosts or the NAME address will fail.  A typical entry in
X   /etc/hosts looks like this:
X
X   130.253.1.15    orion.cair.du.edu orion.du.edu orion    # BSD 4.3
X
X   This particular example is the Host ORION at the University of Denver. 
X   Notice that on the far left is the NUMERIC Address for orion.  The
X   next few ENGLISH words are the NAME addresses that can be used for orion,
X   "orion.cair.du.edu", "orion.du.edu", "orion".  ALL of these NAME addresses
X   will return the NUMERIC address "130.253.1.15" which IRC will use to
X   connect to the TARGET UNIX. (when I say TARGET UNIX I am refering to the
X   UNIX you want to connect to for IRC). Any futher questions about /etc/hosts 
X   should be directed to "man hosts".
X
X
X7) SERVER CONNECTIONS:  How to connect to other servers/ How other servers can
X                        connect to you:
X
X   EDIT the file you speicifed in "struct.h" under the #DEFINE CONFIGFILE:
X   Create this file using the same UNIX path and Filename you specified in 
X   that #DEFINE.  (typically this file should be called "irc.conf").
X
X   Now you must decide WHICH hosts you want to connect to and WHAT ORDER you
X   want to connect to them in.  For my example let us assume I am on the
X   UNIX "tolsun.oulu.fi" and I want to establish SOCKET connections to 3
X   other IRCD running hosts (yeah - they must be running an IRCD there ;-)
X
X   My other three hosts I want to connect to are:
X
X         "naakka.tut.fi"           - PRIMARY Connection
X         "orion.cair.du.edu"       - Secondary Connection
X         "hal.oce.orst.edu"        - Third Connection
X
X   And I want to connect to them in THAT order, meaning I first want to
X   try connecting to "naakka.tut.fi", then to "orion.cair.du.edu", and
X   finally to "hal.oce.orst.edu".  So if "naakka.tut.fi" is DOWN (not
X   functioning whatever) - the program will try to connect to "orion".
X   If orion is DOWN it will try to connect to "hal" and so forth.
X   PLEASE limit the number of hosts you will attempt to connect to 3
X   hosts - we are trying to limit the amount of Network Traffic IRC creates.
X
X   The format for the CONNECT entry in the "irc.conf" is:
X
X       C:<TARGET Host Addr>:<Password>:<TARGET Host NAME>:<TARGET Host PORT>
XField: 1        2              3                4               5
X
X   for example:
X   
X    C:orion.cair.du.edu:passwd:orion.cair.du.edu:6667 
X
X          - or -
X
X    C:130.253.1.15:passwd:orion.cair.du.edu:6667
X
X    Explaination:
X
X    Each field is separted with a ":" charcter:
X
X    Field 1: Field 1 tells the IRC program why type of COMMAND we want to 
X             carry out.  In this case I have specified "C", stating I want
X             to CONNECT to another host.
X
X    Field 2: Tells the IRC program what HOST we want to connect to and the
X             NAME or NUMERIC address to connect to it.  You can use either
X             the NAME or NUMERIC address, but don't use both of them.  Use
X             the address that works the best.  If the host is listed in
X             /etc/hosts or your program can use the NFS server use the NAME
X             Address, otherwise use the NUMERIC address.
X
X    Field 3: Is the password needed to CONNECT to the TARGET host.  Some hosts
X             require Password protected validation when you connect to them,
X             and it is in this field that you specify any passwords you might
X             need.  If there is NO password needed, leave this field BLANK
X             with no SPACES. 
X
X    Field 4: The HOSTNAME of the TARGET Host goes here, including DOMAINNAME
X             if any.  This is the name that the TARGET server will identify
X             itself with when you connect to it.  If you were connecting to
X             orion you would recieve "orion.cair.du.edu" - and that is what
X             you should place in this field.
X  
X    Field 5: The INTERNET Port that you want to connect to on the TARGET Unix.
X             Most of the time this will be set to "6667".  If there is NO
X             information in this field (IT'S BLANK) then no connections will 
X             be attempted to the TARGET HOST, and your host will ACCEPT
X             connections FROM the TARGET Host instead.
X
X   Some examples:
X
X            C:naakka.tut.fi::naakka.tut.fi:6667
X 
X            This reads: Connect to host "naakka.tut.fi", with NO PASSWORD,
X            and expect this server to identify itself to you as "naakka.tu.fi".
X            *YOU* will connect to this host at PORT 6667.
X
X            C:130.253.1.15:Jeff:orion.cair.du.edu:6667
X
X            This reads: Connect to a host at adress "130.253.1.15", using a
X            login password of "Jeff".  The TARGET server should Identify
X            itself as "orion.cair.du.edu".  *YOU* will connect at Internet
X            Port 6667 on this host.
X
X            C:orion.cair.du.edu::orion.cair.du.edu
X                                                                               
X            This reads: *DO NOT CONNECT* to "orion.cair.du.edu", but if         
X            "orion.cair.du.edu" happens to request a CONNECTION with me,       
X            allow it, and let "orion.cair.du.edu" connect TO ME.               
X
X   Now back to our original problem, we wanted OUR server CONNECT to 3
X   hosts,  "naakka.tut.fi", "orion.cair.du.edu" and "hal.oce.orst.edu" in
X   that order.  So as we enter these entries into the file they must be
X   done in REVERSE order of how we could want to connect to them.
X   Here's how it would look if we connected "naakka.tut.fi" first:
X
X      C:hal.oce.orst.edu::hal.oce.orst.edu:6667
X      C:orion.cair.du.edu::orion.cair.du.edu:6667
X      C:naakka.tut.fi::naakka.tut.fi:6667
X
X   IRCD would first connect to "naakka..", then to "orion..." and finally
X   to "hal...".
X
X          *** RECIPROCAL ENTRIES - MUST HAVE FOR IRC TO WORK ***
X
X   FOR THESE SERVERS TO CONNECT TO YOU, you must also have a CORRESPONDING
X   "N" entry in your file that takes the SAME FORMAT as the "C" entry
X   did (above).
X
X   Even though you have a "C" entry you also need the "N" entry or the IRC
X   Program will fail.  the "N" entry allows you to SPECIFY any passwords
X   that you will REQUIRE from any CONNECING servers to give you so that they 
X   can be authorized to connect to your IRCD.  (If your lost, stay with me it
X   will be clearer in a moment).
X    
X   Let us assume that "orion.cair.du.edu" connects to *YOUR* server: 
X   Well you want to place PASSWORD authorization on ORION so you
X   make your "N" entry for Orion to be:
X
X          N:orion.cair.du.edu:golden:orion.cair.du.edu
X  
X   What this line says is: Expect a Connection from host "orion.cair.du.edu",
X   and expect a login password of "golden" (or any other password *YOU* want)
X   and expect the host to Identify itself as "orion.cair.du.edu".
X     
X          N:130.253.1.15::orion.cair.du.edu
X
X   What this line says is: Expect a Connection from host "130.253.1.15", and 
X   DON'T EXPECT a login password.  The TARGET Host should identify itself
X   as "orion.cair.du.edu".
X
X   ** NOTE ** Do not add a PORT NUMBER to any "N" entry fields, it is not 
X   needed because the OTHER HOSTS are CONNECTING TO YOU, you aren't connecting
X   to them.
X
X   So now, our "irc.conf" file looks like this:
X
X
X      C:hal.oce.orst.edu::hal.oce.orst.edu:6667
X      C:orion.cair.du.edu::orion.cair.du.edu:6667
X      C:naakka.tut.fi::naakka.tut.fi:6667
X
X      N:hal.oce.orst.edu::hal.oce.orst.edu
X      N:orion.cair.du.edu::orion.cair.du.edu
X      N:naakka.tut.fi::naakka.tut.fi
X
X
X   a good rule of thumb is - "For every "C" entry you have in the file, you
X   MUST have a cooresponding "N" entry".
X
X
X8) DEFINING YOUR LOCAL HOST INFORMATION  - How to tell IRC about your local
X                                           UNIX Host.
X
X   IRC needs to know a few things about your UNIX site, and the "M" command
X   specifies this information for IRC.  The fomat of this command is:
X
X           M:<YOUR Host NAME>:xxx:xxx:<Internet Port>
X   Field:  1         2         3   4      5
X
X   Explaination:
X
X      Field 1: Tells IRC that you are providing local UNIX HOST infomation
X               Command "M".
X
X      Field 2: The name of YOUR host adding any Internet DOMAINNAME that 
X               might also be present.  
X
X      Field 3: -- NOT USED --: Set to Value "xxx".
X    
X      Field 4: -- NOT USED --: Set to Value "xxx".
X 
X      Field 5: This specifed which Internet Port you wish to use for your
X              IRC Server.  Use the same port as you defined in "struct.h".
X
X      Example:
X                M:tolsun.oulu.fi:xxx:xxx:6667
X
X                This line reads: My Host's name is "tolsun.oulu.fi" and
X                I have defied Internet Port Number "6667" to be used as
X                my IRCD Socket Port.
X
X
X9) CLIENT CONNECTIONS -   How to let Clients Connect to your IRCD.
X
X   A Client is a program that connects to the "ircd".  When you compile
X   all of the program files, two different files are created "irc" and
X   "ircd".  The "irc" program is the CLIENT and the "ircd" is the SERVER
X   [Deamon].  Whenever ANYONE wants to talk to other users on IRC they 
X   must run the CLIENT program (irc).
X
X   To allow you and your users to connect and run a session of Internet Relay 
X   Chat you must make some entries to the "irc.conf" file.  
X
X   A) LOCAL CLIENTS: (Defined the DEFAULT Host to connect to when IRC is run) 
X
X      This defines the DEFAULT connection for the "irc" CLIENT.  If you are
X      running an "ircd" SERVER on this SAME UNIX, you will want to define
X      this command to connect to *YOUR OWN* host.  If your site is not running
X      a server then this command should contain the TARGET Hosts connection
X      information and login password (if any).  The format for this command is:
X
X              U:<TARGET Host addr>:<Password>:<TARGET Host NAME>:<Internet Port>
X      Field:  1         2              3                4            5
X   
X      [ For a DETAILED description of the FIELD NUMBERS - see item "7)" above ]
X
X      For example:
X
X           U:tolsun.oulu.fi::tolsun.oulu.fi:6667
X
X                          - OR -
X
X           U:128.214.5.6::tolsun.oulu.fi:6667
X
X      You can also optionally leave off the Internet PORT Number
X      and IRC will attempt a DEFAULT connection to Internet Port 6667 as in:
X 
X           U:tolsun.oulu.fi::tolsun.oulu.fi
X
X   B) REMOTE CLIENTS:
X
X      This command tells the "ircd" SERVER what clients are allowed to connect
X      to *YOUR SERVER*.  Obviously you want to let your *OWN* clients connect,
X      and also any other CLIENTS that want to connect as well.  REMOTE CLIENTS
X      are those clients which are run by users on other UNIXES (anywhere in
X      the world) and connect your server so that they can talk to other users.
X      The CLIENTS would be using your server as a CONNECTION point, therefore
X      the SERVER will be SERVE-ING the CLIENT, even though the REMOTE client
X      was not part of your LOCAL UNIX Network.  All IRC Messages that were
X      sent to this REMOTE CLIENT would be sent to your server and then passed
X      on to where-ever the REMOTE CLIENT was connecting from by *your* "ircd".
X  
X      -----------------------------------------------------------------------
X 
X      The way a REMOTE CLIENT can connect to your "ircd" server is to type: 
X      (At the UNIX "%" prompt:)
X 
X             % irc <nickname> <TARGET Host Addr> <Internet Port>
X
X                    - For Example -
X
X             % irc Jeff tolsun.oulu.fi 6667
X      
X          ... would connect a USER on a REMOTE UNIX to the IRCD Server at
X          "tolsun.oulu.edu" - using a NICKNAME of "Jeff" and connecting
X          to TOLSUN's Internet Port 6667.    
X
X      ------------------------------------------------------------------------
X
X      Format of this command in the "irc.conf" file is:
X
X             I:<TARGET Host Addr>:<Password>:<TARGET Hosts NAME>:<Internet Port>
X      Field: 1         2               3             4                5
X
X          [For a detailed description of these fields see item "7)" above]
X
X      For examples sake let us assume you were making this file for TOLSUN
X      and you wanted to let your *OWN* clients to connect to your server,
X      you would add this entry to the file:
X
X          I:tolsun.oulu.fi::tolsun.oulu.fi
X
X      If you wanted to let REMOTE CLIENTS from other UNIX's to connect to your
X      server (for examples sake let's say you wanted let REMOTE UNIX Sites:
X      "naakka.tut.fi", "orion.cair.du.edu" and "hal.oce.orst.edu" connect their
X      CLIENTS to your site)  You *could* add them to "irc.conf" like this:
X
X          I:orion.cair.du.edu::orion.cair.du.edu
X          I:128.193.64.132::hal.oce.orst.edu
X          I:naakka.tut.fi:password:naakka.tu.fi
X
X      and any REMOTE CLIENTS that want to connect to you can.  The ORDER in
X      which these is entered into the file is NOT IMPORTANT, enter them in
X      any way you want, it won't effect the PRIORITY of IRC in any way.
X
X
X
X10) OPERATOR PRIVILEDGES:  How to become the IRC Adminestor on your site
X
X   To become an IRC Adminestrator, IRC must know who is authorized to become
X   an operator and what their "Nickname" and "Password" is.  To add this
X   information, EDIT your "irc.conf" file and add the following command
X   line to it:
X
X          O:<TARGET Host NAME>:<password>:<nickname>
X  Field:  1          2             3          4
X
X  Explaination:
X 
X     Field 1: Is the command to tell IRC that this is an OPERATOR command
X              entry.  This is the "O" command.
X 
X     Field 2: Tells IRC which host you have the PRIVILEDGES FROM.  This
X              means that you should be logged into this host when you
X              ask for the priviledges.  If you specify "tolsun.oulu.fi"
X              then IRC will expect your CLIENT to be connected at 
X              "tolsun.oulu.fi" - when you ask for OPERATOR PRIVILEDGES
X              from "tolsun.oulu.fi".  You cannot be logged in at any
X              other host and be able to use your OPERATOR PRIVILEDGES
X              at tolsun, only when you are connected at TOLSUN will this
X              work - this is a safe guard against unauthorized sites
X              trying to STEAL your operator priviledges.
X
X     Field 3: If your AUTHORIZATION Password - this is the password that 
X              let's IRC know you are who you say you are!  Never tell anyone
X              your password and always keep the "irc.conf" file protected
X              from all of the other users.
X 
X     Field 4: The Nickname you usually go by - but you can make this what
X              you want.  It is better to make this a NICKNAME that no one
X              else knows, but anything will do.  I usually use my own
X              loginname (or Unix)
X
X  Example:
X              O:orion.cair.du.edu:pyunxc:Jeff
X
X              There is an OPERATOR at "orion.cair.du.edu" that can get
X              Operator priviledges if he specifies a password of "pyunxc"
X              and uses a NICKNAME of "Jeff".
X
X  +-----------------------------------------------------------------------+
X  +        E N A B L I N G    O P E R A T O R    P R I V I L E D G E S    +
X  +-----------------------------------------------------------------------+
X 
X  If you ever want (or need) to use your OPERATOR priviledges, run "irc" and
X  login to the "ircd" normally - then type the following:
X
X      /oper <nickname> <password>
X
X  If you entered the OPERATOR COMMAND the way I did in the example above you
X  would type:
X
X      /oper Jeff pyunxc
X  
X  and if you entered everything correctly you would get the message:
X  "Good morning Gentleman, I am a Hal 9000 Computer" - if you MESSED up
X  you will probable get a message like "No mere mortals may enter the
X  twilight zone" - or other funny messages ;-)
X
X  You can confirm that your operator priviledges are ACTIVE by typing "/w"
X  and seeing if there is a "*" next to your name in the listing.  If there
X  is then you have successfully become an IRC ADMINESTRATOR.
X
X
X11) AN EXAMPLE "irc.conf" FILE:
X
X    Keep one last thought in mind, if the OTHER IRCD Unix Site doesn't have
X    your site listed in THEIR "irc.conf" file - you won't be able to 
X    connect to them - no matter how right your file is!  It is simply
X    useless to attempt connections to IRCD Hosts that don't have you listed
X    in their files because they'll just HANGUP on you everytime you 
X    connect.
X
X    After an exhausting description of every aspect of the "irc.conf" file,
X    here is a REAL and working example of a totally complete "irc.conf"
X    file.  This is the real file I use on my UNIX site (orion.cair.du.edu)
X    and I am displaying it for you now so that you'll know how yours should
X    look after you've completed it:
X
X    Since this is that last time I will be speaking to you - good luck and
X    make a prayer to whichever UNIX God's you may worship ;-)  I pray to
X    UUCP and Yellow Pages myself ;-)  Have fun and hope to talk to you 
X    soon on IRC.
X
X----------------- Cut here -------------------------- Cut here ---------------
X
XC:128.193.64.132::hal.oce.orst.edu:6667
XC:accuvax.nwu.edu::accuvax.nwu.edu:6667
XC:128.214.5.6::tolsun.oulu.fi
X
XN:128.193.64.132::hal.oce.orst.edu
XN:accuvax.nwu.edu::accuvax.nwu.edu
XN:128.214.5.6::tolsun.oulu.fi
X
XI:orion.cair.du.edu::orion.cair.du.edu
XI:128.193.64.132::hal.oce.orst.edu
XI:accuvax.nwu.edu::accuvax.nwu.edu
XI:128.214.5.6::tolsun.oulu.fi
XI:128.193.32.13::jacobs.CS.ORST.EDU
X
XO:orion.cair.du.edu:*censored*:jtrim
X
XU:orion.cair.du.edu::orion.cair.du.edu:6667
XM:orion.cair.du.edu:xxx:xxx:6667
X
X-------------- Cut Here ---------------------------- Cut Here ----------------
X
X
X12) UPDATES TO THE PROGRAM:   Lists any program changes that were done after
X                              this manual was written
X
X    This section was written to show any changes or upgrading that was done
X    after version v2.01.4 was released.  We have been releasing new versions
X    of the program very quickly so it is necessary to Document what's new
X    about each version to the best of our ability ;-)  The above documentation
X    is by no means out of date - and any MAJOR changes that take place in
X    the program will mean that I will rewrite the ABOVE Documentation so
X    that it once again reflect reality.  This section is used to tell you
X    about the SMALL fixes to the program that may or may not effect you,
X    for example MY SITE does not use SUBNETING, but many other sites do,
X    so if you were using a SUBNET you would want to know that we do in fact
X    support subneting.
X
X    *NOTE* That if we added a new feature in ONE VERSION, the feature *is*
X    included in the next version as well.  For example we added SUBNETING
X    in version v2.01.5 and it will be included in all future versions of
X    IRC.
X    
X
X    A) SUBNETING  (v2.01.5+)
X
X       IRC now supports SUBNETING, which is the ability to use WILD CARDS
X       (*.*) notation when refering to a NAME or NUMERIC host.  For example,
X       Let us say that you wanted the CLIENTS of ANY HOST in your UNIX domain 
X       of "cair.du.edu" to be able to connect to your IRCD Server.  You can
X       now specify a WILD CARD host listing in the "irc.conf" file of:
X      
X           C:*.cair.du.edu::*.cair.du.edu:6667
X           N:*.cair.du.edu::*.cair.du.edu
X          
X       ... and that would allow ANY HOST that has a UNIX domainname of 
X       "cair.du.edu" to connect to your host.
X
X       This also works for NUMERIC addresses as well.  If you wanted all
X       of the UNIX.  For example if you wanted to allow ANY UNIX with
X       a NUMERIC address of "130.253.1.*" to be able to connect to your
X       host you could say:
X
X           C:130.253.1.*::*.cair.du.edu:6667
X           N:130.253.1.*::*.cair.du.edu
X
X       The reason I added the "*.cair.du.edu" is because the CONNECTING
X       Host would indetify itself as a REAL NAME address, like
X       "orion.cair.du.edu", but your don't care if IT IS "orion", but
X       rather you care that it is FROM A DOMAIN of "cair.du.edu".  You
X       would set this up so that "130.253.1.*" refers to ALL OF THE 
X       MACHINES in the "cair.du.edu" domain, and you would hope that any
X       Machine within this UNIX DOMAIN would have an INTERNET ADRESS
X       that begins with "130.253.1", the LAST NUMBER would be the only
X       ones that's different.  But, this isn't always the case.
X 
X       Examples:
X
X              C:128.214.5.*::*.oulu.fi:6667
X              N:128.214.5.*::*.oulu.fi
X  
X              This line reads: If any machine with an INTERNET ADDRESS
X              that starts with "128.214.5" connects to my server, and
X              identifies itself with a NAME address that ENDS in "oulu.fi",
X              let them connect to my server.
X
X              C:*.du.edu::*.du.edu:6667
X              N:*.du.edu::*.du.edu
X 
X              This line reads: If any host conects to me and identifies itself
X              as a host that ENDS with a NAME Address of "du.edu".
X
X              C:*::*:6667
X              N:*::*
X
X              This ones says: Let ANYONE connect to my server! ;-)  In
X              Reality the computer reads this as:  I don't care what
X              what INTERNET ADRESS or NAME ADDRESS they are from, just
X              let them connect.  I DON'T RECOMMEND YOU DO THIS, but this
X              is a possible option if you need it.
X
X
X 
X     -=> End of IRC README Document <=-
SHAR_EOF
chmod 0600 README || echo "restore of README fails"
set `wc -c README`;Sum=$1
if test "$Sum" != "32568"
then echo original size 32568, current size $Sum;fi
echo "x - extracting bsd.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > bsd.c &&
X/*************************************************************************
X ** bsd.c  Beta  v2.0    (22 Aug 1988)
X **
X ** This file is part of Internet Relay Chat v2.0
X **
X ** Author:           Jarkko Oikarinen 
X **         Internet: jto@tolsun.oulu.fi
X **             UUCP: ...!mcvax!tut!oulu!jto
X **           BITNET: toljto at finou
X **
X ** Copyright (c) 1988 University of Oulu, Computing Center
X **
X ** All rights reserved.
X **
X ** See file COPYRIGHT in this package for full copyright.
X ** 
X *************************************************************************/
X
Xchar bsd_id[] = "bsd.c v2.0 (c) 1988 University of Oulu, Computing Center";
X
X#include "struct.h"
X
Xdummy()
X{
X  return(0);
X}
X
Xdeliver_it(fd, str, len)
Xint fd, len;
Xchar *str;
X{
X  int retval;
X  alarm(WRITEWAITDELAY);
X  retval = write(fd, str, len);
X  alarm(0);
X  return(retval);
X}
X
SHAR_EOF
chmod 0600 bsd.c || echo "restore of bsd.c fails"
set `wc -c bsd.c`;Sum=$1
if test "$Sum" != "853"
then echo original size 853, current size $Sum;fi
echo "x - extracting bsd.h (Text)"
sed 's/^X//' << 'SHAR_EOF' > bsd.h &&
X/*************************************************************************
X ** bsd.h  Beta  v2.0    (22 Aug 1988)
X **
X ** This file is part of Internet Relay Chat v2.0
X **
X ** Author:           Jarkko Oikarinen 
X **         Internet: jto@tolsun.oulu.fi
X **             UUCP: ...!mcvax!tut!oulu!jto
X **           BITNET: toljto at finou
X **
X ** Copyright (c) 1988 University of Oulu, Computing Center
X **
X ** All rights reserved.
X **
X ** See file COPYRIGHT in this package for full copyright.
X ** 
X *************************************************************************/
X
X#if HPUX
X#include <string.h>
X#define index         strchr
X#define rindex        strrchr
X#define bcopy(a,b,s)  memcpy(b,a,s)
X#define bzero(a,s)    memset(a,0,s)
Xextern char *strchr(), *strrchr();
Xextern char *inet_ntoa();
X#else 
X#include <strings.h>
X#endif
X#include <ctype.h>
X#include <pwd.h>
SHAR_EOF
chmod 0600 bsd.h || echo "restore of bsd.h fails"
set `wc -c bsd.h`;Sum=$1
if test "$Sum" != "866"
then echo original size 866, current size $Sum;fi
echo "x - extracting c_bsd.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > c_bsd.c &&
X/*************************************************************************
X ** c_bsd.c  Beta  v2.0    (22 Aug 1988)
X **
X ** This file is part of Internet Relay Chat v2.0
X **
X ** Author:           Jarkko Oikarinen 
X **         Internet: jto@tolsun.oulu.fi
X **             UUCP: ...!mcvax!tut!oulu!jto
X **           BITNET: toljto at finou
X **
X ** Copyright (c) 1988 University of Oulu, Computing Center
X **
X ** All rights reserved.
X **
X ** See file COPYRIGHT in this package for full copyright.
X ** 
X *************************************************************************/
X
Xchar c_bsd_id[] = "c_bsd.c v2.0 (c) 1988 University of Oulu, Computing Center";
X
X#include "struct.h"
X#if HPUX
X#include <time.h>
X#else
X#include <sys/time.h>
X#endif
X#include <sys/types.h>
X#include <sys/socket.h>
X#include <sys/file.h>
X#include <sys/ioctl.h>
X#include <netinet/in.h>
X#include <netdb.h>
X#include <stdio.h>
X#include <signal.h>
X#include <fcntl.h>
X#include <curses.h>
X#if BSD42 || ULTRIX || HPUX
X#include "sock.h"
X#endif
X#include "sys.h"
X
X#define STDINBUFSIZE (0x80)
X
Xextern struct Client me;
Xint
Xclient_init(host, portnum)
Xchar *host;
Xint portnum;
X{
X  int sock, tryagain = 1;
X  static struct hostent *hp;
X  static struct sockaddr_in server;
X
X  gethostname(me.host,HOSTLEN);
X
X  /* FIX:  jtrim@duorion.cair.du.edu -- 3/4/89 
X     and jto@tolsun.oulu.fi -- 3/7/89 */
X
X  while (tryagain) {
X    sock = socket(AF_INET, SOCK_STREAM, 0);
X    if (sock < 0) {
X      perror("opening stream socket");
X      exit(1);
X    }
X    server.sin_family = AF_INET;
X    
X    /* MY FIX -- jtrim@duorion.cair.du.edu   (2/10/89) */
X    if ( isdigit(*host))
X      {
X	server.sin_addr.s_addr = inet_addr(host);
X      }
X    else
X      { 
X	hp = gethostbyname(host);
X	if (hp == 0) {
X	  fprintf(stderr, "%s: unknown host", host);
X	  exit(2);
X	}
X	bcopy(hp->h_addr, &server.sin_addr, hp->h_length);
X      }
X    server.sin_port = htons(portnum);
X    /* End Fix */
X    
X    if (connect(sock, (struct sockaddr *) &server, sizeof(server)) < 0) {
X	if (!strcmp(host, me.host) && tryagain == 1)  /* Is this MY host? */
X	  {
X	    if (fork() == 0)   /* - server is SUID/SGID to ME so it's my UID */
X	      {
X		execl(MYNAME, "ircd", (char *)0);
X		exit(1);
X	      }
X	    printf("Connection refused at your own host!\n");
X	    printf("Rebooting IRCD Daemon and trying again....\n");
X	    printf("Wait a moment...\n");
X	    close(sock);
X	    sleep(5);
X	    tryagain = 2;
X	  } else {
X	    perror("irc");
X	    exit(1);
X	  }
X      } else
X	tryagain = 0;
X    }
X  return(sock);
X}
X/* End Fix */
X
Xclient_loop(sock)
Xint sock;
X{
X  int i = 0, size, pos;
X  char apubuf[STDINBUFSIZE+1], ch;
X  fd_set ready;
X  do {
X    ready.fds_bits[0] = (1 << sock) | 1;
X    move(LINES-1,i); refresh();
X    if (select(sock+1, &ready, 0, 0, NULL) < 0) {
X/*      perror("select"); */
X      continue;
X    }
X    if (ready.fds_bits[0] & (1 << sock)) {
X      if ((size = read(sock, apubuf, STDINBUFSIZE)) < 0)
X	perror("receiving stream packet");
X      if (size == 0) return(-1);
X      dopacket(&me, apubuf, size);
X    }
X    if (ready.fds_bits[0] & 1) {
X      if ((size = read(0, apubuf, STDINBUFSIZE)) < 0) {
X	move(0,0);
X	addstr("\rFATAL ERROR: End of stdin file !\n\r");
X	refresh();
X	return;
X      }
X      for (pos = 0; pos < size; pos++) {
X	i=do_char(apubuf[pos]);
X	move(LINES-1, i);
X      }
X    }
X  } while (1);
X}
SHAR_EOF
chmod 0600 c_bsd.c || echo "restore of c_bsd.c fails"
set `wc -c c_bsd.c`;Sum=$1
if test "$Sum" != "3319"
then echo original size 3319, current size $Sum;fi
echo "x - extracting c_msg.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > c_msg.c &&
X/*************************************************************************
X ** c_msg.c    Beta v2.0    (22 Aug 1988)
X **
X ** This file is part of Internet Relay Chat v2.0
X **
X ** Author:           Jarkko Oikarinen
X **         Internet: jto@tolsun.oulu.fi
X **             UUCP: ...!mcvax!tut!oulu!jto
X **           BITNET: toljto at finou
X **
X ** Copyright (c) 1988 University of Oulu, Computing Center
X **
X ** All rights reserved.
X **
X ** See file COPYRIGHT in this package for full copyright.
X **
X *************************************************************************/
X 
Xchar c_msg_id[] = "c_msg.c v2.0 (c) 1988 University of Oulu, Computing Center";
X
X#include "struct.h"
X#include "msg.h"
X#include <curses.h>
X
Xchar mybuf[513];
Xchar abuf1[20], abuf2[20], abuf3[20], abuf4[20];
X
Xextern struct Ignore *find_ignore();
Xextern char *center();
Xextern struct Client *client;
X
Xm_restart() {
X  putline("*** Oh boy... somebody wants *me* to restart... exiting...\n");
X  sleep(5);
X  exit(0);
X}
X
Xm_time() {
X  putline("*** Received time message..!");
X}
X
Xm_admin() {
X  putline("*** Received time message..!");
X}
X
Xm_trace() {
X  putline("*** Received trace message..!");
X}
X
Xm_rehash() {
X  putline("*** Received rehash message..!");
X}
X
Xm_die() {
X  exit(-1);
X}
X
Xm_pass() {
X  putline("*** Received Pass message !");
X}
X
Xm_oper() {
X  putline("*** Received Oper message !");
X}
X
Xm_names() {
X  putline("*** Received Names message !");
X}
X
Xm_wall(sptr, cptr, sender, message) 
Xstruct Client *sptr, *cptr;
Xchar *sender, *message;
X{
X  sprintf(abuf1, "*** #%s# %s", sender, message);
X  putline(abuf1);
X}
X
Xm_connect() {
X  putline("*** Received Connect message !");
X}
X
Xm_ping(sptr, cptr, sender, para1, para2) 
Xstruct Client *sptr, *cptr;
Xchar *sender, *para1, *para2;
X{
X  if (para2 && *para2)
X    sendto_one(client, "PONG %s@%s %s", client->username, client->host, para2);
X  else
X    sendto_one(client, "PONG %s@%s", client->username, client->host);
X}
X
Xm_pong(sptr, cptr, sender, para1, para2)
Xstruct Client *sptr, *cptr;
Xchar *sender, *para1, *para2;
X{
X  sprintf(mybuf, "*** Received PONG message: %s %s",
X	  para1, (para2) ? para2 : "");
X  putline(mybuf);
X}
X
Xm_nick(sptr, cptr, sender, nickname)
Xstruct Client *sptr, *cptr;
Xchar *sender, *nickname;
X{
X  sprintf(mybuf,"*** Change: %s is now known as %s", sender, nickname);
X  putline(mybuf);
X}
X
Xm_away(sptr, cptr, sender, text)
Xstruct Client *sptr, *cptr;
Xchar *sender, *text;
X{
X  sprintf(mybuf,"*** %s is away: \"%s\"",sender,text);
X  putline(mybuf);
X}
X
Xm_who() { 
X  putline("*** Oh boy... server asking who from client... exiting...");
X}
X
Xm_whois() {
X  putline("*** Oh boy... server asking whois from client... exiting...");
X}
X
Xm_user() {
X  putline("*** Oh boy... server telling me user messages... exiting...");
X}
X
Xm_server(sptr, cptr, sender, serv) 
Xstruct Client *cptr, *sptr;
Xchar *sender, *serv;
X{
X  sprintf(mybuf,"*** New server: %s", serv);
X  putline(mybuf);
X}
X
Xm_list() {
X  putline("*** Oh boy... server asking me channel lists... exiting...");
X}
X
Xm_topic(sptr, cptr, sender, topic)
Xstruct Client *sptr, *cptr;
Xchar *sender, *topic;
X{
X  putline("*** Oh boy... server telling me the topic... exiting...");
X}
X
Xm_channel(sptr, cptr, sender, ch)
Xstruct Client *cptr, *sptr;
Xchar *sender, *ch;
X{
X  if (ch == (char *) 0 || *ch == '\0' || atoi(ch) == 0)
X    sprintf(mybuf,"*** Change: %s has left this Channel", sender);
X  else
X    sprintf(mybuf,"*** Change: %s has joined this Channel (%d)", 
X	    sender, atoi(ch));
X  putline(mybuf);
X}
X
Xm_version(sptr, cptr, sender, version)
Xstruct Client *cptr, *sptr;
Xchar *sender, *version;
X{
X  sprintf(mybuf,"*** Version: %s", version);
X  putline(mybuf);
X}
X
Xm_bye()
X{
X  echo();
X  nocrmode();
X  clear();
X  refresh();
X  exit(-1);    
X}
X
Xm_quit(sptr, cptr, sender)
Xstruct Client *sptr, *cptr;
Xchar *sender;
X{
X  sprintf(mybuf,"*** Signoff: %s", sender);
X  putline(mybuf);
X}
X
Xm_kill() {
X  putline("*** Received KILL message");
X}
X
Xm_info(sptr, cptr, sender, info)
Xstruct Client *cptr, *sptr;
Xchar *sender, *info;
X{
X  sprintf(mybuf,"*** Info: %s", info);
X  putline(mybuf);
X}
X
Xm_links() { 
X  putline("*** Received LINKS message");
X}
X
Xm_summon() {
X  putline("*** Received SUMMON message");
X}
X
Xm_stats() {
X  putline("*** Received STATS message");
X}
X
Xm_users() {
X  putline("*** Received USERS message");
X}
X
Xm_help() {
X  putline("*** Received HELP message");
X}
X
Xm_squit(sptr, cptr, sender, server)
Xstruct Client *cptr, *sptr;
Xchar *sender, *server;
X{
X  sprintf(mybuf,"*** Server %s has died. Snif.", server);
X  putline(mybuf);
X}
X
Xm_whoreply(sptr, cptr, sender, channel, username, host, server,
X	   nickname, away, realname)
Xstruct Client *sptr, *cptr;
Xchar *sender, *channel, *username, *host, *server, *nickname, *away;
Xchar *realname;
X{
X  int i = atoi(channel);
X  if (username)
X    center(abuf1, username, 8);
X  else
X    abuf1[0] = '\0';
X  if (host)
X    center(abuf2, host, 8);
X  else
X    abuf2[0] = '\0';
X  if (server)
X    center(abuf3, server, 8);
X  else
X    abuf3[0] = '\0';
X  if (nickname)
X    center(abuf4, nickname, 8);
X  else
X    abuf4[0] = '\0';
X  if (i != 0)
X    sprintf(mybuf,"Channel %3d: %8s@%8s %8s (%8s) %s %s",i ,abuf1, abuf2,
X	    abuf3, abuf4, away, realname);
X  else
X    sprintf(mybuf,"* Private *: %8s@%8s %8s (%8s) %s %s", abuf1, abuf2,
X	    abuf3, abuf4, away, realname);
X  putline(mybuf);
X}
X
Xm_mytext(sptr, cptr, sender, buf)
Xstruct Client *sptr, *cptr;
Xchar *sender, *buf;
X{
X  if (sender)
X    sprintf(mybuf,"<%s> %s", sender, buf);
X  else
X    sprintf(mybuf,"> %s",buf);
X  putline(mybuf);
X}
X
Xm_text(sptr, cptr, sender, buf)
Xstruct Client *sptr, *cptr;
Xchar *buf, *sender;
X{
X  struct Ignore *iptr;
X  if ((iptr = find_ignore(sender, (struct Ignore *) 0)) &&
X      (iptr->flags & IGNORE_PUBLIC))
X      return(0);
X  if (sender && sender[0]) {
X    sprintf(mybuf,"<%s> %s", sender, buf);
X    putline(mybuf);
X  } else
X    putline(buf);
X}
X
Xm_namreply(sptr, cptr, sender, buf, buf2, buf3)
Xstruct Client *sptr, *cptr;
Xchar *buf, *sender, *buf2, *buf3;
X{
X  if (buf) {
X    switch (*buf) {
X      case '*':
X	sprintf(mybuf,"*** %-3s %s", buf2, buf3);
X        break;
X      case '=':
X        sprintf(mybuf,">>> %-3s %s", buf2, buf3);
X        break;
X      case '@':
X        sprintf(mybuf,"%%%%%% %-3s %s", buf2, buf3);
X        break;
X      default:
X        sprintf(mybuf,"??? %-3s %s", buf2, buf3);
X        break;
X    }
X  } else
X    sprintf(mybuf, "*** Internal Error: namreply");
X  putline(mybuf);
X}
X
Xm_linreply(sptr, cptr, sender, buf, buf2)
Xstruct Client *sptr, *cptr;
Xchar *buf, *sender, *buf2;
X{
X  sprintf(mybuf,"*** Server: %s (%s)", buf, buf2);
X  putline(mybuf);
X}
X
Xm_myprivate(sptr, cptr, sender, buf, buf2)
Xstruct Client *sptr, *cptr;
Xchar *buf, *buf2, *sender;
X{
X  sprintf(mybuf,"-> *%s* %s",buf,buf2);
X  putline(mybuf);
X}
X
Xm_private(sptr, cptr, sender, buf, buf2)
Xstruct Client *sptr, *cptr;
Xchar *buf, *buf2, *sender;
X{
X  struct Ignore *iptr;
X  if ((iptr = find_ignore(sender, (struct Ignore *) 0)) &&
X      (iptr->flags & IGNORE_PRIVATE)) {
X	sendto_one(client,
X		   "PRIVMSG %s :*** Automatic reply: You have been ignored");
X	return(0);
X      }
X  if (sender && sender[0]) {
X    if ((buf[0] >= '0' && buf[0] <= '9') || buf[0] == '-')
X      sprintf(mybuf,"(%s) %s", sender, buf2);
X    else
X      sprintf(mybuf,"*%s* %s", sender, buf2);
X    putline(mybuf);
X  }
X  else
X    putline(buf2);
X}
X
Xm_invite(sptr, cptr, sender, buf, buf2)
Xstruct Client *sptr, *cptr;
Xchar *buf, *buf2, *sender;
X{
X  struct Ignore *iptr;
X  if ((iptr = find_ignore(sender, (struct Ignore *) 0)) &&
SHAR_EOF
echo "End of part 2"
echo "File c_msg.c is continued in part 3"
echo "3" > s2_seq_.tmp
exit 0

bleckmd@jacobs.cs.orst.edu (david bleckmann) (06/20/89)

---- Cut Here and unpack ----
#!/bin/sh
# this is part 3 of a multipart archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file c_msg.c continued
#
CurArch=3
if test ! -r s2_seq_.tmp
then echo "Please unpack part 1 first!"
     exit 1; fi
( read Scheck
  if test "$Scheck" != $CurArch
  then echo "Please unpack part $Scheck next!"
       exit 1;
  else exit 0; fi
) < s2_seq_.tmp || exit 1
echo "x - Continuing file c_msg.c"
sed 's/^X//' << 'SHAR_EOF' >> c_msg.c
X      (iptr->flags & IGNORE_PRIVATE) && (iptr->flags & IGNORE_PUBLIC)) {
X	sendto_one(client,
X		   "PRIVMSG %s :*** Automatic reply: You have been ignored");
X	return(0);
X      }
X  sprintf(mybuf,"*** %s Invites you to channel %s", sender, buf2);
X  putline(mybuf);
X}
X
Xm_error(sptr, cptr, sender, buf, buf2)
Xstruct Client *sptr, *cptr;
Xchar *buf, *buf2, *sender;
X{
X  sprintf(mybuf,"*** Error: %s %s", buf, (buf2) ? buf2 : "");
X  putline(mybuf);
X}
SHAR_EOF
echo "File c_msg.c is complete"
chmod 0600 c_msg.c || echo "restore of c_msg.c fails"
set `wc -c c_msg.c`;Sum=$1
if test "$Sum" != "7884"
then echo original size 7884, current size $Sum;fi
echo "x - extracting c_sysv.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > c_sysv.c &&
X/*************************************************************************
X ** c_sysv.c  Beta  v2.0    (22 Aug 1988)
X **
X ** This file is part of Internet Relay Chat v2.0
X **
X ** Author:           Jarkko Oikarinen 
X **         Internet: jto@tolsun.oulu.fi
X **             UUCP: ...!mcvax!tut!oulu!jto
X **           BITNET: toljto at finou
X **
X ** Copyright (c) 1988 University of Oulu, Computing Center
X **
X ** All rights reserved.
X **
X ** See file COPYRIGHT in this package for full copyright.
X ** 
X *************************************************************************/
X
Xchar c_sysv_id[]="c_sysv.c v2.0 (c) 1988 University of Oulu, Computing Center";
X
X#include <sys/time.h>
X#include <sys/types.h>
X#include <sys/file.h>
X#include <sys/ioctl.h>
X#include <stdio.h>
X#include <signal.h>
X#include <fcntl.h>
X#include <curses.h>
X#include "struct.h"
X#ifdef BSD42
X#include "sock.h"
X#endif
X
Xextern struct Client me;
Xint
Xclient_init(host, portnum)
Xchar *host;
Xint portnum;
X{
X  int sock;
X  static struct hostent *hp;
X  static struct sockaddr_in server;
X  sock = msgget(portnum, 0);
X  if (sock < 0) {
X    perror("opening stream socket");
X    exit(1);
X  }
X  server.sin_family = AF_INET;
X  gethostname(me.host,HOSTLEN);
X  hp = gethostbyname(host);
X  if (hp == 0) {
X    fprintf(stderr, "%s: unknown host", host);
X    exit(2);
X  }
X  bcopy(hp->h_addr, &server.sin_addr, hp->h_length);
X  server.sin_port = htons(portnum);
X  if (connect(sock, (struct sockaddr *) &server, sizeof(server)) < 0) {
X    perror("connect");
X    exit(3);
X  }
X  return(sock);
X}
X
Xclient_loop(sock)
Xint sock;
X{
X  int i = 0, size;
X  char apubuf[101], ch;
X  fd_set ready;
X  do {
X    ready.fds_bits[0] = (1 << sock) | 1;
X    move(LINES-1,i); refresh();
X    if (select(sock+1, &ready, 0, 0, NULL) < 0) {
X      perror("select");
X      continue;
X    }
X    if (ready.fds_bits[0] & (1 << sock)) {
X      if ((size = read(sock, apubuf, 100)) < 0)
X	perror("receiving stream packet");
X      if (size == 0) return(-1);
X      dopacket(&me, apubuf, size);
X    }
X    if (ready.fds_bits[0] & 1) {
X      if ((ch = getchar()) == -1) {
X	move(0,0);
X	addstr("\rFATAL ERROR: End of stdin file !\n\r");
X	refresh();
X	return;
X      }
X      i=do_char(ch);
X    }
X  } while (1);
X}
SHAR_EOF
chmod 0600 c_sysv.c || echo "restore of c_sysv.c fails"
set `wc -c c_sysv.c`;Sum=$1
if test "$Sum" != "2209"
then echo original size 2209, current size $Sum;fi
echo "x - extracting card.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > card.c &&
X/*************************************************************************
X ** card.c  Beta v2.0    (22 Aug 1988)
X **
X ** This file is part of Internet Relay Chat v2.0
X **
X ** Author:           Jarkko Oikarinen
X **         Internet: jto@tolsun.oulu.fi
X **             UUCP: ...!mcvax!tut!oulu!jto
X **           BITNET: toljto at finou
X **
X ** Copyright (c) 1988 University of Oulu, Computing Center
X **
X ** All rights reserved.
X **
X ** See file COPYRIGHT in this package for full copyright.
X **
X *************************************************************************/
X
Xchar card_id[]="card.c v2.0 (c) 1988 University of Oulu, Computing Center";
X
X#include <sys/types.h>
X#include <stdio.h>
X#include <signal.h>
X#include "sys.h"
X
X#define MAIN
X#define DEPTH 10
X#include "struct.h"
X#include "msg.h"
X#undef MAIN
X
X#define NICKNAME "Bartender"
X#define USERNAME "ron"
X#define REALNAME "Ron the Bartender"
X
Xchar *makeclientbuf();
X
Xint timeout();
Xchar buf[BUFSIZE];
Xchar *mycncmp(), *real_name();
Xstruct Client me;
Xstruct Client *client = &me;
Xint portnum;
Xint debuglevel;
X
Xmain(argc, argv)
X     int argc;
X     char *argv[];
X{
X  int sock,length, streamfd, msgsock, i;
X  struct passwd *userdata;
X  char *ch, *argv0=argv[0], *nickptr, *servptr, *getenv();
X  extern int exit();
X  portnum = PORTNUM;
X/*  signal(SIGTSTP, SIG_IGN); */
X  buf[0] = '\0';
X  initconf(buf, me.passwd, me.host, &me.channel);
X  while (argc > 1 && argv[1][0] == '-') {
X    switch(argv[1][1]) {
X      case 'p':
X        if ((length = atoi(&argv[1][2])) > 0)
X          portnum = length;
X        break;
X    }
X    argv++; argc--;
X  }
X  me.buffer[0] = '\0'; me.next = NULL;
X  me.status = STAT_ME;
X  if (servptr = getenv("IRCSERVER")) {
X    strncpy(buf, servptr, HOSTLEN);
X    buf[HOSTLEN] = '\0';
X  }
X  sock = client_init((argc > 2) ? argv[2] : ((buf[0]) ? buf : me.host),
X		     (me.channel > 0) ? me.channel : portnum);
X  userdata = getpwuid(getuid());
X  if (strlen(userdata->pw_name) >= USERLEN) {
X    userdata->pw_name[USERLEN-1] = '\0';
X  }
X  if (strlen(userdata->pw_gecos) >= REALLEN) {
X    userdata->pw_gecos[REALLEN-1] = '\0';
X  }
X  /* FIX:    jtrim@orion.cair.du.edu -- 3/14/88 
X           & jto@tolsun.oulu.fi */
X  if (argc >= 2) {
X    strncpy(me.nickname, argv[1], NICKLEN);
X  } else if (nickptr = getenv("IRCNICK")) {
X    strncpy(me.nickname, nickptr, NICKLEN);
X  } else
X    strncpy(me.nickname,NICKNAME,NICKLEN);
X
X  me.nickname[NICKLEN] = '\0';
X  /* END FIX */
X
X  if (argv0[0] == ':') {
X    strcpy(me.host,"OuluBox");
X    strncpy(me.realname, &argv0[1], REALLEN);
X    strncpy(me.username, argv[1], USERLEN);
X  }
X  else {
X    strncpy(me.realname,REALNAME,REALLEN);
X    strncpy(me.username,USERNAME,USERLEN);
X  }
X  strcpy(me.server,me.host);
X  me.username[USERLEN] = '\0';
X  me.realname[REALLEN] = '\0';
X  me.fd = sock;
X  if (me.passwd[0])
X    sendto_one(&me, "PASS %s", me.passwd);
X  sendto_one(&me, "NICK %s", me.nickname);
X  sendto_one(&me, "USER %s %s %s %s", me.username, me.host,
X	     me.server, me.realname);
X  myloop(sock,streamfd);
X}
X
Xmyloop(sock,fd)
Xint sock,fd;
X{
X  client_loop(sock);
X}
X
X/*
Xsendit(sock,line)
Xint sock;
Xchar *line;
X{
X  static char queryuser[NICKLEN+2];
X  static char cmdch = '/';
X  int i;
X  char *ptr, *ptr2;
X  if (line[0] != cmdch) {
X    if (*queryuser) {
X      m_myprivate(NULL, NULL, NULL, queryuser, line);
X      sendto_one(&me, "PRIVMSG %s :%s", queryuser, line);
X    }
X    else {
X      sendto_one(&me, "MSG :%s", line);
X      m_mytext(NULL, NULL, NULL, line);
X    }
X  }
X  else {
X    if (mycncmp(&line[1],"SIGNOFF", 1))
X      sendto_one(&me, "QUIT");
X    else if (mycncmp(&line[1],"BYE", 1))
X      sendto_one(&me, "QUIT");
X    else if (mycncmp(&line[1],"EXIT", 1))
X      sendto_one(&me, "QUIT");
X    else if (mycncmp(&line[1],"QUIT", 1))
X      sendto_one(&me, "QUIT");
X    else if (ptr=mycncmp(&line[1],"KILL", 2)) {
X      if (unixuser())
X	sendto_one(&me, "KILL %s", ptr);
X      else
X	putline("`tis is no game for mere mortal souls...");
X    }
X    else if (ptr=mycncmp(&line[1],"SUMMON", 2)) {
X	sendto_one(&me, "SUMMON %s", ptr);
X    }
X    else if (ptr=mycncmp(&line[1],"STATS", 2)) 
X      sendto_one(&me, "STATS %s", ptr);
X    else if (ptr=mycncmp(&line[1],"USERS", 1)) 
X      sendto_one(&me, "USERS %s", ptr);
X    else if (ptr=mycncmp(&line[1],"TIME", 1))
X      sendto_one(&me, "TIME %s", ptr);
X    else if (ptr=mycncmp(&line[1],"DATE", 1))
X      sendto_one(&me, "TIME %s", ptr);
X    else if (ptr=mycncmp(&line[1],"NICK", 1)) 
X      sendto_one(&me, "NICK %s", ptr);
X    else if (ptr=mycncmp(&line[1],"WHOIS", 4)) 
X      sendto_one(&me, "WHOIS %s", ptr);
X    else if (ptr=mycncmp(&line[1],"WHO", 1)) 
X      sendto_one(&me, "WHO %s", ptr);
X    else if (ptr=mycncmp(&line[1],"JOIN", 1))
X      sendto_one(&me, "CHANNEL %s", ptr);
X    else if (ptr=mycncmp(&line[1],"WALL", 2))
X      sendto_one(&me, "WALL %s", ptr);
X    else if (ptr=mycncmp(&line[1],"CHANNEL", 1))
X      sendto_one(&me, "CHANNEL %s", ptr);
X    else if (ptr=mycncmp(&line[1],"AWAY", 1))
X      sendto_one(&me, "AWAY %s", ptr);
X    else if (ptr=mycncmp(&line[1],"MSG", 1)) {
X      if ((ptr2 = index(ptr, ' ')) == NULL)
X	putline("ERROR: No message");
X      else {
X	*ptr2 = '\0';
X	sendto_one(&me, "PRIVMSG %s :%s", ptr, ++ptr2);
X	m_myprivate(NULL, NULL, NULL, ptr, ptr2);
X      }
X    }
X    else if (ptr=mycncmp(&line[1],"TOPIC", 1))
X      sendto_one(&me, "TOPIC :%s", ptr);
X    else if (ptr=mycncmp(&line[1],"CMDCH", 2)) {
X      if (ptr && *ptr) {
X	sprintf(buf, "*** Command character changed from '%c' to '%c'",
X		cmdch, *ptr);
X	cmdch = *ptr;
X	putline(buf);
X      } else {
X	putline("*** Error: Command character not changed");
X      }
X    }
X    else if (ptr=mycncmp(&line[1],"INVITE", 2))
X      sendto_one(&me, "INVITE %s", ptr);
X    else if (ptr=mycncmp(&line[1],"INFO", 2))
X      sendto_one(&me, "INFO");
X    else if (ptr=mycncmp(&line[1],"LIST", 1))
X      sendto_one(&me, "LIST %s",ptr);
X    else if (ptr=mycncmp(&line[1],"KILL", 1))
X      sendto_one(&me, "KILL %s",ptr);
X    else if (ptr=mycncmp(&line[1],"OPER", 1))
X      sendto_one(&me, "OPER %s",ptr);
X    else if (ptr=mycncmp(&line[1],"QUOTE", 1))
X      sendto_one(&me, "%s",ptr);
X    else if (ptr=mycncmp(&line[1],"LINKS", 2)) 
X      sendto_one(&me, "LINKS %s", ptr);
X    else if (ptr=mycncmp(&line[1],"HELP", 1))
X      help(ptr);
X    else if (mycncmp(&line[1],"VERSION", 1))
X      sendto_one(&me, "VERSION");
X    else if (mycncmp(&line[1],"CLEAR", 1))
X      doclear();
X    else if (mycncmp(&line[1],"REHASH", 1))
X      sendto_one(&me, "REHASH");
X    else if (ptr=mycncmp(&line[1],"QUERY", 2)) {
X      if (ptr == NULL || *ptr == '\0') {
X	sprintf(buf,"NOTE: Finished chatting with %s",queryuser);
X	putline(buf);
X        queryuser[0] = '\0';
X      }
X      else {
X	strncpy(queryuser,ptr,NICKLEN);
X	queryuser[NICKLEN] = '\0';
X	if (ptr = index(queryuser,' ')) *ptr = '\0';
X	sprintf(buf,"NOTE: Beginning private chat with %s",queryuser);
X	putline(buf);
X      }
X    }
X    else
X      putline("* Illegal Command *");
X  } 
X} */
X
Xchar *mycncmp(str1, str2, len)
Xchar *str1, *str2;
Xint len;
X{
X  int flag = 0;
X  char *s1;
X  for (s1 = str1; *s1 != ' ' && *s1 && *str2; s1++, str2++) {
X    if (!isascii(*s1)) return 0;
X    if (islower(*s1)) *s1 = toupper(*s1);
X    if (*s1 != *str2) flag = 1;
X  }
X  if (flag) return 0;
X  if (len != 0 && s1 - str1 < len)
X    return 0;
X  if (*s1) return s1 + 1;
X  else return s1;
X}
X/*
Xstatic int apu = 0;
X
Xdoclear()
X{
X  char header[HEADERLEN];
X  apu = 0;
X  sprintf(header,HEADER,version);
X  clear();
X  standout();
X  mvaddstr(LINES - 2, 0, header);
X  standend();
X  refresh();
X}
X
Xputline(line)
Xchar *line;
X{
X  char *ptr = line, *ptr2 = NULL;
X  char ch='\0';
X  static char blanko[] = "                                        ";
X  while (ptr) {
X    if (strlen(ptr) > COLS) {
X      ch = ptr[COLS];
X      ptr[COLS] = '\0';
X      ptr2 = &ptr[COLS-1];
X    } 
X    else
X      ptr2 = NULL;
X    move(apu++,0);
X    if (apu > LINES - 4) apu = 0;
X    addstr(ptr);
X    if (apu == 0) 
X      mvaddstr(0,0,"\n\n");
X    else if (apu == LINES - 4) {
X      mvaddstr(LINES - 4, 0, "\n");
X      mvaddstr(0,0,"\n");
X    }
X    else {
X      addstr(blanko); addstr(blanko);
X      addstr("\n");
X      addstr(blanko); addstr(blanko);
X    }
X    ptr = ptr2;
X    if (ptr2) {
X      *ptr2++ = '+';
X      *ptr2 = ch;
X    }
X  }
X  refresh();
X}
X*/
Xint
Xunixuser()
X{
X  return(strcmp(me.host,"OuluBox"));
X}
X
Xstruct Client *
Xmake_client()
X{
X  return(NULL);
X}
X
Xputline(str)
Xchar *str;
X{
X  printf("%s\n",str);
X}
SHAR_EOF
chmod 0600 card.c || echo "restore of card.c fails"
set `wc -c card.c`;Sum=$1
if test "$Sum" != "8400"
then echo original size 8400, current size $Sum;fi
echo "x - extracting card.h (Text)"
sed 's/^X//' << 'SHAR_EOF' > card.h &&
X/*************************************************************************
X ** msg.h  Beta  v2.0    (22 Aug 1988)
X **
X ** This file is part of Internet Relay Chat v2.0
X **
X ** Author:           Jarkko Oikarinen 
X **         Internet: jto@tolsun.oulu.fi
X **             UUCP: ...!mcvax!tut!oulu!jto
X **           BITNET: toljto at finou
X **
X ** Copyright (c) 1988 University of Oulu, Computing Center
X **
X ** All rights reserved.
X **
X ** See file COPYRIGHT in this package for full copyright.
X ** 
X *************************************************************************/
X
X#define CMD_RESET   "RESET"
X#define CMD_SHUFFLE "SHUFFLE"
X#define CMD_GAME    "GAME"
X#define CMD_DEAL    "DEAL"
X#define CMD_BET     "BET"
X#define CMD_DROP    "DROP"
X#define CMD_TAKE    "TAKE"
X#define CMD_PLAYER  "PLAYER"
X#define CMD_SWITCH  "SWITCH"
X#define CMD_PUT     "PUT"
X
Xstruct Game {
X  char *name;
X  int decks;           /* Decks in use in the game */
X  int jokers;          /* No. of jokers in game */
X  int initial_cards;   /* Initial cards delt to players */
X  int newcardtimes;    /* How many times a player can take new cards */
X  int newcardflag;     /* flag = 0, player can take new cards with
X                                    no restriction.
X                          flag = 1, player can take one new card at a time
X                          flag = 2, player can switch some of his cards to
X                                    new ones
X                          flag = 4, player can always take new cards so that
X                                    he always has them number of initial_cards
X		        */
X  int (*cmp)();        /* Compare function used to detect who won the game */
X  int betflag;         /* flag = 0, players can make bets always after
X                                    new cards have been dealt
X                          flag = 1, players can make bet at the start of game
X                          flag = 2, players can make bet after first deal */
X  int basicpot;        /* Total amount of basic pot */
X};
X                          
Xextern int r_reset(), r_shuffle(), r_game(), r_deal(), r_bet(), r_drop();
Xextern int r_take(), r_player(), r_switch();
X
Xstruct Message cmdtab[] = {
X  { CMD_RESET,   r_reset 0, 3 },
X  { CMD_SHUFFLE, r_shuffle 0, 3 },
X  { CMD_GAME,    r_game 0, 3 },
X  { CMD_DEAL,    r_deal 0, 3 },
X  { CMD_BET,     r_bet 0, 3 },
X  { CMD_DROP,    r_drop 0, 3 },
X  { CMD_TAKE,    r_take 0, 3 },
X  { CMD_PLAYER,  r_player 0, 3 },
X  { CMD_SWITCH,  r_switch 0, 3 },
X  { CMD_PUT,     r_put 0, 3 },
X  { NULL,        (int (*)()) 0, 0, 3 }
X};
SHAR_EOF
chmod 0600 card.h || echo "restore of card.h fails"
set `wc -c card.h`;Sum=$1
if test "$Sum" != "2565"
then echo original size 2565, current size $Sum;fi
echo "x - extracting channel.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > channel.c &&
X/*************************************************************************
X ** channel.c  Beta  v2.0    (27 Apr 1989)
X **
X ** This file is part of Internet Relay Chat v2.0
X **
X ** Author:           Jarkko Oikarinen 
X **         Internet: jto@tolsun.oulu.fi
X **             UUCP: ...!mcvax!tut!oulu!jto
X **           BITNET: toljto at finou
X **
X ** Copyright (c) 1988 University of Oulu, Computing Center
X **
X ** All rights reserved.
X **
X ** See file COPYRIGHT in this package for full copyright.
X ** 
X *************************************************************************/
X
Xchar channel_id[] = "channel.c v2.0 (c) 1988 University of Oulu, Computing Center";
X
X#include "struct.h"
Xextern struct Channel *channel;
X
Xint
Xchan_isprivate(channel)
Xstruct Channel *channel;
X{
X  if (channel->channo > 999 || channel->channo < 1)
X    return 1;
X  else
X    return 0;
X}
X
Xint
Xchan_conv(name)
Xchar *name;
X{
X  return (atoi(name));
X}
X
Xint
Xchan_match(channel, channo)
Xstruct Channel *channel;
Xint channo;
X{
X  if (channel->channo == channo)
X    return 1;
X  else
X    return 0;
X}
X
Xint
Xchan_issecret(channel)
Xstruct Channel *channel;
X{
X  if (channel->channo < 0)
X    return 1;
X  else
X    return 0;
X}
X
Xstruct Channel *
Xfind_channel(chname, para)
Xchar *chname;
Xstruct Channel *para;
X{
X  struct Channel *ch2ptr = channel;
X  char *ch = chname;
X  int chan;
X  while (*ch) {
X    if (*ch < '0' || *ch > '9')
X      break;
X    ch++;
X  }
X  if (*ch)
X    return (para);
X  if ((chan = atoi(chname)) == 0)
X    return (para);
X  while (ch2ptr) {
X    if (ch2ptr->channo == chan)
X      break;
X    ch2ptr = ch2ptr->nextch;
X  }
X  if (ch2ptr)
X    return (ch2ptr);
X  else
X    return (para);
X}
SHAR_EOF
chmod 0600 channel.c || echo "restore of channel.c fails"
set `wc -c channel.c`;Sum=$1
if test "$Sum" != "1651"
then echo original size 1651, current size $Sum;fi
echo "x - extracting conf.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > conf.c &&
X/*************************************************************************
X ** conf.c  Beta  v2.0    (22 Aug 1988)
X **
X ** This file is part of Internet Relay Chat v2.0
X **
X ** Author:           Jarkko Oikarinen 
X **         Internet: jto@tolsun.oulu.fi
X **             UUCP: ...!mcvax!tut!oulu!jto
X **           BITNET: toljto at finou
X **
X ** Copyright (c) 1988 University of Oulu, Computing Center
X **
X ** All rights reserved.
X **
X ** See file COPYRIGHT in this package for full copyright.
X ** 
X *************************************************************************/
X
Xchar conf_id[] = "conf.c v2.0 (c) 1988 University of Oulu, Computing Center";
X
X#include <stdio.h>
X#include "struct.h"
X#include "sys.h"
X
X#ifdef SERVER
X
Xstruct Confitem *conf = NULL;
Xextern int portnum;
X
Xstruct Confitem *
Xmake_conf()
X{
X  struct Confitem *cptr;
X  if ((cptr = (struct Confitem *) malloc(sizeof (struct Confitem))) == 
X      (struct Confitem *) 0)
X    {
X      perror("malloc");
X      debug(DEBUG_FATAL, "Out of memory: restarting server...");
X      restart();
X    }
X  else {
X    cptr->next = conf;
X    conf = cptr;
X    cptr->host[0] = cptr->passwd[0] = cptr->name[0] = '\0';
X    cptr->status = CONF_ILLEGAL;
X    cptr->port = 0;
X  }
X  return (cptr);
X}
X
Xmatches(name1, name2)
Xchar *name1, *name2;
X{
X  char c1, c2;
X  for (; *name1 && *name2; name1++, name2++) {
X    if (isupper(*name1))
X      c1 = tolower(*name1);
X    else
X      c1 = *name1;
X    if (isupper(*name2))
X      c2 = tolower(*name2);
X    else
X      c2 = *name2;
X    if (c1 == c2) 
X      continue;
X    if (c1 == '?' || c2 == '?')
X      continue;
X    if (*name1 == '*') {
X      if (*(++name1) == '\0')
X	return(0);
X      for (; *name2 && matches(name1, name2); name2++);
X      if (*name2)
X	return(0);
X      else
X	return(1);
X    }
X/*    if (*name2 == '*') {
X      if (*(++name2) == '\0')
X	return(0);
X      for (; *name1 && matches(name1, name2); name1++);
X      if (*name1)
X	return(0);
X      else
X	return(1);
X    } */
X    break;
X  }
X  if (*name1 == '\0' && *name2 == '\0')
X    return(0);
X  else
X    return(1);
X}
X
Xstruct Confitem *
Xfind_admin()
X{
X  struct Confitem *aconf = conf;
X  while (aconf) {
X    if (aconf->status & CONF_ADMIN)
X      break;
X    aconf = aconf->next;
X  }
X  return (aconf);
X}
X
Xstruct Confitem *
Xfind_me()
X{
X  struct Confitem *aconf = conf;
X  while (aconf) {
X    if (aconf->status & CONF_ME)
X      break;
X    aconf = aconf->next;
X  }
X  return (aconf);
X}
X
Xstruct Confitem *
Xfind_conf(host, aconf, name, statmask)
Xchar *host, *name;
Xstruct Confitem *aconf;
Xint statmask;
X{
X  struct Confitem *tmp = conf;
X  int len = strlen(host);
X  int namelen;
X  if (name)
X    namelen = strlen(name);
X  while (tmp) {
X    if ((tmp->status & statmask) && len < HOSTLEN &&
X	matches(tmp->host, host) == 0) 
X      if (name == NULL || (matches(tmp->name, name) == 0 &&
X			   namelen < HOSTLEN))
X      break;
X    tmp = tmp->next;
X  }
X  return((tmp) ? tmp : aconf);
X}
X
X#endif
X
Xchar *
Xgetfield(newline)
Xchar *newline;
X{
X  static char *line = NULL;
X  char *end, *field;
X
X  if (newline)
X    line = newline;
X  if (line == NULL)
X    return(NULL);
X  field = line;
X  if ((end = index(line,':')) == NULL) {
X    line = NULL;
X    if ((end = index(field,'\n')) == NULL)
X      end = field + strlen(field);
X  } else
X    line = end + 1;
X  *end = '\0';
X  return(field);
X}
X
X#ifdef SERVER
X
Xrehash()
X{
X  struct Confitem *tmp = conf, *tmp2;
X  while (tmp) {
X    tmp2 = tmp->next;
X    free(tmp);
X    tmp = tmp2;
X  }
X  conf = (struct Confitem *) 0;
X  initconf();
X}
X
Xinitconf()
X{
X  FILE *fd;
X  char line[256], *tmp;
X  struct Confitem *aconf;
X  if ((fd = fopen(CONFIGFILE,"r")) == NULL)
X    return(-1);
X  while (fgets(line,255,fd)) {
X    if (line[0] == '#' || line[0] == '\n' || line[0] == ' ' || line[0] == '\t')
X      continue;
X    aconf = make_conf();
X    aconf->status = CONF_ILLEGAL;
X    switch (*getfield(line)) {
X    case 'C':   /* Server where I should try to connect */
X    case 'c':   /* in case of link failures             */
X      aconf->status = CONF_CONNECT_SERVER;
X      break;
X    case 'I':   /* Just plain normal irc client trying  */
X    case 'i':   /* to connect me */
X      aconf->status = CONF_CLIENT;
X      break;
X    case 'K':   /* Kill user line on irc.conf           */
X    case 'k':
X      aconf->status = CONF_KILL;
X      break;
X    case 'N':   /* Server where I should NOT try to     */
X    case 'n':   /* connect in case of link failures     */
X                /* but which tries to connect ME        */
X      aconf->status = CONF_NOCONNECT_SERVER;
X      break;
X    case 'U':   /* Uphost, ie. host where client reading */
X    case 'u':   /* this should connect.                  */
X                /* This is for client only, I must ignore this */
X      aconf->status = CONF_SKIPME;
X      break;    
X    case 'O':   /* Operator. Line should contain at least */
X    case 'o':   /* password and host where connection is  */
X      aconf->status = CONF_OPERATOR;      /* allowed from */
X      break;
X    case 'M':   /* Me. Host field is name used for this host */
X    case 'm':   /* and port number is the number of the port */
X      aconf->status = CONF_ME;
X      break;
X    case 'A':   /* Name, e-mail address of administrator of this */
X    case 'a':   /* server. */
X      aconf->status = CONF_ADMIN;
X      break;
X    default:
X      debug(DEBUG_ERROR, "Error in config file: %s", line);
X      break;
X    }
X    if (aconf->status == CONF_SKIPME || aconf->status == CONF_ILLEGAL) {
X      conf = aconf->next;
X      free(aconf);
X      continue;
X    }
X    if (tmp = getfield(NULL)) {
X      strncpy(aconf->host, tmp, HOSTLEN - 1);
X      aconf->host [HOSTLEN - 1] = '\0';
X      if (tmp = getfield(NULL)) {
X	strncpy(aconf->passwd, tmp, PASSWDLEN - 1);
X	aconf->passwd [PASSWDLEN - 1] = '\0';
X	if (tmp = getfield(NULL)) {
X	  strncpy(aconf->name, tmp, HOSTLEN - 1);
X	  aconf->name [HOSTLEN - 1] = '\0';
X	  if (tmp = getfield(NULL))
X	    if ((aconf->port = atoi(tmp)) == 0)
X	      debug(DEBUG_ERROR, "Error in config file, illegal port field");
X	}
X      }
X    }
X    if (aconf->status == CONF_ME) {
X      if (aconf->port > 0)
X	portnum = aconf->port;
X      if (aconf->host[0]) {
X	strncpy(myhostname,aconf->host,HOSTLEN);
X	myhostname[HOSTLEN] = '\0';
X      }
X    }
X    debug(DEBUG_NOTICE, "Read Init: (%d) (%s) (%s) (%s) (%d)",
X	  aconf->status, aconf->host, aconf->passwd,
X	  aconf->name, aconf->port);
X  }
X}
X
X#endif
X#ifdef CLIENT
X
Xinitconf(host, passwd, myname, port)
Xchar *host, *passwd, *myname;
Xint *port;
X{
X  FILE *fd;
X  char line[256], *tmp;
X  if ((fd = fopen(CONFIGFILE,"r")) == NULL)
X    return(-1);
X  while (fgets(line,255,fd)) {
X    if (line[0] == '#' || line[0] == '\n' || line[0] == ' ' || line[0] == '\t')
X      continue;
X    switch (*getfield(line)) {
X    case 'C':   /* Server where I should try to connect */
X    case 'c':   /* in case of link failures             */
X    case 'I':   /* Just plain normal irc client trying  */
X    case 'i':   /* to connect me */
X    case 'N':   /* Server where I should NOT try to     */
X    case 'n':   /* connect in case of link failures     */
X                /* but which tries to connect ME        */
X    case 'O':   /* Operator. Line should contain at least */
X    case 'o':   /* password and host where connection is  */
X                /* allowed from */
X    case 'M':   /* Me. Host field is name used for this host */
X    case 'm':   /* and port number is the number of the port */
X    case 'a':
X    case 'A':
X    case 'k':
X    case 'K':
X      break;
X    case 'U':   /* Uphost, ie. host where client reading */
X    case 'u':   /* this should connect.                  */
X      if (tmp = getfield(NULL)) {
X	strncpy(host, tmp, HOSTLEN - 1);
X	host[HOSTLEN-1] = '\0';
X	if (tmp = getfield(NULL)) {
X	  strncpy(passwd, tmp, PASSWDLEN - 1);
X	  passwd[PASSWDLEN-1] = '\0';
X	  if (tmp = getfield(NULL)) {
X	    strncpy(myname, tmp, HOSTLEN - 1);
X	    myname[HOSTLEN-1] = '\0';
X	    if (tmp = getfield(NULL)) {
X	      if ((*port = atoi(tmp)) == 0)
X		debug(DEBUG_ERROR, "Error in config file, illegal port field");
X	    }
X	  }
X	}
X      }
X      break;    
X    default:
X      debug(DEBUG_ERROR, "Error in config file: %s", line);
X      break;
X    }
X}
X}
X
X#endif
X
X  
SHAR_EOF
chmod 0600 conf.c || echo "restore of conf.c fails"
set `wc -c conf.c`;Sum=$1
if test "$Sum" != "8132"
then echo original size 8132, current size $Sum;fi
echo "x - extracting date.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > date.c &&
X/*************************************************************************
X ** date.c  Beta v2.0    (23 Mar 1989)
X **
X ** This file is part of Internet Relay Chat v2.0
X **
X ** Author:           Jarkko Oikarinen
X **         Internet: jto@tolsun.oulu.fi
X **             UUCP: ...!mcvax!tut!oulu!jto
X **           BITNET: toljto at finou
X **
X ** Copyright (c) 1988 University of Oulu, Computing Center
X **
X ** All rights reserved.
X **
X ** See file COPYRIGHT in this package for full copyright.
X **
X *************************************************************************/
X
Xchar date_id[]="date.c v2.0 (c) 1988 University of Oulu, Computing Center";
X
X#include <time.h>
X
Xstatic char *months[] = {
X	"January",	"February",	"March",	"April",
X	"May",	        "June",	        "July",	        "August",
X	"September",	"October",	"November",	"December"
X};
X
Xstatic char *weekdays[] = {
X	"Sunday",	"Monday",	"Tuesday",	"Wednesday",
X	"Thursday",	"Friday",	"Saturday"
X};
X
Xchar *date() {
X	long clock;
X	struct tm *ltbuf;
X	static char buf[80];
X
X	time(&clock);
X	ltbuf = localtime(&clock);
X	sprintf(buf, "%s %s %d 19%02d -- %d:%02d",
X		weekdays[ltbuf->tm_wday], months[ltbuf->tm_mon],
X		ltbuf->tm_mday, ltbuf->tm_year, ltbuf->tm_hour, ltbuf->tm_min);
X	return buf;
X}
SHAR_EOF
chmod 0600 date.c || echo "restore of date.c fails"
set `wc -c date.c`;Sum=$1
if test "$Sum" != "1246"
then echo original size 1246, current size $Sum;fi
echo "x - extracting debug.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > debug.c &&
X/*************************************************************************
X ** debug.c  Beta  v2.0    (22 Aug 1988)
X **
X ** This file is part of Internet Relay Chat v2.0
X **
X ** Author:           Jarkko Oikarinen
X **         Internet: jto@tolsun.oulu.fi
X **             UUCP: ...!mcvax!tut!oulu!jto
X **           BITNET: toljto at finou
X **
X ** Copyright (c) 1988 University of Oulu, Computing Center
X **
X ** All rights reserved.
X **
X ** See file COPYRIGHT in this package for full copyright.
X **
X *************************************************************************/
X 
Xchar debug_id[] = "debug.c v2.0 (c) 1988 University of Oulu, Computing Center";
X
X#include <sys/types.h>
X#include <sys/file.h>
X#include <stdio.h>
X#include "struct.h"
X#if HPUX
X#include <fcntl.h>
X#endif
X
Xextern int debuglevel;
X
Xdebug(level, form, para1, para2, para3, para4, para5, para6)
Xint level;
Xchar *form, *para1, *para2, *para3, *para4, *para5, *para6;
X{
X  if (debuglevel >= 0) 
X    if (level <= debuglevel) { 
X      fprintf(stderr, form, para1, para2, para3, para4, para5, para6);
X      fprintf(stderr, "\n");
X    } 
X}
X
Xopenlog()
X{
X  int fd;
X#ifdef NOTTY
X  if (debuglevel >= 0) {
X    if ((fd = open(LOGFILE, O_WRONLY | O_CREAT, 0600)) < 0) 
X      if ((fd = open("/dev/null", O_WRONLY)) < 0)
X        exit(-1);
X    if (fd != 2) {
X      dup2(fd, 2);
X      close(fd); 
X    }
X  } else {
X    if ((fd = open("/dev/null", O_WRONLY)) < 0) 
X      exit(-1);
X    if (fd != 2) {
X      dup2(fd, 2);
X      close(fd);
X    }
X  }
X#endif
X}
SHAR_EOF
chmod 0600 debug.c || echo "restore of debug.c fails"
set `wc -c debug.c`;Sum=$1
if test "$Sum" != "1501"
then echo original size 1501, current size $Sum;fi
echo "x - extracting deck.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > deck.c &&
X/*************************************************************************
X ** deck.c    Beta v2.0    (22 Aug 1988)
X **
X ** This file is part of Internet Relay Chat v2.0
X **
X ** Author:           Jarkko Oikarinen
X **         Internet: jto@tolsun.oulu.fi
X **             UUCP: ...!mcvax!tut!oulu!jto
X **           BITNET: toljto at finou
X **
X ** Copyright (c) 1988 University of Oulu, Computing Center
X **
X ** All rights reserved.
X **
X ** See file COPYRIGHT in this package for full copyright.
X **
X *************************************************************************/
X 
Xchar deck_id[] = "deck.c v2.0 (c) 1988 University of Oulu, Computing Center";
X
X#include "struct.h"
X#include "deck.h"
X
X#define STATE_NONE   1
X#define STATE_START  2
X#define STATE_BET    3
X#define STATE_TAKE   4
X#define STATE_END    5
X
X#define ST_INGAME    1
X#define ST_GIVEUP    2
X#define ST_NOMORE    3
X#define ST_NEWUSER   4
X
Xstruct Card {
X  char suite;
X  char card;
X  struct Card *next;
X};
X
Xstruct Player {
X  char name[NICKLEN+1];
X  struct Card *cards;
X  int status;
X  int saldo;
X  int pot;
X  struct Player *next;
X};
X
Xstatic int state = STATE_NONE;
Xstatic int pot = 0;
X
Xextern struct Client *client;
X
Xstatic char *suites[] = {
X  "Spade", "Heart", "Diamonds", "Club"
X  };
X
Xstatic char *cards[] = {
X  "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten",
X  "jack", "queen", "king", "ace", "joker"
X  };
X
Xstatic struct Player *player = (struct Player *) 0;
Xstatuc struct Card *trash = (struct Card *) 0;
Xstatic struct Card *deck = (struct Card *) 0;
Xstatic struct Player *turn = (struct Player *) 0, *first = (struct Player *) 0;
Xstatic int cardsondeck = 0;
Xstatic int cardsperdeal = 0;
Xstatic int noofplayers = 0;
X
Xr_reset(user)
Xchar *user;
X{
X  struct Card *ctmp = deck, *ctmp2;
X  struct Player *ptmp = player, *ptmp2;
X  sendto_one(client, "MSG :%s requested game reset...", user);
X  while (ctmp) {
X    ctmp2 = ctmp->next;
X    free (ctmp);
X    ctmp = ctmp2;
X  }
X  while (player) {
X    ctmp = player->cards;
X    while (ctmp) {
X      ctmp2 = ctmp->next;
X      free (ctmp);
X      ctmp = ctmp2;
X    }
X    ptmp2 = ptmp->next;
X    free(ptmp);
X    ptmp = ptmp2;
X  }
X  ctmp = trash;
X  while (ctmp) {
X    ctmp2 = ctmp->next;
X    free(ctmp);
X    ctmp = ctmp2;
X  }
X  cardsondeck = cardsperdeal = noofplayers = 0;
X  deck = trash = (struct Card *) 0;
X  player = turn = first = (struct Player *) 0;
X  return(1);
X}
X
Xstruct Player *nextplayer()
X{
X  if (noofplayers == 0)
X    return (struct Player *) 0;
X  if (turn == (struct Player *) 0)
X    turn = first;
X  do {
X    turn++;
X    if (turn > &(players[MAXPLAYERS-1]))
X      turn = &(players[0]);
X  } while (turn->name[0] == '\0');
X  return (turn);
X}
X
Xshuffle(name)
Xchar *name;
X{
X  int i,j;
X  if (state != START && state != END && state != NO_INIT) {
X    sendto_one(client, "MSG :Shuffling in the middle of game don't work...");
X    return(0);
X  }
X  if (state == NO_INIT) {
X    state = START;
X    init_game(5);
X    return (0);
X  }
X  sendto_one(client, "MSG :%s is shuffling the deck ...", name);
X  cardsondeck = 54;
X  for (i = 0; i < 13; i++)
X    for (j = 0; j < 4; j++) {
X      deck[i + j * 13].suite = j;
X      deck[i + j * 13].card = i+2;
X      deck[i + j * 13].next = &(deck[i + j * 13 + 1]);
X    }
X  deck[52].next = &(deck[53]);
X  deck[53].next = (struct Card *) 0;
X  deck[53].suite = deck[52].suite = 4;
X  deck[53].card = deck[52].card = 15;
X  decktop = &deck[0];
X}
X
Xinit_game(x)
Xint x;
X{
X  int i;
X  shuffle();
X  cardsperdeal = x;
X  for (i=0; i < MAXPLAYERS; i++) {
X    players[i].name[0] = '\0';
X    players[i].cards = (struct Card *) 0;
X    players[i].pot = 0;
X    players[i].saldo = 0;
X  }
X  srandom(time(0));
X  state = START;
X}
X
Xplayer(user)
Xchar *user;
X{
X  int i;
X  if (state != START) {
X    sendto_one(client,"PRIVMSG %s :You cannot enter in the middle of game",
X	       user);
X    return(-1);
X  }
X  for (i=0; players[i].name[0] && i < MAXPLAYERS; i++);
X  if (i == MAXPLAYERS) {
X    sendto_one(client,"PRIVMSG %s :Sorry, no room for more players...",
X	       user);
X    return(-1);
X  }
X  noofplayers++;
X  strncpy(players[i].name, user, NICKLEN);
X  players[i].name[NICKLEN] = '\0';
X  players[i].pot = 0;
X  players[i].saldo = 0;
X  players[i].status = ST_INGAME;
X  sendto_one(client,"MSG :Player %s entered the game...", user);
X  return(0);
X}
X
Xnames()
X{
X  int i;
X  sendto_one(client,"MSG :Players on game:");
X  for (i=0; i<MAXPLAYERS; i++) {
X    if (players[i].name[0])
X      sendto_one(client,"MSG :%s", players[i].name);
X  }
X}
X
Xstruct Player *getplayer(name)
Xchar *name;
X{
X  int i;
X  for (i=0; i<MAXPLAYERS; i++)
X    if (strncmp(name, players[i].name) == 0)
X      break;
X  if (i < MAXPLAYERS)
X    return (&players[i]);
X  else
X    return (struct Player *) 0;
X}
X
Xstruct Card *pickcard()
X{
X  int i;
X  struct Card *cp1 = (struct Card *) 0, *cp2 = decktop;
X  if (cardsondeck < 1)
X    return (struct Card *) 0;
X  i = random() % cardsondeck;
X  cardsondeck--;
X  while (i-- > 0) {
X    cp1 = cp2;
X    cp2 = cp2->next;
X  }
X  if (cp1)
X    cp1->next = cp2->next;
X  cp2->next = (struct Card *) 0;
X  return cp2;
X}
X
Xdeal()
X{
X  int i,j;
X  struct Card *tmp;
X  if (state != START) {
X    sendto_one(client, "MSG :Cannot deal now...");
X    return(-1);
X  }
X  state = DEAL;
X  sendto_one(client, "MSG :Dealing cards ...");
X  for (i=0; i<MAXPLAYERS; i++)
X    if (players[i].name[0]) {
X      sendto_one(client, "MSG :Player %s... %d cards",
X		 players[i].name, cardsperdeal);
X      for (j=0; j<cardsperdeal; j++) {
X	tmp = pickcard();
X	if (tmp == (struct Card *) 0) {
X	  sendto_one(client, "MSG :No more cards... player %s got only %d..",
X		     players[i].name, j);
X	  break;
X	}
X	tmp->next = players[i].cards;
X	players[i].cards = tmp;
X      }
X    }
X}
X
Xhand(sender)
Xchar *sender;
X{
X  struct Card *tmp;
X  struct Player *playerptr = getplayer(sender);
X  if (playerptr == (struct Player *) 0) {
X    sendto_one(client,"PRIVMSG %s :You are not playing !");
X    return(-1);
X  }
X  if (state == START) {
X    sendto_one(client,"PRIVMSG %s :Game has not started yet !");
X    return(-1);
X  }
X  tmp = playerptr->cards;
X  sendto_one(client,"PRIVMSG %s :Your cards:", sender);
X  sendto_one(client,"MSG :%s is having a look at his cards...", sender);
X  while (tmp) {
X    sendto_one(client, "PRIVMSG %s :%s of %s", sender,
X		   cards[tmp->card - 2], suites[tmp->suite]);
X    tmp = tmp->next;
X  }
X}
X
X  
SHAR_EOF
chmod 0600 deck.c || echo "restore of deck.c fails"
set `wc -c deck.c`;Sum=$1
if test "$Sum" != "6293"
then echo original size 6293, current size $Sum;fi
echo "x - extracting edit.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > edit.c &&
X/*************************************************************************
X ** edit.c  Beta  v2.0    (22 Aug 1988)
X **
X ** This file is part of Internet Relay Chat v2.0
X **
X ** Author:           Jarkko Oikarinen 
X **         Internet: jto@tolsun.oulu.fi
X **             UUCP: ...!mcvax!tut!oulu!jto
X **           BITNET: toljto at finou
X **
X ** Copyright (c) 1988 University of Oulu, Computing Center
X **
X ** All rights reserved.
X **
X ** See file COPYRIGHT in this package for full copyright.
X ** 
X *************************************************************************/
X
Xchar edit_id[] = "edit.c v2.0 (c) 1988 University of Oulu, Computing Center";
X
X#include <curses.h>
X#include <signal.h>
X#include "struct.h"
X
X#ifdef TRUE
X#undef TRUE
X#endif
X#define FALSE (0)
X#define TRUE  (!FALSE)
X
X#define FROM_START 0
X#define FROM_END   1
X#define RELATIVE   2
X
Xstatic int esc=0;
Xstatic int literal=0;
X
Xdo_char(ch, sock)
Xchar ch;
X{
X    static int first_time=0;
X
X    if (!first_time) {
X	toggle_ins();
X	toggle_ins();
X	first_time=1;
X	refresh();
X    }
X    if (esc==1) {
X	do_after_esc(ch);
X	return tulosta_viimeinen_rivi();
X    }
X    switch (ch) {
X    case '\000':		/* NULL */
X	break;
X    case '\001':		/* ^A */
X	bol();			/* beginning of line */
X	break;
X    case '\002':		/* ^B */
X	back_ch();		/* backward char */
X	break;
X    case '\003':		/* ^C */
X	rev_line();		/* reverse line */
X	break;
X    case '\004':		/* ^D */
X	del_ch_right();		/* delete char from right */
X	break;
X    case '\005':		/* ^E */
X	eol();			/* end of line */
X	break;
X    case '\006':		/* ^F */
X	forw_ch();		/* forward char */
X	break;
X    case '\007':		/* ^G */
X	add_ch(ch);		/* bell */
X	break;
X    case '\010':		/* ^H */
X	del_ch_left();		/* delete char to left */
X	break;
X    case '\011':		/* TAB */
X	toggle_ins();		/* toggle insert mode */
X	break;
X    case '\012':		/* ^J */
X	send_this_line(sock);	/* send this line */
X	break;
X    case '\013':		/* ^K */
X	kill_eol();		/* kill to end of line */
X	break;
X    case '\014':		/* ^L */
X	refresh_screen();	/* refresh screen */
X	break;
X    case '\015':		/* ^M */
X	send_this_line(sock);	/* send this line */
X	break;
X    case '\016':		/* ^N */
X	next_in_history();	/* next in history */
X	break;
X    case '\017':		/* ^O */
X	break;
X    case '\020':		/* ^P */
X	previous_in_history();	/* previous in history */
X	break;
X    case '\021':		/* ^Q */
X	break;
X    case '\022':		/* ^R */
X    case '\023':		/* ^S */
X    case '\024':		/* ^T */
X	break;
X    case '\025':		/* ^U */
X	kill_whole_line();	/* kill whole line */
X	break;
X    case '\026':		/* ^V */
X	literal_next();		/* literal next */
X	break;
X    case '\027':		/* ^W */
X	del_word_left();        /* delete word left */
X	break;
X    case '\030':		/* ^X */
X	break;
X    case '\031':		/* ^Y */
X	yank();			/* yank */
X	break;
X    case '\032':		/* ^Z */
X	suspend_irc();		/* suspend irc */
X	break;
X    case '\033':		/* ESC */
X	got_esc();
X	break;
X    case '\177':		/* DEL */
X	del_ch_left();		/* delete char to left */
X	break;
X    default:
X	add_ch(ch);
X	break;
X    }
X    return tulosta_viimeinen_rivi();
X}
X
Xbol()
X{
X    set_position(0, FROM_START);
X}
X
Xeol()
X{
X    set_position(0, FROM_END);
X    set_position(1, RELATIVE);
X}
X
Xback_ch()
X{
X    set_position(-1, RELATIVE);
X}
X
Xforw_ch()
X{
X    set_position(1, RELATIVE);
X}
X
Xrev_line()
X{
X    int i1, i2, i3, i4;
X    
X    i4=get_position();
X    set_position(0, FROM_START);
X    i1=get_position();
X    set_position(0, FROM_END);
X    i1=get_position()-i1;
X    set_position(i4, FROM_START);
X
X    for( i2=0; i2>i1/2; i2++) {
X	i3=get_char(i2);
X	set_char(i2, get_char(i1-i2-1));
X	set_char(i1-i2-1, i3);
X    }
X}
X
Xdel_ch_right()
X{
X    int i1, i2, i3;
X
X    i1=get_position();
X    
X    if (!get_char(i1))
X	return;			/* last char in line */
X    set_position(0, FROM_END);
X    i2=get_position();
X    for (i3=i1; i3<i2; i3++)
X	set_char(i3, get_char(i3+1));
X    set_char(i3, 0);
X    set_position(i1, FROM_START);
X}
X
Xdel_ch_left()
X{
X    int i1, i2, i3;
X
X    i1=get_position();
X    
X    if (!i1)
X	return;			/* first pos in line */
X    set_position(0, FROM_END);
X    i2=get_position();
X    for (i3=i1-1; i3<i2; i3++)
X	set_char(i3, get_char(i3+1));
X    set_char(i3, 0);
X    set_position(i1, FROM_START);
X    set_position(-1, RELATIVE);
X}
X
Xsuspend_irc()
X{
X#if HPUX
X#ifdef SIGSTOP
X  kill(getpid(), SIGSTOP);
X#endif
X#else
X  tstp(); 
X#endif
X}
X
Xgot_esc()
X{
X    esc = 1;
X}
X
Xdo_after_esc(ch)
Xchar ch;
X{
X    if (literal) {
X	literal=0;
X	add_ch(ch);
X	return;
X    }
X    esc = 0;
X    switch (ch) {
X    case 'b':
X	word_back();
X	break;
X    case 'd':
X	del_word_right();
X	break;
X    case 'f':
X	word_forw();
X	break;
X    case 'y':
X	yank();
X	break;
X    case '\177':
X	del_word_left();
X	break;
X    default:
X	break;
X    }
X}
X
Xrefresh_screen()
X{
X
X    clearok(curscr, TRUE);
X    refresh();
X}
X
Xadd_ch(ch)
Xint ch;
X{
X    int i1, i2, i3;
X    if (in_insert_mode()) {
X	i1=get_position();
X	set_position(0, FROM_END);
X	i2=get_position();
X	for (i3=i2; i3>=0; i3--)
X	    set_char(i1+i3+1, get_char(i3+i1));
X	set_char(i1, ch);
X	set_position(i1, FROM_START);
X	set_position(1, RELATIVE);
X    } else {
X	i1=get_position();
X	set_char(i1, ch);
X	set_position(i1, FROM_START);
X	set_position(1, RELATIVE);
X    }
X}
X
Xliteral_next()
X{
X    got_esc();
X    literal=1;
X}
X
Xword_forw()
X{
X    int i1,i2;
X
X    i1=get_position();
X    while( i2=get_char(i1) )
X	if ((i2==(int)' ') ||
X	    (i2==(int)'\t') ||
X	    (i2==(int)'_') ||
X	    (i2==(int)'-'))
X	    i1++;
X	else
X	    break;
X    while( i2=get_char(i1) )
X	if ((i2==(int)' ') ||
X	    (i2==(int)'\t') ||
X	    (i2==(int)'_') ||
X	    (i2==(int)'-'))
X	    break;
X	else
X	    i1++;
X    set_position(i1, FROM_START);
X}
X
Xword_back()
X{
X    int  i1,i2;
X
X    i1=get_position();
X    if (i1!=0)
X	i1--;
X    while( i2=get_char(i1) )
X	if ((i2==(int)' ') ||
X	    (i2==(int)'\t') ||
X	    (i2==(int)'_') ||
X	    (i2==(int)'-'))
X	    i1--;
X	else
X	    break;
X    while( i2=get_char(i1) )
X	if ((i2==(int)' ') ||
X	    (i2==(int)'\t') ||
X	    (i2==(int)'_') ||
X	    (i2==(int)'-'))
X	    break;
X	else
X	    i1--;
X    if (i1<=0)
X	i1=0;
X    else
X	i1++;
X    set_position(i1, FROM_START);
X}
X
Xdel_word_left()
X{
X    int i1, i2, i3, i4;
X
X    i1=get_position();
X    word_back();
X    i2=get_position();
X    set_position(0, FROM_END);
X    i3=get_position();
X    for(i4=i2; i4<=i3-(i1-i2); i4++)
X	set_char(i4, get_char(i4+(i1-i2)));
X    for(; i4<=i3; i4++)
X	set_char(i4, (int)'\0');
X    set_position(i2, FROM_START);
X}
X
Xdel_word_right()
X{
X    int i1, i2, i3, i4;
X
X    i2=get_position();
X    word_forw();
X    i1=get_position();
X    set_position(0, FROM_END);
X    i3=get_position();
X    for(i4=i2; i4<=i3-(i1-i2); i4++)
X	set_char(i4, get_char(i4+(i1-i2)));
X    for(; i4<=i3; i4++)
X	set_char(i4, (int)'\0');
X    set_position(i2, FROM_START);
X}
X
X
SHAR_EOF
chmod 0600 edit.c || echo "restore of edit.c fails"
set `wc -c edit.c`;Sum=$1
if test "$Sum" != "6649"
then echo original size 6649, current size $Sum;fi
echo "x - extracting example.conf (Text)"
sed 's/^X//' << 'SHAR_EOF' > example.conf &&
X# Example file how to set up your irc.conf file. 
X# First, you should find out your hostname (full domainname).
X# Replace my.domain.name in next line (and everywhere in this file)
X# with it.
XM:my.domain.name:*:*:6667
X#
X# Next, you should find out all machines where you want to allow
X# clients (that is: irc users, NOT servers) to connect you. Those
X# machines should be systems on the same cluster or department as
X# you so it is not necessary to start separate irc daemons for
X# each of them. Let's assume that you want to give client access
X# to hosts dog.zoo.xx, cat.zoo.xx, cow.zoo.xx, tolsun.oulu.fi and
X# my.domain.name
XI:my.domain.name::my.domain.name
XI:tolsun.oulu.fi::tolsun.oulu.fi
XI:dog.zoo.xx::dog.zoo.xx
XI:cat.zoo.xx::cat.zoo.xx
XI:cow.zoo.xx::cow.zoo.xx
X# The empty fields in previous lines are for passwords, so if you
X# want to set up passwords, you should insert that password in between
X# those colons. Like:
X# I:dog.zoo.xx:password:dog.zoo.xx
X#
X# Next, you should set up a operator access. 
X# Remember that operator has responsibility and power in IRCnet, so
X# you should not allow anyone to be operator. That is why password
X# is always needed with operator account.
X# The first field (tolsun.oulu.fi) is the name of the system where
X# operator is allowed to log into irc. Second field (poiuyt) is password
X# field and third field is operator nickname in IRCnet.
XO:tolsun.oulu.fi:poiuyt:wiz
X#
X# Next line is only for irc clients. You do not need this unless
X# this irc.conf file is used by systems without ircdaemon and they
X# should connect to daemon on this host OR if you have set up
X# passwords for irc clients above (lines beginning with I:).
X# If you have not set uo any passwords for clients, you MUST leave
X# this password field empty. The second field (before password)
X# contains name of the host clients should connect to. (Typically
X# your hostname).
XU:tolsun.oulu.fi:password:tolsun.oulu.fi:6667
X#
X# By now you have working irc.conf for ONE SERVER ircd system. That is,
X# you cannot connect to other ircds yet. For those connections you need
X# to set up a couple of lines for each other ircdaemon you wish
X# your daemon to be directly connected. You should ASK those systems
X# (and passwords for all of them) from the nearest IRC administrator.
X# If in doubt, mail irc@tolsun.oulu.fi and ask there.
X#
X# Now we assume you have a list of hosts available. You should have one
X# of them marked as your UPHOST. (At first you normally have just this
X# one host, no more). It might also be possible to have several UPHOSTs.
X# Next two lines are an example of uphost configuration.
XC:tolsun.oulu.fi:tolsun_password:tolsun.oulu.fi:6667
XN:tolsun.oulu.fi:my_password_for_tolsun:tolsun.oulu.fi
X# If you do not have passwords, just leave those couple of lines empty.
X#
X# Next, you might also have a list of other hosts that might try to
X# connect you (also YOU are their UPHOST). An example configuration
X# file for host 'hal.oce.orst.edu'
XC:hal.oce.orst.edu:hal_password:hal.oce.orst.edu
XN:hal.oce.orst.edu:my_password_for_hal:hal.oce.orst.edu
X# Note that the only difference is the lack of PORT number. That
X# one number is quite important and it makes the difference between
X# UPHOST and DOWNHOST. You should never have too many UPHOSTs, that
X# might cause severe problems on IRCnet.
X# Now your irc.conf installation should be ok. Try to start ircd and
X# then after a short while try to start irc and see how it works.
X#
X# If you happen to be installing another ircd connecting to this
X# one, then you might need some instructions more. Let's assume you're
X# trying to connect hal.oce.orst.edu's daemon to my.domain.name
X# (this example file was made for an imaginary system called my.domain.name).
X# Also you have the following lines in my.domain.name for hal.oce.orst.edu.
X# C:hal.oce.orst.edu:hal_password:hal.oce.orst.edu
X# N:hal.oce.orst.edu:my_password_for_hal:hal.oce.orst.edu
X# What lines should you add to hal.oce.orst.edu's irc.conf-file for
X# my.domain.name ? They are:
X# C:my.domain.name:my_password_for_hal:my.domain.name
X# N:my.domain.name:hal_password:my.domain.name
X#
X# Good Luck ! (You're going to need it ;-)
SHAR_EOF
chmod 0600 example.conf || echo "restore of example.conf fails"
set `wc -c example.conf`;Sum=$1
if test "$Sum" != "4150"
then echo original size 4150, current size $Sum;fi
echo "x - extracting help.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > help.c &&
X/*************************************************************************
X ** help.c  Beta v2.0    (22 Aug 1988)
X **
X ** This file is part of Internet Relay Chat v2.0
X **
X ** Author:           Jarkko Oikarinen
X **         Internet: jto@tolsun.oulu.fi
X **             UUCP: ...!mcvax!tut!oulu!jto
X **           BITNET: toljto at finou
X **
X ** Copyright (c) 1988 University of Oulu, Computing Center
X **
X ** All rights reserved.
X **
X ** See file COPYRIGHT in this package for full copyright.
X **
X *************************************************************************/
X
Xchar help_id[]="help.c v2.0 (c) 1988 University of Oulu, Computing Center";
X
X#include "struct.h"
X#include "sys.h"
X#include "help.h"
X
Xchar helpbuf[80];
X
Xhelp(ptr)
Xchar *ptr;
X{
X  struct Help *hptr;
X  int count;
X  char *ch;
X
X  if (ptr == NULL || *ptr == '\0') {
X    sprintf(helpbuf, "*** Help: Internet Relay Chat v%s Commands:", version);
X    putline(helpbuf);
X    count = 0;
X    for (hptr = helplist; hptr->command; hptr++) {
X      sprintf(&helpbuf[count*10], "%10s", hptr->command);
X      if (++count >= 4) {
X	count = 0;
X	putline(helpbuf);
X      }
X    }
X    if (count)
X      putline(helpbuf);
X    putline("Write /help <command> to get help about particular command");
X    putline("For example /help signoff gives you help about command signoff");
X    putline("To use a command you must prefix it with a slash (/),");
X    putline("For example, to signoff IRC you write /SIGNOFF");
X    putline("*** End Help");
X  } else {
X/*    for (ch = ptr; *ch; ch++)
X      if (islower(*ch))
X	*ch = toupper(*ch); */
X    hptr = helplist;
X    while (hptr->command) {
X      if (mycncmp(ptr, hptr->command, 0)) 
X	break;
X      hptr++;
X    }
X    if (hptr->command == (char *) 0) {
X      putline("*** Error: No such command available via help");
X      putline("*** Write /help to get general help");
X      return(0);
X    }
X    sprintf(helpbuf, "*** Help: %s", hptr->syntax);
SHAR_EOF
echo "End of part 3"
echo "File help.c is continued in part 4"
echo "4" > s2_seq_.tmp
exit 0

bleckmd@jacobs.cs.orst.edu (david bleckmann) (06/20/89)

---- Cut Here and unpack ----
#!/bin/sh
# this is part 4 of a multipart archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file help.c continued
#
CurArch=4
if test ! -r s2_seq_.tmp
then echo "Please unpack part 1 first!"
     exit 1; fi
( read Scheck
  if test "$Scheck" != $CurArch
  then echo "Please unpack part $Scheck next!"
       exit 1;
  else exit 0; fi
) < s2_seq_.tmp || exit 1
echo "x - Continuing file help.c"
sed 's/^X//' << 'SHAR_EOF' >> help.c
X    putline(helpbuf);
X    for (count = 0; count < 5; count++)
X      if (hptr->explanation[count] && *(hptr->explanation[count])) {
X	sprintf(helpbuf, "          %s", hptr->explanation[count]);
X	putline(helpbuf);
X      }
X    putline("*** End Help");
X  }
X  return(0);
X}
X
SHAR_EOF
echo "File help.c is complete"
chmod 0600 help.c || echo "restore of help.c fails"
set `wc -c help.c`;Sum=$1
if test "$Sum" != "2192"
then echo original size 2192, current size $Sum;fi
echo "x - extracting help.h (Text)"
sed 's/^X//' << 'SHAR_EOF' > help.h &&
X/*************************************************************************
X ** help.h  Beta v2.0    (22 Aug 1988)
X **
X ** This file is part of Internet Relay Chat v2.0
X **
X ** Author:           Jarkko Oikarinen
X **         Internet: jto@tolsun.oulu.fi
X **             UUCP: ...!mcvax!tut!oulu!jto
X **           BITNET: toljto at finou
X **
X ** Copyright (c) 1988 University of Oulu, Computing Center
X **
X ** All rights reserved.
X **
X ** See file COPYRIGHT in this package for full copyright.
X **
X *************************************************************************/
X
Xstruct Help {
X  char *command, *syntax, *explanation[5];
X};
X
X#define NULL ((char *) 0)
X
Xstruct Help helplist[] = {
X  { "HELP", "/help <command>",
X    "Query help for specific command",
X    "If called without parameter, lists all commands", "", "", "" },
X  { "SIGNOFF", "/signoff",
X    "The correct way of logging out from IRC.", "", "", "", "" },
X  { "WHO", "/who <channel>",
X    "Lists users on a specific channel",
X    "If <channel> parameter is left out, lists all users",
X    "(you cannot see users on other negative channels though)",
X    "If called '/who *' then lists all users on the same channel as you", "" },
X  { "WHOIS", "/whois <nick>",
X    "Query information about nickname",
X    "Users name, host and server are listed to you", "", "", "" },
X  { "LIST", "/list",
X    "Lists all channels and their topics", "", "", "" },
X  { "TOPIC", "/topic <topic>",
X    "Sets a new topic for the channel you're on.", "", "", "", "" },
X  { "JOIN", "/join <channel>",
X    "Joins a new channel.",
X    "You are automatically removed from your current channel",
X    "This command is exactly the same as /channel command", "", "" },
X  { "CHANNEL", "/channel <channel>",
X    "Joins a new channel.",
X    "You are automatically removed from your current channel",
X    "This command is exactly the same as /join command", "", "" },
X  { "LINKS", "/links",
X    "List all Internet Relay Chat links currently up", "", "", "", "" },
X  { "MSG", "/msg <nicknamelist> <xxx>",
X    "Send private message to <nicknamelist>.",
X    "<nicknamelist> can contain one or more nicknames or channel numbers",
X    "separated by commas (,). For example /m joe,7 Hello! sends message",
X    "Hello! to user joe and channel 7. nicknames and channels must exist",
X    "on ircnet, otherwise an error is returned." },
X  { "INVITE", "/invite <nick>",
X    "Invite user to your channel.",
X    "Nick must be a nickname currently logged on some ircserver", "", "", "" },
X  { "SUMMON", "/summon <user>",
X    "Summon user from operating system level to IRC. User is eg.",
X    "guest@tolsun, where guest is user's username on that host, and tolsun",
X    "is the name of the host user is currently logged in. Host must be",
X    "running irc-daemon before you can summon anyone from there. Do NOT",
X    "use this command unless you really have something important to say"
X    },
X  { "USERS", "/users <host>",
X    "List all users logged on <host>.",
X    "Host must be running irc-daemon before you can list it's users",
X    "If parameter host is omitted, users on the server you're logged on,",
X    "are listed", "" },
X  { "STATS", "/stats",
X    "Show some stats. This command is not much use for ordinary user",
X    "", "", "", "" },
X  { "NICK", "/nick <nick>",
X    "Change your nickname. You cannot choose nickname already in use",
X    "Also some special characters are not allowed in nicknames",
X    "Do not change your nickname too often, it causes unnecessary",
X    "load to IRCnet", "" },
X  { "AWAY", "/away <msg>",
X    "Mark yourself as being away. With msg parameter you can specify",
X    "a message to be sent to all users trying to send private",
X    "messages to you", "", "" },
X  { "INFO", "/info",
X    "Short info of Internet Relay Chat", "", "", "", "" },
X  { "CLEAR", "/clear",
X    "Clears screen.", "", "", "", "" },
X  { "QUERY", "/query <nicknamelist>",
X    "Begins a private chat with <nicknamelist>. All normal messages you",
X    "send from now on are forwarded only to <nicknamelist>.",
X    "You can remove query just by calling query without any parameters,",
X    "e.g. /query", 
X    "/ without any parameters overrides /query's effect, like / blaah" },
X  { "CMDCH", "/cmdch c",
X    "Changes your command prefix character to c. For example, if you",
X    "type '/cmdch .', then you must prefix all commands from now on",
X    "with '.', like .who or .links", "", "" },
X  { "DATE", "/date [daemon]",
X    "Tells you the date in given daemon. If daemon parameter is not given,",
X    "default daemon is current daemon you're logged on", "", "", "" },
X  { "NAMES", "/names [channel]",
X    "List you all users on channel in compressed format. If channel is",
X    "omitted, lists all users on all channels", "", "", "" },
X  { "IGNORE", "/ignore [+|-]<nicknamelist>",
X    "Ignore toggles ignoreflags of given users on and off. Ignore without",
X    "parameters displays current ignorelist. If '+' is specified before",
X    "given nickname, all PUBLIC messages from given nickname are ignored",
X    "'-' respectively ignores all PRIVATE messages. Default is that both",
X    "public and private messages are ignored." },
X  { NULL, NULL, NULL, NULL, NULL, NULL, NULL }
X};
X
SHAR_EOF
chmod 0600 help.h || echo "restore of help.h fails"
set `wc -c help.h`;Sum=$1
if test "$Sum" != "5204"
then echo original size 5204, current size $Sum;fi
echo "x - extracting ignore.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > ignore.c &&
X/*************************************************************************
X ** ignore.c  Beta v2.01.6    (09 May 1989)
X **
X ** This file is part of Internet Relay Chat v2.0
X **
X ** Author:           Jarkko Oikarinen
X **         Internet: jto@tolsun.oulu.fi
X **             UUCP: ...!mcvax!tut!oulu!jto
X **           BITNET: toljto at finou
X **
X ** Copyright (c) 1988 University of Oulu, Computing Center
X **
X ** All rights reserved.
X **
X ** See file COPYRIGHT in this package for full copyright.
X **
X *************************************************************************/
X
Xchar ignore_id[]="ignore.c v2.0 (c) 1988 University of Oulu, Computing Center";
X
X#include "struct.h"
X#include "sys.h"
X
Xstruct Ignore *ignore = (struct Ignore *) 0;
Xchar ibuf[80];
Xextern struct Ignore *find_ignore();
X
Xdo_ignore(user)
Xchar *user;
X{
X  char *ch;
X  struct Ignore *iptr;
X  char *apu = user;
X  int status;
X  if ((user == (char *) 0) || (*user == '\0')) {
X    iptr = ignore;
X    putline("*** Current ignore list entries:");
X    while (iptr) {
X      sprintf(ibuf,"    Ignoring %s messages from user %s", 
X	      (iptr->flags == IGNORE_TOTAL) ? "all" :
X	      (iptr->flags == IGNORE_PRIVATE) ? "private" : "public", 
X	      iptr->user);
X      putline(ibuf);
X      iptr = iptr->next;
X    }
X    putline("*** End of ignore list entries");
X    return (0);
X  }
X  while (apu && *apu) {
X    ch = apu;
X    if (*ch == '+') {
X      ch++;
X      status = IGNORE_PUBLIC;
X    }
X    else if (*ch == '-') {
X      ch++;
X      status = IGNORE_PRIVATE;
X    }
X    else 
X      status = IGNORE_TOTAL;
X    if (apu = index(ch, ','))
X      *(apu++) = '\0';
X    if (iptr = find_ignore(ch, (struct Ignore *) 0)) {
X      sprintf(ibuf,"*** Ignore removed: user %s", iptr->user);
X      putline(ibuf);
X      kill_ignore(iptr);
X    } else {
X      if (strlen(ch) > NICKLEN)
X	ch[NICKLEN] = '\0';
X      if (add_ignore(ch, status) >= 0) {
X	sprintf(ibuf,"*** Ignore %s messages from user %s", 
X		(status == IGNORE_TOTAL) ? "all" :
X		(status == IGNORE_PRIVATE) ? "private" : "public", ch);
X	putline(ibuf);
X      } else
X	putline("Fatal Error: Cannot allocate memory for ignore buffer");
X    }
X  }
X}    
X
Xstruct Ignore *
Xfind_ignore(user, para)
Xchar *user;
Xstruct Ignore *para;
X{
X  struct Ignore *iptr = ignore;
X  while (iptr) {
X    if (myncmp(iptr->user, user, NICKLEN) == 0)
X      break;
X    iptr = iptr->next;
X  }
X  if (iptr)
X    return iptr;
X  else
X    return para;
X}
X
Xint
Xkill_ignore(iptr)
Xstruct Ignore *iptr;
X{
X  struct Ignore *i2ptr = ignore, *i3ptr = (struct Ignore *) 0;
X  while (i2ptr) {
X    if (i2ptr == iptr)
X      break;
X    i3ptr = i2ptr;
X    i2ptr = i2ptr->next;
X  }
X  if (i2ptr) {
X    if (i3ptr)
X      i3ptr->next = i2ptr->next;
X    else
X      ignore = i2ptr->next;
X    free(i2ptr);
X    return (1);
X  }
X  return (-1);
X}
X
Xint add_ignore(ch, status)
Xchar *ch;
Xint status;
X{
X  struct Ignore *iptr;
X  iptr = (struct Ignore *) malloc(sizeof (struct Ignore));
X  if (iptr == (struct Ignore *) 0)
X    return(-1);
X  strncpy(iptr->user, ch, NICKLEN);
X  iptr->user[NICKLEN] = '\0';
X  iptr->next = ignore;
X  ignore = iptr;
X  iptr->flags = status;
X  return(1);
X}
SHAR_EOF
chmod 0600 ignore.c || echo "restore of ignore.c fails"
set `wc -c ignore.c`;Sum=$1
if test "$Sum" != "3111"
then echo original size 3111, current size $Sum;fi
echo "x - extracting irc.1 (Text)"
sed 's/^X//' << 'SHAR_EOF' > irc.1 &&
X.\" @(#)irc.1 2.0 (beta version) 21 Oct 88 
X.TH Irc 1 "21 October 1988"
X.SH NAME
Xirc \- User Interface to Internet Relay Chat Protocol
X.SH SYNOPSIS
X\fBirc\fP [-pportnum] [ \fBnickname\fP [ \fBhost\fP ]]
X.SH DESCRIPTION
X.LP
X\fIIrc\fP is an user interface to Internet Relay Chat. It connects to
Xhost (if host is not given, default is the same host irc is running).
Xif nickname is not given, default is your login name.
XIf portnum is given, irc tries to connect that port on given host.
X.LP
XInside \fIIrc\fP you can get more help by writing /help in the beginning of
Xline.
X.SH EXAMPLE
X.RS
X.nf
Xtolmoon% \fBirc -p6667 Wizard tolsun\fP
X.fi
X.RE
X.LP
Xconnects you to irc server in host tolsun (port 6667) with nickname Wizard
X.SH COPYRIGHT
XCopyright (c) 1988 University of Oulu, Computing Center, Finland.
XAll rights reserved.
XFor full COPYRIGHT see COPYRIGHT file with IRC package.
X.SH "SEE ALSO"
Xircd(8)
X.SH BUGS
XSometimes users get logged off when some server dies. Reason unknown.
XIrc should never be stopped with CTRL-Z, with time buffers fill up and
Xserver may hang.
X.SH AUTHOR
XJarkko Oikarinen, currently jto@tolsun.oulu.fi
SHAR_EOF
chmod 0640 irc.1 || echo "restore of irc.1 fails"
set `wc -c irc.1`;Sum=$1
if test "$Sum" != "1122"
then echo original size 1122, current size $Sum;fi
echo "x - extracting irc.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > irc.c &&
X/*************************************************************************
X ** irc.c  Beta v2.0    (22 Aug 1988)
X **
X ** This file is part of Internet Relay Chat v2.0
X **
X ** Author:           Jarkko Oikarinen
X **         Internet: jto@tolsun.oulu.fi
X **             UUCP: ...!mcvax!tut!oulu!jto
X **           BITNET: toljto at finou
X **
X ** Copyright (c) 1988 University of Oulu, Computing Center
X **
X ** All rights reserved.
X **
X ** See file COPYRIGHT in this package for full copyright.
X **
X *************************************************************************/
X
Xchar irc_id[]="irc.c v2.0 (c) 1988 University of Oulu, Computing Center";
X
X#include <sys/types.h>
X#include <stdio.h>
X#include <curses.h>
X#include <signal.h>
X
X#define MAIN
X#define DEPTH 10
X#include "struct.h"
X#include "msg.h"
X#include "sys.h"
X#undef MAIN
X
Xchar *makeclientbuf();
X
Xint timeout();
Xchar buf[BUFSIZE];
Xchar *mycncmp(), *real_name();
Xstruct Client me;
Xstruct Client *client = &me;
Xint portnum;
Xint debuglevel;
X
Xmain(argc, argv)
X     int argc;
X     char *argv[];
X{
X  int sock, length;
X  struct passwd *userdata;
X  char *argv0=argv[0], *nickptr, *servptr, *getenv();
X  extern int exit();
X  portnum = PORTNUM;
X/*  signal(SIGTSTP, SIG_IGN); */
X  buf[0] = '\0';
X  initconf(buf, me.passwd, me.host, &me.channel);
X  while (argc > 1 && argv[1][0] == '-') {
X    switch(argv[1][1]) {
X      case 'p':
X        if ((length = atoi(&argv[1][2])) > 0)
X          portnum = length;
X        break;
X    }
X    argv++; argc--;
X  }
X  me.buffer[0] = '\0'; me.next = NULL;
X  me.status = STAT_ME;
X  if (servptr = getenv("IRCSERVER")) {
X    strncpy(buf, servptr, HOSTLEN);
X    buf[HOSTLEN] = '\0';
X  }
X  sock = client_init((argc > 2) ? argv[2] : ((buf[0]) ? buf : me.host),
X		     (me.channel > 0) ? me.channel : portnum);
X  userdata = getpwuid(getuid());
X  if (strlen(userdata->pw_name) >= USERLEN) {
X    userdata->pw_name[USERLEN-1] = '\0';
X  }
X  if (strlen(userdata->pw_gecos) >= REALLEN) {
X    userdata->pw_gecos[REALLEN-1] = '\0';
X  }
X  /* FIX:    jtrim@orion.cair.du.edu -- 3/14/88 
X           & jto@tolsun.oulu.fi */
X  if (argc >= 2) {
X    strncpy(me.nickname, argv[1], NICKLEN);
X  } else if (nickptr = getenv("IRCNICK")) {
X    strncpy(me.nickname, nickptr, NICKLEN);
X  } else
X    strncpy(me.nickname,userdata->pw_name,NICKLEN);
X
X  me.nickname[NICKLEN] = '\0';
X  /* END FIX */
X
X  if (argv0[0] == ':') {
X    strcpy(me.host,"OuluBox");
X    strncpy(me.realname, &argv0[1], REALLEN);
X    strncpy(me.username, argv[1], USERLEN);
X  }
X  else {
X    strncpy(me.realname,real_name(userdata),REALLEN);
X    strncpy(me.username,userdata->pw_name,USERLEN);
X  }
X  strcpy(me.server,me.host);
X  me.username[USERLEN] = '\0';
X  me.realname[REALLEN] = '\0';
X  me.fd = sock;
X  if (me.passwd[0])
X    sendto_one(&me, "PASS %s", me.passwd);
X  sendto_one(&me, "NICK %s", me.nickname);
X  sendto_one(&me, "USER %s %s %s %s", me.username, me.host,
X	     me.server, me.realname);
X  initscr();
X  noecho();
X  crmode();
X  clear();
X  refresh();
X/*  signal(SIGTSTP, SIG_IGN); */
X  myloop(sock);
X  echo();
X  nocrmode();
X  clear();
X  refresh();
X  endwin();
X  exit(0);
X}
X
Xmyloop(sock)
Xint sock;
X{
X  char header[HEADERLEN];
X  sprintf(header,HEADER,version);
X  standout();
X  mvaddstr(LINES - 2, 0, header);
X  standend();
X  client_loop(sock);
X}
X
X
Xsendit(sock,line)
Xint sock;
Xchar *line;
X{
X  static char queryuser[NICKLEN+2];
X  static char cmdch = '/';
X  char *ptr, *ptr2;
X  if (line[0] != cmdch) {
X    if (*queryuser) {
X      m_myprivate(NULL, NULL, NULL, queryuser, line);
X      sendto_one(&me, "PRIVMSG %s :%s", queryuser, line);
X    }
X    else {
X      sendto_one(&me, "MSG :%s", line);
X      m_mytext(NULL, NULL, NULL, line);
X    }
X  }
X  else {
X    if (line[1] == ' ') {
X      sendto_one(&me, "MSG :%s", &line[2]);
X      m_mytext(NULL, NULL, NULL, &line[2]);
X    }
X    else if (mycncmp(&line[1],"SIGNOFF", 1))
X      sendto_one(&me, "QUIT");
X    else if (mycncmp(&line[1],"BYE", 1))
X      sendto_one(&me, "QUIT");
X    else if (mycncmp(&line[1],"EXIT", 1))
X      sendto_one(&me, "QUIT");
X    else if (mycncmp(&line[1],"QUIT", 1))
X      sendto_one(&me, "QUIT");
X    else if (ptr=mycncmp(&line[1],"KILL", 2)) {
X      if (unixuser())
X	sendto_one(&me, "KILL %s", ptr);
X      else
X	putline("`tis is no game for mere mortal souls...");
X    }
X    else if (ptr=mycncmp(&line[1],"SUMMON", 2)) {
X/*      if (unixuser()) */
X	sendto_one(&me, "SUMMON %s", ptr);
X/*      else
X	putline("'tis is no game for mere mortal souls..."); */
X    }
X    else if (ptr=mycncmp(&line[1],"STATS", 2)) 
X      sendto_one(&me, "STATS %s", ptr);
X    else if (ptr=mycncmp(&line[1],"USERS", 1)) 
X      sendto_one(&me, "USERS %s", ptr);
X    else if (ptr=mycncmp(&line[1],"TIME", 1))
X      sendto_one(&me, "TIME %s", ptr);
X    else if (ptr=mycncmp(&line[1],"DATE", 1))
X      sendto_one(&me, "TIME %s", ptr);
X    else if (ptr=mycncmp(&line[1],"NAMES", 1)) 
X      sendto_one(&me, "NAMES %s", ptr);
X    else if (ptr=mycncmp(&line[1],"NICK", 2)) 
X      sendto_one(&me, "NICK %s", ptr);
X    else if (ptr=mycncmp(&line[1],"WHOIS", 4)) 
X      sendto_one(&me, "WHOIS %s", ptr);
X    else if (ptr=mycncmp(&line[1],"WHO", 1)) 
X      sendto_one(&me, "WHO %s", ptr);
X    else if (ptr=mycncmp(&line[1],"JOIN", 1))
X      sendto_one(&me, "CHANNEL %s", ptr);
X    else if (ptr=mycncmp(&line[1],"WALL", 2))
X      sendto_one(&me, "WALL %s", ptr);
X    else if (ptr=mycncmp(&line[1],"CHANNEL", 1))
X      sendto_one(&me, "CHANNEL %s", ptr);
X    else if (ptr=mycncmp(&line[1],"AWAY", 1))
X      sendto_one(&me, "AWAY %s", ptr);
X    else if (ptr=mycncmp(&line[1],"MSG", 1)) {
X      if ((ptr2 = index(ptr, ' ')) == (char *) 0)
X	putline("ERROR: No message");
X      else {
X	*ptr2 = '\0';
X	sendto_one(&me, "PRIVMSG %s :%s", ptr, ++ptr2);
X	m_myprivate(NULL, NULL, NULL, ptr, ptr2);
X      }
X    }
X    else if (ptr=mycncmp(&line[1],"TOPIC", 1))
X      sendto_one(&me, "TOPIC :%s", ptr);
X    else if (ptr=mycncmp(&line[1],"CMDCH", 2)) {
X      if (ptr && *ptr) {
X	sprintf(buf, "*** Command character changed from '%c' to '%c'",
X		cmdch, *ptr);
X	cmdch = *ptr;
X	putline(buf);
X      } else {
X	putline("*** Error: Command character not changed");
X      }
X    }
X    else if (ptr=mycncmp(&line[1],"INVITE", 2))
X      sendto_one(&me, "INVITE %s", ptr);
X    else if (ptr=mycncmp(&line[1],"INFO", 2))
X      sendto_one(&me, "INFO");
X    else if (ptr=mycncmp(&line[1],"LIST", 1))
X      sendto_one(&me, "LIST %s",ptr);
X    else if (ptr=mycncmp(&line[1],"KILL", 1))
X      sendto_one(&me, "KILL %s",ptr);
X    else if (ptr=mycncmp(&line[1],"OPER", 1))
X      sendto_one(&me, "OPER %s",ptr);
X    else if (ptr=mycncmp(&line[1],"QUOTE", 1))
X      sendto_one(&me, "%s",ptr);
X    else if (ptr=mycncmp(&line[1],"LINKS", 2)) 
X      sendto_one(&me, "LINKS %s", ptr);
X    else if (ptr=mycncmp(&line[1],"ADMIN", 1)) 
X      sendto_one(&me, "ADMIN %s", ptr);
X    else if (ptr=mycncmp(&line[1],"IGNORE", 1))
X      do_ignore(ptr);
X    else if (ptr=mycncmp(&line[1],"TRACE", 1)) 
X      sendto_one(&me, "TRACE %s", ptr);
X    else if (ptr=mycncmp(&line[1],"HELP", 1))
X      help(ptr);
X    else if (mycncmp(&line[1],"VERSION", 1))
X      sendto_one(&me, "VERSION");
X    else if (mycncmp(&line[1],"CLEAR", 1))
X      doclear();
X    else if (mycncmp(&line[1],"REHASH", 1))
X      sendto_one(&me, "REHASH");
X    else if (ptr=mycncmp(&line[1],"QUERY", 2)) {
X      if (ptr == NULL || *ptr == '\0') {
X	sprintf(buf,"*** Note: Finished chatting with %s",queryuser);
X	putline(buf);
X        queryuser[0] = '\0';
X      }
X      else {
X	strncpy(queryuser,ptr,NICKLEN);
X	queryuser[NICKLEN] = '\0';
X	if (ptr = index(queryuser,' ')) *ptr = '\0';
X	sprintf(buf,"*** Note: Beginning private chat with %s",queryuser);
X	putline(buf);
X      }
X    }
X    else
X      putline("* Illegal Command *");
X  }
X}
X
Xchar *mycncmp(str1, str2, len)
Xchar *str1, *str2;
Xint len;
X{
X  int flag = 0;
X  char *s1;
X  for (s1 = str1; *s1 != ' ' && *s1 && *str2; s1++, str2++) {
X    if (!isascii(*s1)) return 0;
X    if (islower(*s1)) *s1 = toupper(*s1);
X    if (*s1 != *str2) flag = 1;
X  }
X  if (*s1 && *s1 != ' ' && *str2 == '\0')
X    return 0;
X  if (flag) return 0;
X  if (len != 0 && s1 - str1 < len)
X    return 0;
X  if (*s1) return s1 + 1;
X  else return s1;
X}
X
Xstatic int apu = 0;
X
Xdoclear()
X{
X  char header[HEADERLEN];
X  apu = 0;
X  sprintf(header,HEADER,version);
X  clear();
X  standout();
X  mvaddstr(LINES - 2, 0, header);
X  standend();
X  refresh();
X}
X
Xputline(line)
Xchar *line;
X{
X  char *ptr = line, *ptr2 = NULL;
X  char ch='\0';
X  static char blanko[] = "                                        ";
X  while (ptr) {
X    if (strlen(ptr) > COLS) {
X      ch = ptr[COLS];
X      ptr[COLS] = '\0';
X      ptr2 = &ptr[COLS-1];
X    } 
X    else
X      ptr2 = NULL;
X    move(apu++,0);
X    if (apu > LINES - 4) apu = 0;
X    addstr(ptr);
X    if (apu == 0) 
X      mvaddstr(0,0,"\n\n");
X    else if (apu == LINES - 4) {
X      mvaddstr(LINES - 4, 0, "\n");
X      mvaddstr(0,0,"\n");
X    }
X    else {
X      addstr(blanko); addstr(blanko);
X      addstr("\n");
X      addstr(blanko); addstr(blanko);
X    }
X    ptr = ptr2;
X    if (ptr2) {
X      *ptr2++ = '+';
X      *ptr2 = ch;
X    }
X  }
X  refresh();
X}
X
Xint
Xunixuser()
X{
X  return(strcmp(me.host,"OuluBox"));
X}
X
Xstruct Client *
Xmake_client()
X{
X  return(NULL);
X}
SHAR_EOF
chmod 0600 irc.c || echo "restore of irc.c fails"
set `wc -c irc.c`;Sum=$1
if test "$Sum" != "9158"
then echo original size 9158, current size $Sum;fi
echo "x - extracting ircd.8 (Text)"
sed 's/^X//' << 'SHAR_EOF' > ircd.8 &&
X.\" @(#)ircd.8 2.0 (beta version) 29 Mar 1989 
X.TH IRCD 8 "29 March 1989"
X.SH NAME
Xircd \- The Internet Relay Chat Program Server 
X.SH SYNOPSIS
X\fBircd\fP [-hhostname] [-pportnum] 
X.SH DESCRIPTION
X.LP
X\fIircd\fP is the server (daemon) program for the Internet Relay Chat
XProgram.  The \fIircd\fP is a server in that its function is to "serve"
Xthe client program \fIirc(1)\fP with messages and commands.  All commands
Xand user messages are passed directly to the \fIircd\fP for processing
Xand relaying to other UNIX sites.  The \fIirc(1)\fP program depends upon
Xthere being an \fIircd\fP server running somewhere (either on your local
XUNIX site or a remote UNIX site) so that it will have somewhere to connect
Xto and thus allow the user to begin talking to other users. 
X.LP
XIf you plan to connect your \fIircd\fP server to an existing Irc-Network,
Xyou will need to alter your local IRC CONFIGURATION FILE (typically named
X"irc.conf") so that it will accept and make connections to other \fIircd\fP
Xservers.  This file contains the hostnames, Network Addresses, and sometimes
Xpasswords for connections to other UNIXES around the world.  Because 
Xdescription of the actual file format of the "irc.conf" file is beyond the
Xscope of this document, please refer to the file README in the IRC source
Xfiles directory.
X.LP
XBOOTING THE SERVER:  The \fIircd\fP server can be started as part of the
XUNIX boot procedure or just by placing the server into Unix Background.
XKeep in mind that if it is *not* part of your UNIXES Boot-up procedure 
Xthen you will have to manually start the \fIircd\fP server each time your
XUNIX is rebooted.  This means if your UNIX is prone to crashing
Xor going for for repairs a lot it would make sense to start the \fIircd\fP
Xserver as part of your UNIX bootup procedure.  In some cases the \fIirc(1)\fP
Xwill automatically attempt to boot the \fIircd\fP server if the user is
Xon the SAME UNIX that the \fIircd\fP is supposed to be running on.  If the
X\fIirc(1)\fP cannot connect to the \fIircd\fP server it will try to start
Xthe server on it's own and will then try to reconnect to the newly booted
X\fIircd\fP server.
X.SH EXAMPLE
X.RS
X.nf
Xtolsun% \fBircd\fP
X.fi
X.RE
X.LP
XPlaces \fIircd\fP into UNIX Background and starts up the server for use.
XNote:  You do not have to add the "&" to this command, the program will
Xautomatically place itself into UNIX Background after it has been executed.
X.SH COPYRIGHT
XCopyright (c) 1988 University of Oulu, Computing Center, Finland.
XAll rights reserved.
XFor full COPYRIGHT see COPYRIGHT file with IRC package.
X.SH FILES
X /etc/utmp
X "irc.conf"
X.SH "SEE ALSO"
Xirc(1)
X.SH BUGS
XNone... ;-) if somebody finds one, please inform author
X.SH AUTHOR
XJarkko Oikarinen, currently jto@tolsun.oulu.fi,
Xmanual page written by Jeff Trim, jtrim@orion.cair.du.edu.
SHAR_EOF
chmod 0600 ircd.8 || echo "restore of ircd.8 fails"
set `wc -c ircd.8`;Sum=$1
if test "$Sum" != "2804"
then echo original size 2804, current size $Sum;fi
echo "x - extracting ircd.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > ircd.c &&
X/*************************************************************************
X ** ircd.c  Beta  v2.0    (22 Aug 1988)
X **
X ** This file is part of Internet Relay Chat v2.0
X **
X ** Author:           Jarkko Oikarinen 
X **         Internet: jto@tolsun.oulu.fi
X **             UUCP: ...!mcvax!tut!oulu!jto
X **           BITNET: toljto at finou
X **
X ** Copyright (c) 1988 University of Oulu, Computing Center
X **
X ** All rights reserved.
X **
X ** See file COPYRIGHT in this package for full copyright.
X ** 
X *************************************************************************/
X
Xchar ircd_id[] = "ircd.c v2.0 (c) 1988 University of Oulu, Computing Center";
X
X#include <sys/types.h>
X#include <sys/file.h>
X#include <stdio.h>
X#include <signal.h>
X#define MAIN
X#include "struct.h"
X#undef MAIN
X#define TRUE 1
X
Xextern int dummy();
Xextern struct Client *make_client();
Xstruct Client me;                /* That's me */
Xstruct Client *client = &me;    /* Pointer to beginning of Client list */
Xextern struct Confitem *conf;
Xextern struct Confitem *find_me();
Xchar *uphost;
Xchar **myargv;
Xint portnum;
Xint debuglevel;
Xint maxusersperchannel = MAXUSERSPERCHANNEL;
X
Xrestart()
X{
X  int i;
X  debug(DEBUG_NOTICE,"Restarting server...");
X#ifdef NOTTY
X  for (i=0; i<MAXFD; i++) 
X#else
X  for (i=3; i<MAXFD; i++)
X#endif
X    close(i);
X  execv(MYNAME, myargv);
X  debug(DEBUG_FATAL,"Couldn't restart server !!!!!!!!");
X  exit(-1);
X}
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X  struct Client *cptr;
X  struct Confitem *aconf;
X  int length;                      /* Length of message received from client */
X  char buffer[BUFSIZE];
X  int counter;
X  long lasttime, lastconnecttry;
X  myargv = argv;
X  signal(SIGPIPE, SIG_IGN);
X  signal(SIGHUP, restart);
X  signal(SIGALRM, dummy);
X  setuid(geteuid());
X  if (getuid() == 0) {
X    setgid(-2);
X    setuid(-2);
X  } 
X  getmyname(myhostname,HOSTLEN-1);
X  portnum = PORTNUM;
X  debuglevel = -1;
X  while (argc > 1 && argv[1][0] == '-') {
X    switch (argv[1][1]) {
X      case 'h':
X        strncpy(myhostname, &argv[1][2], HOSTLEN-1);
X        myhostname[HOSTLEN] = '\0';
X        break;
X      case 'p':
X        if ((length = atoi(&argv[1][2])) > 0 )
X          portnum = length;
X        break;
X      case 'x':
X        debuglevel = atoi(&argv[1][2]);
X        break;
X/*      case 'c':
X	maxusersperchannel = atoi(&argv[1][2]);
X	break; */
X      default:
X	printf("Illegal option\n");
X	break;
X    }
X    argv++; argc--;
X  }
X  if (argc > 1 && argv[1][0] > '9')
X    uphost = argv[1];
X  else
X    uphost = NULL;
X  init_sys();
X  openlog();
X  initconf();
X  if (aconf = find_me())
X    strcpy(me.server, aconf->name);
X  else
X    me.server[0] = '\0';
X  me.next = NULL;
X  strcpy(me.host,myhostname);
X  me.fromhost[0] = me.nickname[0] = me.realname[0] = '\0';
X  me.fd = open_port(portnum);
X  me.status = STAT_ME;
X  lastconnecttry = getlongtime();
X  aconf = conf;
X  while (aconf) {
X    if (aconf->status == CONF_CONNECT_SERVER && aconf->port > 0) {
X      if (connect_server(aconf) == 0)
X	break;
X    }
X    aconf = aconf->next;
X  }
X  debug(DEBUG_DEBUG,"Server ready...");
X  
X  for (;;) {
X    if ((length = read_msg(buffer, BUFSIZE, &cptr)) > 0) {
X      cptr->lasttime = getlongtime();
X      cptr->flags &= ~FLAGS_PINGSENT;
X      dopacket(cptr, buffer, length);
X    } 
X
X    debug(DEBUG_DEBUG,"Got message");
X
X    lasttime = getlongtime();
X    if (lasttime - lastconnecttry > CONNECTFREQUENCY) {
X      lastconnecttry = lasttime;
X      aconf = conf;
X      while (aconf) {
X	if (aconf->status == CONF_CONNECT_SERVER) {
X	  cptr = client;
X	  while (cptr) {
X	    if ((cptr->status == STAT_SERVER || cptr->status == STAT_ME) &&
X		strcmp(cptr->host, aconf->name) == 0)
X	      break;
X	    cptr = cptr->next;
X	  }
X	  if (cptr == NULL && aconf->port > 0) 
X	    if (connect_server(aconf) == 0)
X	      break;
X	}
X	aconf = aconf->next;
X      }
X      lasttime = getlongtime();
X    }
X
X    cptr = client;
X    while (cptr) {
X      if (cptr->status != STAT_ME && cptr->fd >= 0 &&
X	  (lasttime - cptr->lasttime) > PINGFREQUENCY) {
X	if ((lasttime - cptr->lasttime) > 2 * PINGFREQUENCY) {
X	  m_bye(cptr, cptr);
X	  cptr = client;
X	}
X	else if ((cptr->flags & FLAGS_PINGSENT) == 0) {
X	  cptr->flags |= FLAGS_PINGSENT;
X	  sendto_one(cptr, "PING %s", myhostname);
X	}
X      }
X      cptr = cptr->next;
X    }
X  }
X}
SHAR_EOF
chmod 0600 ircd.c || echo "restore of ircd.c fails"
set `wc -c ircd.c`;Sum=$1
if test "$Sum" != "4264"
then echo original size 4264, current size $Sum;fi
echo "x - extracting list.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > list.c &&
X/*************************************************************************
X ** list.c  Beta  v2.0    (22 Aug 1988)
X **
X ** This file is part of Internet Relay Chat v2.0
X **
X ** Author:           Jarkko Oikarinen 
X **         Internet: jto@tolsun.oulu.fi
X **             UUCP: ...!mcvax!tut!oulu!jto
X **           BITNET: toljto at finou
X **
X ** Copyright (c) 1988 University of Oulu, Computing Center
X **
X ** All rights reserved.
X **
X ** See file COPYRIGHT in this package for full copyright.
X ** 
X *************************************************************************/
X
Xchar list_id[] = "list.c v2.0 (c) 1988 University of Oulu, Computing Center";
X
X#include "struct.h"
X#define NULL ((char *) 0)
X
Xextern struct Client *client;
Xextern struct Confitem *conf;
Xextern int maxusersperchannel;
X
Xstruct Client *
Xmake_client()
X{
X  struct Client *cptr;
X  if ((cptr = (struct Client *) malloc(sizeof (struct Client))) == 
X      (struct Client *) 0)
X    {
X      perror("malloc");
X      debug(DEBUG_FATAL, "Out of memory: restarting server...");
X      restart();
X    }
X  else {
X    cptr->next = client;
X    cptr->away = NULL;
X    cptr->host[0] = cptr->nickname[0] = cptr->username[0] = '\0';
X    cptr->realname[0] = cptr->server[0] = cptr->buffer[0] = '\0';
X    cptr->passwd[0] = cptr->sockhost[0] = '\0';
X    cptr->status = STAT_UNKNOWN; cptr->channel = 0; cptr->fd = -1;
X    cptr->lasttime = getlongtime(); cptr->flags = 0;
X  }
X  return (cptr);
X}
X
Xint
Xis_full(channel, users)
Xint channel, users;
X{
X  if (channel > 0 && channel < 10)
X    return(0);
X  if (users >= maxusersperchannel)
X    return(1);
X  return(0);
X}
X
SHAR_EOF
chmod 0600 list.c || echo "restore of list.c fails"
set `wc -c list.c`;Sum=$1
if test "$Sum" != "1608"
then echo original size 1608, current size $Sum;fi
echo "x - extracting main.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > main.c &&
Xmain()
X{
X  printf("date = %s\n",date());
X}
SHAR_EOF
chmod 0600 main.c || echo "restore of main.c fails"
set `wc -c main.c`;Sum=$1
if test "$Sum" != "43"
then echo original size 43, current size $Sum;fi
echo "x - extracting msg.h (Text)"
sed 's/^X//' << 'SHAR_EOF' > msg.h &&
X/*************************************************************************
X ** msg.h  Beta  v2.0    (22 Aug 1988)
X **
X ** This file is part of Internet Relay Chat v2.0
X **
X ** Author:           Jarkko Oikarinen 
X **         Internet: jto@tolsun.oulu.fi
X **             UUCP: ...!mcvax!tut!oulu!jto
X **           BITNET: toljto at finou
X **
X ** Copyright (c) 1988 University of Oulu, Computing Center
X **
X ** All rights reserved.
X **
X ** See file COPYRIGHT in this package for full copyright.
X ** 
X *************************************************************************/
X
X#define MSG_TEXT     "MSG"
X#define MSG_PRIVATE  "PRIVMSG"
X#define MSG_WHO      "WHO"
X#define MSG_WHOIS    "WHOIS"
X#define MSG_USER     "USER"
X#define MSG_NICK     "NICK"
X#define MSG_SERVER   "SERVER"
X#define MSG_LIST     "LIST"
X#define MSG_TOPIC    "TOPIC"
X#define MSG_INVITE   "INVITE"
X#define MSG_CHANNEL  "CHANNEL"
X#define MSG_VERSION  "VERSION"
X#define MSG_QUIT     "QUIT"
X#define MSG_SQUIT    "SQUIT"
X#define MSG_KILL     "KILL"
X#define MSG_INFO     "INFO"
X#define MSG_LINKS    "LINKS"
X#define MSG_SUMMON   "SUMMON"
X#define MSG_STATS    "STATS"
X#define MSG_USERS    "USERS"
X#define MSG_RESTART  "RESTART"
X#define MSG_HELP     "HELP"
X#define MSG_WHOREPLY "WHOREPLY"
X#define MSG_ERROR    "ERROR"
X#define MSG_AWAY     "AWAY"
X#define MSG_DIE      "DIE"
X#define MSG_CONNECT  "CONNECT"
X#define MSG_PING     "PING"
X#define MSG_PONG     "PONG"
X#define MSG_OPER     "OPER"
X#define MSG_PASS     "PASS"
X#define MSG_WALL     "WALL"
X#define MSG_TIME     "TIME"
X#define MSG_REHASH   "REHASH"
X#define MSG_NAMES    "NAMES"
X#define MSG_NAMREPLY "NAMREPLY"
X#define MSG_ADMIN    "ADMIN"
X#define MSG_TRACE    "TRACE"
X#define MSG_LINREPLY "LINREPLY"
X
X#define MAXPARA    10 
X
Xextern int m_text(), m_private(), m_who(), m_whois(), m_user(), m_list();
Xextern int m_topic(), m_invite(), m_channel(), m_version(), m_quit();
Xextern int m_server(), m_kill(), m_info(), m_links(), m_summon(), m_stats();
Xextern int m_users(), m_nick(), m_error(), m_help(), m_whoreply();
Xextern int m_squit(), m_restart(), m_away(), m_die(), m_connect();
Xextern int m_ping(), m_pong(), m_oper(), m_pass(), m_wall(), m_trace();
Xextern int m_time(), m_rehash(), m_names(), m_namreply(), m_admin();
Xextern int m_linreply();
X
Xstruct Message {
X  char *cmd;
X  int (* func)();
X  int count;
X  int parameters;
X};
X
X#ifdef MSGTAB
Xstruct Message msgtab[] = {
X  { MSG_NICK,    m_nick,     0, 1 },
X  { MSG_TEXT,    m_text,     0, 1 },
X  { MSG_PRIVATE, m_private,  0, 2 },
X  { MSG_WHO,     m_who,      0, 1 },
X  { MSG_WHOIS,   m_whois,    0, 1 },
X  { MSG_USER,    m_user,     0, 4 },
X  { MSG_SERVER,  m_server,   0, 2 },
X  { MSG_LIST,    m_list,     0, 1 },
X  { MSG_TOPIC,   m_topic,    0, 1 },
X  { MSG_INVITE,  m_invite,   0, 2 },
X  { MSG_CHANNEL, m_channel,  0, 1 },
X  { MSG_VERSION, m_version,  0, 1 },
X  { MSG_QUIT,    m_quit,     0, 1 },
X  { MSG_SQUIT,   m_squit,    0, 1 },
X  { MSG_KILL,    m_kill,     0, 2 },
X  { MSG_INFO,    m_info,     0, 1 },
X  { MSG_LINKS,   m_links,    0, 1 },
X  { MSG_SUMMON,  m_summon,   0, 1 },
X  { MSG_STATS,   m_stats,    0, 1 },
X  { MSG_USERS,   m_users,    0, 1 },
X  { MSG_RESTART, m_restart,  0, 1 },
X  { MSG_WHOREPLY,m_whoreply, 0, 7 },
X  { MSG_HELP,    m_help,     0, 2 },
X  { MSG_ERROR,   m_error,    0, 1 },
X  { MSG_AWAY,    m_away,     0, 1 },
X  { MSG_DIE,     m_die,      0, 1 },
X  { MSG_CONNECT, m_connect,  0, 3 },
X  { MSG_PING,    m_ping,     0, 2 },
X  { MSG_PONG,    m_pong,     0, 3 },
X  { MSG_OPER,    m_oper,     0, 3 },
X  { MSG_PASS,    m_pass,     0, 2 },
X  { MSG_WALL,    m_wall,     0, 1 },
X  { MSG_TIME,    m_time,     0, 1 },
X  { MSG_REHASH,  m_rehash,   0, 1 },
X  { MSG_NAMES,   m_names,    0, 1 },
X  { MSG_NAMREPLY,m_namreply, 0, 3 },
X  { MSG_ADMIN,   m_admin,    0, 1 },
X  { MSG_TRACE,   m_trace,    0, 1 },
X  { MSG_LINREPLY,m_linreply, 0, 2 },
X  { (char *) 0, (int (*)()) 0 }  
X};
X#else
Xextern struct Message msgtab[];
X#endif
SHAR_EOF
chmod 0600 msg.h || echo "restore of msg.h fails"
set `wc -c msg.h`;Sum=$1
if test "$Sum" != "3905"
then echo original size 3905, current size $Sum;fi
echo "x - extracting packet.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > packet.c &&
X/*************************************************************************
X ** packet.c  Beta  v2.0    (22 Aug 1988)
X **
X ** This file is part of Internet Relay Chat v2.0
X **
X ** Author:           Jarkko Oikarinen
X **         Internet: jto@tolsun.oulu.fi
X **             UUCP: ...!mcvax!tut!oulu!jto
X **           BITNET: toljto at finou
X **
X ** Copyright (c) 1988 University of Oulu, Computing Center
X **
X ** All rights reserved.
X **
X ** See file COPYRIGHT in this package for full copyright.
X **
X *************************************************************************/
X 
Xchar packet_id[]="packet.c v2.0 (c) 1988 University of Oulu, Computing Center";
X
X#include "struct.h"
X#include "msg.h"
X
Xdopacket(cptr, buffer, length)
Xstruct Client *cptr;
Xchar *buffer;
Xint length;
X{
X  char *ch1, *ch2, *ch3;
X  strncat(cptr->buffer, buffer, length);
X  ch1 = ch2 = cptr->buffer;
X  while (*ch2) {
X    if (*ch2 == '\r' || *ch2 == '\n') {
X      if (ch2 != ch1) {
X	ch1[ch2-ch1] = '\0';
X	if (parse(cptr, ch1, ch2 - ch1, msgtab) == FLUSH_BUFFER) 
X	  return(0);
X      }
X      if (*(ch2+1) == '\r' || *(ch2+1) == '\n')
X	ch2++;
X      ch1 = ch2+1;
X    }
X    ch2++;
X  }
X  for (ch3 = cptr->buffer; *ch1; ch1++, ch3++)
X    *ch3 = *ch1;
X  *ch3 = '\0';
X}
SHAR_EOF
chmod 0600 packet.c || echo "restore of packet.c fails"
set `wc -c packet.c`;Sum=$1
if test "$Sum" != "1230"
then echo original size 1230, current size $Sum;fi
echo "x - extracting parse.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > parse.c &&
X/*************************************************************************
X ** parse.c  Beta  v2.0    (22 Aug 1988)
X **
X ** This file is part of Internet Relay Chat v2.0
X **
X ** Author:           Jarkko Oikarinen
X **         Internet: jto@tolsun.oulu.fi
X **             UUCP: ...!mcvax!tut!oulu!jto
X **           BITNET: toljto at finou
X **
X ** Copyright (c) 1988 University of Oulu, Computing Center
X **
X ** All rights reserved.
X **
X ** See file COPYRIGHT in this package for full copyright.
X **
X *************************************************************************/
X 
Xchar parse_id[] = "parse.c v2.0 (c) 1988 University of Oulu, Computing Center";
X
X#include <ctype.h>
X#define MSGTAB
X#include "msg.h"
X#undef MSGTAB
X#include "struct.h"
X#include "sys.h"
X
X#define NULL ((char *) 0)
X
Xint msgcount[40];
Xextern struct Client *client;
Xchar sender[20];
X
Xint
Xmyncmp(str1, str2, n)
Xchar *str1, *str2;
Xint n;
X{
X  while ((islower(*str1) ? toupper(*str1) : *str1) ==
X	 (islower(*str2) ? toupper(*str2) : *str2)) {
X    str1++; str2++; n--;
X    if (n == 0 || (*str1 == '\0' && *str2 == '\0'))
X      return(0);
X  }
X  return(1);
X}
X
Xstruct Client *
Xfind_client(ch, cptr)
Xchar *ch;
Xstruct Client *cptr;
X{
X  struct Client *c2ptr=client;
X  int len;
X  char *ch2 = index(ch,' ');
X  if (ch2)
X    len = ch2 - ch;
X  else
X    len = strlen(ch);
X  while (c2ptr) {
X    if (strlen(c2ptr->nickname) == len &&
X	myncmp(ch, c2ptr->nickname, len) == 0)
X      break;
X    c2ptr = c2ptr->next;
X  }
X  return ((c2ptr) ? c2ptr : cptr);
X}
X
Xstruct Client *
Xfind_server(ch, cptr)
Xchar *ch;
Xstruct Client *cptr;
X{
X  struct Client *c2ptr=client;
X  int len;
X  char *ch2;
X  if (ch == NULL)
X    return(cptr);
X  ch2 = index(ch,' ');
X  if (ch2)
X    len = ch2 - ch;
X  else
X    len = strlen(ch);
X  while (c2ptr) {
X    if ((c2ptr->status == STAT_SERVER || c2ptr->status == STAT_ME) &&
X        strlen(c2ptr->host) == len && myncmp(ch, c2ptr->host, len) == 0)
X      break;
X    c2ptr = c2ptr->next;
X  }
X  return ((c2ptr) ? c2ptr : cptr);
X}
X
Xparse(cptr, buffer, length, mptr)
Xstruct Client *cptr;
Xchar *buffer;
Xint length;
Xstruct Message *mptr;
X{
X  struct Client *from = cptr;
X  char *ch, *ch2, *para[MAXPARA+1];
X  int len,i=0;
X  int (*func)();
X  *sender = '\0';
X  for (i=0; i<length; i++)
X    if (buffer[i] && buffer[i] != '\007' &&
X	(buffer[i] < 32 || buffer[i] > 126))
X      buffer[i] = ' '; 
X  for (ch = buffer; *ch == ' '; ch++);
X  if (*ch >= '0' && *ch <= '9') {
X    return(0);     /* Add numeric command parsing here... */
X  }
X  if (*ch == ':') {
X    ch++;
X    if (cptr->status != STAT_OPER && cptr->status != STAT_SERVER)
X      from = cptr;
X    else
X      from = find_client(ch, cptr);
X    strncpy(sender, ch, 15);
X    for (ch2 = sender; (ch2 < &sender[15]) && *ch2 > 32 && *ch2 < 126; ch2++);
X    *ch2 = '\0';
X    ch = index(ch, ' ');
X  }
X  if (ch == NULL) {
X    debug(DEBUG_NOTICE, "Empty message from %s:%s (host %s)",
X	  cptr->nickname,from->nickname, cptr->host);
X    return(-1);
X  }
X  while (*ch == ' ') ch++;
X  ch2 = index(ch, ' ');
X  len = (ch2) ? (ch2 - ch) : strlen(ch);
X  while (mptr->cmd) {
X    if (myncmp(mptr->cmd, ch, len) == 0 && strlen(mptr->cmd) == len)
X      break;
X    mptr++;
X  }
X  if (mptr->cmd == NULL) {
X    if (buffer[0] != '0')
X      sendto_one(from, "ERROR Illegal command %s", ch);
X    return(-1);
X  }
X  i = 0;
X  while (ch2 && *ch2 && i < MAXPARA-1 && i < mptr->parameters) {
X    for (; *ch2 == ' '; ch2++);
X    *(ch2-1) = '\0';
X    if (*ch2 == '\0')
X      para[i++] = NULL;
X    else {
X      para[i] = ch2;
X      if (*ch2 == ':') {
X	para[i] = ch2 + 1;
X	ch2 = NULL;
X      }
X      else 
X	for (; *ch2 != ' ' && *ch2; ch2++);
X      i++;
X    }
X  }
X  mptr->count++;
X  for (; i <= MAXPARA; i++) para[i] = NULL;
X  func = mptr->func;
X  return (*func)(cptr, from, sender,
X		       para[0], para[1], para[2], para[3], para[4], para[5],
X		       para[6], para[7], para[8]);
X}
SHAR_EOF
chmod 0600 parse.c || echo "restore of parse.c fails"
set `wc -c parse.c`;Sum=$1
if test "$Sum" != "3847"
then echo original size 3847, current size $Sum;fi
echo "x - extracting r_bsd.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > r_bsd.c &&
X/*************************************************************************
X ** r_bsd.c  Beta  v2.0    (22 Aug 1988)
X **
X ** This file is part of Internet Relay Chat v2.0
X **
X ** Author:           Jarkko Oikarinen 
X **         Internet: jto@tolsun.oulu.fi
X **             UUCP: ...!mcvax!tut!oulu!jto
X **           BITNET: toljto at finou
X **
X ** Copyright (c) 1988 University of Oulu, Computing Center
X **
X ** All rights reserved.
X **
X ** See file COPYRIGHT in this package for full copyright.
X ** 
X *************************************************************************/
X
Xchar r_bsd_id[] = "r_bsd.c v2.0 (c) 1988 University of Oulu, Computing Center";
X
X#include <sys/time.h>
X#include <sys/types.h>
X#include <sys/socket.h>
X#include <sys/file.h>
X#include <sys/ioctl.h>
X#include <netinet/in.h>
X#include <netdb.h>
X#include <stdio.h>
X#include <signal.h>
X#include <fcntl.h>
X#include "struct.h"
X#if BSD42 || ULTRIX
X#include "sock.h"
X#endif
X#include "sys.h"
X
Xextern struct Client me;
Xint
Xclient_init(host, portnum)
Xchar *host;
Xint portnum;
X{
X  int sock, tryagain = 1;
X  static struct hostent *hp;
X  static struct sockaddr_in server;
X
X  gethostname(me.host,HOSTLEN);
X
X  /* FIX:  jtrim@duorion.cair.du.edu -- 3/4/89 
X     and jto@tolsun.oulu.fi -- 3/7/89 */
X
X    sock = socket(AF_INET, SOCK_STREAM, 0);
X    if (sock < 0) {
X      perror("opening stream socket");
X      exit(1);
X    }
X    server.sin_family = AF_INET;
X    
X    /* MY FIX -- jtrim@duorion.cair.du.edu   (2/10/89) */
X    if ( isdigit(*host))
X      {
X	server.sin_addr.s_addr = inet_addr(host);
X      }
X    else
X      { 
X	hp = gethostbyname(host);
X	if (hp == 0) {
X	  fprintf(stderr, "%s: unknown host", host);
X	  exit(2);
X	}
X	bcopy(hp->h_addr, &server.sin_addr, hp->h_length);
X      }
X    server.sin_port = htons(portnum);
X    /* End Fix */
X    
X    if (connect(sock, (struct sockaddr *) &server, sizeof(server)) < 0) {
X      perror("irc");
X      exit(1);
X    }
X  return(sock);
X}
X/* End Fix */
X
Xclient_loop(sock)
Xint sock;
X{
X  int i = 0, size;
X  char apubuf[101], ch;
X  fd_set ready;
X  do {
X    ready.fds_bits[0] = (1 << sock);
X    if (select(sock+1, &ready, 0, 0, NULL) < 0) {
X/*      perror("select"); */
X      continue;
X    }
X    if (ready.fds_bits[0] & (1 << sock)) {
X      if ((size = read(sock, apubuf, 100)) < 0)
X	perror("receiving stream packet");
X      if (size == 0) return(-1);
X      dopacket(&me, apubuf, size);
X    }
X/*    if (ready.fds_bits[0] & 1) {
X      if ((ch = getchar()) == -1) {
X	move(0,0);
X	addstr("\rFATAL ERROR: End of stdin file !\n\r");
X	refresh();
X	return;
X      }
X      i=do_char(ch);
X    } */
X  } while (1);
X}
SHAR_EOF
chmod 0600 r_bsd.c || echo "restore of r_bsd.c fails"
set `wc -c r_bsd.c`;Sum=$1
if test "$Sum" != "2594"
then echo original size 2594, current size $Sum;fi
echo "x - extracting r_msg.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > r_msg.c &&
X/*************************************************************************
X ** r_msg.c    Beta v2.0    (22 Aug 1988)
X **
X ** This file is part of Internet Relay Chat v2.0
X **
X ** Author:           Jarkko Oikarinen
X **         Internet: jto@tolsun.oulu.fi
X **             UUCP: ...!mcvax!tut!oulu!jto
X **           BITNET: toljto at finou
X **
X ** Copyright (c) 1988 University of Oulu, Computing Center
X **
X ** All rights reserved.
X **
X ** See file COPYRIGHT in this package for full copyright.
X **
X *************************************************************************/
X 
Xchar r_msg_id[] = "r_msg.c v2.0 (c) 1988 University of Oulu, Computing Center";
X
X#include "struct.h"
X#include "msg.h"
X
Xchar mybuf[513];
Xchar abuf1[20], abuf2[20], abuf3[20], abuf4[20];
X
Xextern char *center(), *mycncmp();
Xextern struct Client *client;
X
Xm_restart() {
X  putline("*** Oh boy... somebody wants *me* to restart... exiting...\n");
X  sleep(5);
X  exit(0);
X}
X
Xm_time() {
X  putline("*** Received time message..!");
X}
X
Xm_rehash() {
X  putline("*** Received rehash message..!");
X}
X
Xm_die() {
X  exit(-1);
X}
X
Xm_pass() {
X  putline("*** Received Pass message !");
X}
X
Xm_oper() {
X  putline("*** Received Oper message !");
X}
X
Xm_names() {
X  putline("*** Received Names message !");
X}
X
Xm_wall(sptr, cptr, sender, message) 
Xstruct Client *sptr, *cptr;
Xchar *sender, *message;
X{
X  sprintf(abuf1, "*** #%s# %s", sender, message);
X  putline(abuf1);
X}
X
Xm_connect() {
X  putline("*** Received Connect message !");
X}
X
Xm_ping(sptr, cptr, sender, para1, para2) 
Xstruct Client *sptr, *cptr;
Xchar *sender, *para1, *para2;
X{
X  if (para2 && *para2)
X    sendto_one(client, "PONG %s@%s %s", client->username, client->host, para2);
X  else
X    sendto_one(client, "PONG %s@%s", client->username, client->host);
X}
X
Xm_pong(sptr, cptr, sender, para1, para2)
Xstruct Client *sptr, *cptr;
Xchar *sender, *para1, *para2;
X{
X  putline("*** Received PONG message: %s %s", para1, (para2) ? para2 : "");
X}
X
Xm_nick(sptr, cptr, sender, nickname)
Xstruct Client *sptr, *cptr;
Xchar *sender, *nickname;
X{
X  sprintf(mybuf,"*** Change: %s is now known as %s", sender, nickname);
X  putline(mybuf);
X}
X
Xm_away(sptr, cptr, sender, text)
Xstruct Client *sptr, *cptr;
Xchar *sender, *text;
X{
X  sprintf(mybuf,"*** %s is away: \"%s\"",sender,text);
X  putline(mybuf);
X}
X
Xm_who() { 
X  putline("*** Oh boy... server asking who from client... exiting...");
X}
X
Xm_whois() {
X  putline("*** Oh boy... server asking whois from client... exiting...");
X}
X
Xm_user() {
X  putline("*** Oh boy... server telling me user messages... exiting...");
X}
X
Xm_server(sptr, cptr, sender, serv) 
Xstruct Client *cptr, *sptr;
Xchar *sender, *serv;
X{
X  sprintf(mybuf,"*** New server: %s", serv);
X  putline(mybuf);
X}
X
Xm_list() {
X  putline("*** Oh boy... server asking me channel lists... exiting...");
X}
X
Xm_topic(sptr, cptr, sender, topic)
Xstruct Client *sptr, *cptr;
Xchar *sender, *topic;
X{
X  putline("*** Oh boy... server telling me the topic... exiting...");
X}
X
Xm_channel(sptr, cptr, sender, ch)
Xstruct Client *cptr, *sptr;
Xchar *sender, *ch;
X{
X  if (ch == (char *) 0 || *ch == '\0' || atoi(ch) == 0)
X    sprintf(mybuf,"*** Change: %s has left this Channel", sender);
X  else
X    sprintf(mybuf,"*** Change: %s has joined this Channel (%d)", 
X	    sender, atoi(ch));
X  putline(mybuf);
X}
X
Xm_version(sptr, cptr, sender, version)
Xstruct Client *cptr, *sptr;
Xchar *sender, *version;
X{
X  sprintf(mybuf,"*** Version: %s", version);
X  putline(mybuf);
X}
X
Xm_bye()
X{
X  exit(-1);    
X}
X
Xm_quit(sptr, cptr, sender)
Xstruct Client *sptr, *cptr;
Xchar *sender;
X{
X  sprintf(mybuf,"*** Signoff: %s", sender);
X  putline(mybuf);
X}
X
Xm_kill() {
X  putline("*** Received KILL message");
X}
X
Xm_info(sptr, cptr, sender, info)
Xstruct Client *cptr, *sptr;
Xchar *sender, *info;
X{
X  sprintf(mybuf,"*** Info: %s", info);
X  putline(mybuf);
X}
X
Xm_links() { 
X  putline("*** Received LINKS message");
X}
X
Xm_summon() {
X  putline("*** Received SUMMON message");
X}
X
Xm_stats() {
X  putline("*** Received STATS message");
X}
X
Xm_users() {
X  putline("*** Received USERS message");
X}
X
Xm_help() {
X  putline("*** Received HELP message");
X}
X
Xm_squit(sptr, cptr, sender, server)
Xstruct Client *cptr, *sptr;
Xchar *sender, *server;
X{
X  sprintf(mybuf,"*** Server %s has died. Snif.", server);
X  putline(mybuf);
X}
X
Xm_whoreply(sptr, cptr, sender, channel, username, host, server,
X	   nickname, away, realname)
Xstruct Client *sptr, *cptr;
Xchar *sender, *channel, *username, *host, *server, *nickname, *away;
Xchar *realname;
X{
X  int i = atoi(channel);
X  if (username)
X    center(abuf1, username, 8);
X  else
X    abuf1[0] = '\0';
X  if (host)
X    center(abuf2, host, 8);
X  else
X    abuf2[0] = '\0';
X  if (server)
X    center(abuf3, server, 8);
X  else
X    abuf3[0] = '\0';
X  if (nickname)
X    center(abuf4, nickname, 8);
X  else
X    abuf4[0] = '\0';
X  if (i != 0)
X    sprintf(mybuf,"Channel %3d: %8s@%8s %8s (%8s) %s %s",i ,abuf1, abuf2,
X	    abuf3, abuf4, away, realname);
X  else
X    sprintf(mybuf,"* Private *: %8s@%8s %8s (%8s) %s %s", abuf1, abuf2,
X	    abuf3, abuf4, away, realname);
X  putline(mybuf);
X}
X
Xm_mytext(sptr, cptr, sender, buf)
Xstruct Client *sptr, *cptr;
Xchar *sender, *buf;
X{
X  if (sender)
X    sprintf(mybuf,"<%s> %s", sender, buf);
X  else
X    sprintf(mybuf,"> %s",buf);
X  putline(mybuf);
X}
X
Xm_text(sptr, cptr, sender, buf)
Xstruct Client *sptr, *cptr;
Xchar *buf, *sender;
X{
X  if (sender && sender[0]) {
X    sprintf(mybuf,"<%s> %s", sender, buf);
X    putline(mybuf);
X  } else
X    putline(buf);
X}
X
Xm_myprivate(sptr, cptr, sender, buf, buf2)
Xstruct Client *sptr, *cptr;
Xchar *buf, *buf2, *sender;
X{
X  sprintf(mybuf,"-> *%s* %s",buf,buf2);
SHAR_EOF
echo "End of part 4"
echo "File r_msg.c is continued in part 5"
echo "5" > s2_seq_.tmp
exit 0

bleckmd@jacobs.cs.orst.edu (david bleckmann) (06/20/89)

---- Cut Here and unpack ----
#!/bin/sh
# this is part 5 of a multipart archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file r_msg.c continued
#
CurArch=5
if test ! -r s2_seq_.tmp
then echo "Please unpack part 1 first!"
     exit 1; fi
( read Scheck
  if test "$Scheck" != $CurArch
  then echo "Please unpack part $Scheck next!"
       exit 1;
  else exit 0; fi
) < s2_seq_.tmp || exit 1
echo "x - Continuing file r_msg.c"
sed 's/^X//' << 'SHAR_EOF' >> r_msg.c
X  putline(mybuf);
X}
X
Xm_private(sptr, cptr, sender, buf, buf2)
Xstruct Client *sptr, *cptr;
Xchar *buf, *buf2, *sender;
X{
X  char *ptr;
X  if (sender && sender[0]) {
X    if (myncmp(sender, client->nickname, NICKLEN))
X      sprintf(mybuf,"*%s* %s", sender, buf2);
X    else
X      sprintf(mybuf,"-> *%s* %s", buf, buf2);
X    putline(mybuf);
X    parse(
X    if (ptr = mycncmp(buf2,"DEAL", 1)) {
X      sendto_one(client,"MSG :Deal requested by %s", sender);
X      deal();
X    } else if (ptr = mycncmp(buf2, "PLAYER", 1)) {
X      sendto_one(client,"MSG :%s requested to be added to game",
X		 sender);
X      player(sender);
X    } else if (ptr = mycncmp(buf2, "INIT", 1)) {
X      sendto_one(client,"MSG :%s requested a new game with %d cards",
X		 sender, atoi(ptr));
X      if (atoi(ptr) > 0)
X	init_game(atoi(ptr));
X    } else if (ptr = mycncmp(buf2, "NAMES", 1)) {
X      sendto_one(client,"MSG :Revealing names of players");
X      names();
X    } else if (ptr = mycncmp(buf2, "HAND", 1)) {
X      hand(sender);
X    } else if (ptr = mycncmp(buf2, "SHUFFLE", 1)) {
X      shuffle(sender);
X    } else {
X      sendto_one(client,"PRIVMSG %s :Commands available are:", sender);
X      sendto_one(client,"PRIVMSG %s :INIT PLAYER NAMES DEAL HAND SHUFFLE",
X		 sender);
X    }
X  }
X  else
X    putline(buf2);
X}
X
Xm_invite(sptr, cptr, sender, buf, buf2)
Xstruct Client *sptr, *cptr;
Xchar *buf, *buf2, *sender;
X{
X  sprintf(mybuf,"*** %s Invites you to channel %s", sender, buf2);
X  putline(mybuf);
X  sendto_one(client,"MSG :%s invited me away, Byebye...", sender);
X  sendto_one(client,"CHANNEL %s", buf2);
X  sendto_one(client,"MSG :Hello %s, always ready to serve you...", sender);
X}
X
Xm_error(sptr, cptr, sender, buf, buf2)
Xstruct Client *sptr, *cptr;
Xchar *buf, *buf2, *sender;
X{
X  sprintf(mybuf,"*** Error: %s %s", buf, (buf2) ? buf2 : "");
X  putline(mybuf);
X}
SHAR_EOF
echo "File r_msg.c is complete"
chmod 0600 r_msg.c || echo "restore of r_msg.c fails"
set `wc -c r_msg.c`;Sum=$1
if test "$Sum" != "7406"
then echo original size 7406, current size $Sum;fi
echo "x - extracting s_bsd.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > s_bsd.c &&
X/*************************************************************************
X ** s_bsd.c  Beta  v2.0    (22 Aug 1988)
X **
X ** This file is part of Internet Relay Chat v2.0
X **
X ** Author:           Jarkko Oikarinen 
X **         Internet: jto@tolsun.oulu.fi
X **             UUCP: ...!mcvax!tut!oulu!jto
X **           BITNET: toljto at finou
X **
X ** Copyright (c) 1988 University of Oulu, Computing Center
X **
X ** All rights reserved.
X **
X ** See file COPYRIGHT in this package for full copyright.
X ** 
X *************************************************************************/
X
Xchar s_bsd_id[] = "s_bsd.c v2.0 (c) 1988 University of Oulu, Computing Center";
X
X#include "struct.h"
X#if HPUX
X#include <time.h>
X#else
X#include <sys/time.h>
X#endif
X#include <sys/types.h>
X#include <sys/socket.h>
X#include <sys/file.h>
X#include <sys/ioctl.h>
X#include <netinet/in.h>
X#if !HPUX
X#include <arpa/inet.h>
X#endif
X#include <netdb.h>
X#include <stdio.h>
X#include <signal.h>
X#include <fcntl.h>
X#include <utmp.h>
X#if BSD42 || ULTRIX || HPUX
X#include "sock.h"
X#endif
X#include "sys.h"
X
Xextern struct Client me;
Xextern struct Client *client;
Xextern struct Confitem *find_conf();
Xextern int portnum;
Xextern int dummy();
X
Xint
Xopen_port(portnum)
Xint portnum;
X{
X  int sock, length;
X  static struct sockaddr_in server;
X  /* At first, open a new socket */
X  sock = socket(AF_INET, SOCK_STREAM, 0);
X  if (sock < 0) {
X    perror("opening stream socket");
X    exit(-1);
X  }
X
X  /* Bind a port to listen for new connections */
X  server.sin_family = AF_INET;
X  server.sin_addr.s_addr = INADDR_ANY;
X  server.sin_port = htons(portnum);
X  for (length = 0; length < 10; length++) {
X    if (bind(sock, &server, sizeof(server))) {
X      perror("binding stream socket");
X      if (length >= 9)
X	exit(-1);
X      sleep(20);
X    } else
X      break;
X  }
X  listen(sock, 3);
X  return(sock);
X}
X
Xinit_sys()
X{
X  int fd;
X#ifdef NOTTY
X#if !HPUX
X  setlinebuf(stdout);
X  setlinebuf(stderr);
X#endif
X  if (isatty(0)) {
X    close (0); close(1); close(2);
X    if (fork()) exit(0);
X#ifdef TIOCNOTTY
X    if ((fd = open("/dev/tty", O_RDWR)) >= 0) {
X      ioctl(fd, TIOCNOTTY, (char *) 0);
X      close(fd);
X    }
X#else
X    setpgrp(0,getpid());
X#endif
X  } else {
X    close (0); close(1); close(2);
X  }
X#endif
X}
X
Xint
Xcheck_access(cptr, flags) /* Check whether any clients/daemons/operators */
Xstruct Client *cptr;   /* are allowed to enter from this host         */
Xint flags;
X{
X  struct sockaddr_in name;
X  struct hostent *host;
X  char *hname;
X  int namecount = -1;
X  int len = sizeof(name);
X  if (getpeername(cptr->fd, &name, &len) == -1) {
X    perror("check_access (getpeername)");
X    return(-1);
X  }
X  if ((host = gethostbyaddr(&(name.sin_addr),
X			    sizeof (struct in_addr), AF_INET)) == NULL) {
X#if ULTRIX
X    return(-1);
X#endif
X  }
X#if !ULTRIX
X  hname = inet_ntoa(name.sin_addr);
X#else
X  hname = host->h_name;
X#endif
X  do {
X    debug(DEBUG_DEBUG,"Checking access for (%s) host", hname);
X    if (find_conf(hname, NULL, NULL, flags)) {
X      debug(DEBUG_DEBUG,"Access ok, host (%s)", hname);
X      break;
X    }
X    debug(DEBUG_DEBUG,"Access checked");
X    if (hname) {
X      if (namecount < 0) {
X	if (host == 0)
X	  return -1;
X	hname = host->h_name;
X	namecount = 0;
X      }
X      else {
X	if (host == 0)
X	  return -1;
X	hname = host->h_aliases[namecount++];
X      }
X      if (hname == 0 || *hname == 0)
X	hname = NULL;
X    }
X  } while (hname);
X  if (!hname)
X    return -1;
X  strncpy(cptr->sockhost, hname, HOSTLEN);
X  cptr->sockhost[HOSTLEN] = '\0';
X}
X
Xread_msg(buffer, buflen, from)
Xchar *buffer;
Xint buflen;
Xstruct Client **from;
X{
X  struct timeval wait;
X  int nfds, res, length;
X  fd_set read_set;                 
X  struct Client *cptr;
X  struct Confitem *aconf;
X  res = 0;
X  do {
X    wait.tv_sec = TIMESEC;
X    wait.tv_usec = 0;
X    FD_ZERO(&read_set);
X    cptr = client;
X    while (cptr) {
X      if (cptr->fd >= 0) FD_SET(cptr->fd, &read_set);
X      cptr = cptr->next;
X    }
X    nfds = select(FD_SETSIZE, &read_set, (fd_set *) 0, (fd_set *) 0, &wait);
X    if (nfds < 0) {
X      perror("select");
X      res++;
X      if (res > 5) {
X	restart();
X      }
X      sleep(10);
X    }
X  } while (nfds < 0);
X  if (nfds == 0)
X    return(nfds);
X  else {
X    if (FD_ISSET(me.fd, &read_set)) {
X      nfds--;
X      cptr = make_client();
X      strcpy(cptr->server, myhostname);
X      if ((cptr->fd = accept(me.fd, (struct sockaddr *) 0, (int *) 0)) < 0)
X	{
X	  perror("accept");
X	  free(cptr);
X	}
X      else {
X/*	res = fcntl(cptr->fd, F_GETFL, 0);
X	fcntl(cptr->fd, F_SETFL, res | O_NDELAY); */
X	if (check_access(cptr, CONF_CLIENT | CONF_NOCONNECT_SERVER
X			 | CONF_UPHOST) >= 0)
X	  client = cptr;
X	else {
X	  close(cptr->fd);
X	  free(cptr);
X	}
X      }
X    }
X    cptr = client;
X      while (cptr && nfds) {
X	if (cptr->fd >= 0 && FD_ISSET(cptr->fd, &read_set) && 
X	    cptr->status != STAT_ME) {
X	  nfds--;
X	  if ((length = read(cptr->fd, buffer, buflen)) <= 0) {
X            perror("read");
X	    debug(DEBUG_DEBUG,"READ ERROR (FATAL): fd = %d", cptr->fd);
X	    aconf = (struct Confitem *) 0;
X	    if (cptr->status == STAT_SERVER)
X		aconf = find_conf(cptr->sockhost, NULL, cptr->host,
X				   CONF_CONNECT_SERVER);
X	    m_bye(cptr, cptr);
X	    if (aconf && aconf->port > 0) {
X	      sleep(3);
X	      connect_server(aconf);
X	    }
X	  }
X	  *from = cptr;
X	  return(length);
X	}
X	cptr = cptr->next;
X      }
X    }
X  return(-1);
X}    
X  
X
Xconnect_server(aconf)
Xstruct Confitem *aconf;
X{
X  struct sockaddr_in server;
X  struct hostent *hp;
X  struct Client *acptr;
X  struct Client *cptr = make_client();
X  int res;
X  struct sockaddr_in name;
X  struct hostent *host;
X  int len = sizeof(name);
X  cptr->fd = socket(AF_INET, SOCK_STREAM, 0);
X  if (cptr->fd < 0) {
X    perror("opening stream socket to server");
X    free(cptr);
X    return(-1);
X  }
X  server.sin_family = AF_INET;
X
X /* MY FIX -- jtrim@duorion.cair.du.edu  (2/10/89) */
X#if !ULTRIX
X  if (isdigit(*(aconf->host))) 
X      server.sin_addr.s_addr = inet_addr(aconf->host);
X  else 
X  {
X#endif
X    hp = gethostbyname(aconf->host);
X    if (hp == 0) {
X      close(cptr->fd);
X      free(cptr);
X      debug(DEBUG_FATAL, "%s: unknown host", aconf->host);
X      return(-1);
X    }
X   bcopy(hp->h_addr, &server.sin_addr, hp->h_length);
X#if !ULTRIX
X  }
X#endif
X  server.sin_port = htons((aconf->port > 0) ? aconf->port : portnum);
X
X/*  sleep(5); */
X
X/* End FIX */
X
X  signal(SIGALRM, dummy);
X  alarm(4);
X  if (connect(cptr->fd, (struct sockaddr *) &server, sizeof(server)) < 0) {
X    alarm(0);
X    perror("connect");
X    close(cptr->fd);
X    free(cptr);
X    return(-1);
X  }
X  alarm(0);
X  strncpy(cptr->fromhost, aconf->host, HOSTLEN);
X  cptr->fromhost[HOSTLEN] = '\0';
X  strncpy(cptr->host, aconf->host, HOSTLEN);
X  cptr->host[HOSTLEN] = '\0';
X  cptr->status = STAT_HANDSHAKE;
X/*  strncpy(me.server, aconf->host, HOSTLEN);
X  me.server[HOSTLEN] = '\0'; */
X  if (aconf->passwd[0])
X    sendto_one(cptr, "PASS %s",aconf->passwd);
X  sendto_one(cptr, "SERVER %s %s", myhostname, me.server);
X  if (check_access(cptr, CONF_NOCONNECT_SERVER | CONF_UPHOST) < 0) {
X    close(cptr->fd);
X    free(cptr);
X    debug(DEBUG_DEBUG,"No such host in hosts database !");
X    return(-1);
X  }
X  cptr->next = client;
X  client = cptr;
X  return(0);
X/*  res = fcntl(cptr->fd, F_GETFL, 0);
X  fcntl(cptr->fd, F_SETFL, res | O_NDELAY); */
X}
X
Xint utmp_open()
X{
X  int fd;
X  return (open(UTMP,O_RDONLY));
X}
X
Xint utmp_read(fd, name, line, host)
Xint fd;
Xchar *name, *line, *host;
X{
X  struct utmp ut;
X  while (read(fd, &ut, sizeof (struct utmp)) == sizeof (struct utmp)) {
X    strncpy(name,ut.ut_name,8);  name[8] = '\0';
X    strncpy(line,ut.ut_line,8);  line[8] = '\0';
X#ifdef USER_PROCESS
X    strncpy(host, myhostname, 8); host[8] = '\0';
X    if (ut.ut_type == USER_PROCESS)
X      return(0);
X#else
X    strncpy(host,(ut.ut_host[0]) ? (ut.ut_host) : myhostname, 16);
X    if (ut.ut_name[0])
X      return(0);
X#endif
X  }
X  return(-1);
X}
X
Xint utmp_close(fd)
Xint fd;
X{
X  return(close(fd));
X}
X
Xsummon(who, namebuf, linebuf)
Xstruct Client *who;
Xchar *namebuf, *linebuf;
X{
X  int fd;
X  char line[120], *wrerr = "PRIVMSG %s :Write error. Couldn't summon.";
X  if (strlen(linebuf) > 8) {
X    sendto_one(who,"PRIVMSG %s :Serious fault in SUMMON.");
X    sendto_one(who,"PRIVMSG %s :linebuf too long. Inform Administrator");
X    return(-1);
X  }
X  /* Following line added to prevent cracking to e.g. /dev/kmem if */
X  /* UTMP is for some silly reason writable to everyone... */
X  if ((linebuf[0] != 't' || linebuf[1] != 't' || linebuf[2] != 'y') &&
X      (linebuf[0] != 'c' || linebuf[1] != 'o' || linebuf[2] != 'n')) {
X    sendto_one(who,"PRIVMSG %s :Looks like mere mortal souls are trying to");
X    sendto_one(who,"PRIVMSG %s :enter the twilight zone... ");
X    debug(0, "%s (%s@%s, nick %s, %s)",
X	  "FATAL: major security hack. Notify Administrator !",
X	  who->username, who->host, who->nickname, who->realname);
X    return(-1);
X  }
X  strcpy(line,"/dev/");
X  strcat(line,linebuf);
X  alarm(5);
X  if ((fd = open(line, O_WRONLY | O_NDELAY)) == -1) {
X    alarm(0);
X    sendto_one(who,"PRIVMSG %s :%s seems to have disabled summoning...",
X	       who->nickname, namebuf);
X    return(-1);
X  }
X  alarm(0);
X  strcpy(line,
X	 "\n\r\007ircd: You are being summoned to Internet Relay Chat by\n\r");
X  alarm(5);
X  if (write(fd, line, strlen(line)) != strlen(line)) {
X    alarm(0);
X    close(fd);
X    sendto_one(who,wrerr,who->nickname);
X    return(-1);
X  }
X  alarm(0);
X  sprintf(line, "ircd: Channel %d: %s@%s (%s) %s\n\r", who->channel,
X	  who->username, who->host, who->nickname, who->realname);
X  alarm(5);
X  if (write(fd, line, strlen(line)) != strlen(line)) {
X    alarm(0);
X    close(fd);
X    sendto_one(who,wrerr,who->nickname);
X    return(-1);
X  }
X  alarm(0);
X  strcpy(line,"ircd: Respond with irc\n\r");
X  alarm(5);
X  if (write(fd, line, strlen(line)) != strlen(line)) {
X    alarm(0);
X    close(fd);
X    sendto_one(who,wrerr,who->nickname);
X    return(-1);
X  }
X  close(fd);
X  alarm(0);
X  sendto_one(who, "PRIVMSG %s :%s: Summoning user %s to irc",
X	     who->nickname, myhostname, namebuf);
X  return(0);
X}
X  
Xgetmyname(name, len)
Xchar *name;
Xint len;
X{
X  int namelen;
X  if (gethostname(name,len) < 0)
X    return(-1);
X  name[len] = '\0';
X#if DOMAINNAME
X  if ((index(name,'.') == (char *) 0) && ((namelen = strlen(name)) < len - 1))
X    {
X      name[namelen] = '.';
X      if (getdomainname(&name[namelen+1], len-namelen-1) < 0)
X	return(-1);
X      name[len] = '\0';
X    } 
X  else
X    return(-1);
X#endif
X}
X
Xlong
Xgetlongtime()
X{
X  return(time(0));
X}
SHAR_EOF
chmod 0600 s_bsd.c || echo "restore of s_bsd.c fails"
set `wc -c s_bsd.c`;Sum=$1
if test "$Sum" != "10443"
then echo original size 10443, current size $Sum;fi
echo "x - extracting s_msg.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > s_msg.c &&
X/*************************************************************************
X ** s_msg.c  Beta  v2.0    (22 Aug 1988)
X **
X ** This file is part of Internet Relay Chat v2.0
X **
X ** Author:           Jarkko Oikarinen 
X **         Internet: jto@tolsun.oulu.fi
X **             UUCP: ...!mcvax!tut!oulu!jto
X **           BITNET: toljto at finou
X **
X ** Copyright (c) 1988 University of Oulu, Computing Center
X **
X ** All rights reserved.
X **
X ** See file COPYRIGHT in this package for full copyright.
X ** 
X *************************************************************************/
X
Xchar s_msg_id[] = "s_msg.c v2.0 (c) 1988 University of Oulu, Computing Center";
X
X#include "struct.h"
X#include "sys.h"
X#include <sys/types.h>
X#include <sys/file.h>
X#if APOLLO
X#include <sys/types.h>
X#endif
X#include <utmp.h>
X#include "msg.h"
X
X#define NULL ((char *) 0)
X
Xextern struct Client *client, me;
Xextern struct Client *find_client();
Xextern struct Client *find_server();
Xextern struct Confitem *find_conf(), *find_admin();
Xextern struct Confitem *conf;
Xextern struct Channel *find_channel();
Xextern char *center();
Xextern char *uphost;
Xstruct Channel *channel = (struct Channel *) 0;
Xextern int maxusersperchannel;
X
Xchar buf[BUFSIZE];
Xchar buf2[80];
X
Xm_nick(cptr, sptr, sender, para)
Xstruct Client *cptr, *sptr;
Xchar *para, *sender;
X{
X  struct Client *acptr;
X  char *ch;
X  int flag = 0;
X  if (para == NULL || *para == '\0') {
X    sendto_one(sptr,"ERROR :Nickname %s not changed",sptr->nickname);
X  } else {
X    ch = para;
X    if ((*ch >= '0' && *ch <= '9') || *ch == '-' || *ch == '+')
X      *ch = '\0';
X    while (*ch) {
X      if ((*ch < 65 || *ch > 125) && (*ch < '0' || *ch > '9') &&
X	  *ch != '_' && *ch != '-') *ch = '\0';
X      ch++;
X    }
X    if (*para == '\0') {
X      sendto_one(sptr,"ERROR :Illegal Nickname");
X      return(0);
X    }
X    if ((acptr = find_client(para,NULL)) == (struct Client *) 0) {
X      if (sptr->status == STAT_SERVER) {
X	sptr = make_client();
X	strcpy(sptr->fromhost, cptr->host);
X	flag = 1;
X      }
X      else if (sptr->realname[0]) {
X	if (sptr->fd >= 0 && sptr->status == STAT_UNKNOWN) {
X	  sptr->status = STAT_CLIENT;
X	  dowelcome(sptr);
X	}
X	if (sptr->realname[0] && sptr->nickname[0] == '\0')
X	  flag = 2;
X      }
X      if (sptr->channel != 0)
X	sendto_channel_butserv(sptr->channel, ":%s NICK %s",
X			       sptr->nickname, para);
X      if (sptr->nickname[0])
X	sendto_serv_butone(cptr, ":%s NICK %s",sptr->nickname, para);
X      else
X	sendto_serv_butone(cptr, "NICK %s", para);
X      strncpy(sptr->nickname, para, NICKLEN-1);
X      sptr->nickname[NICKLEN-1] = '\0';
X      if (flag == 2) {
X	sendto_serv_butone(cptr,":%s USER %s %s %s :%s", sptr->nickname,
X			   sptr->username, sptr->host, sptr->server,
X			   sptr->realname);
X      }
X      if (flag == 1) {
X	sptr->next = client;
X	client = sptr;
X      } 
X    } else {
X      sendto_one(sptr,"ERROR :Nickname %s already exists. %s",
X		 para, "No change performed");
X      if (cptr->status == STAT_SERVER)
X	m_bye(acptr, acptr);
X    }
X  }
X  return(0);
X}
X
Xm_text(cptr, sptr, sender, para)
Xstruct Client *cptr, *sptr;
Xchar *para, *sender;
X{
X  if (para == NULL || *para == '\0' || sptr->status < 0) 
X    sendto_one(sptr,"ERROR :No text sent");
X  else if (sptr->channel != 0) 
X    sendto_channel_butone(cptr,
X			  sptr->channel, ":%s MSG :%s", 
X			  sptr->nickname, para);
X  else
X    sendto_one(sptr,"ERROR :You have not joined any channel");
X  return(0);
X}
X
Xm_private(cptr, sptr, sender, para, para2)
Xstruct Client *cptr, *sptr;
Xchar *para, *para2, *sender;
X{
X  struct Client *acptr;
X  struct Channel *chptr;
X  char *nick, *tmp;
X  if (para == NULL || *para == '\0' || para2 == NULL || *para2 == '\0' ||
X      sptr->status < 0)
X    sendto_one(sptr,"ERROR :No text sent");
X  else {
X    tmp = para;
X    do {
X      nick = tmp;
X      if (tmp = index(nick, ',')) {
X	*(tmp++) = '\0';
X      }
X      acptr = find_client(nick, NULL);
X      if (acptr) {
X	if (acptr->away) {
X	  sendto_one(sptr,"PRIVMSG %s :%s has marked himself as being %s",
X		     sptr->nickname, acptr->nickname, 
X		     "away and gave message: ");
X	  sendto_one(sptr,"PRIVMSG %s :\'%s\'",sptr->nickname,acptr->away);
X	  sendto_one(sptr,"PRIVMSG %s :Your message was sent to him anyway",
X		     sptr->nickname);
X	}
X	sendto_one(acptr, ":%s PRIVMSG %s :%s", sptr->nickname, nick, para2);
X      } else if (chptr = find_channel(nick, NULL)) {
X	sendto_channel_butone(cptr, chptr->channo,
X			      ":%s PRIVMSG %d :%s", sptr->nickname,
X			      chptr->channo, para2);
X      } else {
X	sendto_one(sptr, "PRIVMSG %s :*** Error: No such nickname (%s)",
X		   sptr->nickname, nick);
X      }
X    } while (tmp && *tmp);
X  }
X  return (0);
X}
X
Xm_who(cptr, sptr, sender, para)
Xstruct Client *cptr, *sptr;
Xchar *para, *sender;
X{
X  int i;
X  struct Client *acptr = client;
X  if (para == NULL || para[0] == '\0')
X    i = 0;
X  else if (index(para,'*'))
X    i = sptr->channel;
X  else
X    i = atoi(para);
X  sendto_one(sptr,"WHOREPLY * User Host Server Nickname S :Name");
X  while (acptr) {
X    if ((i == 0 || acptr->channel == i) && 
X	(acptr->status == STAT_CLIENT || acptr->status == STAT_OPER) &&
X	(acptr->channel >= 0 || acptr->channel == sptr->channel)) {
X      if ((acptr->channel < 1000 && acptr->channel > 0) ||
X	  (sptr->channel == acptr->channel && sptr->channel != 0))
X	sendto_one(sptr, "WHOREPLY %d %s %s %s %s %c%c :%s",
X		   acptr->channel, acptr->username, acptr->host,
X		   acptr->server, acptr->nickname, (acptr->away) ? 'G' : 'H',
X		   (acptr->status == STAT_OPER) ? '*' : ' ', acptr->realname);
X      else
X	sendto_one(sptr,"WHOREPLY 0 %s %s %s %s %c%c :%s",
X		   acptr->username, acptr->host, acptr->server,
X		   acptr->nickname, (acptr->away) ? 'G' : 'H',
X		   (acptr->status == STAT_OPER) ? '*' : ' ', acptr->realname);
X    }
X    acptr = acptr->next;
X  }
X  return(0);
X}
X
Xm_whois(cptr, sptr, sender, para)
Xstruct Client *cptr, *sptr;
Xchar *para, *sender;
X{
X  struct Client *acptr;
X  if (para == NULL || *para == '\0')
X    sendto_one(sptr,"ERROR No nickname specified");
X  else {
X    acptr = find_client(para,NULL);
X    if (acptr == (struct Client *) 0)
X      sendto_one(sptr,"ERROR :No such nickname");
X    else {
X      sendto_one(sptr,"PRIVMSG %s :%s is %s at %s (%s)",sptr->nickname,
X		 acptr->nickname, acptr->username, acptr->host,
X		 acptr->realname);
X      sendto_one(sptr,"PRIVMSG %s :On IRC via server %s",sptr->nickname,
X		 acptr->server);
X      if (acptr->away) 
X	sendto_one(sptr,"PRIVMSG %s :He is away: \"%s\"",
X		   sptr->nickname, acptr->away);
X    }
X  }
X  return(0);
X}
X
Xm_user(cptr, sptr, sender, username, host, server, realname)
Xstruct Client *cptr, *sptr;
Xchar *username, *server, *host, *realname, *sender;
X{
X  struct Confitem *aconf;
X  if (username == NULL || server == NULL || host == NULL || realname == NULL
X      || *username == '\0' || *server == '\0' || *host == '\0' ||
X      *realname == '\0')
X    sendto_one(sptr,"ERROR Not enough parameters");
X  else if (sptr->status != STAT_UNKNOWN && sptr->status != STAT_OPER)
X    sendto_one(sptr,"ERROR Identity problems, eh ?");
X  else {
X    if (sptr->fd >= 0) {
X      if ((aconf = find_conf(sptr->sockhost, NULL, NULL, CONF_CLIENT)) == 0) {
X	if ((aconf = find_conf("", NULL, NULL, CONF_CLIENT)) == 0) {
X	  sendto_one(sptr,"ERROR :Access denied (no host)");
X	  m_bye(sptr, sptr);
X	  return(FLUSH_BUFFER);
X	} 
X      } else 
X	if (strcmp(sptr->passwd, aconf->passwd)) {
X	  sendto_one(sptr,"ERROR :Access denied (passwd mismatch)");
X	  m_bye(sptr, sptr);
X	  return(FLUSH_BUFFER);
X	}
X      host = sptr->sockhost;
X      if (find_conf(host, NULL, username,
X		    CONF_KILL)) {
X	sendto_one(sptr,"ERROR :Ghosts are not allowed on irc...");
X	m_bye(sptr, sptr);
X	return(FLUSH_BUFFER);
X      }
X    }
X    if (sptr->nickname[0]) {
X      sptr->status = STAT_CLIENT;
X      if (sptr->fd >= 0)
X	dowelcome(sptr);
X    }
X    strncpy(sptr->username, username, USERLEN);
X    sptr->username[USERLEN] = '\0';
X    if (cptr != sptr)
X      strncpy(sptr->server, server, HOSTLEN);
X    else
X      strcpy(sptr->server, myhostname);
X    sptr->server[HOSTLEN] = '\0';
X    strncpy(sptr->host, host, HOSTLEN);
X    sptr->host[HOSTLEN] = '\0';
X    strcpy(sptr->realname, realname);
X    sptr->realname[REALLEN] = '\0';
X    if (sptr->status == STAT_CLIENT)
X      sendto_serv_butone(cptr,":%s USER %s %s %s :%s", sptr->nickname,
X			 username, host, sptr->server, realname);
X  }
X  return(0);
X}
X
Xm_list(cptr, sptr, sender, para)
Xstruct Client *cptr, *sptr;
Xchar *para, *sender;
X{
X  struct Channel *chptr = channel;
X  sendto_one(sptr,"PRIVMSG %s :  Channel  : Users  Name",
X	     sptr->nickname);
X  while (chptr) {
X    if ((chptr->channo < 1000 && chptr->channo > 0) ||
X	(chptr->channo == sptr->channel && sptr->channel != 0))
X      sprintf(buf2,"Channel %3d:",chptr->channo);
X    else
X      strcpy(buf2,"* Private *:");
X    sendto_one(sptr,"PRIVMSG %s :%12s %5d %s",
X	       sptr->nickname, buf2, chptr->users, chptr->name);
X    chptr = chptr->nextch;
X  }
X  return(0);
X}
X
Xm_topic(cptr, sptr, sender, topic)
Xstruct Client *cptr, *sptr;
Xchar *topic, *sender;
X{
X  struct Channel *chptr = channel;
X  if (sptr->status == STAT_UNKNOWN) {
X    sendto_one(sptr,"ERROR :You have not registered yourself yet");
X    return(0);
X  }
X  sendto_serv_butone(cptr,":%s TOPIC %s",sptr->nickname,topic);
X  while (chptr) {
X    if (chptr->channo == sptr->channel) {
X      if (topic == NULL || topic[0] == '\0') {
X	chptr->name[0] = '*'; chptr->name[1] = '\0';
X      } else {
X	strncpy(chptr->name, topic, CHANNELLEN);
X	chptr->name[CHANNELLEN] = '\0';
X      }
X      if (sptr->fd >= 0)
X	sendto_one(sptr,
X		   "PRIVMSG %s :New topic of channel %d (%d users): %s",
X		   sptr->nickname, chptr->channo, chptr->users, chptr->name);
X    }	
X    chptr = chptr->nextch;
X  }
X  return(0);
X}
X
Xm_invite(cptr, sptr, sender, user, channel)
Xstruct Client *cptr, *sptr;
Xchar *user, *channel, *sender;
X{
X  struct Client *acptr;
X  int i;
X  if (sptr->status < 0)
X    sendto_one(sptr,"ERROR :You have not registered yourself yet");
X  else if (user == NULL || *user == '\0')
X    sendto_one(sptr,"ERROR :Not enough parameters");
X  else {
X    acptr = find_client(user,NULL);
X    if (channel == NULL)
X      i = 0;
X    else 
X      i = atoi(channel);
X    if (i == 0)
X      i = sptr->channel;
X    if (acptr == (struct Client *) 0) 
X      sendto_one(sptr,"ERROR :No such nickname");
X    else {
X      sendto_one(sptr,"PRIVMSG %s :%s: Inviting user %s to channel %d",
X		 sptr->nickname, myhostname, acptr->nickname, i);
X      sendto_one(acptr,":%s INVITE %s %d",sptr->nickname,
X		 acptr->nickname, i);
X    }
X  }
X  return(0);
X}
X
Xm_channel(cptr, sptr, sender, ch)
Xstruct Client *cptr, *sptr;
Xchar *ch, *sender;
X{
X  struct Client *acptr;
X  struct Channel *chptr, *pchptr, *ch2ptr;
X  int i;
X  if ((sptr->status != STAT_CLIENT) && (sptr->status != STAT_OPER)) {
X    sendto_one(sptr,"ERROR You have not registered yourself");
X    return(0);
X  }
X  acptr = client;
X  chptr = channel;
X  if (ch == NULL)
X    i = 0;
X  else
X    i = atoi(ch);
X  pchptr = (struct Channel *) 0;
X  if (i > 0) {
X    while (chptr) {
X      if (chptr->channo == i)
X	break;
X      chptr = chptr->nextch;
X    }
X    if (chptr == (struct Channel *) 0) {
X      if ((chptr = (struct Channel *) malloc(sizeof(struct Channel))) == 
X	  (struct Channel *) 0)
X	{
X	  perror("malloc");
X	  debug(DEBUG_FATAL,"Out of memory. Cannot allocate channel");
X	  restart();
X	}
X      chptr->nextch = channel;
X      chptr->channo = i;
X      chptr->name[0] = '\0';
X      chptr->users = 0;
X      channel = chptr;
X    } else if (cptr == sptr && is_full(i, chptr->users)) {
X      sendto_one(sptr,"PRIVMSG %s :Sorry, Channel is full.", sptr->nickname);
X      return(0);
X    }
X    chptr->users++;
X  }
X  chptr = channel;
X  while (chptr) {
X    if (chptr->channo == sptr->channel && chptr->users > 0) 
X      --chptr->users;
X    if (chptr->users <= 0) {
X      if (pchptr)
X	pchptr->nextch = chptr->nextch;
X      else
X	channel = chptr->nextch;
X      free(chptr);
X    }
X    pchptr = chptr;
X    chptr = chptr->nextch;
X  }
X  sendto_serv_butone(cptr, ":%s CHANNEL %d",
X			sptr->nickname, i);
X  if (sptr->channel != 0)
X    sendto_channel_butserv(sptr->channel, ":%s CHANNEL 0", sptr->nickname);
X  sptr->channel = i;
X  if (sptr->channel != 0)
X    sendto_channel_butserv(i, ":%s CHANNEL %d", sptr->nickname, i);
X  return(0);
X}
X
Xm_version(cptr, sptr, sender, vers)
Xstruct Client *sptr, *cptr;
Xchar *sender, *vers;
X{
X  if (vers == NULL)
X    sendto_one(sptr,"VERSION :%s", version);
X  return(0);
X}
X
Xm_quit(cptr, sptr)
Xstruct Client *cptr, *sptr;
X{
X/*  if (sptr->fd >= 0 && strcmp(sptr->fromhost, cptr->fromhost))
X    return(FLUSH_BUFFER); */  /* Fix 12 Mar 1989 by Jto */
X  if (sptr->status != STAT_SERVER) {
X    m_bye(cptr, sptr);
X    if (cptr == sptr)
X      return(FLUSH_BUFFER);
X    else
X      return(0);
X  }
X  return(0);
X}
X
Xm_squit(cptr, sptr, dummy, server)
Xstruct Client *cptr, *sptr;
Xchar *dummy, *server;
X{
X  struct Client *acptr = find_server(server, NULL);
X  if (sptr->status != STAT_SERVER && sptr->status != STAT_OPER) {
X    sendto_one(sptr,"ERROR :'tis is no game for mere mortal souls");
X    return(0);
X  }
X  if (acptr)
X    m_bye(cptr, acptr);
X  return(0);
X}
X
Xm_server(cptr, sptr, user, host, server)
Xstruct Client *cptr, *sptr;
Xchar *host, *server, *user;
X{
X  struct Client *acptr;
X  struct Confitem *aconf, *bconf;
X  if (host == NULL || *host == '\0') {
X    sendto_one(cptr,"ERROR :No hostname");
X    return(0);
X  }
X  if (find_server(host, NULL)) {
X    sendto_one(sptr,"ERROR :Such name already exists... ");
X    if (cptr == sptr) {
X      m_bye(cptr, sptr);
X      return(FLUSH_BUFFER);
X    } else
X      return(0);
X  }
X  if (sptr->status == STAT_SERVER) {
X    if (server == NULL || *server == '\0') {
X      sendto_one(cptr,"ERROR :No servername specified");
X      return(0);
X    }
X    acptr = make_client();
X    strncpy(acptr->host,host,HOSTLEN); strncpy(acptr->server,server,HOSTLEN);
X    acptr->host[HOSTLEN] = '\0';   acptr->server[HOSTLEN] = '\0';
X    acptr->status = STAT_SERVER;
X    acptr->next = client;
X    strncpy(acptr->fromhost,sptr->host,HOSTLEN);
X    client = acptr;
X    sendto_serv_butone(cptr,"SERVER %s %s",acptr->host, acptr->server);
X    return(0);
X  } else if ((sptr->status == STAT_CLIENT) || (sptr->status == STAT_OPER)) {
X    sendto_one(cptr,"ERROR :Client may not currently become server");
X    return(0);
X  } else if (sptr->status == STAT_UNKNOWN || sptr->status == STAT_HANDSHAKE) {
X    if ((aconf = find_conf(sptr->sockhost, NULL, host, CONF_NOCONNECT_SERVER))
X	== 0) {
X      sendto_one(sptr,"ERROR :Access denied (no such server enabled) (%s@%s)",
X		 host, (server) ? (server) : "Master");
X      m_bye(sptr, sptr);
X      return(FLUSH_BUFFER);
X    }
X    if ((bconf = find_conf(sptr->sockhost, NULL, host, CONF_CONNECT_SERVER))
X	== 0) {
X      sendto_one(sptr, "ERROR :Only C field for server.");
X      m_bye(sptr, sptr);
X      return(FLUSH_BUFFER);
X    }
X    if (*(aconf->passwd) && strcmp(aconf->passwd, sptr->passwd)) {
X      sendto_one(sptr,"ERROR :Access denied (passwd mismatch)");
X      m_bye(sptr, sptr);
X      return(FLUSH_BUFFER);
X    }
X    strncpy(sptr->host, host, HOSTLEN);   sptr->host[HOSTLEN] = '\0';
X    if (server && *server) {
X      strncpy(sptr->server, server, HOSTLEN); sptr->server[HOSTLEN] = '\0';
X    }
X    else {
X      strncpy(sptr->server, myhostname, HOSTLEN); sptr->server[HOSTLEN] = '\0';
X    }
X    strncpy(sptr->fromhost, host, HOSTLEN); sptr->fromhost[HOSTLEN] = '\0';
X    acptr = client;
X    if (sptr->status == STAT_UNKNOWN) {
X      if (aconf->passwd[0])
X	sendto_one(cptr,"PASS %s",bconf->passwd);
X      sendto_one(cptr,"SERVER %s %s", myhostname, 
X		 (me.server[0]) ? (me.server) : "Master");
X    }
X    sptr->status = STAT_SERVER;
X    sendto_serv_butone(cptr,"SERVER %s %s",sptr->host, sptr->server);
X    while (acptr) {
X      if ((acptr->status == STAT_CLIENT) ||
X	  (acptr->status == STAT_OPER)) {
X	sendto_one(cptr,"NICK %s",acptr->nickname);
X	sendto_one(cptr,":%s USER %s %s %s :%s",acptr->nickname,
X		   acptr->username, acptr->host, acptr->server,
X		   acptr->realname);
X	sendto_one(cptr,":%s CHANNEL %d",acptr->nickname, acptr->channel);
X	if (acptr->status == STAT_OPER) 
X	  sendto_one(cptr,":%s OPER", acptr->nickname);
X      } else if (acptr->status == STAT_SERVER && acptr != sptr) {
X	  sendto_one(cptr,"SERVER %s %s",acptr->host, acptr->server);
X      }
X      acptr = acptr->next;
X    }
X    return(0);
X  }
X  return(0);
X}
X
Xm_kill(cptr, sptr, sender, user)
Xstruct Client *cptr, *sptr;
Xchar *sender, *user;
X{
X  struct Client *acptr;
X  debug(DEBUG_DEBUG,"%s: m_kill: %s", sptr->nickname, user);
X  if ((user == NULL) || (*user == '\0')) {
X    sendto_one(sptr,"ERROR :No user specified");
X    return(0);
X  }
X  if (sptr->status != STAT_OPER && sptr->status != STAT_SERVER) {
X    sendto_one(sptr,"ERROR :Death before dishonor ?");
X    return(0);
X  }
X  if ((acptr = find_client(user, NULL)) == (struct Client *) 0) {
X    sendto_one(sptr,"ERROR :Hunting for ghosts ?");
X    return(0);
X  }
X  sendto_one(sptr,"PRIVMSG %s :May his soul rest in peace...",sptr->nickname);
X  sendto_serv_butone(cptr,"KILL %s",user);
X  m_bye(acptr, acptr);
X  return(0);
X}
X
Xm_info(cptr, sptr)
Xstruct Client *cptr, *sptr;
X{
X  sendto_one(sptr,"PRIVMSG %s :%s", sptr->nickname, info1);
X  sendto_one(sptr,"PRIVMSG %s :%s", sptr->nickname, info2);
X  sendto_one(sptr,"PRIVMSG %s :%s", sptr->nickname, info3);
X  return(0);
X}
X
Xm_links(cptr, sptr)
Xstruct Client *cptr, *sptr;
X{
X  struct Client *acptr = client;
X  if (sptr->nickname[0] == '\0') {
X    sendto_one(sptr,"ERROR Nickname not specified yet");
X    return(0);
X  }
X  while (acptr) {
X    if (acptr->status == STAT_SERVER || acptr->status == STAT_ME)
X      sendto_one(sptr,"LINREPLY %s %s", acptr->host,
X		 (acptr->server[0] ? acptr->server : "(Unknown Location)"));
X    acptr = acptr->next;
X  }
X  return(0);
X}
X
Xm_summon(cptr, sptr, sender, user)
Xstruct Client *sptr, *cptr;
Xchar *user, *sender;
X{
X  struct Client *acptr=client, *a2cptr=client;
X  char namebuf[10],linebuf[10],hostbuf[17],*host;
X  int fd, flag;
X  if (sptr->nickname[0] == '\0') {
X    sendto_one(sptr,"ERROR Nickname not specified yet");
X    return(0);
X  }
X  if (user == NULL || *user == '\0') {
X    sendto_one(sptr,"PRIVMSG %s :%s: No user specified",sptr->nickname,
X	       myhostname);
X    return(0);
X  }
X  if ((host = index(user,'@')) == NULL)
X    host = myhostname;
X  else 
X    *(host++) = '\0';
X  if (host == NULL || *host == '\0' || strcmp(host,myhostname) == 0) {
X    if ((fd = utmp_open()) == -1) {
X      sendto_one(sptr,"PRIVMSG %s Cannot open %s",sptr->nickname,UTMP);
X      return(0);
X    }
X    while ((flag = utmp_read(fd, namebuf, linebuf, hostbuf)) == 0) 
X      if (strcmp(namebuf,user) == 0)
X	break;
X    utmp_close(fd);
X    if (flag == -1)
X      sendto_one(sptr,"PRIVMSG %s :%s: No such user found",
X		 sptr->nickname, myhostname);
X    else
X      summon(sptr, namebuf, linebuf);
X    return(0);
X  }
X  while (acptr) 
X    if (acptr->status == STAT_SERVER && strcmp(acptr->host, host) == 0)
X      break;
X    else 
X      acptr = acptr->next;
X  if (acptr == (struct Client *) 0) 
X    sendto_one(sptr,"ERROR No such host found");
X  else {
X    while(a2cptr)
X      if (a2cptr->status == STAT_SERVER &&
X	  strcmp(acptr->fromhost, a2cptr->host) == 0)
X	break;
X    else
X      a2cptr = a2cptr->next;
X    if (a2cptr == (struct Client *) 0)
X      sendto_one(sptr,"ERROR Internal Error. Contact Administrator");
X    else 
X      sendto_one(a2cptr,":%s SUMMON %s@%s",sptr->nickname, user, host);
X  }
X  return(0);
X}
X
Xm_stats(cptr, sptr)
Xstruct Client *cptr, *sptr;
X{
X  struct Message *mptr = msgtab;
X  for (; mptr->cmd; mptr++)
X    sendto_one(sptr,"PRIVMSG %s :%s has been used %d times after startup",
X	       sptr->nickname, mptr->cmd, mptr->count);
X  return(0);
X}
X
Xm_users(cptr, sptr, from, host)
Xstruct Client *cptr, *sptr;
Xchar *from, *host;
X{
X  struct Client *acptr=client, *a2cptr=client;
X  char namebuf[10],linebuf[10],hostbuf[17];
X  int fd, flag = 0;
X  if (sptr->nickname[0] == '\0') {
X    sendto_one(sptr,"ERROR Nickname not specified yet");
X    return(0);
X  }
X  if (host == NULL || *host == '\0' || strcmp(host,myhostname) == 0) {
X    if ((fd = utmp_open()) == -1) {
X      sendto_one(sptr,"PRIVMSG %s Cannot open %s",sptr->nickname,UTMP);
X      return(0);
X    }
X    sendto_one(sptr,"PRIVMSG %s :UserID   Terminal Host", sptr->nickname);
X    while (utmp_read(fd, namebuf, linebuf, hostbuf) == 0) {
X      flag = 1;
X      sendto_one(sptr,"PRIVMSG %s :%-8s %-8s %-8s",
X		 sptr->nickname, namebuf, linebuf, hostbuf);
X    }
X    if (flag == 0) 
X      sendto_one(sptr,"PRIVMSG %s :Nobody logged in on %s",
X		 sptr->nickname, host);
X    utmp_close(fd);
X    return(0);
X  }
X  while (acptr) 
X    if (acptr->status == STAT_SERVER && strcmp(acptr->host, host) == 0)
X      break;
X    else 
X      acptr = acptr->next;
X  if (acptr == (struct Client *) 0) 
X    sendto_one(sptr,"ERROR No such host found");
X  else {
X    while(a2cptr)
X      if (a2cptr->status == STAT_SERVER &&
X	  strcmp(acptr->fromhost, a2cptr->host) == 0)
X	break;
X    else
X      a2cptr = a2cptr->next;
X    if (a2cptr == (struct Client *) 0)
X      sendto_one(sptr,"ERROR Internal Error. Contact Administrator");
X    else 
X      sendto_one(a2cptr,":%s USERS %s",sptr->nickname, host);
X  }
X  return(0);
X}
X
Xm_bye(cptr, sptr) 
Xstruct Client *cptr;
Xstruct Client *sptr;
X{
X  struct Client *acptr;
X  struct Channel *chptr = channel, *pchptr;
X  close(sptr->fd); sptr->fd = -20;
X  if (sptr->status == STAT_SERVER && sptr == cptr) {
X    acptr = client;
X    while (acptr) {
X      if ((acptr->status == STAT_CLIENT || acptr->status == STAT_OPER) &&
X	  strcmp(acptr->fromhost, sptr->host) == 0 &&
X	  sptr != acptr) {
X	exit_user(cptr, acptr);
X	acptr = client;
X      } else 
X	acptr = acptr->next;
X    }
X    acptr = client;
X    while (acptr) {
X      if (acptr->status == STAT_SERVER &&
X	  strcmp(acptr->fromhost, sptr->host) == 0 &&
X	  sptr != acptr) {
X	exit_user(cptr, acptr);
X	acptr = client;
X      } else 
X	acptr = acptr->next;
X    }
X  }
X  exit_user(cptr, sptr);
X  return(0);
X}
X
Xexit_user(cptr, sptr)
Xstruct Client *sptr;
Xstruct Client *cptr;
X{
X  struct Client *acptr;
X  struct Channel *chptr = channel, *pchptr;
X  int i;
X  if ((sptr->status == STAT_CLIENT || sptr->status == STAT_OPER) &&
X      ((i = sptr->channel) != 0)) {
X    sptr->channel = 0;
X    sendto_channel_butserv(i,":%s QUIT", sptr->nickname);
X  } else
X    i = 0;
X  if (sptr->status == STAT_SERVER)
X    sendto_serv_butone(cptr,"SQUIT %s",sptr->host);
X  else if (sptr->nickname[0])
X    sendto_serv_butone(cptr,":%s QUIT",sptr->nickname);
X  pchptr = (struct Channel *) 0;
X  while (chptr) {
X    if (chptr->channo == i && chptr->users > 0) 
X      --chptr->users;
X    if (chptr->users <= 0) {
X      if (pchptr)
X	pchptr->nextch = chptr->nextch;
X      else
X	channel = chptr->nextch;
X      free(chptr);
X    }
X    pchptr = chptr;
X    chptr = chptr->nextch;
X  }
X  if (sptr->fd >= 0)
X    close (sptr->fd);
X  if (sptr == client) {
X    client = client->next;
X    if (sptr->away)
X      free(sptr->away);
X    free(sptr);
X    return(0);
X  }
X  acptr = client;
X  while (acptr && acptr->next != sptr) 
X    acptr = acptr->next;
X  if (acptr) {
X    acptr->next = sptr->next;
X  } else {
X    debug(DEBUG_FATAL, "List corrupted");
X    restart();
X  }
X  if (sptr->away)
X    free(sptr->away);
X  free(sptr);
X}
X
Xm_error(cptr, sptr, sender, para1, para2, para3, para4)
Xstruct Client *cptr, *sptr;
Xchar *sender, *para1, *para2, *para3, *para4;
X{
X  debug(DEBUG_ERROR,"Received ERROR message from %s: %s %s %s %s",
X	sptr->nickname, para1, para2, para3, para4);
X  return(0);
X}
X
Xm_help(cptr, sptr)
Xstruct Client *cptr, *sptr;
X{
X  int i;
X  for (i = 0; msgtab[i].cmd; i++)
X    sendto_one(sptr,"PRIVMSG %s :%s",sptr->nickname,msgtab[i].cmd);
X  return(0);
X}
X
Xm_whoreply(cptr, sptr, sender, para1, para2, para3, para4, para5, para6)
Xstruct Client *cptr, *sptr;
Xchar *sender, *para1, *para2, *para3, *para4, *para5, *para6;
X{
X  m_error(cptr, sptr, sender, "Whoreply", para1, para2, para3);
X}
X
Xm_restart(cptr, sptr)
Xstruct Client *cptr, *sptr;
X{
X  if (sptr->status == STAT_OPER)
X    restart();
X}
X
Xm_die(cptr, sptr)
Xstruct Client *cptr, *sptr;
X{
X  if (sptr->status == STAT_OPER)
X    exit(-1);
X}
X
Xdowelcome(sptr)
Xstruct Client *sptr;
X{
X  struct Client *acptr;
X  int s_count = 0, c_count = 0, u_count = 0;
X  sendto_one(sptr,"MSG :%s%s",welcome1,version);
X  acptr = client;
X  while (acptr) {
X    switch (acptr->status) {
X    case STAT_SERVER:
X    case STAT_ME:
X      s_count++;
X      break;
X    case STAT_CLIENT:
X    case STAT_OPER:
X      c_count++;
X      break;
X    default:
X      u_count++;
X      break;
X    }
X    acptr = acptr->next;
X  }
X  sendto_one(sptr,"MSG :There are %d users on %d servers",
X	     c_count, s_count);
X  if (u_count > 0)
X    sendto_one(sptr,"MSG :And %d yet unknown connections", u_count);
X}
X  
X  
X/***********************************************************************
X * m_away() - Added 14 Dec 1988 by jto. 
X *            Not currently really working, I don't like this
X *            call at all...
X ***********************************************************************/
X
Xm_away(cptr, sptr, sender, msg)
Xstruct Client *cptr, *sptr;
Xchar *msg;
X{
X  if (sptr->status != STAT_CLIENT && sptr->status != STAT_SERVICE &&
X      sptr->status != STAT_OPER) {
X    sendto_one(sptr,"ERROR :You must register yourself first");
X    return(-1);
X  }
X  if (sptr->away) {
X    free(sptr->away);
X    sptr->away = NULL;
X  }
X  if (msg && *msg) {
X    sptr->away = (char *) malloc((unsigned int) (strlen(msg)+1));
X    if (sptr->away == NULL)
X      sendto_one(sptr,"ERROR :Randomness of the world has proven its power!");
X    else {
X      sendto_one(sptr,"PRIVMSG %s :You have marked as being away",
X	         sptr->nickname);
X      strcpy(sptr->away, msg);
X    }
X  } else {
X    sendto_one(sptr,"PRIVMSG %s :You are no longer marked as being away",
X               sptr->nickname);
X  }
X  return(0);
X}
X
X/***********************************************************************
X * m_connect() - Added by Jto 11 Feb 1989
X ***********************************************************************/
X
Xm_connect(cptr, sptr, sender, host, portstr)
Xstruct Client *cptr, *sptr;
Xchar *sender, *host, *portstr;
X{
X  int port, tmpport;
X  struct Confitem *aconf;
X  if (sptr->status != STAT_SERVER && sptr->status != STAT_OPER) {
X    sendto_one(cptr,"ERROR :CONNECT: Privileged command");
X    return(-1);
X  }
X  if (!host || *host == '\0' || !portstr || *portstr == '\0') {
X    sendto_one(cptr,"ERROR :CONNECT: Syntax error");
X    return(-1);
X  }
X  if ((port = atoi(portstr)) <= 0) {
X    sendto_one(cptr,"ERROR :CONNECT: Illegal portnumber");
X    return(-1);
X  }
X  aconf = conf;
X  while (aconf) {
X    if (aconf->status == CONF_CONNECT_SERVER &&
X	strcmp(aconf->host, host) == 0) {
X      tmpport = aconf->port;
X      aconf->port = port;
X      connect_server(aconf);
X      aconf->port = tmpport;
X      break;
X    }
X    aconf = aconf->next;
X  }
X  return(0);
X}
X
Xm_ping(cptr, sptr, sender, origin, destination)
Xstruct Client *cptr, *sptr;
Xchar *sender, *origin, *destination;
X{
X  struct Client *acptr;
X  if (origin == NULL || *origin == '\0') {
X    sendto_one(sptr,"ERROR :No origin specified.");
X    return(-1);
X  }
X  if (destination && *destination && strcmp(destination, myhostname)) {
X    if (acptr = find_server(destination,NULL)) {
X      sendto_one(acptr,"PING %s %s", origin, destination);
X      return(0);
X    } else {
X      sendto_one(sptr,"ERROR :No such host found");
X      return(-1);
X    }
X  } else {
X    sendto_one(sptr,"PONG %s %s", 
X	       (destination) ? destination : myhostname, origin);
X    return(0);
X  }
X}
X
Xm_pong(cptr, sptr, sender, origin, destination)
Xstruct Client *cptr, *sptr;
Xchar *sender, *origin, *destination;
X{
X  struct Client *acptr;
X  if (origin == NULL || *origin == '\0') {
X    sendto_one(sptr,"ERROR :No origin specified.");
X    return(-1);
X  }
X  cptr->flags &= ~FLAGS_PINGSENT;
X  sptr->flags &= ~FLAGS_PINGSENT;
X  if (destination && *destination && strcmp(destination, myhostname)) {
X    if (acptr = find_server(destination,NULL)) {
X      sendto_one(acptr,"PONG %s %s", origin, destination);
X      return(0);
X    } else {
X      sendto_one(sptr,"ERROR :No such host found");
X      return(-1);
X    }
X  } else {
X    debug(DEBUG_NOTICE, "PONG: %s %s", origin, destination);
X    return(0);
X  }
X}
X
X/**************************************************************************
X * m_oper() added Sat, 4 March 1989
X **************************************************************************/
X
Xm_oper(cptr, sptr, sender, name, password)
Xstruct Client *cptr, *sptr;
Xchar *sender, *name, *password;
X{
X  struct Confitem *aconf;
X  if (sptr->status != STAT_CLIENT || 
X      (name == NULL || *name == '\0' || password == NULL ||
X      *password == '\0') && cptr == sptr ) {
X    sendto_one(sptr, "ERROR :Dave, don't do that...");
X    return(0);
X  }
X  if (cptr->status == STAT_SERVER) {
X    sptr->status = STAT_OPER;
X    sendto_serv_butone(cptr, ":%s OPER", sptr->nickname);
X    return(0);
X  }
X  if ((aconf = find_conf(cptr->sockhost, NULL, name, CONF_OPERATOR)) 
X      == (struct Confitem *) 0) {
X    sendto_one(sptr, "ERROR :Only few of mere mortals may try to %s",
X	       "enter twilight zone");
X    return(0);
X  } 
X  if (aconf->status == CONF_OPERATOR &&
X      strcmp(password, aconf->passwd) == 0) {
X    sendto_one(sptr, "MSG :Good afternoon, gentleman. %s",
X	       "I am a HAL 9000 computer.");
X    sptr->status = STAT_OPER;
X    sendto_serv_butone(cptr, ":%s OPER", sptr->nickname);
X  } else {
X    sendto_one(sptr, "ERROR :Only real wizards do know the %s",
X	       "spells to open the gates of paradise");
X    return(0);
X  }
X  return(0);
X}
X
X/***************************************************************************
X * m_pass() - Added Sat, 4 March 1989
X ***************************************************************************/
X
Xm_pass(cptr, sptr, sender, password)
Xstruct Client *cptr, *sptr;
Xchar *sender, *password;
X{
X  if ((password == NULL) || (*password == '\0')) {
X    sendto_one(cptr,"ERROR :No password is not good password");
X    return(0);
X  }
X  if (sptr != cptr || (cptr->status != STAT_UNKNOWN &&
X                       cptr->status != STAT_HANDSHAKE)) {
X    sendto_one(cptr,"ERROR :Trying to unlock the door twice, eh ?");
X    return(0);
X  }
X  strncpy(cptr->passwd, password, PASSWDLEN);
X  cptr->passwd[PASSWDLEN] = '\0';
X  return(0);
X}
X
Xm_wall(cptr, sptr, sender, message)
Xstruct Client *cptr, *sptr;
Xchar *sender, *message;
X{
X  if (sptr->status != STAT_OPER) {
X    sendto_one(sptr,"ERROR :Only real wizards know the correct spells to %s",
X	       "open this gate");
X    return(0);
X  }
X  if (sender && *sender) {
X    if (cptr == sptr)
X      sendto_all_butone(NULL, ":%s WALL :%s", sender, message);
X    else
X      sendto_all_butone(cptr, ":%s WALL :%s", sender, message);
X  }
X  else if (cptr == sptr)
X    sendto_all_butone(NULL, ":%s WALL :%s", sptr->nickname, message);
X  else
X    sendto_all_butone(cptr, ":%s WALL :%s", sptr->nickname, message);
X  return(0);
X}
X
X/**************************************************************************
X * time() - Command added 23 March 1989
X **************************************************************************/
X
Xm_time(cptr, sptr, sender, destination)
Xstruct Client *cptr, *sptr;
Xchar *sender, *destination;
X{
X  struct Client *acptr;
X  if (destination && *destination && strcmp(destination, myhostname)) {
X    if (acptr = find_server(destination,NULL)) {
X      sendto_one(acptr,":%s TIME %s", sptr->nickname, destination);
X      return(0);
X    } else {
X      sendto_one(sptr,"ERROR :No such host found");
X      return(-1);
X    }
X  } else {
X    sendto_one(sptr,"PRIVMSG %s :%s (%s)", sptr->nickname, date(), myhostname);
X    return(0);
X  }
X}
X
X/************************************************************************
X * m_rehash() - Added by Jto 20 Apr 1989
X ************************************************************************/
X
Xm_rehash(cptr, sptr)
Xstruct Client *cptr, *sptr;
X{
X  if (sptr->status != STAT_OPER) {
X    sendto_one(sptr,"ERROR :Use the force, Luke !");
X    return(-1);
X  }
X  sendto_one(sptr,"PRIVMSG %s :Rereading irc.conf -file...",sptr->nickname);
X  rehash();
X}
X
X/************************************************************************
X * m_names() - Added by Jto 27 Apr 1989
X ************************************************************************/
X
Xm_names(cptr, sptr, sender, para)
Xstruct Client *cptr, *sptr;
Xchar *para, *sender;
X{ 
X  struct Channel *chptr = channel;
X  struct Client *c2ptr;
X  int idx, flag;
X
X  while (chptr) {
X    if (para == NULL || *para == '\0' ||
X	chan_match(chptr, chan_conv(para))) {
X      if (!chan_isprivate(chptr) || chan_match(chptr, sptr->channel)) {
X	c2ptr = client;
X	if (chan_isprivate(chptr))
X	  sprintf(buf, "* %d ", chptr->channo);
X	else
X	  sprintf(buf, "= %d ", chptr->channo);
X	idx = strlen(buf);
X	flag = 0;
X	while (c2ptr) {
X	  if ((c2ptr->status == STAT_OPER || c2ptr->status == STAT_CLIENT) &&
X	      chan_match(chptr, c2ptr->channel)) {
X	    strncat(buf, c2ptr->nickname, NICKLEN);
X	    idx += strlen(c2ptr->nickname) + 1;
X	    flag = 1;
X	    strcat(buf," ");
X	    if (idx + NICKLEN > BUFSIZE - 2) {
X	      sendto_one(sptr, "NAMREPLY %s", buf);
X	      if (chan_isprivate(channel))
X		sprintf(buf, "* %d ", chptr->channo);
X	      else
X		sprintf(buf, "= %d ", chptr->channo);
X	      idx = strlen(buf);
X	      flag = 0;
X	    }
X	  }
X	  c2ptr = c2ptr->next;
X	}
X	if (flag)
X	  sendto_one(sptr, "NAMREPLY %s", buf);
X      }
X    }
X    chptr = chptr->nextch;
X  }
X
X  if (para != NULL && *para)
X    return(1);
X  strcpy(buf, "* * ");
X  idx = strlen(buf);
X  c2ptr = client;
X  flag = 0;
X  while (c2ptr) {
X    if ((c2ptr->status == STAT_OPER || c2ptr->status == STAT_CLIENT) &&
X	((c2ptr->channel > 999 && (sptr->channel != c2ptr->channel)) ||
X	c2ptr->channel == 0)) {
X      strncat(buf, c2ptr->nickname, NICKLEN);
X      idx += strlen(c2ptr->nickname) + 1;
X      strcat(buf," ");
X      flag = 1;
X      if (idx + NICKLEN > BUFSIZE - 2) {
X	sendto_one(sptr, "NAMREPLY %s", buf);
X	strcpy(buf, "* * ");
X	idx = strlen(buf);
X	flag = 0;
X      }
X    }
X    c2ptr = c2ptr->next;
X  }
X  if (flag)
X    sendto_one(sptr, "NAMREPLY %s", buf);
X  return(1);
X}
X
Xm_namreply(cptr, sptr, sender, para1, para2, para3, para4, para5, para6)
Xstruct Client *cptr, *sptr;
SHAR_EOF
echo "End of part 5"
echo "File s_msg.c is continued in part 6"
echo "6" > s2_seq_.tmp
exit 0

bleckmd@jacobs.cs.orst.edu (david bleckmann) (06/20/89)

---- Cut Here and unpack ----
#!/bin/sh
# this is part 6 of a multipart archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file s_msg.c continued
#
CurArch=6
if test ! -r s2_seq_.tmp
then echo "Please unpack part 1 first!"
     exit 1; fi
( read Scheck
  if test "$Scheck" != $CurArch
  then echo "Please unpack part $Scheck next!"
       exit 1;
  else exit 0; fi
) < s2_seq_.tmp || exit 1
echo "x - Continuing file s_msg.c"
sed 's/^X//' << 'SHAR_EOF' >> s_msg.c
Xchar *sender, *para1, *para2, *para3, *para4, *para5, *para6;
X{
X  m_error(cptr, sptr, sender, "Namreply", para1, para2, para3);
X}
X
Xm_linreply(cptr, sptr, sender, para1, para2, para3, para4, para5, para6)
Xstruct Client *cptr, *sptr;
Xchar *sender, *para1, *para2, *para3, *para4, *para5, *para6;
X{
X  m_error(cptr, sptr, sender, "Linreply", para1, para2, para3);
X}
X
Xm_admin(cptr, sptr, sender, para1)
Xstruct Client *cptr, *sptr;
Xchar *sender, *para1;
X{
X  struct Confitem *aconf;
X  struct Client *acptr;
X  if (para1 && *para1 && strcmp(para1, myhostname) &&
X      (acptr = find_server(para1, (struct Client *) 0))) {
X    sendto_one(acptr, ":%s ADMIN :%s", sptr->nickname, para1);
X    return(0);
X  }
X  if (aconf = find_admin()) {
X    sendto_one(sptr, "PRIVMSG %s :### Administrative info about %s",
X	       sptr->nickname, myhostname);
X    sendto_one(sptr, "PRIVMSG %s :### %s", sptr->nickname, aconf->host);
X    sendto_one(sptr, "PRIVMSG %s :### %s", sptr->nickname, aconf->passwd);
X    sendto_one(sptr, "PRIVMSG %s :### %s", sptr->nickname, aconf->name);
X  } else
X    sendto_one(sptr, 
X	    "PRIVMSG %s :### No administrative info available about server %s",
X	       sptr->nickname, myhostname);
X  return(0);
X}
X
Xm_trace(cptr, sptr, sender, para1)
Xstruct Client *cptr, *sptr;
Xchar *sender, *para1;
X{
X  struct Client *acptr;
X  if (sptr->status != STAT_OPER) {
X    sendto_one(sptr,
X       "PRIVMSG %s :*** Error: %s", sptr->nickname,
X	       "No mere mortals may trace the nets of the universe");
X    return(-1);
X  }
X  if (para1 && *para1 && strcmp(para1, myhostname) &&
X      (acptr = find_server(para1, (struct Client *) 0))) {
X    sendto_one(acptr, ":%s TRACE :%s", sptr->nickname, para1);
X    sendto_one(sptr, "PRIVMSG %s :*** Link %s ==> %s",
X	       sptr->nickname, myhostname, para1);
X    return(0);
X  }
X  acptr = client;
X  while (acptr) {
X    if (acptr->status == STAT_SERVER && acptr->fd >= 0)
X      sendto_one(sptr, "PRIVMSG %s :*** Connection %s ==> %s",
X		 sptr->nickname, myhostname, acptr->host);
X    acptr = acptr->next;
X  }
X  return(0);
X}
X
SHAR_EOF
echo "File s_msg.c is complete"
chmod 0600 s_msg.c || echo "restore of s_msg.c fails"
set `wc -c s_msg.c`;Sum=$1
if test "$Sum" != "36125"
then echo original size 36125, current size $Sum;fi
echo "x - extracting s_sysv.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > s_sysv.c &&
X/*************************************************************************
X ** s_sysv.c  Beta  v2.0    (22 Aug 1988)
X **
X ** This file is part of Internet Relay Chat v2.0
X **
X ** Author:           Jarkko Oikarinen 
X **         Internet: jto@tolsun.oulu.fi
X **             UUCP: ...!mcvax!tut!oulu!jto
X **           BITNET: toljto at finou
X **
X ** Copyright (c) 1988 University of Oulu, Computing Center
X **
X ** All rights reserved.
X **
X ** See file COPYRIGHT in this package for full copyright.
X ** 
X *************************************************************************/
X
Xchar s_sysv_id[]="s_sysv.c v2.0 (c) 1988 University of Oulu, Computing Center";
X
X#include <sys/time.h>
X#include <sys/types.h>
X#include <sys/file.h>
X#include <sys/ioctl.h>
X#include <sys/types.h>
X#include <sys/ipc.h>
X#include <sys/msg.h>
X#include <stdio.h>
X#include <signal.h>
X#include <fcntl.h>
X#include <utmp.h>
X#include "struct.h"
X
Xextern struct Client me;
Xextern struct Client *client;
X
Xdoalrm()
X{
X  return(0);
X}
X
Xint
Xopen_port(portnum)
Xint portnum;
X{
X  int key, length;
X  if ((me.fd = msgget((key_t)portnum, IPC_CREAT | 0622)) == -1)
X    perror("Getting SysV messageport");
X  return(me.fd);
X}
X
Xinit_sys()
X{
X  int fd;
X  setlinebuf(stdout);
X  setlinebuf(stderr);
X#ifdef NOTTY
X  close (0); close(1); close(2);
X  if (fork()) exit(0);
X  if (setpgrp(0,0) == -1)
X    perror("setpgrp");
X#endif
X}
X
Xread_msg(buffer, buflen, from)
Xchar *buffer;
Xint buflen;
Xstruct Client **from;
X{
X  static char buf[BUFSIZE], *ptr;
X  static struct msgbuf *ipcbuf = (struct msgbuf *) buf;
X  int length;
X  struct Client *cptr;
X  signal(SIGALRM, doalrm);
X  length = msgrcv(me.fd, ipcbuf, sizeof (buf), 0, 0);
X  if (length < 0)
X    return(-1);
X  else {
X    cptr = client;
X    while (cptr) {
X      if (cptr->fd == ipcbuf->mtype)
X	break;
X      cptr = cptr->next;
X    }
X    if (cptr == NULL) {
X      cptr = make_client();
X      strcpy(cptr->server, myhostname);
X      cptr->fd = ipcbuf->mtype;
X    }
X    *from = cptr;
X    length -= sizeof(ipcbuf->mtype);
X    buflen = length;
X    ptr = ipcbuf->mtext; 
X    for (; length; length--, ptr++, buffer++)
X      *buffer = *ptr;
X    return(length);
X  }
X}    
X  
X
Xconnect_server(host, port)
Xchar *host;
Xint port;
X{
X/*  struct sockaddr_in server;
X  struct hostent *hp;
X  struct Client *acptr;
X  struct Client *cptr = make_client();
X  int res;
X  cptr->fd = socket(AF_INET, SOCK_STREAM, 0);
X  if (cptr->fd < 0) {
X    perror("opening stream socket to server");
X    free(cptr);
X    return(-1);
X  }
X  server.sin_family = AF_INET;
X  hp = gethostbyname(host);
X  if (hp == 0) {
X    close(cptr->fd);
X    free(cptr);
X    debug(DEBUG_FATAL, "%s: unknown host", host);
X    return(-1);
X  }
X  bcopy(hp->h_addr, &server.sin_addr, hp->h_length);
X  server.sin_port = htons(port);
X
X  if (connect(cptr->fd, (struct sockaddr *) &server, sizeof(server)) < 0) {
X    close(cptr->fd);
X    free(cptr);
X    perror("connect");
X    return(-1);
X  }
X  strncpy(cptr->fromhost, host, HOSTLEN);
X  cptr->fromhost[HOSTLEN] = '\0';
X  strncpy(cptr->host, host, HOSTLEN);
X  cptr->host[HOSTLEN] = '\0';
X  cptr->status = STAT_UNKNOWN;
X  strncpy(me.server, host, HOSTLEN);
X  me.server[HOSTLEN] = '\0';
X  sendto_one(cptr, "SERVER %s",myhostname);
X  cptr->next = client;
X  client = cptr;
X  res = fcntl(cptr->fd, F_GETFL, 0);
X  fcntl(cptr->fd, F_SETFL, res | O_NDELAY); */
X}
X
Xint utmp_open()
X{
X  int fd;
X  return (open(UTMP,O_RDONLY));
X}
X
Xint utmp_read(fd, name, line, host)
Xint fd;
Xchar *name, *line, *host;
X{
X  struct utmp ut;
X  while (read(fd, &ut, sizeof (struct utmp)) == sizeof (struct utmp)) {
X    strncpy(name,ut.ut_name,8);  name[8] = '\0';
X    strncpy(line,ut.ut_line,8);  line[8] = '\0';
X    strncpy(host,(ut.ut_host[0]) ? (ut.ut_host) : myhostname, 16);
X    if (ut.ut_name[0])
X      return(0);
X  }
X  return(-1);
X}
X
Xint utmp_close(fd)
Xint fd;
X{
X  return(close(fd));
X}
X
Xsummon(who, namebuf, linebuf)
Xstruct Client *who;
Xchar *namebuf, *linebuf;
X{
X  int fd;
X  char line[120], *wrerr = "PRIVMSG %s :Write error. Couldn't summon.";
X  if (strlen(linebuf) > 8) {
X    sendto_one(who,"PRIVMSG %s :Serious fault in SUMMON.");
X    sendto_one(who,"PRIVMSG %s :linebuf too long. Inform Administrator");
X    return(-1);
X  }
X  /* Following line added to prevent cracking to e.g. /dev/kmem if */
X  /* UTMP is for some silly reason writable to everyone... */
X  if ((linebuf[0] != 't' || linebuf[1] != 't' || linebuf[2] != 'y') &&
X      (linebuf[0] != 'c' || linebuf[1] != 'o' || linebuf[2] != 'n')) {
X    sendto_one(who,"PRIVMSG %s :Looks like mere mortal souls are trying to");
X    sendto_one(who,"PRIVMSG %s :enter the twilight zone... ");
X    debug(0, "%s (%s@%s, nick %s, %s)",
X	  "FATAL: major security hack. Notify Administrator !",
X	  who->username, who->host, who->nickname, who->realname);
X    return(-1);
X  }
X  strcpy(line,"/dev/");
X  strcat(line,linebuf);
X  if ((fd = open(line, O_WRONLY)) == -1) {
X    sendto_one(who,"PRIVMSG %s :%s seems to have disabled summoning...");
X    return(-1);
X  }
X  strcpy(line,"\007\007ircd: *You* are being summoned to irc by\n");
X  if (write(fd, line, strlen(line)) != strlen(line)) {
X    sendto_one(who,wrerr,who->nickname);
X    return(-1);
X  }
X  sprintf(line, "ircd: Channel %d: %s@%s (%s) %s\n", who->channel,
X	  who->username, who->host, who->nickname, who->realname);
X  if (write(fd, line, strlen(line)) != strlen(line)) {
X    sendto_one(who,wrerr,who->nickname);
X    return(-1);
X  }
X  strcpy(line,"ircd: Respond with irc\n");
X  if (write(fd, line, strlen(line)) != strlen(line)) {
X    sendto_one(who,wrerr,who->nickname);
X    return(-1);
X  }
X  sendto_one(who, "PRIVMSG %s :%s: Summoning user %s to irc",
X	     who->nickname, myhostname, namebuf);
X  return(0);
X}
X  
SHAR_EOF
chmod 0600 s_sysv.c || echo "restore of s_sysv.c fails"
set `wc -c s_sysv.c`;Sum=$1
if test "$Sum" != "5649"
then echo original size 5649, current size $Sum;fi
echo "x - extracting screen.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > screen.c &&
X/*************************************************************************
X ** screen.c  Beta  v2.0    (22 Aug 1988)
X **
X ** This file is part of Internet Relay Chat v2.0
X **
X ** Author:           Jarkko Oikarinen 
X **         Internet: jto@tolsun.oulu.fi
X **             UUCP: ...!mcvax!tut!oulu!jto
X **           BITNET: toljto at finou
X **
X ** Copyright (c) 1988 University of Oulu, Computing Center
X **
X ** All rights reserved.
X **
X ** See file COPYRIGHT in this package for full copyright.
X ** 
X *************************************************************************/
X
Xchar screen_id[] = "screen.c v2.0 (c) 1988 University of Oulu, Computing Center";
X
X#include <stdio.h>
X#include <curses.h>
X
X#ifdef TRUE
X#undef TRUE
X#endif
X#define FALSE (0)
X#define TRUE  (!FALSE)
X#ifdef BUFSIZ
X#undef BUFSIZ
X#endif
X#define BUFSIZ 240
X
X#define FROM_START 0
X#define FROM_END   1
X#define RELATIVE   2
X
X#define HIST_SIZ 1000
X
Xstatic char last_line[BUFSIZ+1];
Xstatic char yank_buffer[BUFSIZ+1];
Xstatic char history[HIST_SIZ][BUFSIZ+1];
Xstatic int position=0;
Xstatic int pos_in_history=0;
Xstatic insert=0;
X
Xget_char(pos)
Xint pos;
X{
X    if (pos>=BUFSIZ || pos<0)
X	return 0;
X    return (int)last_line[pos];
X}
X
Xset_char(pos, ch)
Xint pos, ch;
X{
X    if (pos<0 || pos>=BUFSIZ)
X	return;
X    if (ch<0)
X	ch=0;
X    last_line[pos]=(char)ch;
X}
X
Xget_yank_char(pos)
Xint pos;
X{
X    if (pos>=BUFSIZ || pos<0)
X	return 0;
X    return (int)yank_buffer[pos];
X}
X
Xset_yank_char(pos, ch)
Xint pos, ch;
X{
X    if (pos<0 || pos>=BUFSIZ)
X	return;
X    if (ch<0)
X	ch=0;
X    yank_buffer[pos]=(char)ch;
X}
X
Xset_position(disp, from)
Xint disp, from;
X{
X    int i1;
X
X    switch (from) {
X    case FROM_START:
X	position=disp;
X	break;
X    case RELATIVE:
X	position+=disp;
X	break;
X    case FROM_END:
X	for (i1=0; get_char(i1); i1++);
X	position=i1-1;
X	break;
X    default:
X	position=0;
X	break;
X    }
X}
X
Xget_position()
X{
X    return position;
X}
X
Xtoggle_ins()
X{
X    insert = ~insert;
X    standout();
X    if (insert)
X	mvaddstr(LINES-2, 75, "INS");
X    else
X	mvaddstr(LINES-2, 75, "OWR");
X    standend();
X}
X
Xin_insert_mode()
X{
X    return insert;
X}
X
Xsend_this_line(sock)
X{
X    record_line();
X    sendit(sock, last_line);
X    clear_last_line();
X    bol();
X    tulosta_viimeinen_rivi();
X    refresh();
X}
X
Xrecord_line()
X{
X    static int place=0;
X    int i1;
X
X    for(i1=0; i1<BUFSIZ; i1++)
X	history[place][i1]=get_char(i1);
X    place++;
X    if (place==HIST_SIZ)
X	place=0;
X    pos_in_history=place;
X}
X    
Xclear_last_line()
X{
X    int i1;
X
X    for(i1=0; i1<BUFSIZ; i1++)
X	set_char(i1,(int)'\0');
X}
X
Xkill_eol()
X{
X    int i1, i2, i3;
X
X    i1=get_position();
X    set_position(0, FROM_END);
X    i2=get_position();
X    for(i3=0; i3<BUFSIZ; i3++)
X	set_yank_char(i3,(int)'\0');
X    for(i3=0; i3<=(i2-i1); i3++) {
X	set_yank_char(i3,get_char(i1+i3));
X	set_char(i1+i3, 0);
X    }
X    set_position(i1, FROM_START);
X}
X
Xnext_in_history()
X{
X    int i1=0;
X
X    pos_in_history++;
X    if (pos_in_history==HIST_SIZ)
X	pos_in_history=0;
X    clear_last_line();
X    while (history[pos_in_history][i1]) {
X	set_char(i1, history[pos_in_history][i1]);
X	i1++;
X    }
X    set_position(0, FROM_START);
X}
X
Xprevious_in_history()
X{
X    int i1=0;
X
X    pos_in_history--;
X    if (pos_in_history<0)
X	pos_in_history=HIST_SIZ-1;
X    clear_last_line();
X    while (history[pos_in_history][i1]) {
X	set_char(i1, history[pos_in_history][i1]);
X	i1++;
X    }
X    set_position(0, FROM_START);
X}
X
Xkill_whole_line()
X{
X    clear_last_line();
X    set_position(0, FROM_START);
X}
X
Xyank()
X{
X    int i1, i2, i3;
X    
X    i1=get_position();
X    i2=0;
X    while (get_yank_char(i2))
X	i2++;
X    
X    for(i3=BUFSIZ-1; i3>=i1+i2; i3--)
X	set_char(i3, get_char(i3-i2));
X    for(i3=0; i3<i2; i3++)
X	set_char(i1+i3, get_yank_char(i3));
X}
X
Xtulosta_viimeinen_rivi()
X{
X    static int paikka=0;
X    int i1, i2, i3;
X
X    i1=get_position();
X    /* taytyyko siirtaa puskuria */
X    if (i1<(get_disp(paikka)+10) && paikka) {
X	paikka--;
X	i2=get_disp(paikka);
X    } else if (i1>(get_disp(paikka)+70)) {
X	paikka++;
X	i2=get_disp(paikka);
X    } else {
X	i2=get_disp(paikka);
X    }
X
X    move(LINES-1,0);
X    for(i3=0; i3<78; i3++)
X        if (get_char(i2+i3))
X	    mvaddch(LINES-1, i3, get_char(i2+i3));
X    clrtoeol();
X    move(LINES-1, i1-get_disp(paikka));
X    refresh();
X    return (i1-get_disp(paikka));
X}
X
Xget_disp(paikka)
Xint paikka;
X{
X    static int place[]={0,55,110,165,220};
X
X    if (paikka>4 || paikka<0)
X	return 0;
X    return place[paikka];
X}
SHAR_EOF
chmod 0600 screen.c || echo "restore of screen.c fails"
set `wc -c screen.c`;Sum=$1
if test "$Sum" != "4403"
then echo original size 4403, current size $Sum;fi
echo "x - extracting send.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > send.c &&
X/*************************************************************************
X ** send.c  Beta  v2.0    (22 Aug 1988)
X **
X ** This file is part of Internet Relay Chat v2.0
X **
X ** Author:           Jarkko Oikarinen 
X **         Internet: jto@tolsun.oulu.fi
X **             UUCP: ...!mcvax!tut!oulu!jto
X **           BITNET: toljto at finou
X **
X ** Copyright (c) 1988 University of Oulu, Computing Center
X **
X ** All rights reserved.
X **
X ** See file COPYRIGHT in this package for full copyright.
X ** 
X *************************************************************************/
X
Xchar send_id[] = "send.c v2.0 (c) 1988 University of Oulu, Computing Center";
X
X#include "struct.h"
X
X#define NULL ((char *) 0)
X
Xchar sendbuf[1024];
X
Xextern struct Client *client;
Xextern struct Client *find_server();
X
Xsendto_one(to, pattern, para1, para2, para3, para4, para5, para6, para7, para8)
Xstruct Client *to;
Xchar *pattern, *para1, *para2, *para3, *para4, *para5, *para6, *para7, *para8;
X{
X  struct Client *cptr;
X  sprintf(sendbuf, pattern, para1, para2, para3, para4, para5, para6, para7,
X	  para8);
X  if (to->status != STAT_ME)
X    debug(DEBUG_NOTICE,"%s", sendbuf);
X  if (to->fd < 0) {
X    if (to->fromhost[0] == '\0' && to->status != STAT_ME) {
X      debug(DEBUG_ERROR,"Client %s with negative fd and no fromhost... AARGH!",
X	    to->nickname);
X      if (to->fd != -20) m_bye(to, to);
X    } else if (to->status != STAT_ME){
X      if ((cptr = find_server(to->fromhost, NULL)) == (struct Client *) 0)
X	return(-1);
X      if (deliver_it(cptr->fd, sendbuf, strlen(sendbuf)) == -1)
X/*	m_bye(cptr, cptr); */ ;
X      else if (deliver_it(cptr->fd, "\n", 1) == -1)
X/*	m_bye(cptr, cptr); */ ;
X    }
X  } else {
X    if (deliver_it(to->fd, sendbuf, strlen(sendbuf)) == -1)
X/*      m_bye(cptr, cptr); */ ;
X    else if (deliver_it(to->fd, "\n", 1) == -1)
X/*      m_bye(cptr, cptr); */ ;
X  }
X}
X
Xsendto_channel_butone(one, channel, pattern,
X		      para1, para2, para3, para4, para5, para6, para7, para8)
Xstruct Client *one;
Xchar *pattern, *para1, *para2, *para3, *para4, *para5, *para6, *para7, *para8;
Xint channel;
X{
X  struct Client *cptr=client, *acptr;
X  sprintf(sendbuf, pattern, para1, para2, para3, para4, para5, para6, para7,
X	  para8);
X  debug(DEBUG_NOTICE,"%s", sendbuf);
X  while (cptr) {
X    if (cptr != one && cptr->fd >= 0 && 
X	(cptr->status == STAT_SERVER || 
X	 (cptr->channel == channel && 
X	  (cptr->status == STAT_OPER || cptr->status == STAT_CLIENT)))) {
X      acptr = client;
X      if (cptr->status == STAT_SERVER) {
X	while (acptr) {
X	  if (acptr->channel == channel && 
X	      (acptr->status == STAT_CLIENT || acptr->status == STAT_OPER) &&
X	      strcmp(acptr->fromhost, cptr->host) == 0 && cptr->host[0])
X	    break;
X	  acptr = acptr->next;
X	}
X      }
X      if (acptr) {
X	if (deliver_it(cptr->fd, sendbuf, strlen(sendbuf)) == -1)
X/*	  m_bye(cptr, cptr); */ ;
X	else if (deliver_it(cptr->fd, "\n", 1) == -1)
X/*	  m_bye(cptr, cptr); */ ;
X      }
X    }
X    cptr = cptr->next;
X  }
X}
X
Xsendto_serv_butone(one, pattern, para1, para2, para3, para4, para5, para6,
X		   para7, para8)
Xstruct Client *one;
Xchar *pattern, *para1, *para2, *para3, *para4, *para5, *para6, *para7, *para8;
X{
X  struct Client *cptr = client;
X  sprintf(sendbuf, pattern, para1, para2, para3, para4, para5, para6, para7,
X	  para8);
X  debug(DEBUG_NOTICE,"%s", sendbuf);
X  while(cptr) {
X    if (cptr->status == STAT_SERVER && cptr != one && cptr->fd >= 0) {
X      if (deliver_it(cptr->fd, sendbuf, strlen(sendbuf)) == -1)
X/*	m_bye(cptr, cptr); */ ;
X      else if (deliver_it(cptr->fd, "\n", 1) == -1)
X/* 	m_bye(cptr, cptr); */ ;
X    }
X    cptr = cptr->next;
X  }
X}
X
Xsendto_channel_butserv(channel, pattern,
X		       para1, para2, para3, para4, para5, para6, para7, para8)
Xint channel;
Xchar *pattern, *para1, *para2, *para3, *para4, *para5, *para6, *para7, *para8;
X{
X  struct Client *cptr = client;
X  sprintf(sendbuf, pattern, para1, para2, para3, para4, para5, para6, para7,
X	  para8);
X  debug(DEBUG_NOTICE,"%s", sendbuf);
X  while(cptr) {
X    if (cptr->status != STAT_SERVER && cptr->fd >= 0 &&
X	(cptr->channel == channel || channel == 0)) {
X      if (deliver_it(cptr->fd, sendbuf, strlen(sendbuf)) == -1)
X/*	m_bye(cptr, cptr); */ ;
X      else if (deliver_it(cptr->fd, "\n", 1) == -1)
X/*	m_bye(cptr, cptr); */ ;
X    }
X    cptr = cptr->next;
X  }
X}
Xsendto_all_butone(one, pattern, para1, para2, para3, para4, para5,
X                  para6, para7, para8)
Xstruct Client *one;
Xchar *pattern, *para1, *para2, *para3, *para4, *para5, *para6, *para7, *para8;
X{
X  struct Client *cptr = client;
X  sprintf(sendbuf, pattern, para1, para2, para3, para4, para5, para6, para7,
X	  para8);
X  debug(DEBUG_NOTICE,"%s", sendbuf);
X  while(cptr) {
X    if (one != cptr) {
X      if (deliver_it(cptr->fd, sendbuf, strlen(sendbuf)) == -1)
X        /*	m_bye(cptr, cptr); */ ;
X      else if (deliver_it(cptr->fd, "\n", 1) == -1)
X        /*	m_bye(cptr, cptr); */ ;
X    }
X    cptr = cptr->next;
X  }
X}
X
SHAR_EOF
chmod 0600 send.c || echo "restore of send.c fails"
set `wc -c send.c`;Sum=$1
if test "$Sum" != "4920"
then echo original size 4920, current size $Sum;fi
echo "x - extracting sock.h (Text)"
sed 's/^X//' << 'SHAR_EOF' > sock.h &&
X/*************************************************************************
X ** sock.h  Beta  v2.0    (22 Aug 1988)
X **
X ** This file is part of Internet Relay Chat v2.0
X **
X ** Author:           Jarkko Oikarinen 
X **         Internet: jto@tolsun.oulu.fi
X **             UUCP: ...!mcvax!tut!oulu!jto
X **           BITNET: toljto at finou
X **
X ** Copyright (c) 1988 University of Oulu, Computing Center
X **
X ** All rights reserved.
X **
X ** See file COPYRIGHT in this package for full copyright.
X ** 
X *************************************************************************/
X
Xchar sockh_id[] = "sock.h v2.0 (c) 1988 University of Oulu, Computing Center";
X
X#define FD_ZERO(set)      (((set)->fds_bits[0]) = 0)
X#define FD_SET(s1, set)   (((set)->fds_bits[0]) |= 1 << (s1))
X#define FD_ISSET(s1, set) (((set)->fds_bits[0]) & (1 << (s1)))
X#define FD_SETSIZE        30
SHAR_EOF
chmod 0600 sock.h || echo "restore of sock.h fails"
set `wc -c sock.h`;Sum=$1
if test "$Sum" != "862"
then echo original size 862, current size $Sum;fi
echo "x - extracting str.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > str.c &&
X/*************************************************************************
X ** str.c  Beta  v2.0    (22 Aug 1988)
X **
X ** This file is part of Internet Relay Chat v2.0
X **
X ** Author:           Jarkko Oikarinen 
X **         Internet: jto@tolsun.oulu.fi
X **             UUCP: ...!mcvax!tut!oulu!jto
X **           BITNET: toljto at finou
X **
X ** Copyright (c) 1988 University of Oulu, Computing Center
X **
X ** All rights reserved.
X **
X ** See file COPYRIGHT in this package for full copyright.
X ** 
X *************************************************************************/
X
Xchar str_id[] = "str.c v2.0 (c) 1988 University of Oulu, Computing Center";
X
X#include "struct.h"
X#include "sys.h"
X
Xchar *
Xcenter(buf,str,len)
Xchar *buf, *str;
Xint len;
X{
X  char i,j,k;
X  if ((i = strlen(str)) > len) {
X    buf[len-1] = '\0';
X    for(len--; len > 0; len--) buf[len-1] = str[len-1];
X    return(buf);
X  }
X  j = (len-i)/2;
X  for (k=0; k<j; k++) buf[k] = ' ';
X  buf[k] = '\0';
X  strcat(buf,str);
X  for (k=j+i; k<len; k++) buf[k] = ' ';
X  buf[len] = '\0';
X  return (buf);
X}
X
X/* William Wisner <wisner@b.cc.umich.edu>, 16 March 1989 */
Xchar *
Xreal_name(user)
X     struct passwd *user;
X{
X  char *bp, *cp;
X  static char name[REALLEN+1];
X
X  bp = user->pw_gecos;
X  cp = name;
X
X  name[REALLEN] = '\0';
X  do {
X    switch(*bp) {
X    case '&':
X      *cp = '\0';
X      strncat(name, user->pw_name, REALLEN-strlen(name));
X      name[REALLEN] = '\0';
X      if (islower(*cp))
X	*cp = toupper(*cp);
X      cp = index(name, '\0');
X      bp++;
X      break;
X    case ',':
X      *bp = *cp = '\0';
X      break;
X    case '\0':
X      *cp = *bp;
X      break;
X    default:
X      *cp++ = *bp++;
X    }
X  } while (*bp != '\0' && strlen(name) < REALLEN);
X  return(name);
X}
X
SHAR_EOF
chmod 0600 str.c || echo "restore of str.c fails"
set `wc -c str.c`;Sum=$1
if test "$Sum" != "1728"
then echo original size 1728, current size $Sum;fi
echo "x - extracting struct.h (Text)"
sed 's/^X//' << 'SHAR_EOF' > struct.h &&
X/*************************************************************************
X ** struct.h  Beta  v2.0    (22 Aug 1988)
X **
X ** This file is part of Internet Relay Chat v2.0
X **
X ** Author:           Jarkko Oikarinen 
X **         Internet: jto@tolsun.oulu.fi
X **             UUCP: ...!mcvax!tut!oulu!jto
X **           BITNET: toljto at finou
X **
X ** Copyright (c) 1988 University of Oulu, Computing Center
X **
X ** All rights reserved.
X **
X ** See file COPYRIGHT in this package for full copyright.
X ** 
X *************************************************************************/
X
X/* Type of host... currently only BSD and similar are supported */
X#define BSD42      1          /* Tested on SUN OS 3.4 */
X#define BSD43      0          /* I've heard this works... never have had
X                                 chance to test it by myself... :-) */
X#define HPUX       0          /* HP-UX */
X#define ULTRIX     0          /* Vax Ultrix. */
X#define APOLLO      0         /* Apollo Domain IX. Currently dumps core :-( */
X#define SYSV        0         /* Does not work yet. Under construction */
X
X#define DOMAINNAME  1         /* Define this if your system has   */
X                              /* getdomainname() -call */
X
X/* define NOTTY if you want to run ircd as a daemon. */
X/* (That's the normal way to run it)                 */
X#define NOTTY    1                             /* */  
X
X/* Full path name of the server executable */
X#define MYNAME     "/usr/users/jto/cta/bbs/ircd"
X
X/* Configurationfile seems to work... */
X#define CONFIGFILE "/usr/users/jto/cta/bbs/irc/irc.conf"
X
X/* Port where ircd resides. NOTE: This *MUST* be greater than 1024, */
X/* if you plan to run ircd under any other uid than root. Command line */
X/* parameter port DOES NOT  affect this port, but only the port, where ircd */
X/* tries to connect, ie. the port another server uses, not the one this uses */
X#define PORTNUM 6667
X
X/* Logfile is not in use unless you specifically say sop when starting  */
X/* ircd. It might take lots of disk space so I recommend using logfile  */
X/* only when you need it for debugging purposes                         */
X#define LOGFILE "/usr/users/jto/cta/bbs/irc/loki"
X
X#define TIMESEC  60           /* Time interval to wait and if no        */
X                              /* messages has been received, check      */
X                              /* for PINGFREQUENCY and CONNECTFREQUENCY */
X
X#define PINGFREQUENCY    120  /* If daemon doesn't receive anything */
X                              /* from some daemon/client within     */
X                              /* PINGFREQUENCY seconds, it tries to */
X                              /* wake it up with PING message       */
X                              /* If no reply is received within     */
X                              /* 2 * PINGFREQUENCY seconds,         */
X                              /* connection will be closed          */
X
X#define CONNECTFREQUENCY 1200 /* if connection to to uphost is down,  */
X                              /* try to reconnect about every         */
X                              /* CONNECTFREQUENCY  seconds            */
X
X#define MAXUSERSPERCHANNEL 10 /* 10 is currently recommended. If this is */
X                              /* zero or negative, no restrictions exist */
X                              /* If you are connected to other ircds, do */
X                              /* NOT change this from default without    */
X                              /* asking from other irc administrators    */
X                              /* first !                                 */
X
X#define WRITEWAITDELAY     15  /* Number of seconds to wait for write     */
X                              /* to complete if stuck...                 */
X
X/* You probably shouldn't touch constants after this line... */
X
X#define HOSTLEN   50  /* Length of hostname... this should be changed */
X                      /* longer due to domain system... */
X#define NICKLEN   10
X#define USERLEN   10
X#define REALLEN   30
X#define HEADERLEN 200
X#define PASSWDLEN 20
X
X#define CHANNELLEN 50
X#define BUFSIZE  256 
X#define MAXBUFLEN 512
X
X#define STAT_HANDSHAKE -3
X#define STAT_ME        -2
X#define STAT_UNKNOWN   -1
X#define STAT_SERVER     0
X#define STAT_CLIENT     1
X#define STAT_LOG        2
X#define STAT_SERVICE    3      /* Services not implemented yet */
X#define STAT_OPER       4      /* Operator */
X
X#define CONF_ILLEGAL          0
X#define CONF_SKIPME           1
X#define CONF_CLIENT           2
X#define CONF_CONNECT_SERVER   4
X#define CONF_NOCONNECT_SERVER 8
X#define CONF_UPHOST           16
X#define CONF_OPERATOR         32
X#define CONF_ME               64
X#define CONF_KILL             128
X#define CONF_ADMIN            256
X
X#define DEBUG_FATAL  0
X#define DEBUG_ERROR  1
X#define DEBUG_NOTICE 2
X#define DEBUG_DEBUG  3
X
X#define IGNORE_TOTAL    3
X#define IGNORE_PRIVATE  1
X#define IGNORE_PUBLIC   2
X
X#define FLAGS_PINGSENT 1
X
X#define FLUSH_BUFFER   -2
X#define MAXFD        32
X#define UTMP         "/etc/utmp"
X
Xstruct Client {
X  struct Client *next;
X  char host[HOSTLEN+1];
X  char nickname[NICKLEN+1];
X  char username[USERLEN+1];
X  char realname[REALLEN+1];
X  char server[HOSTLEN+1];
X  char fromhost[HOSTLEN+1];
X  char buffer[MAXBUFLEN+1];
X  char sockhost[HOSTLEN+1];
X  char passwd[PASSWDLEN+1];
X  char *away;
X  short status;
X  int fd;
X  int channel;
X  long lasttime;
X  short flags;
X};
X
Xstruct Ignore {
X  char user[NICKLEN+1];
X  int flags;
X  struct Ignore *next;
X};
X
Xstruct Channel {
X  struct Channel *nextch;
X  int channo;
X  char name[CHANNELLEN+1];
X  int users;
X};
X
Xstruct Confitem {
X  int status;
X  char host[HOSTLEN+1];
X  char passwd[PASSWDLEN+1];
X  char name[HOSTLEN+1];
X  int port;
X  struct Confitem *next;
X};
X
X#ifdef MAIN
Xchar *intro = "Internet Relay Chat v%s";
Xchar *version = "2.01.6";
Xchar *info1 = "Programmed by Jarkko Oikarinen";
Xchar *info2 = "(c)  1988,1989   University of Oulu,   Computing Center";
Xchar *info3 = "INTERNET: jto@tolsun.oulu.fi    BITNET: toljto at finou";
Xchar myhostname[HOSTLEN+1];
Xchar *HEADER = 
X" *** Internet Relay Chat *** Type /help to get help *** Client v%s ***      ";
Xchar *welcome1 = "Welcome to Internet Relay Server v";
X#else
Xextern char *version, *info1, *info2, *info3; 
Xextern char myhostname[], *HEADER, *welcome1;
Xextern char *intro;
X#endif
X
Xextern struct Client *make_client();
Xextern long getlongtime();
SHAR_EOF
chmod 0600 struct.h || echo "restore of struct.h fails"
set `wc -c struct.h`;Sum=$1
if test "$Sum" != "6336"
then echo original size 6336, current size $Sum;fi
echo "x - extracting swear.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > swear.c &&
X/*************************************************************************
X ** swear.c  Beta v2.0    (1 Apr 1989)
X **
X ** This file is part of Internet Relay Chat v2.0
X **
X ** Author:           Jarkko Oikarinen
X **         Internet: jto@tolsun.oulu.fi
X **             UUCP: ...!mcvax!tut!oulu!jto
X **           BITNET: toljto at finou
X **
X ** Copyright (c) 1988 University of Oulu, Computing Center
X **
X ** All rights reserved.
X **
X ** See file COPYRIGHT in this package for full copyright.
X **
X *************************************************************************/
X
Xchar swear_id[]="swear.c v2.0 (c) 1988 University of Oulu, Computing Center";
X
X/* Curses replacement routines. Uses termcap */
X
X#include <sys/ioctl.h>
X#include <stdio.h>
X#include <sys/file.h>
X#include <ctype.h>
X#include <strings.h>
X#include "struct.h"
X
X#define LLEN 60
X
Xstatic struct sgttyb oldtty, newtty;
Xstatic char termcapentry[1024];
Xstatic char codes[1024], *cls;
Xstatic char *tgoto();
Xstatic int currow = 0;
Xint lines, columns, scroll = 0;
Xextern int insert;
X
Xmove(row, col)
Xint row, col;
X{
X  cls = codes;
X  tgetstr("cm",&cls);
X  cls = tgoto(codes, col, row);
X  printf("%s",cls);
X  fflush(stdout);
X}
X
Xclear_to_eol(row, col)
Xint row, col;
X{
X  move(row, col);
X  cls = codes;
X  tgetstr("ce", &cls);
X  printf("%s",codes);
X  fflush(stdout);
X}
X
Xclearscreen()
X{
X  cls = codes;
X  tgetstr("cl",&cls);
X  printf("%s",codes);
X  fflush(stdout);
X  currow = 0;
X}
X  
Xint
Xio_on(flag)
Xint flag;
X{
X  if (ioctl(0, TIOCGETP, &oldtty) < 0)
X    return(-1);
X  newtty = oldtty;
X  newtty.sg_flags &= ~ECHO;
X  newtty.sg_flags |= CBREAK;
X  ioctl(0, TIOCSETP, &newtty);
X  tgetent(termcapentry,"screen");
X  lines = tgetnum("li");
X  columns = tgetnum("co");
X  return(0);
X}
X
Xint
Xio_off()
X{
X  if (scroll)
X    scroll_off();
X  if (ioctl(0, TIOCSETP, &oldtty) < 0)
X    return(-1);
X  return(0);
X}
X
Xscroll_off()
X{
X  cls = codes;
X  tgetstr("cs",&cls);
X  cls = tgoto(codes, lines-1, 0);
X  printf("%s",cls); 
X  scroll = 0;
X}
X
Xscroll_on()
X{
X  cls = codes;
X  tgetstr("cm",&cls);
X  cls = tgoto(codes, 0, 0);
X  printf("%s",cls);
X  cls = codes;
X  tgetstr("cs",&cls);
X  cls = tgoto(codes, lines-3, 0);
X  printf("%s",cls);
X  fflush(stdout);
X  scroll = 1;
X}
X
Xput_insflag(flag)
Xint flag;
X{
X  flag = insert;
X  move(lines - 2, columns - 5);
X    cls = codes;
X    tgetstr("mr",&cls);
X    printf("%s",codes);
X  printf((flag) ? "INS" : "OWR");
X    cls = codes;
X    tgetstr("me",&cls);
X    printf("%s",codes);
X  fflush(stdout);
X}
X  
Xput_statusline()
X{
X  move (lines - 2, 0);
X    cls = codes;
X    tgetstr("mr",&cls);
X    printf("%s",codes);
X  printf(HEADER, version);
X    cls = codes;
X    tgetstr("me",&cls);
X    printf("%s",codes);
X  fflush(stdout);
X}
X
Xputline(line)
Xchar *line;
X{
X  char *ptr = line, *ptr2 = NULL, *newl;
X  char ch='\0';
X  while (ptr) {
X    if (strlen(ptr) > columns-1) {
X      ch = ptr[columns-1];
X      ptr[columns-1] = '\0';
X      ptr2 = &ptr[columns-2];
X    } 
X    else
X      ptr2 = NULL;
X    if (scroll) {
X      move(lines-3, 0);
X    } else {
X      move(currow++,0);
X      if (currow > lines - 4) currow = 0;
X    }
X    while (newl = index(ptr,'\n'))
X      *newl = '\0';
X    printf("%s",ptr);
X    if (scroll) 
X      printf("\n",ptr); 
X    else {
X      if (currow == 0) {
X	clear_to_eol(1,0);
X	clear_to_eol(2,0);
X      }
X      else if (currow == lines - 4) {
X	clear_to_eol(lines-4,0);
X	clear_to_eol(0,0);
X      }
X      else {
X	clear_to_eol(currow+1,0);
X	clear_to_eol(currow+2,0);
X      }
X    }
X    ptr = ptr2;
X    if (ptr2) {
X      *ptr2++ = '+';
X      *ptr2 = ch;
X    }
X  }
X  fflush(stdout);
X}
X
X/*
Xmain()
X{
X  int i;
X  io_on();
X  scroll_on(); 
X  put_statusline();
X  put_insflag(0);
X  for (i=0; i<40; i++) {
X    if (i == 15) {
X      sprintf(kissa,"test #%d v{h{n lis{{ ja %s", i,
X	      "jonkinlainen apustringi, ett{ saadaan pitk{{{{{{{{ rivi");
X    }
X    else
X      sprintf(kissa,"test #%d", i);
X    putline(kissa);
X    if (i == 15)
X      sleep(5);
X  }
X  getchar();
X  io_off();
X}
X*/
SHAR_EOF
chmod 0600 swear.c || echo "restore of swear.c fails"
set `wc -c swear.c`;Sum=$1
if test "$Sum" != "3925"
then echo original size 3925, current size $Sum;fi
echo "x - extracting sys.h (Text)"
sed 's/^X//' << 'SHAR_EOF' > sys.h &&
X/*************************************************************************
X ** bsd.h  Beta  v2.0    (22 Aug 1988)
X **
X ** This file is part of Internet Relay Chat v2.0
X **
X ** Author:           Jarkko Oikarinen 
X **         Internet: jto@tolsun.oulu.fi
X **             UUCP: ...!mcvax!tut!oulu!jto
X **           BITNET: toljto at finou
X **
X ** Copyright (c) 1988 University of Oulu, Computing Center
X **
X ** All rights reserved.
X **
X ** See file COPYRIGHT in this package for full copyright.
X ** 
X *************************************************************************/
X
X#if HPUX
X#include <string.h>
X#define index         strchr
X#define rindex        strrchr
X#define bcopy(a,b,s)  memcpy(b,a,s)
X#define bzero(a,s)    memset(a,0,s)
Xextern char *strchr(), *strrchr();
Xextern char *inet_ntoa();
X#else 
X#include <strings.h>
X#endif
X#include <ctype.h>
X#include <pwd.h>
SHAR_EOF
chmod 0600 sys.h || echo "restore of sys.h fails"
set `wc -c sys.h`;Sum=$1
if test "$Sum" != "866"
then echo original size 866, current size $Sum;fi
echo "x - extracting sysv.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > sysv.c &&
X/*************************************************************************
X ** bsd.c  Beta  v2.0    (22 Aug 1988)
X **
X ** This file is part of Internet Relay Chat v2.0
X **
X ** Author:           Jarkko Oikarinen 
X **         Internet: jto@tolsun.oulu.fi
X **             UUCP: ...!mcvax!tut!oulu!jto
X **           BITNET: toljto at finou
X **
X ** Copyright (c) 1988 University of Oulu, Computing Center
X **
X ** All rights reserved.
X **
X ** See file COPYRIGHT in this package for full copyright.
X ** 
X *************************************************************************/
X
Xchar bsd_id[] = "bsd.c v2.0 (c) 1988 University of Oulu, Computing Center";
X
Xdeliver_it(fd, str, len)
Xint fd, len;
Xchar *str;
X{
X  return (write(fd, str, len));
X}
X
SHAR_EOF
chmod 0600 sysv.c || echo "restore of sysv.c fails"
set `wc -c sysv.c`;Sum=$1
if test "$Sum" != "737"
then echo original size 737, current size $Sum;fi
echo "x - extracting sysv.h (Text)"
sed 's/^X//' << 'SHAR_EOF' > sysv.h &&
X/*************************************************************************
X ** bsd.h  Beta  v2.0    (22 Aug 1988)
X **
X ** This file is part of Internet Relay Chat v2.0
X **
X ** Author:           Jarkko Oikarinen 
X **         Internet: jto@tolsun.oulu.fi
X **             UUCP: ...!mcvax!tut!oulu!jto
X **           BITNET: toljto at finou
X **
X ** Copyright (c) 1988 University of Oulu, Computing Center
X **
X ** All rights reserved.
X **
X ** See file COPYRIGHT in this package for full copyright.
X ** 
X *************************************************************************/
X
X#include <strings.h>
SHAR_EOF
chmod 0600 sysv.h || echo "restore of sysv.h fails"
set `wc -c sysv.h`;Sum=$1
if test "$Sum" != "595"
then echo original size 595, current size $Sum;fi
rm -f s2_seq_.tmp
echo "You have unpacked the last part"
exit 0