1 /* $NetBSD: rwalld.c,v 1.18 2000/06/14 17:25:18 cgd 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.18 2000/06/14 17:25:18 cgd 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 62 static int from_inetd = 1; 63 64 static void cleanup(int); 65 static void wallprog_1(struct svc_req *, SVCXPRT *); 66 67 int main(int, char *[]); 68 69 static void 70 cleanup(int n) 71 { 72 73 (void)rpcb_unset(WALLPROG, WALLVERS, NULL); 74 exit(0); 75 } 76 77 int 78 main(int argc, char *argv[]) 79 { 80 SVCXPRT *transp; 81 struct sockaddr_storage from; 82 int fromlen; 83 84 if (geteuid() == 0) { 85 struct passwd *pep = getpwnam("nobody"); 86 if (pep) 87 setuid(pep->pw_uid); 88 else 89 setuid(getuid()); 90 } 91 92 /* 93 * See if inetd started us 94 */ 95 fromlen = sizeof(from); 96 if (getsockname(0, (struct sockaddr *)&from, &fromlen) < 0) 97 from_inetd = 0; 98 99 if (!from_inetd) { 100 daemon(0, 0); 101 102 (void) rpcb_unset(WALLPROG, WALLVERS, NULL); 103 104 (void) signal(SIGINT, cleanup); 105 (void) signal(SIGTERM, cleanup); 106 (void) signal(SIGHUP, cleanup); 107 } 108 109 openlog("rpc.rwalld", LOG_PID, LOG_DAEMON); 110 111 if (from_inetd) { 112 transp = svc_dg_create(0, 0, 0); 113 if (transp == NULL) { 114 syslog(LOG_ERR, "cannot create udp service."); 115 exit(1); 116 } 117 if (!svc_reg(transp, WALLPROG, WALLVERS, wallprog_1, NULL)) { 118 syslog(LOG_ERR, "unable to register " 119 "(WALLPROG, WALLVERS)."); 120 exit(1); 121 } 122 } else { 123 if (!svc_create(wallprog_1, WALLPROG, WALLVERS, "udp")) { 124 syslog(LOG_ERR, "unable to create " 125 "(WALLPROG, WALLVERS.)"); 126 exit(1); 127 } 128 } 129 130 svc_run(); 131 syslog(LOG_ERR, "svc_run returned"); 132 exit(1); 133 134 } 135 136 void * 137 wallproc_wall_1_svc(char **s, struct svc_req *rqstp) 138 { 139 FILE *pfp; 140 141 pfp = popen(WALL_CMD, "w"); 142 if (pfp != NULL) { 143 fprintf(pfp, "\007\007%s", *s); 144 pclose(pfp); 145 } 146 147 return (*s); 148 } 149 150 static void 151 wallprog_1(struct svc_req *rqstp, SVCXPRT *transp) 152 { 153 union { 154 char *wallproc_wall_1_arg; 155 } argument; 156 char *result; 157 xdrproc_t xdr_argument, xdr_result; 158 char *(*local) __P((char **, struct svc_req *)); 159 160 switch (rqstp->rq_proc) { 161 case NULLPROC: 162 (void)svc_sendreply(transp, xdr_void, (char *)NULL); 163 goto leave; 164 165 case WALLPROC_WALL: 166 xdr_argument = (xdrproc_t)xdr_wrapstring; 167 xdr_result = (xdrproc_t)xdr_void; 168 local = (char *(*) __P((char **, struct svc_req *))) 169 wallproc_wall_1_svc; 170 break; 171 172 default: 173 svcerr_noproc(transp); 174 goto leave; 175 } 176 memset((char *)&argument, 0, sizeof(argument)); 177 if (!svc_getargs(transp, xdr_argument, (caddr_t)&argument)) { 178 svcerr_decode(transp); 179 goto leave; 180 } 181 result = (*local)((char **)&argument, rqstp); 182 if (result != NULL && !svc_sendreply(transp, xdr_result, result)) { 183 svcerr_systemerr(transp); 184 } 185 if (!svc_freeargs(transp, xdr_argument, (caddr_t)&argument)) { 186 syslog(LOG_ERR, "unable to free arguments"); 187 exit(1); 188 } 189 leave: 190 if (from_inetd) 191 exit(0); 192 } 193