home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / N / TCPIP / NETKIT-B.05 / NETKIT-B / NetKit-B-0.05 / rpc.rwalld / rwalld.c < prev   
Encoding:
C/C++ Source or Header  |  1994-05-23  |  5.3 KB  |  211 lines

  1. /*
  2.  * Copyright (c) 1993 Christopher G. Demetriou
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. The name of the author may not be used to endorse or promote
  14.  *    products derived from this software without specific prior written
  15.  *    permission.
  16.  *
  17.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
  18.  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  19.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
  21.  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  23.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  24.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  25.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  26.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  27.  * SUCH DAMAGE.
  28.  */
  29.  
  30. #ifndef lint
  31. static char rcsid[] = "$Id: rwalld.c,v 1.1 1994/05/23 09:08:34 rzsfl Exp rzsfl $";
  32. #endif /* not lint */
  33.  
  34. #include <unistd.h>
  35. #include <sys/types.h>
  36. #include <pwd.h>
  37. #include <stdio.h>
  38. #include <string.h>
  39. #include <errno.h>
  40. #include <sys/socket.h>
  41. #include <signal.h>
  42. #include <sys/wait.h>
  43. #include <rpc/rpc.h>
  44. #include <rpcsvc/rwall.h>
  45.  
  46. #ifdef OSF
  47. #define WALL_CMD "/usr/sbin/wall"
  48. #else
  49. #define WALL_CMD "/usr/bin/wall -n"
  50. #endif
  51.  
  52. void wallprog_1();
  53. void possess();
  54. void killkids();
  55.  
  56. int nodaemon = 0;
  57. int from_inetd = 1;
  58.  
  59. main(argc, argv)
  60.     int argc;
  61.     char *argv[];
  62. {
  63.     SVCXPRT *transp;
  64.     int s, salen;
  65.     struct sockaddr_in sa;
  66.         int sock = 0;
  67.         int proto = 0;
  68.  
  69.     if (argc == 2 && !strcmp(argv[1], "-n"))
  70.         nodaemon = 1;
  71.     if (argc != 1 && !nodaemon) {
  72.         printf("usage: %s [-n]\n", argv[0]);
  73.         exit(1);
  74.     }
  75.  
  76.     if (geteuid() == 0) {
  77.         struct passwd *pep = getpwnam("nobody");
  78.         if (pep)
  79.             setuid(pep->pw_uid);
  80.         else
  81.             setuid(getuid());
  82.     }
  83.  
  84.         /*
  85.          * See if inetd started us
  86.          */
  87.         if (getsockname(0, (struct sockaddr *)&sa, &salen) < 0) {
  88.                 from_inetd = 0;
  89.                 sock = RPC_ANYSOCK;
  90.                 proto = IPPROTO_UDP;
  91.         }
  92.         
  93.         if (!from_inetd) {
  94.                 if (!nodaemon)
  95.                         possess();
  96.  
  97.                 (void)pmap_unset(WALLPROG, WALLVERS);
  98.                 if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
  99.                         perror("socket");
  100.                         exit(1);
  101.                 }
  102.                 bzero((char *)&sa, sizeof sa);
  103.                 if (bind(s, (struct sockaddr *)&sa, sizeof sa) < 0) {
  104.                         perror("bind");
  105.                         exit(1);
  106.                 }
  107.  
  108.                 salen = sizeof sa;
  109.                 if (getsockname(s, (struct sockaddr *)&sa, &salen)) {
  110.                         perror("getsockname");
  111.                         exit(1);
  112.                 }
  113.  
  114.                 pmap_set(WALLPROG, WALLVERS, IPPROTO_UDP, ntohs(sa.sin_port));
  115.                 if (dup2(s, 0) < 0) {
  116.                         perror("dup2");
  117.                         exit(1);
  118.                 }
  119.                 (void)pmap_unset(WALLPROG, WALLVERS);
  120.         }
  121.  
  122.     (void)signal(SIGCHLD, killkids);
  123.  
  124.     transp = svcudp_create(sock);
  125.     if (transp == NULL) {
  126.         (void)fprintf(stderr, "cannot create udp service.\n");
  127.         exit(1);
  128.     }
  129.     if (!svc_register(transp, WALLPROG, WALLVERS, wallprog_1, proto)) {
  130.         (void)fprintf(stderr, "unable to register (WALLPROG, WALLVERS, udp).\n");
  131.         exit(1);
  132.     }
  133.     svc_run();
  134.     (void)fprintf(stderr, "svc_run returned\n");
  135.     exit(1);
  136.  
  137. }
  138.  
  139. void possess()
  140. {
  141.     daemon(0, 0);
  142. }
  143.  
  144. void killkids()
  145. {
  146.     while(wait4(-1, NULL, WNOHANG, NULL) > 0)
  147.         ;
  148. }
  149.  
  150. void *wallproc_wall_1(s, tmp1)
  151.     char **s;
  152.     CLIENT *tmp1;
  153. {
  154.     /* fork, popen wall with special option, and send the message */
  155.     if (fork() == 0) {
  156.         FILE *pfp;
  157.  
  158.         pfp = popen(WALL_CMD, "w");
  159.         if (pfp != NULL) {
  160.             fprintf(pfp, "\007\007%s", *s);
  161.             pclose(pfp);
  162.             exit(0);
  163.         }
  164.     }
  165. }
  166.  
  167. void
  168. wallprog_1(rqstp, transp)
  169.     struct svc_req *rqstp;
  170.     SVCXPRT *transp;
  171. {
  172.     union {
  173.         char *wallproc_wall_1_arg;
  174.     } argument;
  175.     char *result;
  176.     bool_t (*xdr_argument)(), (*xdr_result)();
  177.     char *(*local)();
  178.  
  179.     switch (rqstp->rq_proc) {
  180.     case NULLPROC:
  181.         (void)svc_sendreply(transp, xdr_void, (char *)NULL);
  182.         goto leave;
  183.  
  184.     case WALLPROC_WALL:
  185.         xdr_argument = xdr_wrapstring;
  186.         xdr_result = xdr_void;
  187.         local = (char *(*)()) wallproc_wall_1;
  188.         break;
  189.  
  190.     default:
  191.         svcerr_noproc(transp);
  192.         goto leave;
  193.     }
  194.     bzero((char *)&argument, sizeof(argument));
  195.     if (!svc_getargs(transp, xdr_argument, &argument)) {
  196.         svcerr_decode(transp);
  197.         goto leave;
  198.     }
  199.     result = (*local)(&argument, rqstp);
  200.     if (result != NULL && !svc_sendreply(transp, xdr_result, result)) {
  201.         svcerr_systemerr(transp);
  202.     }
  203.     if (!svc_freeargs(transp, xdr_argument, &argument)) {
  204.         (void)fprintf(stderr, "unable to free arguments\n");
  205.         exit(1);
  206.     }
  207. leave:
  208.         if (from_inetd)
  209.                 exit(0);
  210. }
  211.