emv@math.lsa.umich.edu (Edward Vielmetti) (03/02/90)
Found this while rummaging around in Japan. Some high bits are set, so it might be somewhat garbled, and I can't read Japanese no matter whatever the encoding is -- translation welcomed. I used port 2314 on duby.math.lsa.umich.edu to install this, everything compiled but I don't know if it works. --Ed Edward Vielmetti, U of Michigan Math dept. From: kamei@cs1.cs.oki.co.jp (Masako Kamei) Newsgroups: fj.sources Subject: vtalk for SPARCstation1 Date: 25 Jan 90 02:08:52 GMT Distribution: fj Organization: Oki Electric Industry Co.,Ltd. Warabi, Saitama, Japan. !!$O$8$a$^$7$F!"2-EE5$$N550f$G$9!# !!SUN SPARCstation1MQ$Nvtalk!JVoice TALK!K%3%^%s%I$G$9!#%M%C%H%o!<%/ $G$D$J$,$C$F$$$k!"#2Bf$NSUN SPARCstation1$K%^%$%/$r$D$1$k$H!"EEOC$N $h$&$K$*OC$7$,$G$-$^$9!#$G$-$l$P!"%X%C%I%;%C%H$N$[$&$,<~0O$K%R%s%7%e%/ $r$+$o$:$K:Q$`$+$b$7$l$^$;$s!#$G$b!"$I$A$i$K$7$F$bFMA3%3%s%T%e!<%?$K 8~$+$C$FC}$j$@$9$H!"3'$,!I$I$&$7$?$s$@$m$&!"$3$N?M!#!I$H!"Gr$$L\$G8+ $^$9!#!J$3$s$J$3$H$r=q$/$H!"C/$b;H$C$F$/$l$J$$$+$b$7$l$J$$...!K !!$H$K$+$/!"0lEY;H$C$F$_$F$/$@$5$$!#;H$$J}$K$D$$$F$O!"README$K=q$$$F $"$j$^$9!#$40U8+!"$4MWK>!"$*BT$A$7$F$*$j$^$9!# * * 2-EE5$9)6H * _ * * * /_| * 550f!!2m;R (^_^) * * ( ) * ------------------------------- CUT HERE ------------------------------ #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # Makefile # README # audio.c # netwk.c # netwk.h # vtalk.c # vtalk.h # vtalkd.c # This archive created: Thu Jan 25 10:41:37 JST 1990 export PATH; PATH=/bin:/usr/bin:/usr/ucb if test -f Makefile then echo "shar: will not over-write existing file 'Makefile'" else echo 'x - Makefile' sed 's/^X//' << '\SHAR_EOF' > Makefile X# 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 XDEST = . X X#EXTHDRS = X X#CFLAGS = -g -DDEBUG X#CFLAGS = -g XCFLAGS = -O X XHDRS = netwk.h \ X vtalk.h X XLDFLAGS = X XLIBS = X XWLIBS = X XLINKER = cc X XMAKEFILE = Makefile X XOBJS = vtalk.o \ X netwk.o \ X audio.o X XDOBJS = vtalkd.o X XPRINT = pr X XPROGRAM = vtalk \ X vtalkd X XSRCS = vtalk.c \ X netwk.c \ X audio.c X XDSRCS = vtalkd.c X Xall: $(PROGRAM) X Xvtalk: $(OBJS) $(LIBS) $(HDRS) X @echo -n "Loading vtalk ... " X @$(LINKER) $(LDFLAGS) $(OBJS) $(LIBS) -o vtalk X @echo "done" X Xvtalkd: $(DOBJS) $(LIBS) $(HDRS) X @echo -n "Loading vtalkd ... " X @$(LINKER) $(LDFLAGS) $(DOBJS) $(LIBS) -o vtalkd X @echo "done" X Xclean:; @rm -f $(OBJS) $(DOBJS) X Xdepend:; @mkmf -f $(MAKEFILE) PROGRAM=$(PROGRAM) DEST=$(DEST) X Xindex:; @ctags -wx $(HDRS) $(SRCS) X Xinstall: $(PROGRAM) X @echo Installing $(PROGRAM) in $(DEST) X @install -s $(PROGRAM) $(DEST) X Xprint:; @$(PRINT) $(HDRS) $(SRCS) X Xprogram: $(PROGRAM) X Xtags: $(HDRS) $(SRCS); @ctags $(HDRS) $(SRCS) X Xupdate: $(DEST)/$(PROGRAM) X Xlint:; lint $(SRCS) X### \SHAR_EOF if test `wc -c < Makefile` -ne 1376 then echo "shar: 'Makefile' was damaged during transit (should have been 1376 bytes)" fi fi if test -f README then echo "shar: will not over-write existing file 'README'" else echo 'x - README' sed 's/^X//' << '\SHAR_EOF' > README X-------------------------- X#v#t#a#l#k%$%s%9%H!<%k<j=g X-------------------------- X 1. #m#a#k#e$9$k!# X #2$D$N<B9T7A<0%U%!%$%k!"vtalk!"vtalkd$,:n@.$5$l$k!# X X 2. vtalk $r/usr/local/bin$K0\$9!# X % mv vtalk /usr/local/bin X X 3. vtalkd $r/usr/local/lib$K0\$9!# X % mv vtalkd /usr/local/lib X X X------------------ X#v#t#a#l#k;HMQJ}K! X------------------ X X vtalk $O!"SUN SPARCstation1 MQ$Nvoice talk%3%^%s%I$G$9!#vtalk%3%^%s%I$r X;HMQ$9$k$K$O!"M=$avtalk%G!<%b%s$rN)$A>e$2$F$*$/I,MW$,$"$j$^$9!#0J2<$K!" X X #1!%vtalk %3%^%s%I(vtalk) X #2!%vtalk %G!<%b%s(vtalkd) X X$N=g$G@bL@$7$^$9!# X X X#1!%vtalk %3%^%s%I X XL>A0 vtalk - voice talk to another user on SUN SPARCstation1 X X7A<0!!!!vtalk [username@hostname] X X5!G=!!!!%^%7%s4V!JSUN SPARCstation1)$G"$*OC"$r$9$k!"talk%3%^%s%I$NvoiceHG!# X X;HMQ>r7o X!J%O!<%I!K X 1.#2Bf0J>eSUN SPARCstation1$,$"$k!# X 2.3F%^%7%s$K%^%$%/$,<hIU$i$l$F$$$k!# X X!J%=%U%H!K X 1./etc/services $K!""vtalk"$H$$$&%5!<%S%9$,tcp$GDj5A$5$l$F$$$k!# X Nc!Kvtalk xxx/tcp X (xxx $O!"%7%9%F%`$G6u$$$F$$$kE,Ev$J%]!<%HHV9f$r;XDj$9$k!#!K X X 2.3F%^%7%s$G vtalkd(vtalk%G!<%b%s!K$,5/F0$5$l$F$$$k!# X X;HMQJ}K! X!R8F$SB&!S X % vtalk Aj<j$NL>A0!wAj<j$N%^%7%sL> X X Aj<j$N%^%7%s$G0J2<$N%a%C%;!<%8$,I=<($5$l$k!# X X Message from VtalkDaemon at <time>... X vtalk:connection requested by 8F$SB&$NL>A0!w8F$SB&$N%^%7%sL> X vtalk:respond with: vtalk X X!R<u$1B&!S X % vtalk X (Cm0U :$3$3$G$O!"8F$SB&$NL>A0!w8F$SB&$N%^%7%sL>$r;XDj$7$J$$!#) X X X#2!%vtalk %G!<%b%s X XL>A0 vtalkd - voice talk daemon X X7A<0 vtalkd X X5!G= vtalk(voice talk)%3%^%s%I$r%5%]!<%H$9$k!"%G!<%b%s%W%m%0%i%`!# X X X;HMQ>r7o X /etc/services $K!""vtalk"$H$$$&%5!<%S%9$,tcp$GDj5A$5$l$F$$$k!# X X;HMQJ}K! X %9!<%Q!<%f!<%6$K$J$j!"%P%C%/%0%i%&%s%I$GN)$A>e$2$k(rc.local X %U%!%$%kEy$G!K X X # vtalkd & X X \SHAR_EOF if test `wc -c < README` -ne 2101 then echo "shar: 'README' was damaged during transit (should have been 2101 bytes)" fi fi if test -f audio.c then echo "shar: will not over-write existing file 'audio.c'" else echo 'x - audio.c' sed 's/^X//' << '\SHAR_EOF' > audio.c X/* 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/* 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 X#include <stdio.h> X#include <sys/ioctl.h> /* for audio */ X#include <sbusdev/audioreg.h> X#include <sun/audioio.h> X Xint fd_audio; X X Xdevice_open() X{ 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 X Xvoid Xset_volume() X{ 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 X \SHAR_EOF if test `wc -c < audio.c` -ne 2069 then echo "shar: 'audio.c' was damaged during transit (should have been 2069 bytes)" fi fi if test -f netwk.c then echo "shar: will not over-write existing file 'netwk.c'" else echo 'x - netwk.c' sed 's/^X//' << '\SHAR_EOF' > netwk.c X/* 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/* 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 X#include <errno.h> X#include <stdio.h> X#include <string.h> X#include <netdb.h> X#include <sys/file.h> X#include <sys/types.h> X#include <sys/socket.h> X#include <netinet/in.h> X#include <sys/param.h> X#include <sys/time.h> X#include "netwk.h" X X X/* #define BUFFER_SIZE 256 */ X#define BUFFER_SIZE 64 /* record */ X#define INT sizeof(int) X X Xstruct daemon_msg msg; X Xstruct in_addr machine_addr; /* inet address */ Xint machine_addrtype; Xint dsockt; /* socket for daemon */ Xint vsockt; /* socket for voice talk */ X X Xvoid X check_args(argc, argv, flag) Xint argc; Xchar **argv; Xint *flag; X{ 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@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 X Xvoid X open_dsocket() X{ X struct sockaddr_in daemon; /* daemon sockname */ X struct servent* sp; /* server entry */ X X#ifdef DEBUG X fprintf(stderr,"vtalk:open_dsocket\n"); X#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 X Xcall_vtalkd(caller) X int caller; X{ X X#ifdef DEBUG X fprintf(stderr,"vtalk:call vtalk daemon\n"); X#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 X Xvoid X call() X{ X struct sockaddr_in sin; X int sd; X X#ifdef DEBUG X fprintf(stderr,"vtalk:open vtalk socket\n"); X#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 X#ifdef DEBUG X fprintf(stderr,"vtalk:sin=%d %d %d \n",sin.sin_port, X sin.sin_addr,sin.sin_family); X#endif DEBUG X X if(bind(sd, (struct sockaddr*)&sin, sizeof(sin)) X < 0){ X X#ifdef DEBUG X fprintf(stderr,"vtalk:bind:errno = %d\n",errno); X#endif DEBUG X X perror("vtalk: binding local socket"); X exit(1); X } X X /* LISTEN */ X listen(sd, 5); X X#ifdef DEBUG X fprintf(stderr,"vtalk:caller:listen\n"); X#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 X#ifdef DEBUG X fprintf(stderr,"vtalk:caller:accepted\n"); X#endif X /* CLOSE old sockt */ X close(sd); X X} X X Xvoid X response() X{ X struct sockaddr_in sin; X X#ifdef DEBUG X fprintf(stderr,"vtalk:open vtalk socket\n"); X#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 X#ifdef DEBUG X fprintf(stderr,"vtalk:receiver:connected\n"); X#endif X} X X Xvoid X vtalk(audio_fd, caller) Xint audio_fd; Xint caller; X{ 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 X Xstatic 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 "Anyone is not waiting for you", X}; X#define NANSWERS (sizeof(messages) /sizeof (messages[0])) X X Xoutput_err(status) X int status; X{ X if(status < NANSWERS) X fprintf(stderr,"[%s]\n",messages[status]); X X} X \SHAR_EOF if test `wc -c < netwk.c` -ne 6791 then echo "shar: 'netwk.c' was damaged during transit (should have been 6791 bytes)" fi fi if test -f netwk.h then echo "shar: will not over-write existing file 'netwk.h'" else echo 'x - netwk.h' sed 's/^X//' << '\SHAR_EOF' > netwk.h X/* 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 X#include "vtalk.h" X Xstruct 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 X}; \SHAR_EOF if test `wc -c < netwk.h` -ne 547 then echo "shar: 'netwk.h' was damaged during transit (should have been 547 bytes)" fi fi if test -f vtalk.c then echo "shar: will not over-write existing file 'vtalk.c'" else echo 'x - vtalk.c' sed 's/^X//' << '\SHAR_EOF' > vtalk.c X/* 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/* 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 X#include "vtalk.h" X Xmain(argc, argv) Xint argc; Xchar *argv[]; X{ 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 X \SHAR_EOF if test `wc -c < vtalk.c` -ne 929 then echo "shar: 'vtalk.c' was damaged during transit (should have been 929 bytes)" fi fi if test -f vtalk.h then echo "shar: will not over-write existing file 'vtalk.h'" else echo 'x - vtalk.h' sed 's/^X//' << '\SHAR_EOF' > vtalk.h X/* 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 X#define MAX_QUEUE 10 X#define NAME_LEN 64 X X/* server -> client msg.status */ X#define SUCCESS 0 X#define NOEXIST 1 X#define FAILED 2 X#define UNKNOWN 3 X#define PERMISSION_DENIED 4 X#define NOWAIT 5 \SHAR_EOF if test `wc -c < vtalk.h` -ne 476 then echo "shar: 'vtalk.h' was damaged during transit (should have been 476 bytes)" fi fi if test -f vtalkd.c then echo "shar: will not over-write existing file 'vtalkd.c'" else echo 'x - vtalkd.c' sed 's/^X//' << '\SHAR_EOF' > vtalkd.c X/* 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/* 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 X#include <errno.h> X#include <stdio.h> X#include <netdb.h> X#include <sys/file.h> X#include <sys/types.h> X#include <sys/socket.h> X#include <sys/stat.h> X#include <netinet/in.h> X#include <utmp.h> X#include <syslog.h> X#include <sys/time.h> X#include <signal.h> X#include "netwk.h" X X Xstruct sockaddr_in caller_queue[MAX_QUEUE]; Xint current_caller = 0; Xint sockt; Xint daemon_sockt; X Xmain(argc, argv) X int argc; X char *argv[]; X{ 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 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 X Xvoid X open_dsocket() X{ 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 X Xreceive_msg(msg) X struct daemon_msg *msg; X{ 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"); X#ifdef DEBUG X fprintf(stderr,"errno = %d\n",errno); X#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 X Xcheck_user(name, ftty) X char *name; X char *ftty; X{ 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; X#ifdef DEBUG X fprintf(stderr,"ftty: %s\n", ftty); X#endif DEBUG X status = SUCCESS; X break; X } X } X fclose(fp); X return (status); X} X X Xopen_socket(msg) X struct daemon_msg *msg; X{ 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 X Xannounce(msg, ftty) X struct daemon_msg *msg; X char *ftty; X{ 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 vtalkdaemon at %d:%02d ...\n", X time->tm_hour, time->tm_min); X fprintf(fp,"Vtalk: connection requested by %s@%s.\n", X msg->caller_name, msg->caller_host_name); X fprintf(fp,"Vtalk: respond with: vtalk\n"); X fflush(fp); X X fclose(fp); X return(SUCCESS); X} X X Xcheck_caller(sin) X struct sockaddr_in *sin; X{ 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 X Xreturn_msg(msg) X struct daemon_msg *msg; X{ 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 X Xdie(sig) X int sig; X{ X close(daemon_sockt); X exit(sig != 0); X} \SHAR_EOF if test `wc -c < vtalkd.c` -ne 5910 then echo "shar: 'vtalkd.c' was damaged during transit (should have been 5910 bytes)" fi fi echo "End of part 1/1" exit 0