[comp.sources.misc] talk

forys@boulder.Colorado.EDU (Jeff Forys) (08/11/87)

What follows is a set of patches that will enhance `talk' as
distributed with 4.3BSD.  No functionality is lost if these patches
are applied (i.e. it is still compatible with other machines who
run stock 4.3BSD talk).  Here is a summary of what the patches do:

	1) Fix a bug in 4.3BSD talk which results in bogus error
	   messages being displayed under various circumstances.
	   I posted this fix back in November, everyone should
	   apply it, hence it is separate from the `enhancements'.

	2) Makes the 4.3BSD version of talk portable to the following
	   flavours of Unix: Pyramid (OSx2.5,OSx3.1,OSx4.0), Ultrix (1.2),
	   Sun (3.0,3.1,3.2).  This is nice, since few of these speak the
	   4.3BSD talk protocol; it'll probably port to 4.2BSD with OSx2.5.

	3) Allow for special control codes to be expanded locally.
	   (e.g. ^A maps into "<go ahead>", ^N displays a menu, etc)
	   While it is possible to send the *mappings* out to people
	   not running these enhancements, doing it `right' requires
	   awful code (e.g. some control chars are only meaningful
	   locally and shouldnt be sent).  Instead, because of #2
	   above (easy portability), we simply run it everywhere here.

	4) Resolve internet addresses (e.g. 128.138.240.1) so that
	   things like `talk user@128.138.240.1' will work, and
	   talkd may display "respond with: talk user@128.138.240.1".
	   (this is good for internet hosts that dont yet run a
	   nameserver, and dont have up-to-date /etc/hosts files)

	5) If a person you are trying to contact has messages off,
	   and they have a file called ".busy" in their home directory,
	   it will be sent to you and displayed in their half of the
	   screen.  The file generally contains the `reason' your
	   messages are off.

	6) A "dumb terminal" interface called `chat'.  This is good
	   for consoles and terminals without termcaps.  `chat' is
	   hard-linked to `talk' and each does the right thing.

	7) A revised manual page explaining these enhancements.

One thing that would be easy to add to the talk daemon, and probably will
be added in the future (if you or I ever get the time) is a ".talkrc" file
that would contain options to:

	1) list people you will talk to (when your messages are off).
	2) list people who you wont talk to even though your messages are on.

I have tested these `enhancements' under many circumstances for
compatibility with 4.3BSD.  Most of these mods have been running for
a couple years and I've fixed any little bugs that have since appeared.
Finally, this is available via anonymous ftp from boulder.Colorado.EDU.

What follows, is a shar archive containing the files:

	4.3talk_fix   - a fix that should be applied to every 4.3BSD talk.
	talk.1_diffs  - patch to /usr/man/man1/talk.1 (move the patched
			file to /usr/src/ucb/talk/talk.1 for `make install')
	talk_diffs    - patches for talk; cd /usr/src/ucb/talk & patch...
	talkd_diffs   - patches for talkd; cd /usr/src/etc/talkd & patch...
	talkd.h_diffs - patch to /usr/include/protocols/talkd.h

[I split talkd_diffs into a separate file because of the 64K message limit
on some machines.  ++bsa]

If you make any changes or fix a bug, please let me know... thanks!
---
Jeff Forys @ UC/Boulder Engineering Research Comp Cntr (303-492-4991)
forys@boulder.Colorado.Edu  -or-  ..!{hao|nbires}!boulder!forys

#--------------------------------CUT HERE-------------------------------------
#! /bin/sh
#
# This is a shell archive.  Save this into a file, edit it
# and delete all lines above this comment.  Then give this
# file to sh by executing the command "sh file".  The files
# will be extracted into the current directory owned by
# you with default permissions.
#
# The files contained herein are:
#
# -rw-r--r--   1 allbery  System      1886 Aug 10 20:02 4.3talk_fix
# -rw-r--r--   1 allbery  System      5947 Aug 10 20:02 talk.1_diffs
# -rw-r--r--   1 allbery  System     38180 Aug 10 20:03 talk_diffs
# -rw-r--r--   1 allbery  System       512 Aug 10 20:02 talkd.h_diffs
#
echo 'x - 4.3talk_fix'
if test -f 4.3talk_fix; then echo 'shar: not overwriting 4.3talk_fix'; else
sed 's/^X//' << '________This_Is_The_END________' > 4.3talk_fix
XFrom: forys@sunybcs.UUCP (Jeff Forys)
XNewsgroups: net.bugs.4bsd
XSubject: talk(1) displays incorrect error messages
XDate: 8 Nov 86 08:12:12 GMT
X
XIndex:	/usr/src/ucb/talk/invite.c 4.3BSD +FIX
X
XDescription:
X
X	talk(1) returns wrong error message under various circumstances.
X
XRepeat by:
X
X	% talk foo		# where `foo' is someone not logged in
X	  [No connection yet]
X     >>>  [Target machine does not recognize us]  <<<
X	% 
X
XFix:
X	The error messages do not jibe with their respective #define's
X	in "/usr/include/protocols/talkd.h".  The solution is to reorder
X	the error messages properly as the following diff illustrates...
X
X*** invite.c_old	Sat Nov  8 00:46:33 1986
X--- invite.c	Sat Nov  8 00:46:32 1986
X***************
X*** 92,102 ****
X  }
X  
X  static	char *answers[] = {
X  	"Your party is not logged on",			/* NOT_HERE */
X- 	"Target machine does not recognize us",		/* MACHINE_UNKNOWN */
X- 	"Target machine can not handle remote talk",	/* UNKNOWN_REQUEST */
X  	"Target machine is too confused to talk to us",	/* FAILED */
X  	"Your party is refusing messages",		/* PERMISSION_REFUSED */
X  	"Target machine indicates protocol mismatch",	/* BADVERSION */
X  	"Target machine indicates protocol botch (addr)",/* BADADDR */
X  	"Target machine indicates protocol botch (ctl_addr)",/* BADCTLADDR */
X--- 92,103 ----
X  }
X  
X  static	char *answers[] = {
X+ 	"",						/* SUCCESS */
X  	"Your party is not logged on",			/* NOT_HERE */
X  	"Target machine is too confused to talk to us",	/* FAILED */
X+ 	"Target machine does not recognize us",		/* MACHINE_UNKNOWN */
X  	"Your party is refusing messages",		/* PERMISSION_REFUSED */
X+ 	"Target machine can not handle remote talk",	/* UNKNOWN_REQUEST */
X  	"Target machine indicates protocol mismatch",	/* BADVERSION */
X  	"Target machine indicates protocol botch (addr)",/* BADADDR */
X  	"Target machine indicates protocol botch (ctl_addr)",/* BADCTLADDR */
________This_Is_The_END________
if test `wc -l < 4.3talk_fix` -ne 51; then
	echo 'shar: 4.3talk_fix was damaged during transit (should have been 51 bytes)'
fi
fi		; : end of overwriting check
echo 'x - talk.1_diffs'
if test -f talk.1_diffs; then echo 'shar: not overwriting talk.1_diffs'; else
sed 's/^X//' << '________This_Is_The_END________' > talk.1_diffs
X*** /tmp/,RCSt1019856	Fri Aug  7 17:36:46 1987
X--- talk.1	Fri Aug  7 17:36:43 1987
X***************
X*** 4,28 ****
X  .\"
X  .\"	@(#)talk.1	6.2 (Berkeley) 5/5/86
X  .\"
X! .TH TALK 1 "May 5, 1986"
X  .UC 5
X  .SH NAME
X! talk \- talk to another user
X  .SH SYNOPSIS
X  .B talk
X! person [ ttyname ]
X  .SH DESCRIPTION
X  .I Talk
X! is a visual communication program which
X! copies lines from your terminal to that of
X! another user.
X  .PP 
X! If you wish to talk to someone on you own machine, then
X  .I person
X  is just the person's login name. If you wish to talk to
X! a user on another host, then
X  .I person
X! is of the form :
X  .sp
X  .in +2.0i
X  .I host!user
X--- 4,39 ----
X  .\"
X  .\"	@(#)talk.1	6.2 (Berkeley) 5/5/86
X  .\"
X! .TH TALK 1 "Jun 15, 1987"
X  .UC 5
X  .SH NAME
X! talk, chat \- communicate with another user
X  .SH SYNOPSIS
X  .B talk
X! person [tty]
X! .br
X! .B chat
X! person [tty]
X  .SH DESCRIPTION
X  .I Talk
X! and
X! .I chat
X! allow you to carry on conversations with other users.
X! .I Talk
X! uses windows to split the screen in half giving a clear
X! picture of who is typing what.
X! .I Chat
X! displays characters in a line-by-line fashion which may
X! cause confusion if both parties are typing at the same time.
X! Characters are displayed and sent as soon as they are typed.
X  .PP 
X! The command line syntax for both programs is identical.
X! If you wish to talk to someone on the same machine, then
X  .I person
X  is just the person's login name. If you wish to talk to
X! a user on another machine, then
X  .I person
X! can be of the form:
X  .sp
X  .in +2.0i
X  .I host!user
X***************
X*** 39,96 ****
X  .in -2.0i
X  .sp
X  though
X! .I host@user 
X! is perhaps preferred.
X  .PP
X  If you want to talk to a user who is logged in more than once,
X  the
X! .I ttyname
X  argument may be used to indicate the
X  appropriate terminal name.
X  .PP
X! When first called,
X! it sends the message
X  .PP
X!      Message from TalkDaemon@his_machine...
X       talk: connection requested by your_name@your_machine.
X!      talk: respond with: talk your_name@your_machine
X  .PP
X! to the user you wish to talk to. At this point, the recipient
X! of the message should reply by 
X! typing 
X  .PP
X       talk \ your_name@your_machine
X  .PP
X  It doesn't matter from 
X  which machine the recipient replies, as long as his login-name is
X  the same.
X! Once communication is established, the two parties may type 
X! simultaneously, with their output appearing in separate windows. 
X! Typing control L will cause the screen to be reprinted, while your 
X! erase, kill, and word kill characters will work in talk as normal.
X! To exit,
X! just type your interrupt character;
X  .I talk
X! then moves the cursor to the bottom of the screen and restores 
X! the terminal.
X  .PP
X  Permission to talk may be denied or granted by use of the
X  .I mesg
X  command.
X! At the outset talking is allowed.
X! Certain commands, in particular
X! .I nroff
X! and
X! .IR  pr (1)
X! disallow
X! messages in order to prevent messy output.
X  .PP
X  .SH FILES
X  /etc/hosts	to find the recipient's machine
X  .br
X! /etc/utmp	to find the recipient's tty
X  .SH "SEE ALSO"
X! mesg(1), who(1), mail(1), write(1)
X  .SH BUGS
X  The version of 
X  .IR talk (1)
X--- 50,130 ----
X  .in -2.0i
X  .sp
X  though
X! .I user@host
X! is perhaps preferred, since it allows
X! .I host
X! to be a domain name (e.g. boulder.Colorado.EDU)
X! or an internet address (e.g. 128.138.240.1)
X! as well as a local host.
X  .PP
X  If you want to talk to a user who is logged in more than once,
X  the
X! .I tty
X  argument may be used to indicate the
X  appropriate terminal name.
X  .PP
X! When first called the message:
X  .PP
X!      Message from Talk_Daemon@his_machine at <time> ...
X       talk: connection requested by your_name@your_machine.
X!      talk: respond with:  talk your_name@your_machine
X  .PP
X! is sent to the user you wish to talk to. At this point, the
X! recipient of the message should reply with either
X  .PP
X       talk \ your_name@your_machine
X+  or
X+      chat \ your_name@your_machine
X  .PP
X+ depending on the interface one wants to use.
X  It doesn't matter from 
X  which machine the recipient replies, as long as his login-name is
X  the same.
X! .PP
X! There are some special predefined commands.  Typing a control-A
X! causes the message "<go ahead>" to appear on both terminals.
X! Control-B toggles a beep which will accompany the message.  Control-N
X! will display a list of available commands on only your screen.
X! When someone is using
X! .I chat
X! you may find control-E (Sorry to interrupt you) and control-X
X! (thats okay) useful.  When using
X  .I talk
X! a control-L will cause the screen to be reprinted and a control-F
X! will clear your window (on both sides).  When you are finished
X! conversing, a control-D can be used to display the message
X! "<over and out>".
X  .PP
X+ Both programs use your erase, word kill, and line kill characters and
X+ .I chat
X+ provides for your line reprint character to work as well.
X+ To exit, just type your interrupt character (usually control-C);
X+ both programs will restore your terminal leaving the cursor at the
X+ bottom of your screen.
X+ .PP
X  Permission to talk may be denied or granted by use of the
X  .I mesg
X  command.
X! At the outset talking is allowed.  If the person you are trying
X! to contact has messages off, the message "[Your party is refusing
X! messages]" will be displayed.  If this person also has a file called
X! .I .busy
X! in his home directory, the contents of this file will be sent
X! to you.  This file generally contains the reason messages were turned
X! off (as an aid to good manners) and is limited to 512 characters.
X  .PP
X  .SH FILES
X  /etc/hosts	to find the recipient's machine
X  .br
X! /etc/utmp		to find the recipient's tty
X  .SH "SEE ALSO"
X! mesg(1), who(1), rwho(1), mail(1), write(1), send(1)
X! .SH "ENHANCEMENTS"
X! Jeff Forys
X! .RS 4
X! Chat interface, Busy message, Special control codes,
X! Internet address resolution.
X! .RE
X  .SH BUGS
X  The version of 
X  .IR talk (1)
________This_Is_The_END________
if test `wc -l < talk.1_diffs` -ne 208; then
	echo 'shar: talk.1_diffs was damaged during transit (should have been 208 bytes)'
fi
fi		; : end of overwriting check
echo 'x - talk_diffs'
if test -f talk_diffs; then echo 'shar: not overwriting talk_diffs'; else
sed 's/^X//' << '________This_Is_The_END________' > talk_diffs
X*** /tmp/,RCSt1019480	Fri Aug  7 17:15:25 1987
X--- Makefile	Fri Aug  7 17:07:45 1987
X***************
X*** 3,17 ****
X  # All rights reserved.  The Berkeley software License Agreement
X  # specifies the terms and conditions for redistribution.
X  #
X! #	@(#)Makefile	5.4 (Berkeley) 4/12/86
X  #
X! DESTDIR=
X  OBJS=	talk.o get_names.o display.o io.o ctl.o init_disp.o \
X  	msgs.o get_addrs.o ctl_transact.o invite.o look_up.o
X  SRCS=	talk.c get_names.c display.c io.c ctl.c init_disp.c \
X  	msgs.c get_addrs.c ctl_transact.c invite.c look_up.c
X  INCLUDE=talk.h talk_ctl.h
X- CFLAGS= -O
X  
X  all:	talk
X  
X--- 3,40 ----
X  # All rights reserved.  The Berkeley software License Agreement
X  # specifies the terms and conditions for redistribution.
X  #
X! #	@(#)Makefile	5.4.1 (Berkeley) 4/12/86
X  #
X! #
X! 
X! #	Sun Jan 11 20:08:22 MST 1987	JEF	forys@Boulder.Colorado.Edu
X! #	Conditional compilations for different machines...
X! #
X! #	4.3 BSD
X! CFLAGS=-O
X! #
X! #	Pyramid OSx2.5 OSx3.1
X! #CFLAGS=-O -DPYRAMID
X! #
X! #	Pyramid OSx4.0
X! #CFLAGS=-O -DPYRAMID -DBSD4_3
X! #
X! #	Sun 3.1, 3.0
X! #CFLAGS=-O -DSUN3_1
X! #
X! #	Sun 3.2
X! #CFLAGS=-O -DSUN3_2
X! #
X! #	Ultrix 1.2
X! #CFLAGS=-O -DULTRIX1_2
X! 
X! DESTDIR=/usr/ucb
X! MANDIR=/usr/man/man1
X  OBJS=	talk.o get_names.o display.o io.o ctl.o init_disp.o \
X  	msgs.o get_addrs.o ctl_transact.o invite.o look_up.o
X  SRCS=	talk.c get_names.c display.c io.c ctl.c init_disp.c \
X  	msgs.c get_addrs.c ctl_transact.c invite.c look_up.c
X  INCLUDE=talk.h talk_ctl.h
X  
X  all:	talk
X  
X***************
X*** 21,30 ****
X  ${OBJS}: talk.h talk_ctl.h
X  
X  install: talk
X! 	install -g tty -m 2755 -s talk ${DESTDIR}/usr/ucb/talk
X  
X  clean:
X! 	rm -f ${OBJS} a.out errs core talk
X  
X  tags:	${SRCS} ${INCLUDE}
X  	ctags ${SRCS} ${INCLUDE}
X--- 44,57 ----
X  ${OBJS}: talk.h talk_ctl.h
X  
X  install: talk
X! 	install -m 755 -s talk ${DESTDIR}/talk
X! 	rm -f ${DESTDIR}/chat ${MANDIR}/chat.1
X! 	ln ${DESTDIR}/talk ${DESTDIR}/chat
X! 	cp talk.1 ${MANDIR}
X! 	ln ${MANDIR}/talk.1 ${MANDIR}/chat.1
X  
X  clean:
X! 	rm -f ${OBJS} a.out errs core talk chat
X  
X  tags:	${SRCS} ${INCLUDE}
X  	ctags ${SRCS} ${INCLUDE}
X***************
X*** 31,37 ****
X  
X  depend: ${SRCS}
X  	for i in ${SRCS}; do \
X! 	    cc -M $$i | sed 's/\.o//' | \
X  	    awk ' { if ($$1 != prev) \
X  		{ if (rec != "") print rec; rec = $$0; prev = $$1; } \
X  		else { if (length(rec $$2) > 78) { print rec; rec = $$0; } \
X--- 58,64 ----
X  
X  depend: ${SRCS}
X  	for i in ${SRCS}; do \
X! 	    cc -M ${CFLAGS} $$i | sed 's/\.o//' | \
X  	    awk ' { if ($$1 != prev) \
X  		{ if (rec != "") print rec; rec = $$0; prev = $$1; } \
X  		else { if (length(rec $$2) > 78) { print rec; rec = $$0; } \
X***************
X*** 59,66 ****
X  get_names: /usr/include/machine/machparam.h /usr/include/signal.h
X  get_names: /usr/include/sys/types.h /usr/include/protocols/talkd.h
X  get_names: /usr/include/sys/types.h /usr/include/sys/socket.h
X! display: display.c ./talk.h /usr/include/curses.h /usr/include/stdio.h
X! display: /usr/include/sgtty.h /usr/include/sys/ioctl.h
X  display: /usr/include/sys/ttychars.h /usr/include/sys/ttydev.h
X  display: /usr/include/utmp.h
X  io: io.c ./talk.h /usr/include/curses.h /usr/include/stdio.h
X--- 86,94 ----
X  get_names: /usr/include/machine/machparam.h /usr/include/signal.h
X  get_names: /usr/include/sys/types.h /usr/include/protocols/talkd.h
X  get_names: /usr/include/sys/types.h /usr/include/sys/socket.h
X! get_names: /usr/include/pwd.h
X! display: display.c /usr/include/stdio.h ./talk.h /usr/include/curses.h
X! display: /usr/include/stdio.h /usr/include/sgtty.h /usr/include/sys/ioctl.h
X  display: /usr/include/sys/ttychars.h /usr/include/sys/ttydev.h
X  display: /usr/include/utmp.h
X  io: io.c ./talk.h /usr/include/curses.h /usr/include/stdio.h
X***************
X*** 76,82 ****
X  init_disp: init_disp.c ./talk.h /usr/include/curses.h /usr/include/stdio.h
X  init_disp: /usr/include/sgtty.h /usr/include/sys/ioctl.h
X  init_disp: /usr/include/sys/ttychars.h /usr/include/sys/ttydev.h
X! init_disp: /usr/include/utmp.h /usr/include/signal.h
X  msgs: msgs.c /usr/include/signal.h /usr/include/stdio.h /usr/include/sys/time.h
X  msgs: /usr/include/time.h ./talk.h /usr/include/curses.h /usr/include/stdio.h
X  msgs: /usr/include/sgtty.h /usr/include/sys/ioctl.h /usr/include/sys/ttychars.h
X--- 104,110 ----
X  init_disp: init_disp.c ./talk.h /usr/include/curses.h /usr/include/stdio.h
X  init_disp: /usr/include/sgtty.h /usr/include/sys/ioctl.h
X  init_disp: /usr/include/sys/ttychars.h /usr/include/sys/ttydev.h
X! init_disp: /usr/include/utmp.h /usr/include/signal.h /usr/include/sgtty.h
X  msgs: msgs.c /usr/include/signal.h /usr/include/stdio.h /usr/include/sys/time.h
X  msgs: /usr/include/time.h ./talk.h /usr/include/curses.h /usr/include/stdio.h
X  msgs: /usr/include/sgtty.h /usr/include/sys/ioctl.h /usr/include/sys/ttychars.h
X***************
X*** 87,93 ****
X  get_addrs: /usr/include/curses.h /usr/include/stdio.h /usr/include/sgtty.h
X  get_addrs: /usr/include/sys/ioctl.h /usr/include/sys/ttychars.h
X  get_addrs: /usr/include/sys/ttydev.h /usr/include/utmp.h /usr/include/errno.h
X! get_addrs: /usr/include/netdb.h
X  ctl_transact: ctl_transact.c ./talk_ctl.h /usr/include/sys/types.h
X  ctl_transact: /usr/include/protocols/talkd.h /usr/include/sys/types.h
X  ctl_transact: /usr/include/sys/socket.h /usr/include/netinet/in.h ./talk.h
X--- 115,122 ----
X  get_addrs: /usr/include/curses.h /usr/include/stdio.h /usr/include/sgtty.h
X  get_addrs: /usr/include/sys/ioctl.h /usr/include/sys/ttychars.h
X  get_addrs: /usr/include/sys/ttydev.h /usr/include/utmp.h /usr/include/errno.h
X! get_addrs: /usr/include/sys/param.h /usr/include/machine/machparam.h
X! get_addrs: /usr/include/signal.h /usr/include/sys/types.h /usr/include/netdb.h
X  ctl_transact: ctl_transact.c ./talk_ctl.h /usr/include/sys/types.h
X  ctl_transact: /usr/include/protocols/talkd.h /usr/include/sys/types.h
X  ctl_transact: /usr/include/sys/socket.h /usr/include/netinet/in.h ./talk.h
X*** /tmp/,RCSt1019480	Fri Aug  7 17:15:29 1987
X--- ctl_transact.c	Fri Aug  7 17:08:25 1987
X***************
X*** 18,28 ****
X   * not recieved an acknowledgement within a reasonable amount
X   * of time
X   */
X! ctl_transact(target, msg, type, rp)
X  	struct in_addr target;
X  	CTL_MSG msg;
X  	int type;
X  	CTL_RESPONSE *rp;
X  {
X  	int read_mask, ctl_mask, nready, cc;
X  	struct timeval wait;
X--- 18,29 ----
X   * not recieved an acknowledgement within a reasonable amount
X   * of time
X   */
X! ctl_transact(target, msg, type, rp, busy)
X  	struct in_addr target;
X  	CTL_MSG msg;
X  	int type;
X  	CTL_RESPONSE *rp;
X+ 	CTL_BUSY *busy;
X  {
X  	int read_mask, ctl_mask, nready, cc;
X  	struct timeval wait;
X***************
X*** 68,73 ****
X--- 69,88 ----
X  					continue;
X  				p_error("Error on read from talk daemon");
X  			}
X+ 
X+ 			read_mask = ctl_mask;
X+ 			if (rp->answer == PERMISSION_DENIED &&
X+ 			    select(32, &read_mask, 0, 0, &wait)) {
X+ 
X+ 				/*
X+ 				 * Read in what we hope is a `.busy' message.
X+ 				 * Check later to make sure it's not junk.
X+ 				 */
X+ 
X+ 				(void) recv(ctl_sockt, (char *) busy,
X+ 						sizeof (*busy), 0);
X+ 			}
X+ 
X  			read_mask = ctl_mask;
X  			/* an immediate poll */
X  			timerclear(&wait);
X*** /tmp/,RCSt1019480	Fri Aug  7 17:15:33 1987
X--- display.c	Fri Aug  7 17:08:31 1987
X***************
X*** 12,24 ****
X--- 12,45 ----
X   * The window 'manager', initializes curses and handles the actual
X   * displaying of text
X   */
X+ 
X+ #include <stdio.h>
X  #include "talk.h"
X  
X+ /*
X+  * This local version contains some extra control codes:
X+  *	^N	Display menu
X+  *	^F	Clear window
X+  *	^B	Toggle beep
X+  *	^A	display <go ahead>\n
X+  *	^E	display <sorry to interrupt you>\n
X+  *	^X	display <thats ok>\n
X+  *	^D	display <over and out>\n
X+  */
X+ 
X+ static char *cc_goahead = "<go ahead>";
X+ static char *cc_beepon  = "<beep on>";
X+ static char *cc_beepoff = "<beep off>";
X+ static char *cc_sorry   = "<sorry to interrupt you>";
X+ static char *cc_thatsok = "<thats okay>";
X+ static char *cc_overout	= "<over and out>";
X+ 
X  xwin_t	my_win;
X  xwin_t	his_win;
X  WINDOW	*line_win;
X  
X  int	curses_initialized = 0;
X+ int	beep = 0;
X  
X  /*
X   * max HAS to be a function, it is called with
X***************
X*** 35,41 ****
X   * Display some text on somebody's window, processing some control
X   * characters while we are at it.
X   */
X! display(win, text, size)
X  	register xwin_t *win;
X  	register char *text;
X  	int size;
X--- 56,62 ----
X   * Display some text on somebody's window, processing some control
X   * characters while we are at it.
X   */
X! talk_display(win, text, size)
X  	register xwin_t *win;
X  	register char *text;
X  	int size;
X***************
X*** 43,52 ****
X  	register int i;
X  	char cch;
X  
X! 	for (i = 0; i < size; i++) {
X  		if (*text == '\n') {
X  			xscroll(win, 0);
X- 			text++;
X  			continue;
X  		}
X  		/* erase character */
X--- 64,72 ----
X  	register int i;
X  	char cch;
X  
X! 	for (i = 0; i < size; i++, text++) {
X  		if (*text == '\n') {
X  			xscroll(win, 0);
X  			continue;
X  		}
X  		/* erase character */
X***************
X*** 56,62 ****
X  			waddch(win->x_win, ' ');
X  			wmove(win->x_win, win->x_line, win->x_col);
X  			getyx(win->x_win, win->x_line, win->x_col);
X- 			text++;
X  			continue;
X  		}
X  		/*
X--- 76,81 ----
X***************
X*** 93,105 ****
X  			wmove(win->x_win, win->x_line, 0);
X  			wclrtoeol(win->x_win);
X  			getyx(win->x_win, win->x_line, win->x_col);
X- 			text++;
X  			continue;
X  		}
X  		if (*text == '\f') {
X  			if (win == &my_win)
X  				wrefresh(curscr);
X- 			text++;
X  			continue;
X  		}
X  		if (win->x_col == COLS-1) {
X--- 112,123 ----
X  			wmove(win->x_win, win->x_line, 0);
X  			wclrtoeol(win->x_win);
X  			getyx(win->x_win, win->x_line, win->x_col);
X  			continue;
X  		}
X+ 		/* clear screen */
X  		if (*text == '\f') {
X  			if (win == &my_win)
X  				wrefresh(curscr);
X  			continue;
X  		}
X  		if (win->x_col == COLS-1) {
X***************
X*** 106,112 ****
X  			/* check for wraparound */
X  			xscroll(win, 0);
X  		}
X! 		if (*text < ' ' && *text != '\t') {
X  			waddch(win->x_win, '^');
X  			getyx(win->x_win, win->x_line, win->x_col);
X  			if (win->x_col == COLS-1) /* check for wraparound */
X--- 124,188 ----
X  			/* check for wraparound */
X  			xscroll(win, 0);
X  		}
X! 
X! 		switch(*text) {		/* Expand special control codes */
X! 			case '\001':
X! 				if (win->x_col) xscroll(win,0);
X! 				waddstr(win->x_win,cc_goahead);
X! 				if (beep) putchar('\007');
X! 				xscroll(win,0);
X! 				continue;
X! 			case '\002':
X! 				beep = !beep;
X! 				if (win->x_col) xscroll(win,0);
X! 				waddstr(win->x_win,beep?cc_beepon:cc_beepoff);
X! 				xscroll(win,0);
X! 				continue;
X! 			case '\004':
X! 				if (win->x_col) xscroll(win,0);
X! 				waddstr(win->x_win,cc_overout);
X! 				xscroll(win,0);
X! 				continue;
X! 			case '\005':
X! 				if (win->x_col) xscroll(win,0);
X! 				waddstr(win->x_win,cc_sorry);
X! 				xscroll(win,0);
X! 				continue;
X! 			case '\006':
X! 				wclear(win->x_win);
X! 				xscroll(win,-1);
X! 				continue;
X! 			case '\030':
X! 				if (win->x_col) xscroll(win,0);
X! 				waddstr(win->x_win,cc_thatsok);
X! 				xscroll(win,0);
X! 				continue;
X! 			case '\016':
X! 				wclear(win->x_win);
X! 				xscroll(win,-1);
X! 				waddstr(win->x_win,"\n^A\t\"<go ahead>\"");
X! 				xscroll(win,0);
X! 				waddstr(win->x_win,"^D\t\"<over and out>\"");
X! 				xscroll(win,0);
X! 				waddstr(win->x_win,"^E\t\"<sorry to interrupt you>\"");
X! 				xscroll(win,0);
X! 				waddstr(win->x_win,"^X\t\"<thats ok>\"");
X! 				xscroll(win,0);
X! 				waddstr(win->x_win,"^F\tClear your window");
X! 				xscroll(win,0);
X! 				waddstr(win->x_win,"^B\tToggle beep");
X! 				xscroll(win,0);
X! 				waddstr(win->x_win,"^C\tQuit talk");
X! 				xscroll(win,0);
X! 				waddstr(win->x_win,"^N\tThis menu");
X! 				xscroll(win,0);
X! 				xscroll(win,0); 
X! 				continue;
X! 		};
X! 
X! 		if (*text == '\007' && beep)	/* just send out the beep */
X! 			putchar(*text);
X! 		else if (*text < ' ' && *text != '\t') {
X  			waddch(win->x_win, '^');
X  			getyx(win->x_win, win->x_line, win->x_col);
X  			if (win->x_col == COLS-1) /* check for wraparound */
X***************
X*** 116,122 ****
X  		} else
X  			waddch(win->x_win, *text);
X  		getyx(win->x_win, win->x_line, win->x_col);
X- 		text++;
X  	}
X  	wrefresh(win->x_win);
X  }
X--- 192,197 ----
X***************
X*** 145,151 ****
X  	register xwin_t *win;
X  	int flag;
X  {
X- 
X  	if (flag == -1) {
X  		wmove(win->x_win, 0, 0);
X  		win->x_line = 0;
X--- 220,225 ----
X***************
X*** 159,162 ****
X--- 233,365 ----
X  	wmove(win->x_win, (win->x_line + 1) % win->x_nlines, win->x_col);
X  	wclrtoeol(win->x_win);
X  	wmove(win->x_win, win->x_line, win->x_col);
X+ }
X+ 
X+ chat_display(win, text, size)	/* Display chars using the 'chat' interface */
X+ register xwin_t *win;
X+ register char *text;
X+ int size;
X+ {
X+     register int i, j, c;
X+ 
X+     for (i=0; i<size; i++, text++) {
X+ 
X+ 	c = *text;
X+ 
X+ 	if (c == win->cerase && win->column) {	/* Character erase */
X+ 		printf("\b \b");
X+ 		win->column--;
X+ 	} else if (c == win->werase) {		/* Word erase */
X+ 		while (win->column && win->chatline[win->column-1]==' ') {
X+ 			putchar('\b');
X+ 			win->column--;
X+ 		}
X+ 		while (win->column && win->chatline[win->column-1]!=' ') {
X+ 			printf("\b \b");
X+ 			win->column--;
X+ 		}
X+ 	} else if (c == win->kill) {		/* Line erase */
X+ 		while (win->column) {
X+ 			printf("\b \b");
X+ 			win->column--;
X+ 		}
X+ 	} else if (c == win->redraw) {		/* Line redraw */
X+ 		if (c < ' ') {
X+ 			putchar('^');
X+ 			putchar(c+64);
X+ 		} else if (c < 0177)
X+ 			putchar(c);
X+ 		printf("\r\n");
X+ 		for(j=0; j<win->column; j++)
X+ 			putchar(win->chatline[j]);
X+ 	} else if (c == '\t') {			/* Tab display and expansion */
X+ 		putchar('\t');
X+ 		for (j=0; j<8-win->column%8 && win->column<CHAT_SIZ; j++)
X+ 			win->chatline[win->column+j] = ' ';
X+ 		win->column += j;
X+ 	} else					
X+ 		switch(c) {		/* Expand special control codes */
X+ 			case '\001':
X+ 				printf("%s%s%c\r\n", win->column? "\r\n": "",
X+ 					cc_goahead, beep? '\007': '\0');
X+ 				win->column = 0;
X+ 				break;
X+ 			case '\002':
X+ 				beep = !beep;
X+ 				printf("%s%s\r\n", win->column? "\r\n": "",
X+ 					beep? cc_beepon: cc_beepoff);
X+ 				break;
X+ 			case '\030':
X+ 				printf("%s%s\r\n", win->column? "\r\n": "",
X+ 					cc_thatsok);
X+ 				win->column = 0;
X+ 				break;
X+ 			case '\004':
X+ 				printf("%s%s\r\n", win->column? "\r\n": "",
X+ 					cc_overout);
X+ 				win->column = 0;
X+ 				break;
X+ 			case '\005':
X+ 				printf("%s%s\r\n", win->column? "\r\n": "",
X+ 					cc_sorry);
X+ 				win->column = 0;
X+ 				break;
X+ 			case '\006':
X+ 				win->column = 0;
X+ 				break;
X+ 			case '\016':
X+ 				if (win->column)
X+ 					printf("\r\n");
X+ 				printf("\r\n^A\t\"<go ahead>\"\r\n");
X+ 				printf("^D\t\"<over and out>\"\r\n");
X+ 				printf("^E\t\"<sorry to interrupt you>\"\r\n");
X+ 				printf("^X\t\"<thats okay>\"\r\n");
X+ 				printf("^F\tClear your window\r\n");
X+ 				printf("^B\tToggle beep\r\n");
X+ 				printf("^C\tQuit chat\r\n");
X+ 				printf("^N\tThis menu\r\n\r\n");
X+ 				break;
X+ 			case '\n':
X+ 				printf("\r\n");
X+ 				win->column = 0;
X+ 				break;
X+ 			case '\007':
X+ 				if (beep) {
X+ 					putchar(c);
X+ 					break;
X+ 				}
X+ 			default:	/* Just a character -- display it */
X+ 				/* Display control chars like "cat -v" does */
X+ 
X+ 				if (c > 0177) {		/* A meta character! */
X+ 					sendchar('M', win);
X+ 					sendchar('-', win);
X+ 					c &= 0177;	/* zero the high bit */
X+ 				}
X+ 				if (c < ' ' || c == 0177) {	/* ctrl char */
X+ 					if (c=='\007' && beep)	/* a beep */
X+ 						putchar(c);
X+ 					else {		/* Display '^' first */
X+ 						sendchar('^', win);
X+ 						if (c == 0177)
X+ 							c = '?';
X+ 						else
X+ 							c += 64;
X+ 					}
X+ 				}
X+ 				sendchar(c, win);	/* Display character */
X+ 		}
X+ 
X+ 		(void) fflush(stdout);	/* One character at-a-time display */
X+     }
X+ }
X+ 
X+ sendchar(c, win)	/* Display char to tty and add it to users' line */
X+ char c;
X+ register xwin_t *win;
X+ {
X+ 	putchar(c);
X+ 
X+ 	if (win->column < CHAT_SIZ-1)	/* save char in users' line buffer */
X+ 		win->chatline[win->column++] = c;
X  }
X*** /tmp/,RCSt1019480	Fri Aug  7 17:15:37 1987
X--- get_addrs.c	Fri Aug  7 17:08:34 1987
X***************
X*** 9,14 ****
X--- 9,15 ----
X  #endif not lint
X  
X  #include "talk_ctl.h"
X+ #include <sys/param.h>
X  #include <netdb.h>
X  
X  get_addrs(my_machine_name, his_machine_name)
X***************
X*** 21,30 ****
X  	/* look up the address of the local host */
X  	hp = gethostbyname(my_machine_name);
X  	if (hp == (struct hostent *) 0) {
X! 		fprintf(stderr,
X! 		    "talk: %s: Can't figure out network address.\n",
X! 		    my_machine_name);
X! 		exit(-1);
X  	}
X  	bcopy(hp->h_addr, (char *)&my_machine_addr, hp->h_length);
X  	/*
X--- 22,52 ----
X  	/* look up the address of the local host */
X  	hp = gethostbyname(my_machine_name);
X  	if (hp == (struct hostent *) 0) {
X! 		static struct hostent my_def;
X! 		static struct in_addr my_defaddr;
X! #ifdef BSD4_3
X! 		static char *my_alist[1];
X! #endif
X! 		static char my_namebuf[128];
X! 		int inet_addr();
X! 
X! 		my_defaddr.s_addr = inet_addr(my_machine_name);
X! 		if (my_defaddr.s_addr == -1) {
X! 			fprintf(stderr,
X! 			    "talk: %s: Can't figure out network address.\n",
X! 			    my_machine_name);
X! 			exit(-1);
X! 		}
X! 		strcpy(my_namebuf, my_machine_name);
X! 		my_def.h_name = my_namebuf;
X! #ifdef BSD4_3
X! 		my_def.h_addr_list = my_alist,
X! #endif
X! 		my_def.h_addr = (char *)&my_defaddr;
X! 		my_def.h_length = sizeof (struct in_addr);
X! 		my_def.h_addrtype = AF_INET;
X! 		my_def.h_aliases = 0;
X! 		hp = &my_def;
X  	}
X  	bcopy(hp->h_addr, (char *)&my_machine_addr, hp->h_length);
X  	/*
X***************
X*** 34,43 ****
X  	if (strcmp(his_machine_name, my_machine_name)) {
X  		hp = gethostbyname(his_machine_name);
X  		if (hp == (struct hostent *) 0 ) {
X! 			fprintf(stderr,
X! 			    "talk: %s: Can't figure out network address.\n",
X! 			    his_machine_name);
X! 			exit(-1);
X  		}
X  		bcopy(hp->h_addr, (char *) &his_machine_addr, hp->h_length);
X  	} else
X--- 56,86 ----
X  	if (strcmp(his_machine_name, my_machine_name)) {
X  		hp = gethostbyname(his_machine_name);
X  		if (hp == (struct hostent *) 0 ) {
X! 			static struct hostent his_def;
X! 			static struct in_addr his_defaddr;
X! #ifdef BSD4_3
X! 			static char *his_alist[1];
X! #endif
X! 			static char his_namebuf[128];
X! 			int inet_addr();
X! 
X! 			his_defaddr.s_addr = inet_addr(his_machine_name);
X! 			if (his_defaddr.s_addr == -1) {
X! 				fprintf(stderr,
X! 				    "talk: %s: Can't figure out network address.\n",
X! 				    his_machine_name);
X! 				exit(-1);
X! 			}
X! 			strcpy(his_namebuf, his_machine_name);
X! 			his_def.h_name = his_namebuf;
X! #ifdef BSD4_3
X! 			his_def.h_addr_list = his_alist,
X! #endif
X! 			his_def.h_addr = (char *)&his_defaddr;
X! 			his_def.h_length = sizeof (struct in_addr);
X! 			his_def.h_addrtype = AF_INET;
X! 			his_def.h_aliases = 0;
X! 			hp = &his_def;
X  		}
X  		bcopy(hp->h_addr, (char *) &his_machine_addr, hp->h_length);
X  	} else
X*** /tmp/,RCSt1019480	Fri Aug  7 17:15:41 1987
X--- get_names.c	Fri Aug  7 17:08:38 1987
X***************
X*** 11,17 ****
X--- 11,23 ----
X  #include "talk.h"
X  #include <sys/param.h>
X  #include <protocols/talkd.h>
X+ #include <pwd.h>
X  
X+ #if PYRAMID
X+ #define	htonl(x)	(x)
X+ #define	htons(x)	(x)
X+ #endif
X+ 
X  char	*getlogin();
X  char	*ttyname();
X  char	*rindex();
X***************
X*** 28,38 ****
X  	char hostname[MAXHOSTNAMELEN];
X  	char *his_name, *my_name;
X  	char *my_machine_name, *his_machine_name;
X! 	char *my_tty, *his_tty;
X  	register char *cp;
X  
X  	if (argc < 2 ) {
X! 		printf("Usage: talk user [ttyname]\n");
X  		exit(-1);
X  	}
X  	if (!isatty(0)) {
X--- 34,52 ----
X  	char hostname[MAXHOSTNAMELEN];
X  	char *his_name, *my_name;
X  	char *my_machine_name, *his_machine_name;
X! 	char *his_tty;
X  	register char *cp;
X+ 	struct passwd *pw, *getpwuid();
X  
X+ 	argv[0] = (cp = rindex(argv[0],'/')) ? ++cp : *argv;	/* strip path */
X+ 
X+ 	if (!strcmp(argv[0], "talk"))		/* use the `talk' interface */
X+ 		my_interfac = I_TALK;
X+ 	else if (!strcmp(argv[0], "chat"))	/* use the `chat' interface */
X+ 		my_interfac = I_CHAT;
X+ 
X  	if (argc < 2 ) {
X! 		printf("Usage: %s user [ttyname]\n", argv[0]);
X  		exit(-1);
X  	}
X  	if (!isatty(0)) {
X***************
X*** 41,52 ****
X  	}
X  	my_name = getlogin();
X  	if (my_name == NULL) {
X! 		printf("You don't exist. Go away.\n");
X! 		exit(-1);
X  	}
X  	gethostname(hostname, sizeof (hostname));
X  	my_machine_name = hostname;
X- 	my_tty = rindex(ttyname(0), '/') + 1;
X  	/* check for, and strip out, the machine name of the target */
X  	for (cp = argv[1]; *cp && !any(*cp, "@:!."); cp++)
X  		;
X--- 55,68 ----
X  	}
X  	my_name = getlogin();
X  	if (my_name == NULL) {
X! 		if ((pw=getpwuid(getuid())) == NULL) {
X! 			printf("You don't exist. Go away.\n");
X! 			exit(-1);
X! 		}
X! 		my_name = pw->pw_name;
X  	}
X  	gethostname(hostname, sizeof (hostname));
X  	my_machine_name = hostname;
X  	/* check for, and strip out, the machine name of the target */
X  	for (cp = argv[1]; *cp && !any(*cp, "@:!."); cp++)
X  		;
X*** /tmp/,RCSt1019480	Fri Aug  7 17:15:45 1987
X--- init_disp.c	Fri Aug  7 17:08:41 1987
X***************
X*** 15,21 ****
X--- 15,29 ----
X  
X  #include "talk.h"
X  #include <signal.h>
X+ #include <sgtty.h>
X  
X+ #if (SUN3_1 | PYRAMID | ULTRIX1_2)
X+ #define sigmask(m)	(1 << ((m)-1))
X+ #endif
X+ 
X+ static struct sgttyb old_t, new_t;
X+ int onstop();
X+ 
X  /* 
X   * Set up curses, catch the appropriate signals,
X   * and build the various windows.
X***************
X*** 25,58 ****
X  	void sig_sent();
X  	struct sigvec sigv;
X  
X! 	initscr();
X  	(void) sigvec(SIGTSTP, (struct sigvec *)0, &sigv);
X  	sigv.sv_mask |= sigmask(SIGALRM);
X  	(void) sigvec(SIGTSTP, &sigv, (struct sigvec *)0);
X- 	curses_initialized = 1;
X- 	clear();
X- 	refresh();
X- 	noecho();
X- 	crmode();
X  	signal(SIGINT, sig_sent);
X  	signal(SIGPIPE, sig_sent);
X  	/* curses takes care of ^Z */
X- 	my_win.x_nlines = LINES / 2;
X- 	my_win.x_ncols = COLS;
X- 	my_win.x_win = newwin(my_win.x_nlines, my_win.x_ncols, 0, 0);
X- 	scrollok(my_win.x_win, FALSE);
X- 	wclear(my_win.x_win);
X  
X! 	his_win.x_nlines = LINES / 2 - 1;
X! 	his_win.x_ncols = COLS;
X! 	his_win.x_win = newwin(his_win.x_nlines, his_win.x_ncols,
X! 	    my_win.x_nlines+1, 0);
X! 	scrollok(his_win.x_win, FALSE);
X! 	wclear(his_win.x_win);
X  
X! 	line_win = newwin(1, COLS, my_win.x_nlines, 0);
X! 	box(line_win, '-', '-');
X! 	wrefresh(line_win);
X  	/* let them know we are working on it */
X  	current_state = "No connection yet";
X  }
X--- 33,80 ----
X  	void sig_sent();
X  	struct sigvec sigv;
X  
X!  	ioctl(0, TIOCGETP, &old_t);	/* save old tty settings */
X! 
X! 	if (my_interfac == I_TALK) {	/* do some window junk */
X! 		initscr();
X! 		curses_initialized = 1;
X! 		clear();
X! 		refresh();
X! 		noecho();
X! 		crmode();
X! 	}
X! 
X  	(void) sigvec(SIGTSTP, (struct sigvec *)0, &sigv);
X  	sigv.sv_mask |= sigmask(SIGALRM);
X  	(void) sigvec(SIGTSTP, &sigv, (struct sigvec *)0);
X  	signal(SIGINT, sig_sent);
X  	signal(SIGPIPE, sig_sent);
X  	/* curses takes care of ^Z */
X  
X! 	if (my_interfac == I_TALK) {	/* do more window junk */
X! 		my_win.x_nlines = LINES / 2;
X! 		my_win.x_ncols = COLS;
X! 		my_win.x_win = newwin(my_win.x_nlines, my_win.x_ncols, 0, 0);
X! 		scrollok(my_win.x_win, FALSE);
X  
X! 		his_win.x_nlines = LINES / 2 - 1;
X! 		his_win.x_ncols = COLS;
X! 		his_win.x_win = newwin(his_win.x_nlines, his_win.x_ncols,
X! 		    my_win.x_nlines+1, 0);
X! 		scrollok(his_win.x_win, FALSE);
X! 		wclear(his_win.x_win);
X! 
X! 		line_win = newwin(1, COLS, my_win.x_nlines, 0);
X! 		box(line_win, '-', '-');
X! 		wrefresh(line_win);
X!  	} else if (my_interfac == I_CHAT) {	/* change tty for 'chat' */
X!  		signal(SIGTSTP, onstop);	/* catch TSTP to reset tty */
X!  		new_t = old_t;
X!  		new_t.sg_flags &= ~ECHO;	/* turn off echo */
X!  		new_t.sg_flags |= CBREAK;	/* get chars when typed */
X!  		ioctl(0, TIOCSETP, &new_t);	/* make new tty settings */
X!  	}
X! 
X  	/* let them know we are working on it */
X  	current_state = "No connection yet";
X  }
X***************
X*** 73,78 ****
X--- 95,104 ----
X  	ioctl(0, TIOCGLTC, (struct sgttyb *)&ltc);
X  	my_win.cerase = tty.sg_erase;
X  	my_win.kill = tty.sg_kill;
X+ 	if (ltc.t_rprntc == (char) -1)
X+ 		my_win.redraw = '\022';  /* control R */
X+ 	else
X+ 		my_win.redraw = ltc.t_rprntc;
X  	if (ltc.t_werasc == (char) -1)
X  		my_win.werase = '\027';	 /* control W */
X  	else
X***************
X*** 89,100 ****
X  	his_win.cerase = buf[0];
X  	his_win.kill = buf[1];
X  	his_win.werase = buf[2];
X  }
X  
X  void
X  sig_sent()
X  {
X- 
X  	message("Connection closing. Exiting");
X  	quit();
X  }
X--- 115,127 ----
X  	his_win.cerase = buf[0];
X  	his_win.kill = buf[1];
X  	his_win.werase = buf[2];
X+ 	his_win.redraw = '\0';
X+ 	my_win.column = his_win.column = 0;
X  }
X  
X  void
X  sig_sent()
X  {
X  	message("Connection closing. Exiting");
X  	quit();
X  }
X***************
X*** 105,117 ****
X  quit()
X  {
X  
X! 	if (curses_initialized) {
X  		wmove(his_win.x_win, his_win.x_nlines-1, 0);
X  		wclrtoeol(his_win.x_win);
X  		wrefresh(his_win.x_win);
X  		endwin();
X  	}
X  	if (invitation_waiting)
X  		send_delete();
X  	exit(0);
X  }
X--- 132,178 ----
X  quit()
X  {
X  
X! 	if (curses_initialized && my_interfac == I_TALK) {
X  		wmove(his_win.x_win, his_win.x_nlines-1, 0);
X  		wclrtoeol(his_win.x_win);
X  		wrefresh(his_win.x_win);
X  		endwin();
X  	}
X+ #ifdef NOFLUSH
X+ 	else if (my_interfac == I_CHAT) {
X+ 		ioctl(2, TIOCSETP, &old_t);
X+ 	}
X+ #endif
X+ 
X  	if (invitation_waiting)
X  		send_delete();
X+ 
X+ 	/*
X+ 	 * The ioctl below is ONLY required for the `chat' inteface, however
X+ 	 * it is used here to flush the input buffer.  If you dont want the
X+ 	 * input buffer flushed when exiting `talk', define NOFLUSH...
X+ 	 */
X+ 
X+ #ifndef NOFLUSH
X+ 	ioctl(2, TIOCSETP, &old_t);
X+ #endif
X  	exit(0);
X+ }
X+ 
X+ #define	BIT(_a)		(1<<((_a)-1))
X+ 
X+ onstop()	/* when using `chat' trap to here on a SIGTSTP to restore tty */
X+ {
X+ 	int signo = SIGTSTP;
X+ 
X+ 	ioctl(0, TIOCSETP, &old_t);	/* restore tty to origional settings */
X+ 	signal(SIGTSTP, SIG_DFL);
X+ 	(void) sigsetmask(sigblock(0) & ~BIT(signo));
X+ 	(void) kill(getpid(), SIGTSTP);
X+ 
X+ 	/* Wait until we are started up again */
X+ 
X+ 	signal(SIGTSTP, onstop);	/* put the trap back */
X+ 	(void) sigsetmask(sigblock(0) | BIT(signo));
X+ 	ioctl(0, TIOCSETP, &new_t);	/* change the tty for 'chat' again */
X  }
X*** /tmp/,RCSt1019480	Fri Aug  7 17:15:50 1987
X--- invite.c	Fri Aug  7 17:08:45 1987
X***************
X*** 13,18 ****
X--- 13,23 ----
X  #include <signal.h>
X  #include <setjmp.h>
X  
X+ #if PYRAMID
X+ #define	htonl(x)	(x)
X+ #define	htons(x)	(x)
X+ #endif
X+ 
X  /*
X   * There wasn't an invitation waiting, so send a request containing
X   * our sockt address to the remote talk daemon so it can invite
X***************
X*** 31,39 ****
X  
X  invite_remote()
X  {
X! 	int nfd, read_mask, template, new_sockt;
X  	struct itimerval itimer;
X  	CTL_RESPONSE response;
X  
X  	itimer.it_value.tv_sec = RING_WAIT;
X  	itimer.it_value.tv_usec = 0;
X--- 36,45 ----
X  
X  invite_remote()
X  {
X! 	int new_sockt;
X  	struct itimerval itimer;
X  	CTL_RESPONSE response;
X+ 	CTL_BUSY busy;
X  
X  	itimer.it_value.tv_sec = RING_WAIT;
X  	itimer.it_value.tv_usec = 0;
X***************
X*** 70,78 ****
X  	start_msgs();
X  
X  	msg.id_num = htonl(local_id);
X! 	ctl_transact(my_machine_addr, msg, DELETE, &response);
X  	msg.id_num = htonl(remote_id);
X! 	ctl_transact(his_machine_addr, msg, DELETE, &response);
X  	invitation_waiting = 0;
X  }
X  
X--- 76,84 ----
X  	start_msgs();
X  
X  	msg.id_num = htonl(local_id);
X! 	ctl_transact(my_machine_addr, msg, DELETE, &response, &busy);
X  	msg.id_num = htonl(remote_id);
X! 	ctl_transact(his_machine_addr, msg, DELETE, &response, &busy);
X  	invitation_waiting = 0;
X  }
X  
X***************
X*** 109,125 ****
X  announce_invite()
X  {
X  	CTL_RESPONSE response;
X  
X  	current_state = "Trying to connect to your party's talk daemon";
X! 	ctl_transact(his_machine_addr, msg, ANNOUNCE, &response);
X  	remote_id = response.id_num;
X  	if (response.answer != SUCCESS) {
X  		if (response.answer < NANSWERS)
X  			message(answers[response.answer]);
X  		quit();
X  	}
X  	/* leave the actual invitation on my talk daemon */
X! 	ctl_transact(my_machine_addr, msg, LEAVE_INVITE, &response);
X  	local_id = response.id_num;
X  }
X  
X--- 116,143 ----
X  announce_invite()
X  {
X  	CTL_RESPONSE response;
X+ 	CTL_BUSY busy;
X+ 	int valid();
X  
X  	current_state = "Trying to connect to your party's talk daemon";
X! 	ctl_transact(his_machine_addr, msg, ANNOUNCE, &response, &busy);
X  	remote_id = response.id_num;
X  	if (response.answer != SUCCESS) {
X  		if (response.answer < NANSWERS)
X  			message(answers[response.answer]);
X+ 		if (response.answer == PERMISSION_DENIED && valid(&busy)) {
X+ 			if (my_interfac == I_TALK)
X+ 				talk_display(&his_win, busy.busy, strlen(busy.busy));
X+ 			else if (my_interfac == I_CHAT) {
X+ 				putchar('\n');
X+ 				chat_display(&his_win, busy.busy, strlen(busy.busy));
X+ 				putchar('\n');
X+ 			}
X+ 		}
X  		quit();
X  	}
X  	/* leave the actual invitation on my talk daemon */
X! 	ctl_transact(my_machine_addr, msg, LEAVE_INVITE, &response, &busy);
X  	local_id = response.id_num;
X  }
X  
X***************
X*** 144,147 ****
X--- 162,177 ----
X  	if (sendto(ctl_sockt, &msg, sizeof (msg), 0, &daemon_addr,
X  	    sizeof (daemon_addr)) != sizeof (msg))
X  		perror("send_delete (local)");
X+ }
X+ 
X+ int valid(busy)		/* see if checksum is correct */
X+ CTL_BUSY *busy;
X+ {
X+ 	long total = 0;
X+ 	register char *s;
X+ 
X+ 	for (s=busy->busy; *s; s++)
X+ 		total += (long) *s;
X+ 
X+ 	return(total==ntohl(busy->chksum));
X  }
X*** /tmp/,RCSt1019480	Fri Aug  7 17:15:57 1987
X--- io.c	Fri Aug  7 17:08:48 1987
X***************
X*** 23,39 ****
X  #define STDIN_MASK (1<<fileno(stdin))	/* the bit mask for standard
X  					   input */
X  extern int errno;
X- 
X  /*
X   * The routine to do the actual talking
X   */
X  talk()
X  {
X! 	register int read_template, sockt_mask;
X  	int read_set, nb;
X  	char buf[BUFSIZ];
X  	struct timeval wait;
X  
X  	message("Connection established\007\007\007");
X  	current_line = 0;
X  	sockt_mask = (1<<sockt);
X--- 23,42 ----
X  #define STDIN_MASK (1<<fileno(stdin))	/* the bit mask for standard
X  					   input */
X  extern int errno;
X  /*
X   * The routine to do the actual talking
X   */
X  talk()
X  {
X! 	register int read_template, sockt_mask, i, j;
X  	int read_set, nb;
X  	char buf[BUFSIZ];
X  	struct timeval wait;
X+ 	static char *chat_mesg = "[I am using the 'chat' interface]\n";
X  
X+ 	if (my_interfac != I_CHAT)
X+ 		*chat_mesg = '\0';
X+ 
X  	message("Connection established\007\007\007");
X  	current_line = 0;
X  	sockt_mask = (1<<sockt);
X***************
X*** 63,70 ****
X  			if (nb <= 0) {
X  				message("Connection closed. Exiting");
X  				quit();
X  			}
X- 			display(&his_win, buf, nb);
X  		}
X  		if (read_set & STDIN_MASK) {
X  			/*
X--- 66,84 ----
X  			if (nb <= 0) {
X  				message("Connection closed. Exiting");
X  				quit();
X+ 			} else {	/* Don't accept ^B and ^N */
X+ 				for (i=j=0; i<nb; i++) {
X+ 					if (buf[i]=='\002' || buf[i]=='\016')
X+ 						continue;
X+ 					buf[j++] = buf[i];
X+ 				}
X+ 				if (j) {	/* use the correct interface */
X+ 					if (my_interfac == I_TALK)
X+ 						talk_display(&his_win, buf, j);
X+ 					else if (my_interfac == I_CHAT)
X+ 						chat_display(&his_win, buf, j);
X+ 				}
X  			}
X  		}
X  		if (read_set & STDIN_MASK) {
X  			/*
X***************
X*** 73,79 ****
X  			 */
X  			ioctl(0, FIONREAD, (struct sgttyb *) &nb);
X  			nb = read(0, buf, nb);
X! 			display(&my_win, buf, nb);
X  			/* might lose data here because sockt is non-blocking */
X  			write(sockt, buf, nb);
X  		}
X--- 87,113 ----
X  			 */
X  			ioctl(0, FIONREAD, (struct sgttyb *) &nb);
X  			nb = read(0, buf, nb);
X! 
X! 			if (my_interfac == I_TALK)
X! 				talk_display(&my_win, buf, nb);
X! 			else if (my_interfac == I_CHAT) {
X! 				for (i=0; i<nb; i++)	/* strip high bit */
X! 					buf[i] &= 0177;
X! 				chat_display(&my_win, buf, nb);
X! 
X! 				/* Do not send the redraw, it looks stupid */
X! 				for (i=j=0; i<nb; i++) {
X! 					if (buf[i] != my_win.redraw)
X! 						buf[j++] = buf[i];
X! 				}
X! 				nb = j;
X! 			}
X! 
X! 			if (*chat_mesg) {   /* inform them we are using chat */
X! 				write(sockt, chat_mesg, strlen(chat_mesg));
X! 				*chat_mesg = '\0';
X! 			}
X! 
X  			/* might lose data here because sockt is non-blocking */
X  			write(sockt, buf, nb);
X  		}
X***************
X*** 96,107 ****
X  	sys = "Unknown error";
X  	if (errno < sys_nerr)
X  		sys = sys_errlist[errno];
X! 	wmove(my_win.x_win, current_line%my_win.x_nlines, 0);
X! 	wprintw(my_win.x_win, "[%s : %s (%d)]\n", string, sys, errno);
X! 	wrefresh(my_win.x_win);
X! 	move(LINES-1, 0);
X! 	refresh();
X! 	quit();
X  }
X  
X  /*
X--- 130,145 ----
X  	sys = "Unknown error";
X  	if (errno < sys_nerr)
X  		sys = sys_errlist[errno];
X! 
X! 	if (my_interfac == I_TALK) {
X! 		wmove(my_win.x_win, current_line%my_win.x_nlines, 0);
X! 		wprintw(my_win.x_win, "[%s : %s (%d)]\n", string, sys, errno);
X! 		wrefresh(my_win.x_win);
X! 		move(LINES-1, 0);
X! 		refresh();
X! 		quit();
X! 	} else if (my_interfac == I_CHAT)
X! 		printf("[%s : %s (%d)]\r\n", string, sys, errno);
X  }
X  
X  /*
X***************
X*** 111,117 ****
X  	char *string;
X  {
X  
X! 	wmove(my_win.x_win, current_line%my_win.x_nlines, 0);
X! 	wprintw(my_win.x_win, "[%s]\n", string);
X! 	wrefresh(my_win.x_win);
X  }
X--- 149,158 ----
X  	char *string;
X  {
X  
X! 	if (my_interfac == I_TALK) {
X! 		wmove(my_win.x_win, current_line%my_win.x_nlines, 0);
X! 		wprintw(my_win.x_win, "[%s]\n", string);
X! 		wrefresh(my_win.x_win);
X! 	} else if (my_interfac == I_CHAT)
X! 		printf("[%s]\r\n", string);
X  }
X*** /tmp/,RCSt1019480	Fri Aug  7 17:16:01 1987
X--- look_up.c	Fri Aug  7 17:08:51 1987
X***************
X*** 10,15 ****
X--- 10,20 ----
X  
X  #include "talk_ctl.h"
X  
X+ #if PYRAMID
X+ #define	htonl(x)	(x)
X+ #define	htons(x)	(x)
X+ #endif
X+ 
X  /*
X   * See if the local daemon has an invitation for us.
X   */
X***************
X*** 17,28 ****
X  {
X  	CTL_RESPONSE response;
X  	register CTL_RESPONSE *rp = &response;
X  
X  	/* the rest of msg was set up in get_names */
X  	msg.ctl_addr = *(struct sockaddr *)&ctl_addr;
X  	msg.ctl_addr.sa_family = htons(msg.ctl_addr.sa_family);
X  	/* must be initiating a talk */
X! 	if (!look_for_invite(rp))
X  		return (0);
X  	/*
X  	 * There was an invitation waiting for us, 
X--- 22,34 ----
X  {
X  	CTL_RESPONSE response;
X  	register CTL_RESPONSE *rp = &response;
X+ 	CTL_BUSY busy;
X  
X  	/* the rest of msg was set up in get_names */
X  	msg.ctl_addr = *(struct sockaddr *)&ctl_addr;
X  	msg.ctl_addr.sa_family = htons(msg.ctl_addr.sa_family);
X  	/* must be initiating a talk */
X! 	if (!look_for_invite(rp, &busy))
X  		return (0);
X  	/*
X  	 * There was an invitation waiting for us, 
X***************
X*** 43,49 ****
X  		 * invitation. (We know there are no newer invitations,
X  		 * the talkd works LIFO.)
X  		 */
X! 		ctl_transact(his_machine_addr, msg, DELETE, rp);
X  		close(sockt);
X  		open_sockt();
X  		return (0);
X--- 49,55 ----
X  		 * invitation. (We know there are no newer invitations,
X  		 * the talkd works LIFO.)
X  		 */
X! 		ctl_transact(his_machine_addr, msg, DELETE, rp, &busy);
X  		close(sockt);
X  		open_sockt();
X  		return (0);
X***************
X*** 55,67 ****
X  /*
X   * Look for an invitation on 'machine'
X   */
X! look_for_invite(rp)
X  	CTL_RESPONSE *rp;
X  {
X  	struct in_addr machine_addr;
X  
X  	current_state = "Checking for invitation on caller's machine";
X! 	ctl_transact(his_machine_addr, msg, LOOK_UP, rp);
X  	/* the switch is for later options, such as multiple invitations */
X  	switch (rp->answer) {
X  
X--- 61,74 ----
X  /*
X   * Look for an invitation on 'machine'
X   */
X! look_for_invite(rp, busy)
X  	CTL_RESPONSE *rp;
X+ 	CTL_BUSY *busy;
X  {
X  	struct in_addr machine_addr;
X  
X  	current_state = "Checking for invitation on caller's machine";
X! 	ctl_transact(his_machine_addr, msg, LOOK_UP, rp, busy);
X  	/* the switch is for later options, such as multiple invitations */
X  	switch (rp->answer) {
X  
X*** /tmp/,RCSt1019480	Fri Aug  7 17:16:05 1987
X--- msgs.c	Fri Aug  7 17:08:54 1987
X***************
X*** 40,46 ****
X  	message(current_state);
X  	signal(SIGALRM, disp_msg);
X  	itimer.it_value = itimer.it_interval = wait;
X! 	setitimer(ITIMER_REAL, &itimer, (struct timerval *)0);
X  }
X  
X  end_msgs()
X--- 40,46 ----
X  	message(current_state);
X  	signal(SIGALRM, disp_msg);
X  	itimer.it_value = itimer.it_interval = wait;
X! 	setitimer(ITIMER_REAL, &itimer, (struct itimerval *)0);
X  }
X  
X  end_msgs()
X***************
X*** 49,53 ****
X  	signal(SIGALRM, SIG_IGN);
X  	timerclear(&itimer.it_value);
X  	timerclear(&itimer.it_interval);
X! 	setitimer(ITIMER_REAL, &itimer, (struct timerval *)0);
X  }
X--- 49,53 ----
X  	signal(SIGALRM, SIG_IGN);
X  	timerclear(&itimer.it_value);
X  	timerclear(&itimer.it_interval);
X! 	setitimer(ITIMER_REAL, &itimer, (struct itimerval *)0);
X  }
X*** /tmp/,RCSt1019480	Fri Aug  7 17:16:08 1987
X--- talk.c	Fri Aug  7 17:08:56 1987
X***************
X*** 16,21 ****
X--- 16,23 ----
X  
X  #include "talk.h"
X  
X+ char my_interfac;	/* set appropriately to I_CHAT or I_TALK */
X+ 
X  /*
X   * talk:	A visual form of write. Using sockets, a two way 
X   *		connection is set up between the two people talking. 
X***************
X*** 28,33 ****
X--- 30,48 ----
X   *		Modified to run under 4.1a by Clem Cole and Peter Moore
X   *		Modified to run between hosts by Peter Moore, 8/19/82
X   *		Modified to run under 4.1c by Peter Moore 3/17/83
X+  *
X+  *	8/11/85		JEF	decvax!sunybcs!forys
X+  *		- Introduced 'chat' interface, 'busy' file and some extra
X+  *		  control codes.
X+  *	11/10/86	JEF	decvax!sunybcs!forys
X+  *		- Ported above changes to 4.3Final.
X+  *
X+  *	1/11/87		JEF	forys@boulder.Colorado.EDU
X+  *		- Added ifdef's for compilation on a variety of machines.
X+  *		- Added one more control code, cleaned my stuff up.
X+  *
X+  *	7/21/87		JEF	forys@boulder.Colorado.EDU
X+  *		- Internet address resolution and 2 more bug fixes.
X   */
X  
X  main(argc, argv)
X*** /tmp/,RCSt1019480	Fri Aug  7 17:16:11 1987
X--- talk.h	Fri Aug  7 17:08:59 1987
X***************
X*** 11,18 ****
X--- 11,26 ----
X  
X  #define forever		for(;;)
X  
X+ #if (SUN3_1 | SUN3_2 | PYRAMID | ULTRIX1_2)
X+ #define	MAXHOSTNAMELEN	64
X+ #endif
X+ 
X  #define BUF_SIZE	512
X+ #define CHAT_SIZ	256
X  
X+ #define I_TALK	0
X+ #define I_CHAT	1
X+ 
X  FILE	*popen();
X  int	quit();
X  int	sleeper();
X***************
X*** 33,40 ****
X--- 41,53 ----
X  	char	kill;
X  	char	cerase;
X  	char	werase;
X+ 	char	redraw;
X+ 	char	chatline[CHAT_SIZ];
X+ 	int	column;
X  } xwin_t;
X  
X  extern	xwin_t my_win;
X  extern	xwin_t his_win;
X  extern	WINDOW *line_win;
X+ 
X+ extern char my_interfac;
________This_Is_The_END________
if test `wc -l < talk_diffs` -ne 1425; then
	echo 'shar: talk_diffs was damaged during transit (should have been 1425 bytes)'
fi
fi		; : end of overwriting check
echo 'x - talkd.h_diffs'
if test -f talkd.h_diffs; then echo 'shar: not overwriting talkd.h_diffs'; else
sed 's/^X//' << '________This_Is_The_END________' > talkd.h_diffs
X*** /tmp/,RCSt1020126	Fri Aug  7 17:48:21 1987
X--- talkd.h	Fri Aug  7 17:47:51 1987
X***************
X*** 57,62 ****
X--- 57,73 ----
X  	struct	sockaddr addr;	/* address for establishing conversation */
X  } CTL_RESPONSE;
X  
X+ /*
X+  * One packet of this type might be sent following PERMISSION_DENIED.
X+  */
X+ typedef struct {
X+ 	long chksum;
X+ #define BUSYSIZE	512
X+ 	char busy[BUSYSIZE];
X+ } CTL_BUSY;
X+ 
X+ #define	BUSYFLNM	".busy"
X+ 
X  #define	TALK_VERSION	1		/* protocol version */
X  
X  /* message type values */
________This_Is_The_END________
if test `wc -l < talkd.h_diffs` -ne 22; then
	echo 'shar: talkd.h_diffs was damaged during transit (should have been 22 bytes)'
fi
fi		; : end of overwriting check
exit 0

forys@boulder.Colorado.EDU (Jeff Forys) (08/11/87)

What follows is a set of patches that will enhance `talk' as
distributed with 4.3BSD.  No functionality is lost if these patches
are applied (i.e. it is still compatible with other machines who
run stock 4.3BSD talk).  Here is a summary of what the patches do:

	1) Fix a bug in 4.3BSD talk which results in bogus error
	   messages being displayed under various circumstances.
	   I posted this fix back in November, everyone should
	   apply it, hence it is separate from the `enhancements'.

	2) Makes the 4.3BSD version of talk portable to the following
	   flavours of Unix: Pyramid (OSx2.5,OSx3.1,OSx4.0), Ultrix (1.2),
	   Sun (3.0,3.1,3.2).  This is nice, since few of these speak the
	   4.3BSD talk protocol; it'll probably port to 4.2BSD with OSx2.5.

	3) Allow for special control codes to be expanded locally.
	   (e.g. ^A maps into "<go ahead>", ^N displays a menu, etc)
	   While it is possible to send the *mappings* out to people
	   not running these enhancements, doing it `right' requires
	   awful code (e.g. some control chars are only meaningful
	   locally and shouldnt be sent).  Instead, because of #2
	   above (easy portability), we simply run it everywhere here.

	4) Resolve internet addresses (e.g. 128.138.240.1) so that
	   things like `talk user@128.138.240.1' will work, and
	   talkd may display "respond with: talk user@128.138.240.1".
	   (this is good for internet hosts that dont yet run a
	   nameserver, and dont have up-to-date /etc/hosts files)

	5) If a person you are trying to contact has messages off,
	   and they have a file called ".busy" in their home directory,
	   it will be sent to you and displayed in their half of the
	   screen.  The file generally contains the `reason' your
	   messages are off.

	6) A "dumb terminal" interface called `chat'.  This is good
	   for consoles and terminals without termcaps.  `chat' is
	   hard-linked to `talk' and each does the right thing.

	7) A revised manual page explaining these enhancements.

One thing that would be easy to add to the talk daemon, and probably will
be added in the future (if you or I ever get the time) is a ".talkrc" file
that would contain options to:

	1) list people you will talk to (when your messages are off).
	2) list people who you wont talk to even though your messages are on.

I have tested these `enhancements' under many circumstances for
compatibility with 4.3BSD.  Most of these mods have been running for
a couple years and I've fixed any little bugs that have since appeared.
Finally, this is available via anonymous ftp from boulder.Colorado.EDU.

What follows, is a shar archive containing the files:

	4.3talk_fix   - a fix that should be applied to every 4.3BSD talk.
	talk.1_diffs  - patch to /usr/man/man1/talk.1 (move the patched
			file to /usr/src/ucb/talk/talk.1 for `make install')
	talk_diffs    - patches for talk; cd /usr/src/ucb/talk & patch...
	talkd_diffs   - patches for talkd; cd /usr/src/etc/talkd & patch...
	talkd.h_diffs - patch to /usr/include/protocols/talkd.h

[I split talkd_diffs into a separate file because of the 64K message limit
on some machines.  ++bsa]

If you make any changes or fix a bug, please let me know... thanks!
---
Jeff Forys @ UC/Boulder Engineering Research Comp Cntr (303-492-4991)
forys@boulder.Colorado.Edu  -or-  ..!{hao|nbires}!boulder!forys

#--------------------------------CUT HERE-------------------------------------
#! /bin/sh
#
# This is a shell archive.  Save this into a file, edit it
# and delete all lines above this comment.  Then give this
# file to sh by executing the command "sh file".  The files
# will be extracted into the current directory owned by
# you with default permissions.
#
# The files contained herein are:
#
# -rw-r--r--   1 allbery  System     21740 Aug 10 20:03 talkd_diffs
#
echo 'x - talkd_diffs'
if test -f talkd_diffs; then echo 'shar: not overwriting talkd_diffs'; else
sed 's/^X//' << '________This_Is_The_END________' > talkd_diffs
X*** /tmp/,RCSt1019995	Fri Aug  7 17:43:15 1987
X--- Makefile	Fri Aug  7 17:40:42 1987
X***************
X*** 3,14 ****
X  # All rights reserved.  The Berkeley software License Agreement
X  # specifies the terms and conditions for redistribution.
X  #
X! #	@(#)Makefile	5.4 (Berkeley) 3/13/86
X  #
X! DESTDIR=
X  OBJS=	talkd.o announce.o process.o table.o print.o
X  SRCS=	talkd.c announce.c process.c table.c print.c
X- CFLAGS= -O
X  
X  all:	talkd
X  
X--- 3,56 ----
X  # All rights reserved.  The Berkeley software License Agreement
X  # specifies the terms and conditions for redistribution.
X  #
X! #	@(#)Makefile	5.4.1 (Berkeley) 3/13/86
X  #
X! 
X! #	Sun Jan 11 20:08:22 MST 1987	JEF	forys@Boulder.Colorado.Edu
X! #	Conditional compilations for different machines...
X! #
X! #	4.3 BSD
X! CFLAGS=-O
X! DESTDIR=/etc/ntalkd
X! #
X! #	Pyramid OSx2.5
X! #CFLAGS=-O -DPYRAMID -DNO_INETD
X! #DESTDIR=/etc/ntalkd
X! #
X! #	Pyramid OSx3.1
X! #CFLAGS=-O -DPYRAMID
X! #DESTDIR=/usr/etc/in.ntalkd
X! #
X! #	Pyramid OSx4.0
X! #CFLAGS=-O -DPYRAMID -DBSD4_3
X! #DESTDIR=/etc/ntalkd
X! #
X! #	Sun 3.1, 3.0
X! #CFLAGS=-O -DSUN3_1
X! #DESTDIR=/usr/etc/in.ntalkd
X! #
X! #	Sun 3.2
X! #CFLAGS=-O -DSUN3_2
X! #DESTDIR=/usr/etc/in.ntalkd
X! #
X! #	Ultrix 1.2
X! #CFLAGS=-O -DULTRIX1_2
X! #DESTDIR=/etc/ntalkd
X! #
X! #	If you are trying to get this to run under a different
X! #	system, the following should help:
X! #		NO_INETD - compile in code to listen for connections
X! #		PYRAMID - defines for byte order stuff, old syslog, 
X! #		SUN3_1 - old 4.2 syslog
X! #		SUN3_2 - old 4.2 syslog
X! #		ULTRIX1_2 - old 4.2 syslog
X! #	We no longer have 4.2BSD machines around, but I'm sure they'll
X! #	need NO_INETD and the old syslog stuff...
X! 
X! MANDIR=/usr/man/man1
X! 
X  OBJS=	talkd.o announce.o process.o table.o print.o
X  SRCS=	talkd.c announce.c process.c table.c print.c
X  
X  all:	talkd
X  
X***************
X*** 16,22 ****
X  	cc ${CFLAGS} -o talkd ${OBJS}
X  
X  install: talkd
X! 	install -s talkd ${DESTDIR}/etc/ntalkd
X  
X  clean:
X  	rm -f ${OBJS} errs core a.out talkd
X--- 58,64 ----
X  	cc ${CFLAGS} -o talkd ${OBJS}
X  
X  install: talkd
X! 	install -s talkd ${DESTDIR}
X  
X  clean:
X  	rm -f ${OBJS} errs core a.out talkd
X***************
X*** 26,32 ****
X  
X  depend: ${SRCS}
X  	for i in ${SRCS}; do \
X! 	    cc -M $$i | sed 's/\.o//' | \
X  	    awk ' { if ($$1 != prev) \
X  		{ if (rec != "") print rec; rec = $$0; prev = $$1; } \
X  		else { if (length(rec $$2) > 78) { print rec; rec = $$0; } \
X--- 68,74 ----
X  
X  depend: ${SRCS}
X  	for i in ${SRCS}; do \
X! 	    cc -M ${CFLAGS} $$i | sed 's/\.o//' | \
X  	    awk ' { if ($$1 != prev) \
X  		{ if (rec != "") print rec; rec = $$0; prev = $$1; } \
X  		else { if (length(rec $$2) > 78) { print rec; rec = $$0; } \
X***************
X*** 52,63 ****
X  announce: /usr/include/sys/ttychars.h /usr/include/sys/ttydev.h
X  announce: /usr/include/sys/ioctl.h /usr/include/sys/time.h /usr/include/time.h
X  announce: /usr/include/stdio.h /usr/include/sys/wait.h /usr/include/errno.h
X! announce: /usr/include/syslog.h /usr/include/protocols/talkd.h
X! announce: /usr/include/sys/types.h /usr/include/sys/socket.h
X  process: process.c /usr/include/sys/types.h /usr/include/sys/stat.h
X  process: /usr/include/stdio.h /usr/include/syslog.h /usr/include/netdb.h
X! process: /usr/include/netinet/in.h /usr/include/protocols/talkd.h
X! process: /usr/include/sys/types.h /usr/include/sys/socket.h /usr/include/utmp.h
X  table: table.c /usr/include/stdio.h /usr/include/sys/time.h /usr/include/time.h
X  table: /usr/include/syslog.h /usr/include/protocols/talkd.h
X  table: /usr/include/sys/types.h /usr/include/sys/socket.h
X--- 94,109 ----
X  announce: /usr/include/sys/ttychars.h /usr/include/sys/ttydev.h
X  announce: /usr/include/sys/ioctl.h /usr/include/sys/time.h /usr/include/time.h
X  announce: /usr/include/stdio.h /usr/include/sys/wait.h /usr/include/errno.h
X! announce: /usr/include/syslog.h /usr/include/strings.h /usr/include/pwd.h
X! announce: /usr/include/protocols/talkd.h /usr/include/sys/types.h
X! announce: /usr/include/sys/socket.h
X  process: process.c /usr/include/sys/types.h /usr/include/sys/stat.h
X  process: /usr/include/stdio.h /usr/include/syslog.h /usr/include/netdb.h
X! process: /usr/include/netinet/in.h /usr/include/sys/param.h
X! process: /usr/include/machine/machparam.h /usr/include/signal.h
X! process: /usr/include/sys/types.h /usr/include/protocols/talkd.h
X! process: /usr/include/sys/types.h /usr/include/sys/socket.h
X! process: /usr/include/arpa/inet.h /usr/include/utmp.h
X  table: table.c /usr/include/stdio.h /usr/include/sys/time.h /usr/include/time.h
X  table: /usr/include/syslog.h /usr/include/protocols/talkd.h
X  table: /usr/include/sys/types.h /usr/include/sys/socket.h
X*** /tmp/,RCSt1019995	Fri Aug  7 17:43:18 1987
X--- announce.c	Fri Aug  7 17:40:46 1987
X***************
X*** 17,25 ****
X--- 17,34 ----
X  #include <sys/wait.h>
X  #include <errno.h>
X  #include <syslog.h>
X+ #include <strings.h>
X+ #include <pwd.h>
X  
X  #include <protocols/talkd.h>
X  
X+ #if PYRAMID
X+ #define	ntohl(x)	(x)
X+ #define	ntohs(x)	(x)
X+ #define	htonl(x)	(x)
X+ #define	htons(x)	(x)
X+ #endif
X+ 
X  extern	int errno;
X  extern	char hostname[];
X  
X***************
X*** 30,45 ****
X   * process to any terminal that it writes on, we must fork a child
X   * to protect ourselves
X   */
X! announce(request, remote_machine)
X  	CTL_MSG *request;
X  	char *remote_machine;
X  {
X  	int pid, val, status;
X  
X  	if (pid = fork()) {
X  		/* we are the parent, so wait for the child */
X! 		if (pid == -1)		/* the fork failed */
X  			return (FAILED);
X  		do {
X  			val = wait(&status);
X  			if (val == -1) {
X--- 39,63 ----
X   * process to any terminal that it writes on, we must fork a child
X   * to protect ourselves
X   */
X! announce(request, remote_machine, busy)
X  	CTL_MSG *request;
X  	char *remote_machine;
X+ 	CTL_BUSY *busy;
X  {
X  	int pid, val, status;
X+ 	int fd[2];
X  
X+ 	if (pipe(fd) < 0)	/* need a pipe to return .busy from child */
X+ 		return(FAILED);
X+ 
X  	if (pid = fork()) {
X  		/* we are the parent, so wait for the child */
X! 		if (pid == -1) {	/* the fork failed */
X! 			close(fd[0]);
X! 			close(fd[1]);
X  			return (FAILED);
X+ 		}
X+ 
X  		do {
X  			val = wait(&status);
X  			if (val == -1) {
X***************
X*** 46,71 ****
X  				if (errno == EINTR)
X  					continue;
X  				/* shouldn't happen */
X  				syslog(LOG_WARNING, "announce: wait: %m");
X  				return (FAILED);
X  			}
X  		} while (val != pid);
X! 		if (status&0377 > 0)	/* we were killed by some signal */
X  			return (FAILED);
X  		/* Get the second byte, this is the exit/return code */
X! 		return ((status >> 8) & 0377);
X  	}
X  	/* we are the child, go and do it */
X! 	_exit(announce_proc(request, remote_machine));
X  }
X! 	
X  /*
X   * See if the user is accepting messages. If so, announce that 
X   * a talk is requested.
X   */
X! announce_proc(request, remote_machine)
X  	CTL_MSG *request;
X  	char *remote_machine;
X  {
X  	int pid, status;
X  	char full_tty[32];
X--- 64,101 ----
X  				if (errno == EINTR)
X  					continue;
X  				/* shouldn't happen */
X+ 				close(fd[0]);
X+ 				close(fd[1]);
X  				syslog(LOG_WARNING, "announce: wait: %m");
X  				return (FAILED);
X  			}
X  		} while (val != pid);
X! 		if (status&0377 > 0) {	/* we were killed by some signal */
X! 			close(fd[0]);
X! 			close(fd[1]);
X  			return (FAILED);
X+ 		}
X  		/* Get the second byte, this is the exit/return code */
X! 		status = (status >> 8) & 0377;
X! 
X! 		if (status == PERMISSION_DENIED)	/* get .busy file */
X! 			get_busy(fd[0], busy);
X! 		close(fd[0]);
X! 		close(fd[1]);
X! 		return(status);
X  	}
X  	/* we are the child, go and do it */
X! 	_exit(announce_proc(request, remote_machine, fd[1]));
X  }
X! 
X  /*
X   * See if the user is accepting messages. If so, announce that 
X   * a talk is requested.
X   */
X! announce_proc(request, remote_machine, fd_write)
X  	CTL_MSG *request;
X  	char *remote_machine;
X+ 	int fd_write;
X  {
X  	int pid, status;
X  	char full_tty[32];
X***************
X*** 75,82 ****
X  	sprintf(full_tty, "/dev/%s", request->r_tty);
X  	if (access(full_tty, 0) != 0)
X  		return (FAILED);
X! 	if ((tf = fopen(full_tty, "w")) == NULL)
X  		return (PERMISSION_DENIED);
X  	/*
X  	 * On first tty open, the server will have
X  	 * it's pgrp set, so disconnect us from the
X--- 105,114 ----
X  	sprintf(full_tty, "/dev/%s", request->r_tty);
X  	if (access(full_tty, 0) != 0)
X  		return (FAILED);
X! 	if ((tf = fopen(full_tty, "w")) == NULL) {
X! 		refuse(request->r_name, fd_write);
X  		return (PERMISSION_DENIED);
X+ 	}
X  	/*
X  	 * On first tty open, the server will have
X  	 * it's pgrp set, so disconnect us from the
X***************
X*** 83,92 ****
X  	 * tty before we catch a signal.
X  	 */
X  	ioctl(fileno(tf), TIOCNOTTY, (struct sgttyb *) 0);
X! 	if (fstat(fileno(tf), &stbuf) < 0)
X  		return (PERMISSION_DENIED);
X! 	if ((stbuf.st_mode&020) == 0)
X  		return (PERMISSION_DENIED);
X  	print_mesg(tf, request, remote_machine);
X  	fclose(tf);
X  	return (SUCCESS);
X--- 115,128 ----
X  	 * tty before we catch a signal.
X  	 */
X  	ioctl(fileno(tf), TIOCNOTTY, (struct sgttyb *) 0);
X! 	if (fstat(fileno(tf), &stbuf) < 0) {
X! 		refuse(request->r_name, fd_write);
X  		return (PERMISSION_DENIED);
X! 	}
X! 	if ((stbuf.st_mode&020) == 0) {
X! 		refuse(request->r_name, fd_write);
X  		return (PERMISSION_DENIED);
X+ 	}
X  	print_mesg(tf, request, remote_machine);
X  	fclose(tf);
X  	return (SUCCESS);
X***************
X*** 154,161 ****
X  		while (*lptr != '\0')
X  			*(bptr++) = *(lptr++);
X  		/* pad out the rest of the lines with blanks */
X! 		for (j = sizes[i]; j < max_size + 2; j++)
X  			*(bptr++) = ' ';
X  		*(bptr++) = '\r';	/* add a \r in case of raw mode */
X  		*(bptr++) = '\n';
X  	}
X--- 190,198 ----
X  		while (*lptr != '\0')
X  			*(bptr++) = *(lptr++);
X  		/* pad out the rest of the lines with blanks */
X! 		for (j = sizes[i]; j < max_size + 2; j++) {
X  			*(bptr++) = ' ';
X+ 		}
X  		*(bptr++) = '\r';	/* add a \r in case of raw mode */
X  		*(bptr++) = '\n';
X  	}
X***************
X*** 163,166 ****
X--- 200,272 ----
X  	fprintf(tf, big_buf);
X  	fflush(tf);
X  	ioctl(fileno(tf), TIOCNOTTY, (struct sgttyb *) 0);
X+ }
X+ 
X+ refuse(r_name, fd_write)	/* try to find out why user is unsociable */
X+ char *r_name;
X+ int fd_write;
X+ {
X+ 	register FILE *fpr;
X+ 	char bpth[100];			/* homedirectory/BUSYFLNM */
X+ 	char bufr[BUSYSIZE];		/* contents of BUSYFLNM */
X+ 	register int c, i=0;
X+ 	struct passwd *my_getpwnam();
X+ 
X+ 	*bufr = '\0';
X+ 	(void) strcat(strcat(strcpy(bpth, my_getpwnam(r_name)->pw_dir), "/"),
X+ 		      BUSYFLNM);
X+ 	if ((fpr=fopen(bpth, "r")) != NULL) {	/* file exists */
X+ 		while ((c=getc(fpr)) != EOF && i<BUSYSIZE-1)
X+ 			bufr[i++] = c;		/* read file to buffer */
X+ 		bufr[i] = '\0';
X+ 		(void) fclose(fpr);
X+ 	}
X+ 	(void) write(fd_write, bufr, BUSYSIZE);	/* write to pipe */
X+ }
X+ 
X+ get_busy(fd_read, busy)		/* read from pipe into CTL_BUSY */
X+ int fd_read;
X+ CTL_BUSY *busy;
X+ {
X+ 	register int i;
X+ 
X+ 	busy->chksum = (long) 0;	/* We also want a check sum */
X+ 
X+ 	(void) read(fd_read, busy->busy, BUSYSIZE);	/* Read from pipe */
X+ 
X+ 	for (i=0; i<BUSYSIZE && busy->busy[i]; i++)	/* Compute checksum */
X+ 		busy->chksum += (long) busy->busy[i];
X+ 	busy->chksum = htonl(busy->chksum);
X+ }
X+ 
X+ /*
X+  *	I had to write my own 'getpwnam' because the one that is
X+  *	provided seems to have an obscure bug in it.  The problem
X+  *	was tracked down to 'endpwent' which calls 'dbm_close'
X+  *	which makes a call to 'free' (and promptly dies).  My
X+  *	solution was to simply eliminate the call to 'endpwent'
X+  *	because if this code was executed, the user must have had
X+  *	his messages off and the daemon will die (thus closing the
X+  *	database files).  Even if the daemon doesn't die quickly
X+  *	and this procedure is called again, 'setpwent' knows that
X+  *	the database is still open and just rewinds it.
X+  *
X+  *	Incidentally, when I used 'endpwent', talk responded:
X+  *
X+  *		[No connection yet]
X+  *		[Target machine is too confused to talk to us]
X+  *		<exit>
X+  */
X+ 
X+ struct passwd *my_getpwnam(usrnam)	/* getpwnam without call to endpwent */
X+ char *usrnam;
X+ {
X+ 	struct passwd *pw;
X+ 
X+ 	(void) setpwent();		/* Open password file */
X+ 
X+ 	while ((pw = getpwent()) && strcmp(usrnam, pw->pw_name))
X+ 		;	/* Find the right entry */
X+ 
X+ 	return(pw);	/* It MUST exist (user is logged in), just return it */
X  }
X*** /tmp/,RCSt1019995	Fri Aug  7 17:43:21 1987
X--- print.c	Fri Aug  7 17:40:50 1987
X***************
X*** 15,20 ****
X--- 15,27 ----
X  
X  #include <protocols/talkd.h>
X  
X+ #if PYRAMID
X+ #define	ntohl(x)	(x)
X+ #define	ntohs(x)	(x)
X+ #define	htonl(x)	(x)
X+ #define	htons(x)	(x)
X+ #endif
X+ 
X  static	char *types[] =
X      { "leave_invite", "look_up", "delete", "announce" };
X  #define	NTYPES	(sizeof (types) / sizeof (types[0]))
X*** /tmp/,RCSt1019995	Fri Aug  7 17:43:24 1987
X--- process.c	Fri Aug  7 17:40:55 1987
X***************
X*** 22,37 ****
X  #include <syslog.h>
X  #include <netdb.h>
X  #include <netinet/in.h>
X  
X  #include <protocols/talkd.h>
X  
X  char	*strcpy();
X  CTL_MSG *find_request();
X  CTL_MSG *find_match();
X  
X! process_request(mp, rp)
X  	register CTL_MSG *mp;
X  	register CTL_RESPONSE *rp;
X  {
X  	register CTL_MSG *ptr;
X  	extern int debug;
X--- 22,48 ----
X  #include <syslog.h>
X  #include <netdb.h>
X  #include <netinet/in.h>
X+ #include <sys/param.h>
X  
X  #include <protocols/talkd.h>
X  
X+ #if PYRAMID
X+ #define	ntohl(x)	(x)
X+ #define	ntohs(x)	(x)
X+ #define	htonl(x)	(x)
X+ #define	htons(x)	(x)
X+ #else /* I wont explain this one; simply believe me -- pyramids hate it */
X+ #include <arpa/inet.h>
X+ #endif
X+ 
X  char	*strcpy();
X  CTL_MSG *find_request();
X  CTL_MSG *find_match();
X  
X! process_request(mp, rp, busy)
X  	register CTL_MSG *mp;
X  	register CTL_RESPONSE *rp;
X+ 	CTL_BUSY *busy;
X  {
X  	register CTL_MSG *ptr;
X  	extern int debug;
X***************
X*** 38,44 ****
X  
X  	rp->vers = TALK_VERSION;
X  	rp->type = mp->type;
X! 	rp->id_num = htonl(0);
X  	if (mp->vers != TALK_VERSION) {
X  		syslog(LOG_WARNING, "Bad protocol version %d", mp->vers);
X  		rp->answer = BADVERSION;
X--- 49,55 ----
X  
X  	rp->vers = TALK_VERSION;
X  	rp->type = mp->type;
X! 	rp->id_num = htonl((long)0);
X  	if (mp->vers != TALK_VERSION) {
X  		syslog(LOG_WARNING, "Bad protocol version %d", mp->vers);
X  		rp->answer = BADVERSION;
X***************
X*** 65,71 ****
X  	switch (mp->type) {
X  
X  	case ANNOUNCE:
X! 		do_announce(mp, rp);
X  		break;
X  
X  	case LEAVE_INVITE:
X--- 76,82 ----
X  	switch (mp->type) {
X  
X  	case ANNOUNCE:
X! 		do_announce(mp, rp, busy);
X  		break;
X  
X  	case LEAVE_INVITE:
X***************
X*** 100,108 ****
X  		print_response("process_request", rp);
X  }
X  
X! do_announce(mp, rp)
X  	register CTL_MSG *mp;
X  	CTL_RESPONSE *rp;
X  {
X  	struct hostent *hp;
X  	CTL_MSG *ptr;
X--- 111,120 ----
X  		print_response("process_request", rp);
X  }
X  
X! do_announce(mp, rp, busy)
X  	register CTL_MSG *mp;
X  	CTL_RESPONSE *rp;
X+ 	CTL_BUSY *busy;
X  {
X  	struct hostent *hp;
X  	CTL_MSG *ptr;
X***************
X*** 110,130 ****
X  
X  	/* see if the user is logged */
X  	result = find_user(mp->r_name, mp->r_tty);
X! 	if (result != SUCCESS) {
X  		rp->answer = result;
X  		return;
X  	}
X  #define	satosin(sa)	((struct sockaddr_in *)(sa))
X! 	hp = gethostbyaddr(&satosin(&mp->ctl_addr)->sin_addr,
X  		sizeof (struct in_addr), AF_INET);
X! 	if (hp == (struct hostent *)0) {
X! 		rp->answer = MACHINE_UNKNOWN;
X! 		return;
X  	}
X  	ptr = find_request(mp);
X  	if (ptr == (CTL_MSG *) 0) {
X  		insert_table(mp, rp);
X! 		rp->answer = announce(mp, hp->h_name);
X  		return;
X  	}
X  	if (mp->id_num > ptr->id_num) {
X--- 122,164 ----
X  
X  	/* see if the user is logged */
X  	result = find_user(mp->r_name, mp->r_tty);
X! 	if (result != SUCCESS && result != PERMISSION_DENIED) {
X  		rp->answer = result;
X  		return;
X  	}
X  #define	satosin(sa)	((struct sockaddr_in *)(sa))
X! 	hp = gethostbyaddr((char *) &satosin(&mp->ctl_addr)->sin_addr,
X  		sizeof (struct in_addr), AF_INET);
X! 	if (hp == (struct hostent *) 0) {
X! 		static struct hostent def;
X! 		static struct in_addr defaddr;
X! 		static char *iaddr_str;
X! #ifdef BSD4_3
X! 		static char *alist[1];
X! #endif
X! 		static char namebuf[128];
X! 
X! 		iaddr_str = (char *)inet_ntoa(satosin(&mp->ctl_addr)->sin_addr);
X! 		defaddr.s_addr = inet_addr(iaddr_str);
X! 		if (defaddr.s_addr == -1) {
X! 			rp->answer = MACHINE_UNKNOWN;
X! 			return;
X! 		}
X! 		strcpy(namebuf, iaddr_str);
X! 		def.h_name = namebuf;
X! #ifdef BSD4_3
X! 		def.h_addr_list = alist,
X! #endif
X! 		def.h_addr = (char *)&defaddr;
X! 		def.h_length = sizeof (struct in_addr);
X! 		def.h_addrtype = AF_INET;
X! 		def.h_aliases = 0;
X! 		hp = &def;
X  	}
X  	ptr = find_request(mp);
X  	if (ptr == (CTL_MSG *) 0) {
X  		insert_table(mp, rp);
X! 		rp->answer = announce(mp, hp->h_name, busy);
X  		return;
X  	}
X  	if (mp->id_num > ptr->id_num) {
X***************
X*** 134,140 ****
X  		 */
X  		ptr->id_num = new_id();
X  		rp->id_num = htonl(ptr->id_num);
X! 		rp->answer = announce(mp, hp->h_name);
X  	} else {
X  		/* a duplicated request, so ignore it */
X  		rp->id_num = htonl(ptr->id_num);
X--- 168,174 ----
X  		 */
X  		ptr->id_num = new_id();
X  		rp->id_num = htonl(ptr->id_num);
X! 		rp->answer = announce(mp, hp->h_name, busy);
X  	} else {
X  		/* a duplicated request, so ignore it */
X  		rp->id_num = htonl(ptr->id_num);
X*** /tmp/,RCSt1019995	Fri Aug  7 17:43:28 1987
X--- table.c	Fri Aug  7 17:40:59 1987
X***************
X*** 22,27 ****
X--- 22,34 ----
X  
X  #include <protocols/talkd.h>
X  
X+ #if PYRAMID
X+ #define	ntohl(x)	(x)
X+ #define	ntohs(x)	(x)
X+ #define	htonl(x)	(x)
X+ #define	htons(x)	(x)
X+ #endif
X+ 
X  #define MAX_ID 16000	/* << 2^15 so I don't have sign troubles */
X  
X  #define NIL ((TABLE_ENTRY *)0)
X*** /tmp/,RCSt1019995	Fri Aug  7 17:43:31 1987
X--- talkd.c	Fri Aug  7 17:41:04 1987
X***************
X*** 27,36 ****
X  
X  #include <protocols/talkd.h>
X  
X  CTL_MSG		request;
X  CTL_RESPONSE	response;
X  
X! int	sockt;
X  int	debug = 0;
X  int	timeout();
X  long	lastmsgtime;
X--- 27,43 ----
X  
X  #include <protocols/talkd.h>
X  
X+ #ifdef NO_INETD
X+ #include <netinet/in.h>
X+ #include <sys/ioctl.h>
X+ #include <netdb.h>
X+ #endif
X+ 
X  CTL_MSG		request;
X  CTL_RESPONSE	response;
X+ CTL_BUSY	busy;
X  
X! int	sockt = 0;
X  int	debug = 0;
X  int	timeout();
X  long	lastmsgtime;
X***************
X*** 37,42 ****
X--- 44,54 ----
X  
X  char	hostname[32];
X  
X+ #ifdef NO_INETD
X+ struct	sockaddr_in sin = { AF_INET };
X+ u_short	port = 0;
X+ #endif
X+ 
X  #define TIMEOUT 30
X  #define MAXIDLE 120
X  
X***************
X*** 44,49 ****
X--- 56,66 ----
X  	int argc;
X  	char *argv[];
X  {
X+ #ifdef NO_INETD
X+ 	struct servent *sp, *getservbyname();
X+ 	struct sockaddr_in from;
X+ 	int fromlen;
X+ #endif
X  	register CTL_MSG *mp = &request;
X  	int cc;
X  
X***************
X*** 51,57 ****
X--- 68,79 ----
X  		fprintf(stderr, "%s: getuid: not super-user", argv[0]);
X  		exit(1);
X  	}
X+ #if (SUN3_1 | SUN3_2 | PYRAMID | ULTRIX1_2)
X+ 	openlog("talkd", LOG_PID);
X+ #else
X  	openlog("talkd", LOG_PID, LOG_DAEMON);
X+ #endif
X+ 
X  	if (gethostname(hostname, sizeof (hostname) - 1) < 0) {
X  		syslog(LOG_ERR, "gethostname: %m");
X  		_exit(1);
X***************
X*** 62,73 ****
X  	}
X  	if (argc > 1 && strcmp(argv[1], "-d") == 0)
X  		debug = 1;
X  	signal(SIGALRM, timeout);
X  	alarm(TIMEOUT);
X  	for (;;) {
X  		extern int errno;
X  
X! 		cc = recv(0, (char *)mp, sizeof (*mp), 0);
X  		if (cc != sizeof (*mp)) {
X  			if (cc < 0 && errno != EINTR)
X  				syslog(LOG_WARNING, "recv: %m");
X--- 84,130 ----
X  	}
X  	if (argc > 1 && strcmp(argv[1], "-d") == 0)
X  		debug = 1;
X+ 
X+ #ifdef NO_INETD
X+ 	if ((sp=getservbyname("ntalk", "udp")) == (struct servent *) 0) {
X+ 		syslog(LOG_ERR, "gethostbyname: %m");
X+ 		_exit(1);
X+ 	}
X+ 	port = sp->s_port;
X+ 
X+ 	if ((sockt=socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
X+ 		syslog(LOG_ERR, "socket: %m");
X+ 		_exit(1);
X+ 	}
X+ 
X+ 	bzero((char *)&sin, sizeof(sin));
X+ 	sin.sin_addr.s_addr = INADDR_ANY;
X+ 	sin.sin_port = port;
X+ 	sin.sin_family = AF_INET;
X+ 
X+ 	if (bind(sockt, (caddr_t)&sin, sizeof(sin)) < 0) {
X+ 		syslog(LOG_ERR, "bind: %m");
X+ 		_exit(1);
X+ 	}
X+ 
X+ 	if (fork())
X+ 		_exit(0);
X+ 	setup_descriptors(sockt);
X+ 
X+ #else
X  	signal(SIGALRM, timeout);
X  	alarm(TIMEOUT);
X+ #endif
X  	for (;;) {
X  		extern int errno;
X  
X! #ifdef NO_INETD
X! 		fromlen = sizeof(from);
X! 		cc = recvfrom(sockt, (char *)mp,
X! 		    sizeof (*mp), 0, &from, &fromlen);
X! #else
X! 		cc = recv(sockt, (char *)mp, sizeof (*mp), 0);
X! #endif
X  		if (cc != sizeof (*mp)) {
X  			if (cc < 0 && errno != EINTR)
X  				syslog(LOG_WARNING, "recv: %m");
X***************
X*** 74,85 ****
X  			continue;
X  		}
X  		lastmsgtime = time(0);
X! 		process_request(mp, &response);
X  		/* can block here, is this what I want? */
X  		cc = sendto(sockt, (char *)&response,
X  		    sizeof (response), 0, &mp->ctl_addr, sizeof (mp->ctl_addr));
X  		if (cc != sizeof (response))
X  			syslog(LOG_WARNING, "sendto: %m");
X  	}
X  }
X  
X--- 131,151 ----
X  			continue;
X  		}
X  		lastmsgtime = time(0);
X! 		process_request(mp, &response, &busy);
X  		/* can block here, is this what I want? */
X  		cc = sendto(sockt, (char *)&response,
X  		    sizeof (response), 0, &mp->ctl_addr, sizeof (mp->ctl_addr));
X  		if (cc != sizeof (response))
X  			syslog(LOG_WARNING, "sendto: %m");
X+ 
X+ 		if (response.answer == PERMISSION_DENIED) {
X+ 			/* send reason why this party is refusing messages */
X+ 
X+ 			cc = sendto(sockt, (char *) &busy, sizeof(busy), 0,
X+ 				&request.ctl_addr, sizeof(request.ctl_addr));
X+ 			if (cc != sizeof(busy))
X+ 				syslog(LOG_WARNING, "sendto: %m");
X+ 		}
X  	}
X  }
X  
X***************
X*** 90,92 ****
X--- 156,181 ----
X  		_exit(0);
X  	alarm(TIMEOUT);
X  }
X+ 
X+ #ifdef NO_INETD
X+ setup_descriptors(sockt)
X+ int sockt;
X+ {
X+ 	int i, tty;
X+ 
X+ 	if (sockt != 0)
X+ 		(void) close(0);
X+ 
X+ 	i = open("/dev/null", 0);
X+ 	if (sockt != 1)
X+ 		(void) dup2(i, 1);
X+ 	if (sockt != 2)
X+ 		(void) dup2(i, 2);
X+ 
X+ 	if ((tty=open("/dev/tty", 0)) != -1) {
X+ 		ioctl(tty, TIOCNOTTY, (struct sgttyb *) 0);
X+ 		(void) close(tty);
X+ 	} else
X+ 		setpgrp(0, getpid());
X+ }
X+ #endif
________This_Is_The_END________
if test `wc -l < talkd_diffs` -ne 840; then
	echo 'shar: talkd_diffs was damaged during transit (should have been 840 bytes)'
fi
fi		; : end of overwriting check
exit 0