rwalld.c revision 4659
1290001Sglebius/* 2290001Sglebius * Copyright (c) 1993 Christopher G. Demetriou 3290001Sglebius * All rights reserved. 4290001Sglebius * 5290001Sglebius * Redistribution and use in source and binary forms, with or without 6290001Sglebius * modification, are permitted provided that the following conditions 7290001Sglebius * are met: 8290001Sglebius * 1. Redistributions of source code must retain the above copyright 9290001Sglebius * notice, this list of conditions and the following disclaimer. 10132451Sroberto * 2. Redistributions in binary form must reproduce the above copyright 11290001Sglebius * notice, this list of conditions and the following disclaimer in the 12290001Sglebius * documentation and/or other materials provided with the distribution. 13290001Sglebius * 3. The name of the author may not be used to endorse or promote 14132451Sroberto * products derived from this software without specific prior written 15290001Sglebius * permission. 16132451Sroberto * 17290001Sglebius * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 18290001Sglebius * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19290001Sglebius * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20290001Sglebius * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 21290001Sglebius * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22290001Sglebius * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23132451Sroberto * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24290001Sglebius * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25290001Sglebius * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26290001Sglebius * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27290001Sglebius * SUCH DAMAGE. 28290001Sglebius */ 29290001Sglebius 30290001Sglebius#ifndef lint 31290001Sglebiusstatic char rcsid[] = "$Id: rwalld.c,v 1.1.1.1 1994/08/28 14:58:36 csgr Exp $"; 32290001Sglebius#endif /* not lint */ 33290001Sglebius 34290001Sglebius#include <unistd.h> 35290001Sglebius#include <sys/types.h> 36132451Sroberto#include <pwd.h> 37290001Sglebius#include <stdio.h> 38290001Sglebius#include <string.h> 39132451Sroberto#include <errno.h> 40290001Sglebius#include <sys/socket.h> 41290001Sglebius#include <signal.h> 42290001Sglebius#include <sys/wait.h> 43290001Sglebius#include <rpc/rpc.h> 44290001Sglebius#include <rpcsvc/rwall.h> 45290001Sglebius 46290001Sglebius#ifdef OSF 47290001Sglebius#define WALL_CMD "/usr/sbin/wall" 48132451Sroberto#else 49132451Sroberto#define WALL_CMD "/usr/bin/wall -n" 50132451Sroberto#endif 51290001Sglebius 52290001Sglebiusvoid wallprog_1(); 53132451Srobertovoid possess(); 54132451Srobertovoid killkids(); 55290001Sglebius 56290001Sglebiusint nodaemon = 0; 57290001Sglebiusint from_inetd = 1; 58132451Sroberto 59132451Srobertomain(argc, argv) 60290001Sglebius int argc; 61290001Sglebius char *argv[]; 62132451Sroberto{ 63290001Sglebius SVCXPRT *transp; 64290001Sglebius int s, salen; 65290001Sglebius struct sockaddr_in sa; 66132451Sroberto int sock = 0; 67290001Sglebius int proto = 0; 68290001Sglebius 69132451Sroberto if (argc == 2 && !strcmp(argv[1], "-n")) 70132451Sroberto nodaemon = 1; 71290001Sglebius if (argc != 1 && !nodaemon) { 72290001Sglebius printf("usage: %s [-n]\n", argv[0]); 73290001Sglebius exit(1); 74290001Sglebius } 75182007Sroberto 76290001Sglebius if (geteuid() == 0) { 77290001Sglebius struct passwd *pep = getpwnam("nobody"); 78290001Sglebius if (pep) 79290001Sglebius setuid(pep->pw_uid); 80290001Sglebius else 81290001Sglebius setuid(getuid()); 82290001Sglebius } 83290001Sglebius 84290001Sglebius /* 85290001Sglebius * See if inetd started us 86290001Sglebius */ 87290001Sglebius salen = sizeof(sa); 88290001Sglebius if (getsockname(0, (struct sockaddr *)&sa, &salen) < 0) { 89290001Sglebius from_inetd = 0; 90290001Sglebius sock = RPC_ANYSOCK; 91290001Sglebius proto = IPPROTO_UDP; 92290001Sglebius } 93182007Sroberto 94290001Sglebius if (!from_inetd) { 95182007Sroberto if (!nodaemon) 96290001Sglebius possess(); 97290001Sglebius 98290001Sglebius (void)pmap_unset(WALLPROG, WALLVERS); 99290001Sglebius if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { 100290001Sglebius perror("socket"); 101290001Sglebius exit(1); 102290001Sglebius } 103290001Sglebius bzero((char *)&sa, sizeof sa); 104290001Sglebius if (bind(s, (struct sockaddr *)&sa, sizeof sa) < 0) { 105290001Sglebius perror("bind"); 106290001Sglebius exit(1); 107290001Sglebius } 108290001Sglebius 109290001Sglebius salen = sizeof sa; 110290001Sglebius if (getsockname(s, (struct sockaddr *)&sa, &salen)) { 111290001Sglebius perror("getsockname"); 112290001Sglebius exit(1); 113290001Sglebius } 114290001Sglebius 115290001Sglebius pmap_set(WALLPROG, WALLVERS, IPPROTO_UDP, ntohs(sa.sin_port)); 116290001Sglebius if (dup2(s, 0) < 0) { 117290001Sglebius perror("dup2"); 118290001Sglebius exit(1); 119290001Sglebius } 120290001Sglebius (void)pmap_unset(WALLPROG, WALLVERS); 121290001Sglebius } 122290001Sglebius 123290001Sglebius (void)signal(SIGCHLD, killkids); 124290001Sglebius 125290001Sglebius transp = svcudp_create(sock); 126290001Sglebius if (transp == NULL) { 127290001Sglebius (void)fprintf(stderr, "cannot create udp service.\n"); 128290001Sglebius exit(1); 129290001Sglebius } 130290001Sglebius if (!svc_register(transp, WALLPROG, WALLVERS, wallprog_1, proto)) { 131290001Sglebius (void)fprintf(stderr, "unable to register (WALLPROG, WALLVERS, udp).\n"); 132290001Sglebius exit(1); 133290001Sglebius } 134290001Sglebius svc_run(); 135290001Sglebius (void)fprintf(stderr, "svc_run returned\n"); 136290001Sglebius exit(1); 137132451Sroberto 138290001Sglebius} 139290001Sglebius 140182007Srobertovoid possess() 141132451Sroberto{ 142132451Sroberto daemon(0, 0); 143132451Sroberto} 144132451Sroberto 145182007Srobertovoid killkids() 146132451Sroberto{ 147290001Sglebius while(wait4(-1, NULL, WNOHANG, NULL) > 0) 148290001Sglebius ; 149290001Sglebius} 150132451Sroberto 151290001Sglebiusvoid *wallproc_wall_1(s) 152290001Sglebius char **s; 153290001Sglebius{ 154290001Sglebius /* fork, popen wall with special option, and send the message */ 155290001Sglebius if (fork() == 0) { 156290001Sglebius FILE *pfp; 157290001Sglebius 158290001Sglebius pfp = popen(WALL_CMD, "w"); 159290001Sglebius if (pfp != NULL) { 160132451Sroberto fprintf(pfp, "\007\007%s", *s); 161132451Sroberto pclose(pfp); 162290001Sglebius exit(0); 163290001Sglebius } 164290001Sglebius } 165290001Sglebius} 166290001Sglebius 167290001Sglebiusvoid 168290001Sglebiuswallprog_1(rqstp, transp) 169290001Sglebius struct svc_req *rqstp; 170290001Sglebius SVCXPRT *transp; 171290001Sglebius{ 172132451Sroberto union { 173290001Sglebius char *wallproc_wall_1_arg; 174290001Sglebius } argument; 175290001Sglebius char *result; 176290001Sglebius bool_t (*xdr_argument)(), (*xdr_result)(); 177290001Sglebius char *(*local)(); 178290001Sglebius 179290001Sglebius switch (rqstp->rq_proc) { 180290001Sglebius case NULLPROC: 181290001Sglebius (void)svc_sendreply(transp, xdr_void, (char *)NULL); 182132451Sroberto goto leave; 183132451Sroberto 184132451Sroberto case WALLPROC_WALL: 185132451Sroberto xdr_argument = xdr_wrapstring; 186290001Sglebius xdr_result = xdr_void; 187290001Sglebius local = (char *(*)()) wallproc_wall_1; 188132451Sroberto break; 189290001Sglebius 190290001Sglebius default: 191290001Sglebius svcerr_noproc(transp); 192290001Sglebius goto leave; 193290001Sglebius } 194290001Sglebius bzero((char *)&argument, sizeof(argument)); 195290001Sglebius if (!svc_getargs(transp, xdr_argument, &argument)) { 196290001Sglebius svcerr_decode(transp); 197290001Sglebius goto leave; 198290001Sglebius } 199290001Sglebius result = (*local)(&argument, rqstp); 200290001Sglebius if (result != NULL && !svc_sendreply(transp, xdr_result, result)) { 201290001Sglebius svcerr_systemerr(transp); 202290001Sglebius } 203290001Sglebius if (!svc_freeargs(transp, xdr_argument, &argument)) { 204132451Sroberto (void)fprintf(stderr, "unable to free arguments\n"); 205290001Sglebius exit(1); 206290001Sglebius } 207290001Sglebiusleave: 208290001Sglebius if (from_inetd) 209290001Sglebius exit(0); 210290001Sglebius} 211290001Sglebius