home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright (c) 1989 Oki Electric Industry Co., Ltd.
- *
- * This file is part of vtalkd.
- *
- * Permission to use, copy, modify and distribute this program without
- * fee is grtanted, provided that the above copyright notice appear
- * in all copies.
- *
- */
- /*
- * vtalkd.c main routine for vtalkd
- *
- * vtalkd is a daemon for
- * Voice TALK with the user on another machine.
- *
- */
-
- #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"
-
-
- struct sockaddr_in caller_queue[MAX_QUEUE];
- int current_caller = 0;
- int sockt;
- int daemon_sockt;
-
- main(argc, argv)
- int argc;
- char *argv[];
- {
-
- struct daemon_msg msg;
- char ftty[20];
- void open_dsocket();
- int die();
-
- /* super user ?
- if(getuid()){
- fprintf(stderr,
- "%s: getuid: not super user\n", argv[0]);
- exit(1);
- }
- */
- openlog("vtalkd", LOG_PID, LOG_DAEMON);
-
- /* daemon */
- open_dsocket();
-
- /* signal handler */
- signal(SIGINT, die);
- signal(SIGQUIT, die);
- signal(SIGTERM, die);
-
- /* waiting for caller */
- while(1){
- receive_msg(&msg);
- if(msg.flag){
- if((msg.status = check_user(msg.receiver_name,
- ftty))== SUCCESS){
- if((msg.status = open_socket(&msg))
- == SUCCESS)
- msg.status = announce(&msg, ftty);
- }
- } else msg.status = check_caller(&msg.sin);
-
- return_msg(&msg);
- close(sockt);
- }
- }
-
-
- void
- open_dsocket()
- {
- struct sockaddr_in sin;
- struct servent* sp;
-
- /* GETSERVBYNAME for vtalk */
- if((sp = getservbyname("vtalk","tcp")) == NULL){
- syslog(LOG_ERR, "getservbyname: %m");
- exit(1);
- }
-
- /* get port */
- bzero((char *)&sin, sizeof(sin));
- sin.sin_port = sp->s_port;
-
- /* SOCKET for server */
- if((daemon_sockt = socket(AF_INET, SOCK_STREAM, 0)) < 0){
- syslog(LOG_ERR, "socket: %m");
- exit(1);
- }
-
- /* BIND to daemon port */
- if(bind(daemon_sockt, (struct sockaddr*)&sin, sizeof(sin))
- < 0){
- syslog(LOG_ERR, "bind: %m");
- exit(1);
- }
-
- /* LISTEN */
- listen(daemon_sockt, 5);
-
- }
-
-
- receive_msg(msg)
- struct daemon_msg *msg;
- {
-
- /* waiting until ACCEPT msg */
- while((sockt = accept(daemon_sockt, (struct sockaddr*)0,
- (int *)0)) < 0){
- if(errno == EINTR)
- continue;
- syslog(LOG_WARNING, "accept: %m");
- #ifdef DEBUG
- fprintf(stderr,"errno = %d\n",errno);
- #endif DEBUG
- }
-
- /* READ msg from client */
- if(read(sockt, (char*)msg, sizeof(struct daemon_msg)) !=
- sizeof(struct daemon_msg)){
- syslog(LOG_WARNING, "read: %m");
- return(FAILED);
- }
- return(SUCCESS);
- }
-
-
- check_user(name, ftty)
- char *name;
- char *ftty;
- {
- struct utmp ubuf;
- int status;
- FILE *fp;
- struct stat sbuf;
-
- /* open utmp file */
- if ((fp = fopen("/etc/utmp", "r")) == NULL) {
- perror("vtalk: can't open /etc/utmp");
- return (FAILED);
- }
-
- /* check user existing */
- status = NOEXIST;
- strcpy(ftty, "/dev/");
- while(fread((char*)&ubuf, sizeof ubuf, 1, fp) == 1)
- if(strncmp(ubuf.ut_name, name, sizeof(ubuf.ut_name)) == 0) {
- status = PERMISSION_DENIED;
- strcpy(ftty+5, ubuf.ut_line);
- if(stat(ftty, &sbuf) == 0) {
- if(!(sbuf.st_mode & 020))
- continue;
- #ifdef DEBUG
- fprintf(stderr,"ftty: %s\n", ftty);
- #endif DEBUG
- status = SUCCESS;
- break;
- }
- }
- fclose(fp);
- return (status);
- }
-
-
- open_socket(msg)
- struct daemon_msg *msg;
- {
- struct sockaddr_in sin; /* address for caller */
- int sd; /* socket discriptor */
- int port; /* port number for vtalk */
- struct hostent *hp;
-
- /* SOCKET for caller & receiver */
- if((sd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
- syslog(LOG_ERR,"socket: %m");
- close(daemon_sockt);
- exit(1);
- }
-
- /* BIND to port(>=5000) */
- bzero((char *)&sin, sizeof(sin));
- sin.sin_family = AF_INET;
- sin.sin_addr.s_addr = htonl(INADDR_ANY);
- port = IPPORT_USERRESERVED - 1;
- do{
- port++;
- sin.sin_port = htons(port);
- }while(bind(sd, (struct sockaddr*)&sin, sizeof(sin))!=0);
-
- /* return port number to client */
- msg->sin.sin_port = htons(port);
-
- /* save request to caller_queue */
- hp = gethostbyname(msg->caller_host_name);
- if (hp == (struct hostent *) 0) {
- return(UNKNOWN);
- }
- bcopy(hp->h_addr, (char *) &sin.sin_addr, hp->h_length);
- caller_queue[current_caller].sin_port = htons(port);
- caller_queue[current_caller].sin_addr = sin.sin_addr;
- caller_queue[current_caller].sin_family = hp->h_addrtype;
- current_caller++;
-
- /* CLOSE socket */
- close(sd);
- return(SUCCESS);
- }
-
-
- announce(msg, ftty)
- struct daemon_msg *msg;
- char *ftty;
- {
- struct timeval tval;
- struct timezone tzone;
- struct tm *localtime();
- struct tm *time;
- FILE *fp;
-
- /* test ftty F_OK? */
- if(access(ftty, 0) != 0)
- return(FAILED);
- if((fp = fopen(ftty, "w")) == NULL)
- return(PERMISSION_DENIED);
-
- /* get time */
- gettimeofday(&tval, &tzone);
- time = localtime(&tval.tv_sec);
-
- /* display message */
- fprintf(fp,"\n");
- fprintf(fp,"\007");
- fprintf(fp,"Vtalk - Message from Voice Talk Daemon at %d:%02d ...\n",
- time->tm_hour, time->tm_min);
- fprintf(fp,"Vtalk - User %s@%s wants to talk to you !\n",
- msg->caller_name, msg->caller_host_name);
- fprintf(fp,"Vtalk - Please respond with: vtalk\n");
- fflush(fp);
-
- fclose(fp);
- return(SUCCESS);
- }
-
-
- check_caller(sin)
- struct sockaddr_in *sin;
- {
- if(current_caller == 0)
- return(NOWAIT);
- else{
- sin->sin_port = caller_queue[0].sin_port;
- sin->sin_addr = caller_queue[0].sin_addr;
- sin->sin_family = caller_queue[0].sin_family;
- current_caller--;
- return(SUCCESS);
- }
-
- }
-
-
- return_msg(msg)
- struct daemon_msg *msg;
- {
- int x;
-
- /* WRITE msg to client */
- x = write(sockt, (char*)msg, sizeof(struct daemon_msg));
- if(x != sizeof(struct daemon_msg)){
- syslog(LOG_WARNING, "write: %m");
- return(FAILED);
- }
- return(SUCCESS);
-
- }
-
-
- die(sig)
- int sig;
- {
- close(daemon_sockt);
- exit(sig != 0);
- }
-