12341Scsgr/* 22341Scsgr * Copyright (c) 1993 Christopher G. Demetriou 32341Scsgr * All rights reserved. 42341Scsgr * 52341Scsgr * Redistribution and use in source and binary forms, with or without 62341Scsgr * modification, are permitted provided that the following conditions 72341Scsgr * are met: 82341Scsgr * 1. Redistributions of source code must retain the above copyright 92341Scsgr * notice, this list of conditions and the following disclaimer. 102341Scsgr * 2. Redistributions in binary form must reproduce the above copyright 112341Scsgr * notice, this list of conditions and the following disclaimer in the 122341Scsgr * documentation and/or other materials provided with the distribution. 132341Scsgr * 3. The name of the author may not be used to endorse or promote 142341Scsgr * products derived from this software without specific prior written 152341Scsgr * permission. 162341Scsgr * 172341Scsgr * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 182341Scsgr * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 192341Scsgr * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 202341Scsgr * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 212341Scsgr * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 222341Scsgr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 232341Scsgr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 242341Scsgr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 252341Scsgr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 262341Scsgr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 272341Scsgr * SUCH DAMAGE. 282341Scsgr */ 292341Scsgr 30216560Scharnier#include <sys/cdefs.h> 31216560Scharnier__FBSDID("$FreeBSD$"); 322341Scsgr 3331488Scharnier#include <err.h> 342341Scsgr#include <pwd.h> 3531488Scharnier#include <signal.h> 362341Scsgr#include <stdio.h> 3731488Scharnier#include <stdlib.h> 382341Scsgr#include <string.h> 3931488Scharnier#include <syslog.h> 4090868Smike#include <arpa/inet.h> 4131488Scharnier#include <rpc/rpc.h> 4231488Scharnier#include <rpcsvc/rwall.h> 432341Scsgr#include <sys/socket.h> 4431488Scharnier#include <sys/types.h> 452341Scsgr#include <sys/wait.h> 4631488Scharnier#include <unistd.h> 472341Scsgr 482341Scsgr#ifdef OSF 492341Scsgr#define WALL_CMD "/usr/sbin/wall" 502341Scsgr#else 512341Scsgr#define WALL_CMD "/usr/bin/wall -n" 522341Scsgr#endif 532341Scsgr 5490336Simpvoid wallprog_1(struct svc_req *rqstp, SVCXPRT *transp); 5590336Simpvoid possess(void); 5690336Simpvoid killkids(int sig); 5790336Simpstatic void usage(void); 582341Scsgr 592341Scsgrint nodaemon = 0; 602341Scsgrint from_inetd = 1; 612341Scsgr 6231488Scharnierint 6390336Simpmain(int argc, char *argv[]) 642341Scsgr{ 652341Scsgr SVCXPRT *transp; 66141918Sstefanf socklen_t salen; 67141918Sstefanf int ok; 68100120Salfred struct sockaddr_storage sa; 692341Scsgr 702341Scsgr if (argc == 2 && !strcmp(argv[1], "-n")) 712341Scsgr nodaemon = 1; 7231488Scharnier if (argc != 1 && !nodaemon) 7331488Scharnier usage(); 742341Scsgr 752341Scsgr if (geteuid() == 0) { 762341Scsgr struct passwd *pep = getpwnam("nobody"); 772341Scsgr if (pep) 782341Scsgr setuid(pep->pw_uid); 792341Scsgr else 802341Scsgr setuid(getuid()); 812341Scsgr } 822341Scsgr 832341Scsgr /* 842341Scsgr * See if inetd started us 852341Scsgr */ 864659Sats salen = sizeof(sa); 872341Scsgr if (getsockname(0, (struct sockaddr *)&sa, &salen) < 0) { 882341Scsgr from_inetd = 0; 892341Scsgr } 908870Srgrimes 912341Scsgr if (!from_inetd) { 922341Scsgr if (!nodaemon) 932341Scsgr possess(); 942341Scsgr 95100120Salfred (void)rpcb_unset(WALLPROG, WALLVERS, NULL); 962341Scsgr } 972341Scsgr 982341Scsgr (void)signal(SIGCHLD, killkids); 992341Scsgr 10031488Scharnier openlog("rpc.rwalld", LOG_CONS|LOG_PID, LOG_DAEMON); 10131488Scharnier 102100120Salfred /* create and register the service */ 103100120Salfred if (from_inetd) { 104100120Salfred transp = svc_tli_create(0, NULL, NULL, 0, 0); 105100120Salfred if (transp == NULL) { 106100120Salfred syslog(LOG_ERR, "couldn't create udp service."); 107100120Salfred exit(1); 108100120Salfred } 109100120Salfred ok = svc_reg(transp, WALLPROG, WALLVERS, 110100120Salfred wallprog_1, NULL); 111100120Salfred } else 112100120Salfred ok = svc_create(wallprog_1, 113100120Salfred WALLPROG, WALLVERS, "udp"); 114100120Salfred if (!ok) { 115100120Salfred syslog(LOG_ERR, "unable to register (WALLPROG, WALLVERS, %s)", (!from_inetd)?"udp":"(inetd)"); 1162341Scsgr exit(1); 1172341Scsgr } 1182341Scsgr svc_run(); 11931488Scharnier syslog(LOG_ERR, "svc_run returned"); 1202341Scsgr exit(1); 12131488Scharnier} 1222341Scsgr 12331488Scharnierstatic void 12490336Simpusage(void) 12531488Scharnier{ 12631488Scharnier fprintf(stderr, "usage: rpc.rwalld [-n]\n"); 12731488Scharnier exit(1); 1282341Scsgr} 1292341Scsgr 13090336Simpvoid 13190336Simppossess(void) 1322341Scsgr{ 1332341Scsgr daemon(0, 0); 1342341Scsgr} 1352341Scsgr 13690336Simpvoid 137216560Scharnierkillkids(int sig __unused) 1382341Scsgr{ 1392341Scsgr while(wait4(-1, NULL, WNOHANG, NULL) > 0) 1402341Scsgr ; 1412341Scsgr} 1422341Scsgr 14390336Simpvoid * 144216560Scharnierwallproc_wall_1_svc(wrapstring *s, struct svc_req *rqstp __unused) 1452341Scsgr{ 14632629Swpaul static void *dummy = NULL; 14732629Swpaul 1482341Scsgr /* fork, popen wall with special option, and send the message */ 1492341Scsgr if (fork() == 0) { 1502341Scsgr FILE *pfp; 1512341Scsgr 1522341Scsgr pfp = popen(WALL_CMD, "w"); 1532341Scsgr if (pfp != NULL) { 1542341Scsgr fprintf(pfp, "\007\007%s", *s); 1552341Scsgr pclose(pfp); 1562341Scsgr exit(0); 1572341Scsgr } 1582341Scsgr } 15932629Swpaul return(&dummy); 1602341Scsgr} 1612341Scsgr 1622341Scsgrvoid 16390336Simpwallprog_1(struct svc_req *rqstp, SVCXPRT *transp) 1642341Scsgr{ 1652341Scsgr union { 1662341Scsgr char *wallproc_wall_1_arg; 1672341Scsgr } argument; 1682341Scsgr char *result; 1692341Scsgr bool_t (*xdr_argument)(), (*xdr_result)(); 1702341Scsgr char *(*local)(); 1712341Scsgr 1722341Scsgr switch (rqstp->rq_proc) { 1732341Scsgr case NULLPROC: 17495658Sdes (void)svc_sendreply(transp, (xdrproc_t)xdr_void, NULL); 1752341Scsgr goto leave; 1762341Scsgr 1772341Scsgr case WALLPROC_WALL: 1782341Scsgr xdr_argument = xdr_wrapstring; 1792341Scsgr xdr_result = xdr_void; 18032629Swpaul local = (char *(*)()) wallproc_wall_1_svc; 1812341Scsgr break; 1822341Scsgr 1832341Scsgr default: 1842341Scsgr svcerr_noproc(transp); 1852341Scsgr goto leave; 1862341Scsgr } 18795658Sdes bzero(&argument, sizeof(argument)); 18895658Sdes if (!svc_getargs(transp, (xdrproc_t)xdr_argument, &argument)) { 1892341Scsgr svcerr_decode(transp); 1902341Scsgr goto leave; 1912341Scsgr } 1922341Scsgr result = (*local)(&argument, rqstp); 19395658Sdes if (result != NULL && 19495658Sdes !svc_sendreply(transp, (xdrproc_t)xdr_result, result)) { 1952341Scsgr svcerr_systemerr(transp); 1962341Scsgr } 19795658Sdes if (!svc_freeargs(transp, (xdrproc_t)xdr_argument, &argument)) { 19831488Scharnier syslog(LOG_ERR, "unable to free arguments"); 1992341Scsgr exit(1); 2002341Scsgr } 2012341Scsgrleave: 2022341Scsgr if (from_inetd) 2032341Scsgr exit(0); 2042341Scsgr} 205