Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/libexec/rpc.rwalld/rwalld.c
34823 views
1
/*-
2
* SPDX-License-Identifier: BSD-3-Clause
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. The name of the author may not be used to endorse or promote
16
* products derived from this software without specific prior written
17
* permission.
18
*
19
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
20
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
23
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29
* SUCH DAMAGE.
30
*/
31
32
#include <sys/cdefs.h>
33
#include <err.h>
34
#include <pwd.h>
35
#include <signal.h>
36
#include <stdio.h>
37
#include <stdlib.h>
38
#include <string.h>
39
#include <syslog.h>
40
#include <arpa/inet.h>
41
#include <rpc/rpc.h>
42
#include <rpcsvc/rwall.h>
43
#include <sys/socket.h>
44
#include <sys/types.h>
45
#include <sys/wait.h>
46
#include <unistd.h>
47
48
#ifdef OSF
49
#define WALL_CMD "/usr/sbin/wall"
50
#else
51
#define WALL_CMD "/usr/bin/wall -n"
52
#endif
53
54
void wallprog_1(struct svc_req *rqstp, SVCXPRT *transp);
55
void possess(void);
56
void killkids(int sig);
57
static void usage(void) __dead2;
58
59
int nodaemon = 0;
60
int from_inetd = 1;
61
62
int
63
main(int argc, char *argv[])
64
{
65
SVCXPRT *transp;
66
socklen_t salen;
67
int ok;
68
struct sockaddr_storage sa;
69
70
if (argc == 2 && !strcmp(argv[1], "-n"))
71
nodaemon = 1;
72
if (argc != 1 && !nodaemon)
73
usage();
74
75
if (geteuid() == 0) {
76
struct passwd *pep = getpwnam("nobody");
77
if (pep)
78
setuid(pep->pw_uid);
79
else
80
setuid(getuid());
81
}
82
83
/*
84
* See if inetd started us
85
*/
86
salen = sizeof(sa);
87
if (getsockname(0, (struct sockaddr *)&sa, &salen) < 0) {
88
from_inetd = 0;
89
}
90
91
if (!from_inetd) {
92
if (!nodaemon)
93
possess();
94
95
(void)rpcb_unset(WALLPROG, WALLVERS, NULL);
96
}
97
98
(void)signal(SIGCHLD, killkids);
99
100
openlog("rpc.rwalld", LOG_CONS|LOG_PID, LOG_DAEMON);
101
102
/* create and register the service */
103
if (from_inetd) {
104
transp = svc_tli_create(0, NULL, NULL, 0, 0);
105
if (transp == NULL) {
106
syslog(LOG_ERR, "couldn't create udp service.");
107
exit(1);
108
}
109
ok = svc_reg(transp, WALLPROG, WALLVERS,
110
wallprog_1, NULL);
111
} else
112
ok = svc_create(wallprog_1,
113
WALLPROG, WALLVERS, "udp");
114
if (!ok) {
115
syslog(LOG_ERR, "unable to register (WALLPROG, WALLVERS, %s)", (!from_inetd)?"udp":"(inetd)");
116
exit(1);
117
}
118
svc_run();
119
syslog(LOG_ERR, "svc_run returned");
120
exit(1);
121
}
122
123
static void
124
usage(void)
125
{
126
fprintf(stderr, "usage: rpc.rwalld [-n]\n");
127
exit(1);
128
}
129
130
void
131
possess(void)
132
{
133
daemon(0, 0);
134
}
135
136
void
137
killkids(int sig __unused)
138
{
139
while(wait4(-1, NULL, WNOHANG, NULL) > 0)
140
;
141
}
142
143
void *
144
wallproc_wall_1_svc(wrapstring *s, struct svc_req *rqstp __unused)
145
{
146
static void *dummy = NULL;
147
148
/* fork, popen wall with special option, and send the message */
149
if (fork() == 0) {
150
FILE *pfp;
151
152
pfp = popen(WALL_CMD, "w");
153
if (pfp != NULL) {
154
fprintf(pfp, "\007\007%s", *s);
155
pclose(pfp);
156
exit(0);
157
}
158
}
159
return(&dummy);
160
}
161
162
void
163
wallprog_1(struct svc_req *rqstp, SVCXPRT *transp)
164
{
165
union {
166
char *wallproc_wall_1_arg;
167
} argument;
168
void *result;
169
xdrproc_t xdr_argument, xdr_result;
170
typedef void *(svc_cb)(void *arg, struct svc_req *rqstp);
171
svc_cb *local;
172
173
switch (rqstp->rq_proc) {
174
case NULLPROC:
175
(void)svc_sendreply(transp, (xdrproc_t)xdr_void, NULL);
176
goto leave;
177
178
case WALLPROC_WALL:
179
xdr_argument = (xdrproc_t)xdr_wrapstring;
180
xdr_result = (xdrproc_t)xdr_void;
181
local = (svc_cb *)wallproc_wall_1_svc;
182
break;
183
184
default:
185
svcerr_noproc(transp);
186
goto leave;
187
}
188
bzero(&argument, sizeof(argument));
189
if (!svc_getargs(transp, xdr_argument, &argument)) {
190
svcerr_decode(transp);
191
goto leave;
192
}
193
result = (*local)(&argument, rqstp);
194
if (result != NULL &&
195
!svc_sendreply(transp, xdr_result, result)) {
196
svcerr_systemerr(transp);
197
}
198
if (!svc_freeargs(transp, xdr_argument, &argument)) {
199
syslog(LOG_ERR, "unable to free arguments");
200
exit(1);
201
}
202
leave:
203
if (from_inetd)
204
exit(0);
205
}
206
207