rwalld.c revision 1.15 1 /* $NetBSD: rwalld.c,v 1.15 2000/06/03 20:31:25 fvdl 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. 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 #ifndef lint
34 __RCSID("$NetBSD: rwalld.c,v 1.15 2000/06/03 20:31:25 fvdl Exp $");
35 #endif /* not lint */
36
37 #include <unistd.h>
38 #include <stdlib.h>
39 #include <sys/types.h>
40 #include <pwd.h>
41 #include <stdio.h>
42 #include <string.h>
43 #include <syslog.h>
44 #include <errno.h>
45 #include <sys/socket.h>
46 #include <signal.h>
47 #include <sys/wait.h>
48 #include <rpc/rpc.h>
49 #include <rpcsvc/rwall.h>
50
51 #ifdef OSF
52 #define WALL_CMD "/usr/sbin/wall"
53 #else
54 #define WALL_CMD "/usr/bin/wall -n"
55 #endif
56
57 static int from_inetd = 1;
58
59 static void cleanup(int);
60 static void wallprog_1(struct svc_req *, SVCXPRT *);
61
62 int main(int, char *[]);
63
64 static void
65 cleanup(int n)
66 {
67
68 (void)rpcb_unset(WALLPROG, WALLVERS, NULL);
69 exit(0);
70 }
71
72 int
73 main(int argc, char *argv[])
74 {
75 SVCXPRT *transp;
76 struct sockaddr_in from;
77 int fromlen;
78
79 if (geteuid() == 0) {
80 struct passwd *pep = getpwnam("nobody");
81 if (pep)
82 setuid(pep->pw_uid);
83 else
84 setuid(getuid());
85 }
86
87 /*
88 * See if inetd started us
89 */
90 fromlen = sizeof(from);
91 if (getsockname(0, (struct sockaddr *)&from, &fromlen) < 0)
92 from_inetd = 0;
93
94 if (!from_inetd) {
95 daemon(0, 0);
96
97 (void) rpcb_unset(WALLPROG, WALLVERS, NULL);
98
99 (void) signal(SIGINT, cleanup);
100 (void) signal(SIGTERM, cleanup);
101 (void) signal(SIGHUP, cleanup);
102 }
103
104 openlog("rpc.rwalld", LOG_PID, LOG_DAEMON);
105
106 if (from_inetd) {
107 transp = svc_dg_create(0, 0, 0);
108 if (transp == NULL) {
109 syslog(LOG_ERR, "cannot create udp service.");
110 exit(1);
111 }
112 if (!svc_reg(transp, WALLPROG, WALLVERS, wallprog_1, NULL)) {
113 syslog(LOG_ERR, "unable to register "
114 "(WALLPROG, WALLVERS).");
115 exit(1);
116 }
117 } else {
118 if (!svc_create(wallprog_1, WALLPROG, WALLVERS, "udp")) {
119 syslog(LOG_ERR, "unable to create "
120 "(WALLPROG, WALLVERS.)");
121 exit(1);
122 }
123 }
124
125 svc_run();
126 syslog(LOG_ERR, "svc_run returned");
127 exit(1);
128
129 }
130
131 void *
132 wallproc_wall_1_svc(char **s, struct svc_req *rqstp)
133 {
134 FILE *pfp;
135
136 pfp = popen(WALL_CMD, "w");
137 if (pfp != NULL) {
138 fprintf(pfp, "\007\007%s", *s);
139 pclose(pfp);
140 }
141
142 return (*s);
143 }
144
145 static void
146 wallprog_1(struct svc_req *rqstp, SVCXPRT *transp)
147 {
148 union {
149 char *wallproc_wall_1_arg;
150 } argument;
151 char *result;
152 xdrproc_t xdr_argument, xdr_result;
153 char *(*local) __P((char **, struct svc_req *));
154
155 switch (rqstp->rq_proc) {
156 case NULLPROC:
157 (void)svc_sendreply(transp, xdr_void, (char *)NULL);
158 goto leave;
159
160 case WALLPROC_WALL:
161 xdr_argument = (xdrproc_t)xdr_wrapstring;
162 xdr_result = (xdrproc_t)xdr_void;
163 local = (char *(*) __P((char **, struct svc_req *)))
164 wallproc_wall_1_svc;
165 break;
166
167 default:
168 svcerr_noproc(transp);
169 goto leave;
170 }
171 memset((char *)&argument, 0, sizeof(argument));
172 if (!svc_getargs(transp, xdr_argument, (caddr_t)&argument)) {
173 svcerr_decode(transp);
174 goto leave;
175 }
176 result = (*local)((char **)&argument, rqstp);
177 if (result != NULL && !svc_sendreply(transp, xdr_result, result)) {
178 svcerr_systemerr(transp);
179 }
180 if (!svc_freeargs(transp, xdr_argument, (caddr_t)&argument)) {
181 syslog(LOG_ERR, "unable to free arguments");
182 exit(1);
183 }
184 leave:
185 if (from_inetd)
186 exit(0);
187 }
188