1e6209940SPedro F. Giffuni /*-
2e6209940SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause
3e6209940SPedro F. Giffuni *
4935a0024SGeoff Rehmet * Copyright (c) 1993 Christopher G. Demetriou
5935a0024SGeoff Rehmet * All rights reserved.
6935a0024SGeoff Rehmet *
7935a0024SGeoff Rehmet * Redistribution and use in source and binary forms, with or without
8935a0024SGeoff Rehmet * modification, are permitted provided that the following conditions
9935a0024SGeoff Rehmet * are met:
10935a0024SGeoff Rehmet * 1. Redistributions of source code must retain the above copyright
11935a0024SGeoff Rehmet * notice, this list of conditions and the following disclaimer.
12935a0024SGeoff Rehmet * 2. Redistributions in binary form must reproduce the above copyright
13935a0024SGeoff Rehmet * notice, this list of conditions and the following disclaimer in the
14935a0024SGeoff Rehmet * documentation and/or other materials provided with the distribution.
15935a0024SGeoff Rehmet * 3. The name of the author may not be used to endorse or promote
16935a0024SGeoff Rehmet * products derived from this software without specific prior written
17935a0024SGeoff Rehmet * permission.
18935a0024SGeoff Rehmet *
19935a0024SGeoff Rehmet * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
20935a0024SGeoff Rehmet * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21935a0024SGeoff Rehmet * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22935a0024SGeoff Rehmet * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
23935a0024SGeoff Rehmet * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24935a0024SGeoff Rehmet * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25935a0024SGeoff Rehmet * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26935a0024SGeoff Rehmet * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27935a0024SGeoff Rehmet * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28935a0024SGeoff Rehmet * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29935a0024SGeoff Rehmet * SUCH DAMAGE.
30935a0024SGeoff Rehmet */
31935a0024SGeoff Rehmet
32f0c80f9bSPhilippe Charnier #include <sys/cdefs.h>
3340150947SPhilippe Charnier #include <err.h>
34935a0024SGeoff Rehmet #include <pwd.h>
35935a0024SGeoff Rehmet #include <signal.h>
3640150947SPhilippe Charnier #include <stdio.h>
3740150947SPhilippe Charnier #include <stdlib.h>
3840150947SPhilippe Charnier #include <string.h>
3940150947SPhilippe Charnier #include <syslog.h>
40fd8e4ebcSMike Barcroft #include <arpa/inet.h>
41935a0024SGeoff Rehmet #include <rpc/rpc.h>
42935a0024SGeoff Rehmet #include <rpcsvc/rwall.h>
4340150947SPhilippe Charnier #include <sys/socket.h>
4440150947SPhilippe Charnier #include <sys/types.h>
4540150947SPhilippe Charnier #include <sys/wait.h>
4640150947SPhilippe Charnier #include <unistd.h>
47935a0024SGeoff Rehmet
48935a0024SGeoff Rehmet #ifdef OSF
49935a0024SGeoff Rehmet #define WALL_CMD "/usr/sbin/wall"
50935a0024SGeoff Rehmet #else
51935a0024SGeoff Rehmet #define WALL_CMD "/usr/bin/wall -n"
52935a0024SGeoff Rehmet #endif
53935a0024SGeoff Rehmet
54a174e5b1SWarner Losh void wallprog_1(struct svc_req *rqstp, SVCXPRT *transp);
55a174e5b1SWarner Losh void possess(void);
56a174e5b1SWarner Losh void killkids(int sig);
57*69c0fb2aSAlfonso Gregory static void usage(void) __dead2;
58935a0024SGeoff Rehmet
59935a0024SGeoff Rehmet int nodaemon = 0;
60935a0024SGeoff Rehmet int from_inetd = 1;
61935a0024SGeoff Rehmet
6240150947SPhilippe Charnier int
main(int argc,char * argv[])63a174e5b1SWarner Losh main(int argc, char *argv[])
64935a0024SGeoff Rehmet {
65935a0024SGeoff Rehmet SVCXPRT *transp;
6678e3eed0SStefan Farfeleder socklen_t salen;
6778e3eed0SStefan Farfeleder int ok;
68af37179bSAlfred Perlstein struct sockaddr_storage sa;
69935a0024SGeoff Rehmet
70935a0024SGeoff Rehmet if (argc == 2 && !strcmp(argv[1], "-n"))
71935a0024SGeoff Rehmet nodaemon = 1;
7240150947SPhilippe Charnier if (argc != 1 && !nodaemon)
7340150947SPhilippe Charnier usage();
74935a0024SGeoff Rehmet
75935a0024SGeoff Rehmet if (geteuid() == 0) {
76935a0024SGeoff Rehmet struct passwd *pep = getpwnam("nobody");
77935a0024SGeoff Rehmet if (pep)
78935a0024SGeoff Rehmet setuid(pep->pw_uid);
79935a0024SGeoff Rehmet else
80935a0024SGeoff Rehmet setuid(getuid());
81935a0024SGeoff Rehmet }
82935a0024SGeoff Rehmet
83935a0024SGeoff Rehmet /*
84935a0024SGeoff Rehmet * See if inetd started us
85935a0024SGeoff Rehmet */
867c760cfdSAndreas Schulz salen = sizeof(sa);
87935a0024SGeoff Rehmet if (getsockname(0, (struct sockaddr *)&sa, &salen) < 0) {
88935a0024SGeoff Rehmet from_inetd = 0;
89935a0024SGeoff Rehmet }
90935a0024SGeoff Rehmet
91935a0024SGeoff Rehmet if (!from_inetd) {
92935a0024SGeoff Rehmet if (!nodaemon)
93935a0024SGeoff Rehmet possess();
94935a0024SGeoff Rehmet
95af37179bSAlfred Perlstein (void)rpcb_unset(WALLPROG, WALLVERS, NULL);
96935a0024SGeoff Rehmet }
97935a0024SGeoff Rehmet
98935a0024SGeoff Rehmet (void)signal(SIGCHLD, killkids);
99935a0024SGeoff Rehmet
10040150947SPhilippe Charnier openlog("rpc.rwalld", LOG_CONS|LOG_PID, LOG_DAEMON);
10140150947SPhilippe Charnier
102af37179bSAlfred Perlstein /* create and register the service */
103af37179bSAlfred Perlstein if (from_inetd) {
104af37179bSAlfred Perlstein transp = svc_tli_create(0, NULL, NULL, 0, 0);
105935a0024SGeoff Rehmet if (transp == NULL) {
106af37179bSAlfred Perlstein syslog(LOG_ERR, "couldn't create udp service.");
107935a0024SGeoff Rehmet exit(1);
108935a0024SGeoff Rehmet }
109af37179bSAlfred Perlstein ok = svc_reg(transp, WALLPROG, WALLVERS,
110af37179bSAlfred Perlstein wallprog_1, NULL);
111af37179bSAlfred Perlstein } else
112af37179bSAlfred Perlstein ok = svc_create(wallprog_1,
113af37179bSAlfred Perlstein WALLPROG, WALLVERS, "udp");
114af37179bSAlfred Perlstein if (!ok) {
115af37179bSAlfred Perlstein syslog(LOG_ERR, "unable to register (WALLPROG, WALLVERS, %s)", (!from_inetd)?"udp":"(inetd)");
116935a0024SGeoff Rehmet exit(1);
117935a0024SGeoff Rehmet }
118935a0024SGeoff Rehmet svc_run();
11940150947SPhilippe Charnier syslog(LOG_ERR, "svc_run returned");
120935a0024SGeoff Rehmet exit(1);
12140150947SPhilippe Charnier }
122935a0024SGeoff Rehmet
12340150947SPhilippe Charnier static void
usage(void)124a174e5b1SWarner Losh usage(void)
12540150947SPhilippe Charnier {
12640150947SPhilippe Charnier fprintf(stderr, "usage: rpc.rwalld [-n]\n");
12740150947SPhilippe Charnier exit(1);
128935a0024SGeoff Rehmet }
129935a0024SGeoff Rehmet
130a174e5b1SWarner Losh void
possess(void)131a174e5b1SWarner Losh possess(void)
132935a0024SGeoff Rehmet {
133935a0024SGeoff Rehmet daemon(0, 0);
134935a0024SGeoff Rehmet }
135935a0024SGeoff Rehmet
136a174e5b1SWarner Losh void
killkids(int sig __unused)137f0c80f9bSPhilippe Charnier killkids(int sig __unused)
138935a0024SGeoff Rehmet {
139935a0024SGeoff Rehmet while(wait4(-1, NULL, WNOHANG, NULL) > 0)
140935a0024SGeoff Rehmet ;
141935a0024SGeoff Rehmet }
142935a0024SGeoff Rehmet
143a174e5b1SWarner Losh void *
wallproc_wall_1_svc(wrapstring * s,struct svc_req * rqstp __unused)144f0c80f9bSPhilippe Charnier wallproc_wall_1_svc(wrapstring *s, struct svc_req *rqstp __unused)
145935a0024SGeoff Rehmet {
146e4a0e42bSBill Paul static void *dummy = NULL;
147e4a0e42bSBill Paul
148935a0024SGeoff Rehmet /* fork, popen wall with special option, and send the message */
149935a0024SGeoff Rehmet if (fork() == 0) {
150935a0024SGeoff Rehmet FILE *pfp;
151935a0024SGeoff Rehmet
152935a0024SGeoff Rehmet pfp = popen(WALL_CMD, "w");
153935a0024SGeoff Rehmet if (pfp != NULL) {
154935a0024SGeoff Rehmet fprintf(pfp, "\007\007%s", *s);
155935a0024SGeoff Rehmet pclose(pfp);
156935a0024SGeoff Rehmet exit(0);
157935a0024SGeoff Rehmet }
158935a0024SGeoff Rehmet }
159e4a0e42bSBill Paul return(&dummy);
160935a0024SGeoff Rehmet }
161935a0024SGeoff Rehmet
162935a0024SGeoff Rehmet void
wallprog_1(struct svc_req * rqstp,SVCXPRT * transp)163a174e5b1SWarner Losh wallprog_1(struct svc_req *rqstp, SVCXPRT *transp)
164935a0024SGeoff Rehmet {
165935a0024SGeoff Rehmet union {
166935a0024SGeoff Rehmet char *wallproc_wall_1_arg;
167935a0024SGeoff Rehmet } argument;
168e4253ae8SJohn Baldwin void *result;
169e4253ae8SJohn Baldwin xdrproc_t xdr_argument, xdr_result;
170e4253ae8SJohn Baldwin typedef void *(svc_cb)(void *arg, struct svc_req *rqstp);
171e4253ae8SJohn Baldwin svc_cb *local;
172935a0024SGeoff Rehmet
173935a0024SGeoff Rehmet switch (rqstp->rq_proc) {
174935a0024SGeoff Rehmet case NULLPROC:
175f249dbccSDag-Erling Smørgrav (void)svc_sendreply(transp, (xdrproc_t)xdr_void, NULL);
176935a0024SGeoff Rehmet goto leave;
177935a0024SGeoff Rehmet
178935a0024SGeoff Rehmet case WALLPROC_WALL:
179e4253ae8SJohn Baldwin xdr_argument = (xdrproc_t)xdr_wrapstring;
180e4253ae8SJohn Baldwin xdr_result = (xdrproc_t)xdr_void;
181e4253ae8SJohn Baldwin local = (svc_cb *)wallproc_wall_1_svc;
182935a0024SGeoff Rehmet break;
183935a0024SGeoff Rehmet
184935a0024SGeoff Rehmet default:
185935a0024SGeoff Rehmet svcerr_noproc(transp);
186935a0024SGeoff Rehmet goto leave;
187935a0024SGeoff Rehmet }
188f249dbccSDag-Erling Smørgrav bzero(&argument, sizeof(argument));
189e4253ae8SJohn Baldwin if (!svc_getargs(transp, xdr_argument, &argument)) {
190935a0024SGeoff Rehmet svcerr_decode(transp);
191935a0024SGeoff Rehmet goto leave;
192935a0024SGeoff Rehmet }
193935a0024SGeoff Rehmet result = (*local)(&argument, rqstp);
194f249dbccSDag-Erling Smørgrav if (result != NULL &&
195e4253ae8SJohn Baldwin !svc_sendreply(transp, xdr_result, result)) {
196935a0024SGeoff Rehmet svcerr_systemerr(transp);
197935a0024SGeoff Rehmet }
198e4253ae8SJohn Baldwin if (!svc_freeargs(transp, xdr_argument, &argument)) {
19940150947SPhilippe Charnier syslog(LOG_ERR, "unable to free arguments");
200935a0024SGeoff Rehmet exit(1);
201935a0024SGeoff Rehmet }
202935a0024SGeoff Rehmet leave:
203935a0024SGeoff Rehmet if (from_inetd)
204935a0024SGeoff Rehmet exit(0);
205935a0024SGeoff Rehmet }
206