vtalk - Voice Talk for SparcStations

Gunnar Forsgren gunnar at falcon.ericsson.se
Fri Dec 21 01:50:59 AEST 1990


'vtalk' is a program that allows two users of Sun SparcStations
to communicate with each other by means of the human voice.
Each partcipant much have a michrophone connected to the
audio port. Voice data is sampled and transmitted as packets
over Ethernet and played on the speaker of the other workstation.
The same sequence occurs in parallell in the opposite direction.
The syntax is the same as for the standard 'talk' command. 

I have modified 'vtalk' for SunOS 4.1, added a man page, etc.

I have tried it and talking is much like making
an overseas call; Voice is delayed appr. 0.5 seconds
from michrophone to the receiving SparcStation.

-------------------------------------------------------------------
                       Gunnar Forsgren
             (__)      Ericsson Telecom AB     
             (oo)      Department for Standard Computer Systems	
      /-------\/       126 25 Stockholm
     / |  G  ||        SWEDEN
    *  ||----||        email: gunnar%beppe.ericsson.se at uunet.uu.net
       ~~    ~~
-------------------------------------------------------------------
#!/bin/sh
# This is a shell archive (produced by shar 3.49)
# To extract the files from this archive, save it to a file, remove
# everything above the "!/bin/sh" line above, and type "sh file_name".
#
# made 12/20/1990 14:48 UTC by gunnar at falcon
# Source directory /usr/local/src/vtalk
#
# existing files will NOT be overwritten unless -c is specified
#
# This shar contains:
# length  mode       name
# ------ ---------- ------------------------------------------
#   2954 -rw-r--r-- README
#   1389 -rw-r--r-- Makefile
#   2653 -rw-r--r-- vtalk.1
#   2091 -rw-r--r-- audio.c
#   6864 -rw-r--r-- netwk.c
#    547 -rw-r--r-- netwk.h
#    929 -rw-r--r-- vtalk.c
#    476 -rw-r--r-- vtalk.h
#   5929 -rw-r--r-- vtalkd.c
#
# ============= README ==============
if test -f 'README' -a X"$1" != X"-c"; then
	echo 'x - skipping README (File already exists)'
else
echo 'x - extracting README (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'README' &&
X
VTALK is a product from OKI Electric Industry, Japan, 
that allows voice talk between two Sun Sparcstation's
over Ethernet. Each machine must have microphones connected
to the audio port. 
X
This is a modified version that works for SunOS 4.1.
X
Vtalk - How to
--------------
X
How to install: 
X
Copy the file 'vtalk.shar' to the directory where you want to
install it.
Unpack the archive by running through /bin/sh (command: sh vtalk.shar).
This will produce .c and .h files, and a Makefile.
Type 'make'.  This will produce the executables
'vtalk' and 'vtalkd'.
X
If not done earlier, a service must be allocated to vtalkd in the NIS database 
and /etc/services.
A service number like 2999 will be suitable.  The entry should
look like:
X    
X	vtalk      2999/tcp
X
This can only be done by the superuser (root), so you should contact
your system administrator to have this done on your system.
X
How to run: 
X    
Start vtalkd ('vtalkd &') on every machine that you want voice talk to work on.
This could be done at startup in the .login file.
To initiate a connection, type 'vtalk user at machine'.  The user on that machine
will be informed of the request.  A user accepts a connection by typing 'vtalk'.
X
Here is some info on how to wire the microphone plug (Swedish version) :
X
***********************************************************************
I/O Connector:
X
This is the view looking at the connector end of an adapter cable. 
X
X       6x  7x  8x
X       3x  4x  5x 
X         1x  2x
X
The connections to these pins are as follows: 
X
X       Pin 1   no connect
X       Pin 2   no connect
X       Pin 3   Michrophone (tip)
X       Pin 4   no connect
X       Pin 5   no connect 
X       Pin 6   Michrophone (sleeve or shield)
X       Pin 7   audio out (tip)
X       Pin 8   audio out (sleeve or shield) 
X
Pin 7 and 8 is only connected if you want to use an external loudspeaker.
A cheap freestyle booster speaker works fine.
My speaker is called 'GALAX PS-388R', made in China and costs 160 Skr,
(appr US$ 28) here in Sweden. I have connected a 12V AC/DC adaptor to it
so batteries are no problem..
NOTE: If you want the external speaker to work with 'vtalk' you might
need to include some code that switches output to the audio jack,
or use the Sun tool 'gaintool' to manually specify speaker output.
X
Mini-DIN plugs for the SPARC audio connector can be ordered in Sweden
from ELFA, phone 08-7353535,
Article no. 42-193-58
X
A suitable screened michrophone cable between this plug and a phono jack is
X        no. 55-801-05, appr 2 metres, or solder the michrophone's own cable
directly to the Mini-DIN plug.
X
If both external speaker and mike is desired, use a stereo audio cable,  
X        no. 55-807-82,  and connect this to some adapter box that 
in turn allows connecting both a michrophone and booster speaker.
The choice is yours.
********************************************************************************
X
Happy talking,
X
gunnar at falcon10.ericsson.se
X
SHAR_EOF
chmod 0644 README ||
echo 'restore of README failed'
Wc_c="`wc -c < 'README'`"
test 2954 -eq "$Wc_c" ||
	echo 'README: original size 2954, current size' "$Wc_c"
fi
# ============= Makefile ==============
if test -f 'Makefile' -a X"$1" != X"-c"; then
	echo 'x - skipping Makefile (File already exists)'
else
echo 'x - extracting Makefile (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'Makefile' &&
# 
#   Copyright (c) 1989 Oki Electric Industry Co., Ltd.
#
#   This file is part of vtalk.
#
#   Permission to use, copy, modify and distribute this program without
#   fee is grtanted,  provided that  the above  copyright notice appear
#   in all copies.
#
#
X
DEST	      = /usr/local/bin
X
#EXTHDRS	      = 
X
#CFLAGS	      = -g -DDEBUG
#CFLAGS	      = -g
CFLAGS	      = -O
X
HDRS	      = netwk.h		\
X		vtalk.h
X
LDFLAGS	      = 
X
LIBS	      = 
X
WLIBS	      =
X
LINKER	      = cc
X
MAKEFILE      = Makefile
X
OBJS	      = vtalk.o		\
X		netwk.o 	\
X		audio.o		
X
DOBJS	      = vtalkd.o
X
PRINT	      = pr
X
PROGRAM	      = vtalk		\
X		vtalkd
X
SRCS	      = vtalk.c		\
X		netwk.c		\
X		audio.c
X
DSRCS         = vtalkd.c
X
all:		$(PROGRAM)
X
vtalk:		$(OBJS) $(LIBS) $(HDRS)
X		@echo -n "Loading vtalk ... "
X		@$(LINKER) $(LDFLAGS) $(OBJS) $(LIBS) -o vtalk
X		@echo "done"
X
vtalkd:		$(DOBJS) $(LIBS) $(HDRS)
X		@echo -n "Loading vtalkd ... "
X		@$(LINKER) $(LDFLAGS) $(DOBJS) $(LIBS) -o vtalkd
X		@echo "done"
X
clean:;		@rm -f $(OBJS) $(DOBJS)
X
depend:;	@mkmf -f $(MAKEFILE) PROGRAM=$(PROGRAM) DEST=$(DEST)
X
index:;		@ctags -wx $(HDRS) $(SRCS)
X
install:	$(PROGRAM)
X		@echo Installing $(PROGRAM) in $(DEST)
X		@install -s $(PROGRAM) $(DEST)
X
print:;		@$(PRINT) $(HDRS) $(SRCS)
X
program:        $(PROGRAM)
X
tags:           $(HDRS) $(SRCS); @ctags $(HDRS) $(SRCS)
X
update:		$(DEST)/$(PROGRAM)
X
lint:;		lint $(SRCS)
###
SHAR_EOF
chmod 0644 Makefile ||
echo 'restore of Makefile failed'
Wc_c="`wc -c < 'Makefile'`"
test 1389 -eq "$Wc_c" ||
	echo 'Makefile: original size 1389, current size' "$Wc_c"
fi
# ============= vtalk.1 ==============
if test -f 'vtalk.1' -a X"$1" != X"-c"; then
	echo 'x - skipping vtalk.1 (File already exists)'
else
echo 'x - extracting vtalk.1 (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'vtalk.1' &&
.TH VTALK 1 "Oct 10, 1990"
.SH NAME
vtalk \- Voice Talk between SparcStation users
.SH SYNOPSIS
.I vtalk
.RB user at machine
.SH DESCRIPTION
.I vtalk
is used to establish communication between workstation users by means
of the human voice. Each of the two persons communicating must have a
Sun SparcStation with a michrophone connected to the audio connector.
VTALK is a product of OKI Electric Industry, Japan.
.I vtalk
works together with the
.I vtalkd
Voice Talk Daemon.
Each node must have a 
.I vtalkd
daemon running to be able to participate in Voice Talk.
Sounds are sampled and transmitted as packets over Ethernet,
received and unpacked at the other end, and played on the
loudspeaker of the receiving machine.
The same thing occurs in duplex on the other machine.
.LP
.SH "HOW TO INSTALL"
If not done earlier, a service must be allocated to vtalkd in the NIS database
and /etc/services.
A service number like 2999 will be suitable.  The entry should
look like:
X
X        vtalk      2999/tcp
X
This can only be done by the superuser (root), so you should contact
your system administrator to have this done on your system.
X
How to run:
X
Start vtalkd ('vtalkd &') on every machine that you want voice talk to work on.
This could be done at startup in the .login file.
To initiate a connection, type 'vtalk user at machine'.  The user on that machine
will be informed of the request.  A user accepts a connection by typing 'vtalk'.
.LP
.SH "AUDIO CONNECTOR INFO"
.LP
I/O Connector:
X 
This is the view looking at the connector end of an adapter cable.
X 
X       6x  7x  8x
X       3x  4x  5x
X         1x  2x
X 
The connections to these pins are as follows:
X 
X       Pin 1   no connect
X       Pin 2   no connect
X       Pin 3   Michrophone (tip)
X       Pin 4   no connect
X       Pin 5   no connect
X       Pin 6   Michrophone (sleeve or shield)
X       Pin 7   audio out (tip)
X       Pin 8   audio out (sleeve or shield)
X 
Pin 7 and 8 is only connected if you want to use an external loudspeaker.
A cheap freestyle booster speaker (price appr 160 Skr) works fine.
X 
Mini-DIN plugs for the SPARC audio connector can be ordered in Sweden
from ELFA, phone 08-7353535,
Article no. 42-193-58
X 
A suitable screened michrophone cable between this plug and a phono jack is
X        no. 55-801-05, appr 2 metres, or solder the michrophone's own cable
directly to the Mini-DIN plug.
X 
If both external speaker and mike is desired, use a stereo audio cable,
X        no. 55-807-82,  and connect this to some adapter box that
in turn allows connecting both a michrophone and booster speaker.
.SH "AUTHOR OF THIS MAN PAGE"
ETX/TM/FM Gunnar Forsgren (gunnar at falcon.ericsson.se)
SHAR_EOF
chmod 0644 vtalk.1 ||
echo 'restore of vtalk.1 failed'
Wc_c="`wc -c < 'vtalk.1'`"
test 2653 -eq "$Wc_c" ||
	echo 'vtalk.1: original size 2653, current size' "$Wc_c"
fi
# ============= audio.c ==============
if test -f 'audio.c' -a X"$1" != X"-c"; then
	echo 'x - skipping audio.c (File already exists)'
else
echo 'x - extracting audio.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'audio.c' &&
/* 
X *   Copyright (c) 1989 Oki Electric Industry Co., Ltd.
X *
X *   This file is part of vtalk.
X *
X *   Permission to use, copy, modify and distribute this program without
X *   fee is grtanted,  provided that  the above  copyright notice appear
X *   in all copies.
X *
X */
/*
X *  audio.c    audio control routine for vtalk
X *
X *  vtalk is a command for 
X *  Voice TALK with the user on another machine.
X *
X */
X
#include <stdio.h>
#include <sys/ioctl.h>            /* for audio */
#define AUDIO_CHIP
#include <sbusdev/audio_79C30.h>
#include <sun/audioio.h>
X
int fd_audio;
X
X
device_open()
{
X	struct audio_ioctl audioreg;
X	
X	if((fd_audio = open("/dev/audio", 2)) < 0){
X		fprintf(stderr,"vtalk: can't open /dev/audio\n");
X		exit(1);
X	}
X
X	/* set MMR1 register */
X	audioreg.control = AUDIO_MAP_MMR1;
X	audioreg.data[0] = AUDIO_MMR1_BITS_LOAD_GX |
X	  AUDIO_MMR1_BITS_LOAD_GR | AUDIO_MMR1_BITS_LOAD_GER;
X	if (ioctl(fd_audio,AUDIOSETREG,&audioreg) < 0) {
X		perror("vtalk: set MMR1 register");
X	}
X	
X	/* set MMR2 register                      *
X         * send the output to the builtin speaker */
X	audioreg.control = AUDIO_MAP_MMR2;
X	if (ioctl(fd_audio,AUDIOGETREG,&audioreg) < 0) {
X		perror("vtalk: set MMR2 register");
X	}
X	audioreg.data[0] |= AUDIO_MMR2_BITS_LS;
X	if (ioctl(fd_audio,AUDIOSETREG,&audioreg) < 0) {
X		perror("vtalk: set MMR2 register");
X	}
X	
X	return(fd_audio);
}
X
X
void
set_volume()
{
X	struct	audio_ioctl	audioreg;
X
X	/* register GR set 5db for play volume */
X	audioreg.control = AUDIO_MAP_GR;
X	audioreg.data[0] = 0x3b;
X	audioreg.data[1] = 0x11;
X	if (ioctl(fd_audio,AUDIOSETREG,&audioreg) < 0) {
X		perror("vtalk: set GR register");
X	}
X	
X	/* register GER set 5db for play volume */
X	audioreg.control = AUDIO_MAP_GER;
X	audioreg.data[0] = 0x31;
X	audioreg.data[1] = 0xdd;
X	if (ioctl(fd_audio,AUDIOSETREG,&audioreg) < 0) {
X		perror("vtalk: set GER register");
X	}
X	
X	/* register GX set 11db for record volume */
X	audioreg.control = AUDIO_MAP_GX;
X	audioreg.data[0] = 0x13;
X	audioreg.data[1] = 0x00;
X	if (ioctl(fd_audio,AUDIOSETREG,&audioreg) < 0) {
X		perror("vtalk: set GX register");
X	}
}
X
X
X
X
SHAR_EOF
chmod 0644 audio.c ||
echo 'restore of audio.c failed'
Wc_c="`wc -c < 'audio.c'`"
test 2091 -eq "$Wc_c" ||
	echo 'audio.c: original size 2091, current size' "$Wc_c"
fi
# ============= netwk.c ==============
if test -f 'netwk.c' -a X"$1" != X"-c"; then
	echo 'x - skipping netwk.c (File already exists)'
else
echo 'x - extracting netwk.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'netwk.c' &&
/* 
X *   Copyright (c) 1989 Oki Electric Industry Co., Ltd.
X *
X *   This file is part of vtalk.
X *
X *   Permission to use, copy, modify and distribute this program without
X *   fee is grtanted,  provided that  the above  copyright notice appear
X *   in all copies.
X *
X */
/*
X *  netwk.c    network control routine for vtalk
X *
X *  vtalk is a command for 
X *  Voice TALK with the user on another machine.
X *  
X */
X
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <netdb.h>
#include <sys/file.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/param.h>
#include <sys/time.h>
#include "netwk.h"
X
X
/* #define BUFFER_SIZE	256    */
#define BUFFER_SIZE	64    /* record */
#define INT sizeof(int)
X
X
struct daemon_msg msg;
X
struct in_addr machine_addr; /* inet address */
int machine_addrtype;
int dsockt;        /* socket for daemon */
int vsockt;        /* socket for voice talk */
X
X
void
X  check_args(argc, argv, flag)
int argc;
char **argv;
int *flag;
{
X	char *my_name;
X	char his_name[256];
X	char *my_host;
X	char *his_host;
X	char host[MAXHOSTNAMELEN];
X	struct in_addr my_host_addr;
X	struct in_addr his_host_addr;
X	int his_host_addrtype;
X	int my_host_addrtype;
X	struct hostent *hp;
X	char *ap, *np;
X	char *getlogin();
X	
X	/* my name */
X	if ((my_name = getlogin()) == NULL) {
X		fprintf(stderr,"%s: you don't exist\n", argv[0]);
X		exit(1);
X	}
X	strcpy(msg.caller_name, my_name);
X	
X	/* my host name */
X	gethostname(host, sizeof (host));
X	my_host = host;
X	strcpy(msg.caller_host_name, host);
X	
X	if(argc == 1){		/* receiver */
X		
X	/* my host address */
X		if ((hp = gethostbyname(my_host))== (struct hostent *) 0) {
X			fprintf(stderr,
X				"%s: %s can't recognize network address.\n",
X				argv[0], my_host);
X			exit(1);
X		}
X		bcopy(hp->h_addr, (char *)&my_host_addr,
X		      hp->h_length);
X		my_host_addrtype = hp->h_addrtype;
X		*flag = 0;
X		machine_addr = my_host_addr;
X		machine_addrtype = my_host_addrtype;
X		
X		
X	}else {                 /* caller */
X		
X	/* his name & his host name */
X		ap = argv[1];
X		np = his_name;
X		while(*ap != '\0'){
X			*np = *ap;
X			if (*ap == '@') {
X				*np = '\0';
X				his_host = ++ap;
X				break;
X			} ap++;np++;
X		}
X		if(*ap == '\0') {
X			fprintf(stderr,"Usage: vtalk user at machine\n");
X			exit(1);
X		}
X		strcpy(msg.receiver_name, his_name);
X		
X	/* his host addrs */
X		if ((hp = gethostbyname(his_host)) == (struct hostent *) 0) {
X			fprintf(stderr,
X				"%s: %s can't recognize network address.\n",
X				argv[0], his_host);
X			exit(1);
X		}
X		bcopy(hp->h_addr, (char *) &his_host_addr, 
X		      hp->h_length);
X		his_host_addrtype = hp->h_addrtype;
X		
X		machine_addrtype = his_host_addrtype;
X		machine_addr = his_host_addr;
X		*flag = 1;       /* caller */
X		msg.sin.sin_addr = my_host_addr;
X	}
X	
}
X
X
void
X  open_dsocket()
{
X	struct sockaddr_in daemon; /* daemon sockname */
X	struct servent* sp;        /* server entry */
X	
#ifdef DEBUG
X	fprintf(stderr,"vtalk:open_dsocket\n");
#endif DEBUG
X	
X	/* vtalk server entry */
X	if((sp = getservbyname("vtalk","tcp")) == NULL){
X		fprintf(stderr,
X			"vtalk: undefined server entry\n");
X		exit(1);
X	}
X	bzero((char *)&daemon, sizeof(daemon));
X	daemon.sin_port = sp->s_port;
X	daemon.sin_addr = machine_addr;
X	daemon.sin_family = machine_addrtype;
X	
X	/* SOCKET for server */
X	if((dsockt = socket(AF_INET, SOCK_STREAM, 0)) < 0){
X		perror("vtalk: can't create socket");
X		exit(1);
X	}
X	
X	/* CONNECT to server */
X	if(connect(dsockt, (struct sockaddr *)&daemon, sizeof(daemon))
X	   < 0){
X		perror("vtalk: binding local socket");
X		exit(1);
X	}
X	
}
X
X
call_vtalkd(caller)
X     int caller;
{
X	
#ifdef DEBUG
X	fprintf(stderr,"vtalk:call vtalk daemon\n");
#endif DEBUG
X	
X	/* WRITE msg to server */
X	msg.flag = caller;
X	if(write(dsockt, (char*)&msg, sizeof(struct daemon_msg)) !=
X	   sizeof(struct daemon_msg)){
X		perror("vtalk: lost the connection with daemon");
X		exit(1);
X	}
X
X	/* READ msg from server */
X	if(read(dsockt, (char*)&msg, sizeof(struct daemon_msg)) !=
X	   sizeof(struct daemon_msg)){
X		perror("vtalk: lost the connection with daemon");
X		exit(1);
X	}
X	
X	/* CLOSE daemon socket */
X	if(close(dsockt)){
X		perror("vtalk: can't close socket\n");
X	}
X
X	return(msg.status);
}
X
X
X
void
X  call()
{
X	struct sockaddr_in sin;
X	int sd;  
X
#ifdef DEBUG 
X	fprintf(stderr,"vtalk:open vtalk socket\n");
#endif DEBUG
X	
X	/* SOCKET for vtalk */
X	if((sd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
X		perror("vtalk: can't create socket");
X		exit(1);
X	}
X
X	/* BIND socket to given port no */
X	bzero((char *)&sin, sizeof(sin));
X	sin.sin_port = msg.sin.sin_port; 
X
#ifdef DEBUG
X	fprintf(stderr,"vtalk:sin=%d %d %d \n",sin.sin_port,
X		sin.sin_addr,sin.sin_family);
#endif DEBUG
X	
X	if(bind(sd, (struct sockaddr*)&sin, sizeof(sin))
X	   < 0){
X
#ifdef DEBUG
X		fprintf(stderr,"vtalk:bind:errno = %d\n",errno);
#endif DEBUG
X		
X		perror("vtalk: binding local socket");
X		exit(1);
X	}
X	
X	/* LISTEN */
X	listen(sd, 5);
X	
#ifdef DEBUG
X	fprintf(stderr,"vtalk:caller:listen\n");
#endif
X
X	/* waiting until ACCEPT */ 
X	while((vsockt = accept(sd, 0, 0)) < 0){
X		if(errno == EINTR)
X		  continue;
X		perror("vtalk: can't accept");
X	}
X
#ifdef DEBUG
X	fprintf(stderr,"vtalk:caller:accepted\n");
#endif
X	/* CLOSE old sockt */
X	close(sd);
X	
}
X
X
void
X  response()
{
X	struct sockaddr_in sin;
X
#ifdef DEBUG 
X	fprintf(stderr,"vtalk:open vtalk socket\n");
#endif DEBUG
X	
X	/* SOCKET for vtalk */
X	if((vsockt = socket(AF_INET, SOCK_STREAM, 0)) < 0){
X		perror("vtalk: can't create socket");
X		exit(1);
X	}
X
X	/* CONNECT to waiting caller */
X	sin.sin_family = msg.sin.sin_family;
X	sin.sin_port = msg.sin.sin_port;
X	sin.sin_addr = msg.sin.sin_addr;
X	if(connect(vsockt, (struct sockaddr*)&sin, 
X		   sizeof(sin)) < 0){
X		perror("vtalk: can't connect");
X		exit(1);
X	}	
X        fprintf(stderr,"Connection established, finish with CTRL/C..");
#ifdef DEBUG
X	fprintf(stderr,"vtalk:receiver:connected\n");
#endif
}
X
X
void
X  vtalk(audio_fd, caller)
int audio_fd;
int caller;
{
X	int read_size;
X	char audio_buffer[BUFFER_SIZE];
X	char sockt_buffer[BUFFER_SIZE];
X	
X	read_size = BUFFER_SIZE;
X	if(caller){
X		while(1) {
X			read(vsockt, &sockt_buffer[0], read_size);
X			write(audio_fd, &sockt_buffer[0], read_size);
X			read(audio_fd, &audio_buffer[0], read_size);
X			write(vsockt, &audio_buffer[0], read_size);
X		}
X        }else{
X		while(1){
X			read(audio_fd, &audio_buffer[0], read_size);
X			write(vsockt, &audio_buffer[0], read_size);
X			read(vsockt, &sockt_buffer[0], read_size);
X			write(audio_fd, &sockt_buffer[0], read_size);
X		}
X        }
}
X
X
static char *messages[] = {
X	"",
X	"Receiver is not existing",
X	"Receiver machine is too confused to vtalk",
X	"Receiver machine cannot recognize us",
X	"Receiver is refusing messages",
X	"Nobody is requesting your reply",
};
#define NANSWERS  (sizeof(messages) /sizeof (messages[0]))
X
X
output_err(status)
X     int status;
{
X	if(status < NANSWERS)
X	  fprintf(stderr,"[%s]\n",messages[status]);
X	
}
X
SHAR_EOF
chmod 0644 netwk.c ||
echo 'restore of netwk.c failed'
Wc_c="`wc -c < 'netwk.c'`"
test 6864 -eq "$Wc_c" ||
	echo 'netwk.c: original size 6864, current size' "$Wc_c"
fi
# ============= netwk.h ==============
if test -f 'netwk.h' -a X"$1" != X"-c"; then
	echo 'x - skipping netwk.h (File already exists)'
else
echo 'x - extracting netwk.h (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'netwk.h' &&
/* 
X *   Copyright (c) 1989 Oki Electric Industry Co., Ltd.
X *
X *   This file is part of vtalk.
X *
X *   Permission to use, copy, modify and distribute this program without
X *   fee is grtanted,  provided that  the above  copyright notice appear
X *   in all copies.
X *
X */
X
#include "vtalk.h"
X
struct daemon_msg {
X	int flag;            /* caller ? receiver flag */
X	int status;          /* is caller exist */
X	struct sockaddr_in sin;
X	char      caller_host_name[NAME_LEN];
X	char      caller_name[NAME_LEN]; 
X	char      receiver_name[NAME_LEN];
X
};
SHAR_EOF
chmod 0644 netwk.h ||
echo 'restore of netwk.h failed'
Wc_c="`wc -c < 'netwk.h'`"
test 547 -eq "$Wc_c" ||
	echo 'netwk.h: original size 547, current size' "$Wc_c"
fi
# ============= vtalk.c ==============
if test -f 'vtalk.c' -a X"$1" != X"-c"; then
	echo 'x - skipping vtalk.c (File already exists)'
else
echo 'x - extracting vtalk.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'vtalk.c' &&
/* 
X *   Copyright (c) 1989 Oki Electric Industry Co., Ltd.
X *
X *   This file is part of vtalk.
X *
X *   Permission to use, copy, modify and distribute this program without
X *   fee is grtanted,  provided that  the above  copyright notice appear
X *   in all copies.
X *
X */
/*
X *  vtalk.c    main routione for vtalk
X *
X *  vtalk is a command for 
X *  Voice TALK with the user on another machine.
X *  
X */
X
#include "vtalk.h"
X
main(argc, argv)
int  argc;
char *argv[];
{
X	int caller;        /* caller ? receiver flag */
X	int audio_fd;
X	int status;
X
X	void check_args(), open_dsocket(), open_socket();
X	void call(), response(), vtalk();
X
X	check_args(argc, argv, &caller);
X	open_dsocket();
X	if((status= call_vtalkd(caller)) != SUCCESS){
X		/* not exit or not response or not waiting */
X		output_err(status);
X		exit(1);
X	}
X	if(caller)
X	  call();
X	else response();
X	audio_fd = device_open();
X	set_volume();
X
X	vtalk(audio_fd, caller);
}
X
X
SHAR_EOF
chmod 0644 vtalk.c ||
echo 'restore of vtalk.c failed'
Wc_c="`wc -c < 'vtalk.c'`"
test 929 -eq "$Wc_c" ||
	echo 'vtalk.c: original size 929, current size' "$Wc_c"
fi
# ============= vtalk.h ==============
if test -f 'vtalk.h' -a X"$1" != X"-c"; then
	echo 'x - skipping vtalk.h (File already exists)'
else
echo 'x - extracting vtalk.h (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'vtalk.h' &&
/* 
X *   Copyright (c) 1989 Oki Electric Industry Co., Ltd.
X *
X *   This file is part of vtalk.
X *
X *   Permission to use, copy, modify and distribute this program without
X *   fee is grtanted,  provided that  the above  copyright notice appear
X *   in all copies.
X *
X */
X
#define MAX_QUEUE 10
#define NAME_LEN 64
X
/* server -> client msg.status */
#define SUCCESS 0  
#define NOEXIST 1  
#define FAILED  2  
#define UNKNOWN 3  
#define PERMISSION_DENIED 4 
#define NOWAIT 5 
SHAR_EOF
chmod 0644 vtalk.h ||
echo 'restore of vtalk.h failed'
Wc_c="`wc -c < 'vtalk.h'`"
test 476 -eq "$Wc_c" ||
	echo 'vtalk.h: original size 476, current size' "$Wc_c"
fi
# ============= vtalkd.c ==============
if test -f 'vtalkd.c' -a X"$1" != X"-c"; then
	echo 'x - skipping vtalkd.c (File already exists)'
else
echo 'x - extracting vtalkd.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'vtalkd.c' &&
/* 
X *   Copyright (c) 1989 Oki Electric Industry Co., Ltd.
X *
X *   This file is part of vtalkd.
X *
X *   Permission to use, copy, modify and distribute this program without
X *   fee is grtanted,  provided that  the above  copyright notice appear
X *   in all copies.
X *
X */
/*
X *  vtalkd.c    main routine for vtalkd
X *
X *  vtalkd is a daemon for 
X *  Voice TALK with the user on another machine.
X *  
X */
X
#include <errno.h>
#include <stdio.h>
#include <netdb.h>
#include <sys/file.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include <utmp.h>
#include <syslog.h>
#include <sys/time.h>
#include <signal.h>
#include "netwk.h"
X
X
struct sockaddr_in caller_queue[MAX_QUEUE];
int current_caller = 0;
int sockt;
int daemon_sockt;
X
main(argc, argv)
X     int argc;
X     char *argv[];
{
X	
X	struct daemon_msg msg;
X	char ftty[20];
X	void open_dsocket();
X	int die();
X	
X	/* super user ? 
X	if(getuid()){
X		fprintf(stderr,
X			"%s: getuid: not super user\n", argv[0]);
X		exit(1);
X	}
*/	
X	openlog("vtalkd", LOG_PID, LOG_DAEMON);
X	
X	/*  daemon  */
X	open_dsocket();
X	
X	/* signal handler */
X	signal(SIGINT, die);
X	signal(SIGQUIT, die);
X	signal(SIGTERM, die);
X	
X	/* waiting for caller */
X	while(1){
X		receive_msg(&msg);
X		if(msg.flag){
X			if((msg.status = check_user(msg.receiver_name,
X						    ftty))== SUCCESS){
X				if((msg.status = open_socket(&msg))
X				   == SUCCESS)
X				  msg.status = announce(&msg, ftty);
X			}
X		} else	msg.status = check_caller(&msg.sin);
X		
X		return_msg(&msg); 
X		close(sockt);
X	}
}
X
X
void
X  open_dsocket()
{
X	struct sockaddr_in sin;
X	struct servent* sp;
X	
X	/* GETSERVBYNAME for vtalk */
X	if((sp = getservbyname("vtalk","tcp")) == NULL){
X		syslog(LOG_ERR, "getservbyname: %m");
X		exit(1);
X	}
X	
X	/* get port */
X	bzero((char *)&sin, sizeof(sin));
X	sin.sin_port = sp->s_port;
X	
X	/* SOCKET for server */
X	if((daemon_sockt = socket(AF_INET, SOCK_STREAM, 0)) < 0){
X		syslog(LOG_ERR, "socket: %m");
X		exit(1);
X	}
X
X	/* BIND to daemon port */
X	if(bind(daemon_sockt, (struct sockaddr*)&sin, sizeof(sin)) 
X	   < 0){
X		syslog(LOG_ERR, "bind: %m");
X		exit(1);
X	}
X	
X	/* LISTEN */
X	listen(daemon_sockt, 5);
X	
}
X
X
receive_msg(msg)
X     struct daemon_msg *msg;
{
X	
X	/* waiting until ACCEPT msg */
X	while((sockt = accept(daemon_sockt, (struct sockaddr*)0,
X			      (int *)0)) < 0){
X		if(errno == EINTR)
X		  continue;
X		syslog(LOG_WARNING, "accept: %m");
#ifdef DEBUG
X		fprintf(stderr,"errno = %d\n",errno);
#endif DEBUG
X	}
X	
X	/* READ msg from client */
X	if(read(sockt, (char*)msg, sizeof(struct daemon_msg)) !=
X	   sizeof(struct daemon_msg)){
X		syslog(LOG_WARNING, "read: %m");
X		return(FAILED);
X	}
X	return(SUCCESS);
}
X
X
check_user(name, ftty)
X     char *name;
X     char *ftty;
{
X	struct utmp ubuf;
X	int status;
X	FILE *fp;
X	struct stat sbuf;
X	
X	/* open utmp file */
X	if ((fp = fopen("/etc/utmp", "r")) == NULL) {
X		perror("vtalk: can't open /etc/utmp");
X		return (FAILED);
X	}
X
X	/* check user existing */
X	status = NOEXIST;
X	strcpy(ftty, "/dev/");
X	while(fread((char*)&ubuf, sizeof ubuf, 1, fp) == 1)
X	  if(strncmp(ubuf.ut_name, name, sizeof(ubuf.ut_name)) == 0) {
X		  status = PERMISSION_DENIED;
X		  strcpy(ftty+5, ubuf.ut_line);
X		  if(stat(ftty, &sbuf) == 0) {
X			  if(!(sbuf.st_mode & 020))
X			    continue;
#ifdef DEBUG 
X			  fprintf(stderr,"ftty: %s\n", ftty);
#endif DEBUG
X			  status = SUCCESS;
X			  break;
X		  }
X	  }
X	fclose(fp);
X	return (status);
}
X
X
open_socket(msg)
X     struct daemon_msg *msg;
{
X	struct sockaddr_in sin; /* address for caller */
X	int sd;                 /* socket discriptor */
X	int port;               /* port number for vtalk */
X	struct hostent *hp;
X	
X	/* SOCKET for caller & receiver */
X	if((sd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
X		syslog(LOG_ERR,"socket: %m");
X		close(daemon_sockt);
X		exit(1);
X	}
X	
X	/* BIND to port(>=5000) */
X	bzero((char *)&sin, sizeof(sin));
X	sin.sin_family = AF_INET;
X	sin.sin_addr.s_addr = htonl(INADDR_ANY);
X	port = IPPORT_USERRESERVED - 1;
X	do{
X		port++;
X		sin.sin_port = htons(port);
X	}while(bind(sd, (struct sockaddr*)&sin, sizeof(sin))!=0);
X	
X	/* return port number to client */
X	msg->sin.sin_port = htons(port);
X	
X	/* save request to caller_queue */
X	hp = gethostbyname(msg->caller_host_name);
X	if (hp == (struct hostent *) 0) {
X		return(UNKNOWN);
X	}
X	bcopy(hp->h_addr, (char *) &sin.sin_addr, hp->h_length);
X	caller_queue[current_caller].sin_port = htons(port);
X	caller_queue[current_caller].sin_addr = sin.sin_addr;
X	caller_queue[current_caller].sin_family = hp->h_addrtype;
X	current_caller++;
X	
X	/* CLOSE socket */
X	close(sd);
X	return(SUCCESS);
}
X
X
announce(msg, ftty)
X     struct daemon_msg *msg;
X     char *ftty;
{
X	struct timeval tval;
X	struct timezone tzone;
X	struct tm *localtime();
X	struct tm *time;
X	FILE *fp;
X	
X	/* test ftty F_OK? */
X	if(access(ftty, 0) != 0)
X	  return(FAILED);
X	if((fp = fopen(ftty, "w")) == NULL)
X	  return(PERMISSION_DENIED);
X
X	/* get time */
X	gettimeofday(&tval, &tzone);
X	time = localtime(&tval.tv_sec);
X	
X	/* display message */
X	fprintf(fp,"\n");
X	fprintf(fp,"\007");
X	fprintf(fp,"Vtalk - Message from Voice Talk Daemon at %d:%02d ...\n",
X		time->tm_hour, time->tm_min);
X	fprintf(fp,"Vtalk - User %s@%s wants to talk to you !\n",
X		msg->caller_name, msg->caller_host_name);
X	fprintf(fp,"Vtalk - Please respond with: vtalk\n");
X	fflush(fp);
X
X	fclose(fp);
X	return(SUCCESS);
}
X
X
check_caller(sin)
X     struct sockaddr_in *sin;
{
X	if(current_caller == 0)
X	  return(NOWAIT);
X	else{
X		sin->sin_port = caller_queue[0].sin_port;
X		sin->sin_addr = caller_queue[0].sin_addr;
X		sin->sin_family = caller_queue[0].sin_family;
X		current_caller--;
X		return(SUCCESS);
X	}
X	
}
X
X
return_msg(msg)
X     struct daemon_msg *msg;
{
X	int x;
X	
X	/* WRITE msg to client */
X	x = write(sockt, (char*)msg, sizeof(struct daemon_msg));
X	if(x != sizeof(struct daemon_msg)){
X		syslog(LOG_WARNING, "write: %m");
X		return(FAILED);
X	}
X	return(SUCCESS);
X	
}
X
X
die(sig)
X     int sig;
{
X	close(daemon_sockt);
X	exit(sig != 0);
}
SHAR_EOF
chmod 0644 vtalkd.c ||
echo 'restore of vtalkd.c failed'
Wc_c="`wc -c < 'vtalkd.c'`"
test 5929 -eq "$Wc_c" ||
	echo 'vtalkd.c: original size 5929, current size' "$Wc_c"
fi
exit 0



More information about the Alt.sources mailing list