1/* $NetBSD: rwalld.c,v 1.22 2011/08/30 17:06:20 plunky Exp $ */ 2 3/* 4 * Copyright (c) 1993 Christopher G. Demetriou 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed for the 18 * NetBSD Project. See http://www.NetBSD.org/ for 19 * information about NetBSD. 20 * 4. The name of the author may not be used to endorse or promote products 21 * derived from this software without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 26 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 28 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 32 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 * 34 * <<Id: LICENSE,v 1.2 2000/06/14 15:57:33 cgd Exp>> 35 */ 36 37#include <sys/cdefs.h> 38#ifndef lint 39__RCSID("$NetBSD: rwalld.c,v 1.22 2011/08/30 17:06:20 plunky Exp $"); 40#endif /* not lint */ 41 42#include <unistd.h> 43#include <stdlib.h> 44#include <sys/types.h> 45#include <pwd.h> 46#include <stdio.h> 47#include <string.h> 48#include <syslog.h> 49#include <errno.h> 50#include <sys/socket.h> 51#include <signal.h> 52#include <sys/wait.h> 53#include <rpc/rpc.h> 54#include <rpcsvc/rwall.h> 55 56#ifdef OSF 57#define WALL_CMD "/usr/sbin/wall" 58#else 59#define WALL_CMD "/usr/bin/wall -n" 60#endif 61 62static int from_inetd = 1; 63 64static void cleanup(int); 65static void wallprog_1(struct svc_req *, SVCXPRT *); 66 67__dead static void 68cleanup(int n) 69{ 70 71 (void)rpcb_unset(WALLPROG, WALLVERS, NULL); 72 exit(0); 73} 74 75int 76main(int argc, char *argv[]) 77{ 78 SVCXPRT *transp; 79 struct sockaddr_storage from; 80 socklen_t fromlen; 81 82 if (geteuid() == 0) { 83 struct passwd *pep = getpwnam("nobody"); 84 if (pep) 85 setuid(pep->pw_uid); 86 else 87 setuid(getuid()); 88 } 89 90 /* 91 * See if inetd started us 92 */ 93 fromlen = sizeof(from); 94 if (getsockname(0, (struct sockaddr *)&from, &fromlen) < 0) 95 from_inetd = 0; 96 97 if (!from_inetd) { 98 daemon(0, 0); 99 100 (void) rpcb_unset(WALLPROG, WALLVERS, NULL); 101 102 (void) signal(SIGINT, cleanup); 103 (void) signal(SIGTERM, cleanup); 104 (void) signal(SIGHUP, cleanup); 105 } 106 107 openlog("rpc.rwalld", LOG_PID, LOG_DAEMON); 108 109 if (from_inetd) { 110 transp = svc_dg_create(0, 0, 0); 111 if (transp == NULL) { 112 syslog(LOG_ERR, "cannot create udp service."); 113 exit(1); 114 } 115 if (!svc_reg(transp, WALLPROG, WALLVERS, wallprog_1, NULL)) { 116 syslog(LOG_ERR, "unable to register " 117 "(WALLPROG, WALLVERS)."); 118 exit(1); 119 } 120 } else { 121 if (!svc_create(wallprog_1, WALLPROG, WALLVERS, "udp")) { 122 syslog(LOG_ERR, "unable to create " 123 "(WALLPROG, WALLVERS.)"); 124 exit(1); 125 } 126 } 127 128 svc_run(); 129 syslog(LOG_ERR, "svc_run returned"); 130 exit(1); 131 132} 133 134void * 135wallproc_wall_1_svc(char **s, struct svc_req *rqstp) 136{ 137 FILE *pfp; 138 139 pfp = popen(WALL_CMD, "w"); 140 if (pfp != NULL) { 141 fprintf(pfp, "\007\007%s", *s); 142 pclose(pfp); 143 } 144 145 return (*s); 146} 147 148static void 149wallprog_1(struct svc_req *rqstp, SVCXPRT *transp) 150{ 151 union { 152 char *wallproc_wall_1_arg; 153 } argument; 154 char *result; 155 xdrproc_t xdr_argument, xdr_result; 156 char *(*local) __P((char **, struct svc_req *)); 157 158 switch (rqstp->rq_proc) { 159 case NULLPROC: 160 (void)svc_sendreply(transp, (xdrproc_t)xdr_void, NULL); 161 goto leave; 162 163 case WALLPROC_WALL: 164 xdr_argument = (xdrproc_t)xdr_wrapstring; 165 xdr_result = (xdrproc_t)xdr_void; 166 local = (char *(*) __P((char **, struct svc_req *))) 167 wallproc_wall_1_svc; 168 break; 169 170 default: 171 svcerr_noproc(transp); 172 goto leave; 173 } 174 memset((char *)&argument, 0, sizeof(argument)); 175 if (!svc_getargs(transp, xdr_argument, (caddr_t)&argument)) { 176 svcerr_decode(transp); 177 goto leave; 178 } 179 result = (*local)((char **)&argument, rqstp); 180 if (result != NULL && !svc_sendreply(transp, xdr_result, result)) { 181 svcerr_systemerr(transp); 182 } 183 if (!svc_freeargs(transp, xdr_argument, (caddr_t)&argument)) { 184 syslog(LOG_ERR, "unable to free arguments"); 185 exit(1); 186 } 187leave: 188 if (from_inetd) 189 exit(0); 190} 191