home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 2 / 2375 / vtalkd.c < prev   
Encoding:
C/C++ Source or Header  |  1990-12-28  |  5.8 KB  |  299 lines

  1. /* 
  2.  *   Copyright (c) 1989 Oki Electric Industry Co., Ltd.
  3.  *
  4.  *   This file is part of vtalkd.
  5.  *
  6.  *   Permission to use, copy, modify and distribute this program without
  7.  *   fee is grtanted,  provided that  the above  copyright notice appear
  8.  *   in all copies.
  9.  *
  10.  */
  11. /*
  12.  *  vtalkd.c    main routine for vtalkd
  13.  *
  14.  *  vtalkd is a daemon for 
  15.  *  Voice TALK with the user on another machine.
  16.  *  
  17.  */
  18.  
  19. #include <errno.h>
  20. #include <stdio.h>
  21. #include <netdb.h>
  22. #include <sys/file.h>
  23. #include <sys/types.h>
  24. #include <sys/socket.h>
  25. #include <sys/stat.h>
  26. #include <netinet/in.h>
  27. #include <utmp.h>
  28. #include <syslog.h>
  29. #include <sys/time.h>
  30. #include <signal.h>
  31. #include "netwk.h"
  32.  
  33.  
  34. struct sockaddr_in caller_queue[MAX_QUEUE];
  35. int current_caller = 0;
  36. int sockt;
  37. int daemon_sockt;
  38.  
  39. main(argc, argv)
  40.      int argc;
  41.      char *argv[];
  42. {
  43.     
  44.     struct daemon_msg msg;
  45.     char ftty[20];
  46.     void open_dsocket();
  47.     int die();
  48.     
  49.     /* super user ? 
  50.     if(getuid()){
  51.         fprintf(stderr,
  52.             "%s: getuid: not super user\n", argv[0]);
  53.         exit(1);
  54.     }
  55. */    
  56.     openlog("vtalkd", LOG_PID, LOG_DAEMON);
  57.     
  58.     /*  daemon  */
  59.     open_dsocket();
  60.     
  61.     /* signal handler */
  62.     signal(SIGINT, die);
  63.     signal(SIGQUIT, die);
  64.     signal(SIGTERM, die);
  65.     
  66.     /* waiting for caller */
  67.     while(1){
  68.         receive_msg(&msg);
  69.         if(msg.flag){
  70.             if((msg.status = check_user(msg.receiver_name,
  71.                             ftty))== SUCCESS){
  72.                 if((msg.status = open_socket(&msg))
  73.                    == SUCCESS)
  74.                   msg.status = announce(&msg, ftty);
  75.             }
  76.         } else    msg.status = check_caller(&msg.sin);
  77.         
  78.         return_msg(&msg); 
  79.         close(sockt);
  80.     }
  81. }
  82.  
  83.  
  84. void
  85.   open_dsocket()
  86. {
  87.     struct sockaddr_in sin;
  88.     struct servent* sp;
  89.     
  90.     /* GETSERVBYNAME for vtalk */
  91.     if((sp = getservbyname("vtalk","tcp")) == NULL){
  92.         syslog(LOG_ERR, "getservbyname: %m");
  93.         exit(1);
  94.     }
  95.     
  96.     /* get port */
  97.     bzero((char *)&sin, sizeof(sin));
  98.     sin.sin_port = sp->s_port;
  99.     
  100.     /* SOCKET for server */
  101.     if((daemon_sockt = socket(AF_INET, SOCK_STREAM, 0)) < 0){
  102.         syslog(LOG_ERR, "socket: %m");
  103.         exit(1);
  104.     }
  105.  
  106.     /* BIND to daemon port */
  107.     if(bind(daemon_sockt, (struct sockaddr*)&sin, sizeof(sin)) 
  108.        < 0){
  109.         syslog(LOG_ERR, "bind: %m");
  110.         exit(1);
  111.     }
  112.     
  113.     /* LISTEN */
  114.     listen(daemon_sockt, 5);
  115.     
  116. }
  117.  
  118.  
  119. receive_msg(msg)
  120.      struct daemon_msg *msg;
  121. {
  122.     
  123.     /* waiting until ACCEPT msg */
  124.     while((sockt = accept(daemon_sockt, (struct sockaddr*)0,
  125.                   (int *)0)) < 0){
  126.         if(errno == EINTR)
  127.           continue;
  128.         syslog(LOG_WARNING, "accept: %m");
  129. #ifdef DEBUG
  130.         fprintf(stderr,"errno = %d\n",errno);
  131. #endif DEBUG
  132.     }
  133.     
  134.     /* READ msg from client */
  135.     if(read(sockt, (char*)msg, sizeof(struct daemon_msg)) !=
  136.        sizeof(struct daemon_msg)){
  137.         syslog(LOG_WARNING, "read: %m");
  138.         return(FAILED);
  139.     }
  140.     return(SUCCESS);
  141. }
  142.  
  143.  
  144. check_user(name, ftty)
  145.      char *name;
  146.      char *ftty;
  147. {
  148.     struct utmp ubuf;
  149.     int status;
  150.     FILE *fp;
  151.     struct stat sbuf;
  152.     
  153.     /* open utmp file */
  154.     if ((fp = fopen("/etc/utmp", "r")) == NULL) {
  155.         perror("vtalk: can't open /etc/utmp");
  156.         return (FAILED);
  157.     }
  158.  
  159.     /* check user existing */
  160.     status = NOEXIST;
  161.     strcpy(ftty, "/dev/");
  162.     while(fread((char*)&ubuf, sizeof ubuf, 1, fp) == 1)
  163.       if(strncmp(ubuf.ut_name, name, sizeof(ubuf.ut_name)) == 0) {
  164.           status = PERMISSION_DENIED;
  165.           strcpy(ftty+5, ubuf.ut_line);
  166.           if(stat(ftty, &sbuf) == 0) {
  167.               if(!(sbuf.st_mode & 020))
  168.                 continue;
  169. #ifdef DEBUG 
  170.               fprintf(stderr,"ftty: %s\n", ftty);
  171. #endif DEBUG
  172.               status = SUCCESS;
  173.               break;
  174.           }
  175.       }
  176.     fclose(fp);
  177.     return (status);
  178. }
  179.  
  180.  
  181. open_socket(msg)
  182.      struct daemon_msg *msg;
  183. {
  184.     struct sockaddr_in sin; /* address for caller */
  185.     int sd;                 /* socket discriptor */
  186.     int port;               /* port number for vtalk */
  187.     struct hostent *hp;
  188.     
  189.     /* SOCKET for caller & receiver */
  190.     if((sd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
  191.         syslog(LOG_ERR,"socket: %m");
  192.         close(daemon_sockt);
  193.         exit(1);
  194.     }
  195.     
  196.     /* BIND to port(>=5000) */
  197.     bzero((char *)&sin, sizeof(sin));
  198.     sin.sin_family = AF_INET;
  199.     sin.sin_addr.s_addr = htonl(INADDR_ANY);
  200.     port = IPPORT_USERRESERVED - 1;
  201.     do{
  202.         port++;
  203.         sin.sin_port = htons(port);
  204.     }while(bind(sd, (struct sockaddr*)&sin, sizeof(sin))!=0);
  205.     
  206.     /* return port number to client */
  207.     msg->sin.sin_port = htons(port);
  208.     
  209.     /* save request to caller_queue */
  210.     hp = gethostbyname(msg->caller_host_name);
  211.     if (hp == (struct hostent *) 0) {
  212.         return(UNKNOWN);
  213.     }
  214.     bcopy(hp->h_addr, (char *) &sin.sin_addr, hp->h_length);
  215.     caller_queue[current_caller].sin_port = htons(port);
  216.     caller_queue[current_caller].sin_addr = sin.sin_addr;
  217.     caller_queue[current_caller].sin_family = hp->h_addrtype;
  218.     current_caller++;
  219.     
  220.     /* CLOSE socket */
  221.     close(sd);
  222.     return(SUCCESS);
  223. }
  224.  
  225.  
  226. announce(msg, ftty)
  227.      struct daemon_msg *msg;
  228.      char *ftty;
  229. {
  230.     struct timeval tval;
  231.     struct timezone tzone;
  232.     struct tm *localtime();
  233.     struct tm *time;
  234.     FILE *fp;
  235.     
  236.     /* test ftty F_OK? */
  237.     if(access(ftty, 0) != 0)
  238.       return(FAILED);
  239.     if((fp = fopen(ftty, "w")) == NULL)
  240.       return(PERMISSION_DENIED);
  241.  
  242.     /* get time */
  243.     gettimeofday(&tval, &tzone);
  244.     time = localtime(&tval.tv_sec);
  245.     
  246.     /* display message */
  247.     fprintf(fp,"\n");
  248.     fprintf(fp,"\007");
  249.     fprintf(fp,"Vtalk - Message from Voice Talk Daemon at %d:%02d ...\n",
  250.         time->tm_hour, time->tm_min);
  251.     fprintf(fp,"Vtalk - User %s@%s wants to talk to you !\n",
  252.         msg->caller_name, msg->caller_host_name);
  253.     fprintf(fp,"Vtalk - Please respond with: vtalk\n");
  254.     fflush(fp);
  255.  
  256.     fclose(fp);
  257.     return(SUCCESS);
  258. }
  259.  
  260.  
  261. check_caller(sin)
  262.      struct sockaddr_in *sin;
  263. {
  264.     if(current_caller == 0)
  265.       return(NOWAIT);
  266.     else{
  267.         sin->sin_port = caller_queue[0].sin_port;
  268.         sin->sin_addr = caller_queue[0].sin_addr;
  269.         sin->sin_family = caller_queue[0].sin_family;
  270.         current_caller--;
  271.         return(SUCCESS);
  272.     }
  273.     
  274. }
  275.  
  276.  
  277. return_msg(msg)
  278.      struct daemon_msg *msg;
  279. {
  280.     int x;
  281.     
  282.     /* WRITE msg to client */
  283.     x = write(sockt, (char*)msg, sizeof(struct daemon_msg));
  284.     if(x != sizeof(struct daemon_msg)){
  285.         syslog(LOG_WARNING, "write: %m");
  286.         return(FAILED);
  287.     }
  288.     return(SUCCESS);
  289.     
  290. }
  291.  
  292.  
  293. die(sig)
  294.      int sig;
  295. {
  296.     close(daemon_sockt);
  297.     exit(sig != 0);
  298. }
  299.