Commit | Line | Data |
---|---|---|
0066ee62 C |
1 | /* |
2 | * Copyright (c) 1993 Christopher G. Demetriou | |
3 | * All rights reserved. | |
4 | * | |
5 | * Redistribution and use in source and binary forms, with or without | |
6 | * modification, are permitted provided that the following conditions | |
7 | * are met: | |
8 | * 1. Redistributions of source code must retain the above copyright | |
9 | * notice, this list of conditions and the following disclaimer. | |
10 | * 2. Redistributions in binary form must reproduce the above copyright | |
11 | * notice, this list of conditions and the following disclaimer in the | |
12 | * documentation and/or other materials provided with the distribution. | |
13 | * 3. The name of the author may not be used to endorse or promote | |
14 | * products derived from this software without specific prior written | |
15 | * permission. | |
16 | * | |
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS | |
18 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
19 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | |
21 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
27 | * SUCH DAMAGE. | |
28 | */ | |
29 | ||
30 | #ifndef lint | |
31 | static char rcsid[] = "$Id: rwalld.c,v 1.2 1993/08/02 17:50:55 mycroft Exp $"; | |
32 | #endif /* not lint */ | |
33 | ||
34 | #include <unistd.h> | |
35 | #include <sys/types.h> | |
36 | #include <pwd.h> | |
37 | #include <stdio.h> | |
38 | #include <string.h> | |
39 | #include <errno.h> | |
40 | #include <sys/socket.h> | |
41 | #include <signal.h> | |
42 | #include <sys/wait.h> | |
43 | #include <rpc/rpc.h> | |
44 | #include <rpcsvc/rwall.h> | |
45 | ||
46 | #ifdef OSF | |
47 | #define WALL_CMD "/usr/sbin/wall" | |
48 | #else | |
49 | #define WALL_CMD "/usr/bin/wall -n" | |
50 | #endif | |
51 | ||
52 | void wallprog_1(); | |
53 | void possess(); | |
54 | void killkids(); | |
55 | ||
56 | int nodaemon = 0; | |
57 | int from_inetd = 1; | |
58 | ||
59 | main(argc, argv) | |
60 | int argc; | |
61 | char *argv[]; | |
62 | { | |
63 | SVCXPRT *transp; | |
64 | int s, salen; | |
65 | struct sockaddr_in sa; | |
66 | int sock = 0; | |
67 | int proto = 0; | |
68 | ||
69 | if (argc == 2 && !strcmp(argv[1], "-n")) | |
70 | nodaemon = 1; | |
71 | if (argc != 1 && !nodaemon) { | |
72 | printf("usage: %s [-n]\n", argv[0]); | |
73 | exit(1); | |
74 | } | |
75 | ||
76 | if (geteuid() == 0) { | |
77 | struct passwd *pep = getpwnam("nobody"); | |
78 | if (pep) | |
79 | setuid(pep->pw_uid); | |
80 | else | |
81 | setuid(getuid()); | |
82 | } | |
83 | ||
84 | /* | |
85 | * See if inetd started us | |
86 | */ | |
87 | if (getsockname(0, (struct sockaddr *)&sa, &salen) < 0) { | |
88 | from_inetd = 0; | |
89 | sock = RPC_ANYSOCK; | |
90 | proto = IPPROTO_UDP; | |
91 | } | |
92 | ||
93 | if (!from_inetd) { | |
94 | if (!nodaemon) | |
95 | possess(); | |
96 | ||
97 | (void)pmap_unset(WALLPROG, WALLVERS); | |
98 | if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { | |
99 | perror("socket"); | |
100 | exit(1); | |
101 | } | |
102 | bzero((char *)&sa, sizeof sa); | |
103 | if (bind(s, (struct sockaddr *)&sa, sizeof sa) < 0) { | |
104 | perror("bind"); | |
105 | exit(1); | |
106 | } | |
107 | ||
108 | salen = sizeof sa; | |
109 | if (getsockname(s, (struct sockaddr *)&sa, &salen)) { | |
110 | perror("getsockname"); | |
111 | exit(1); | |
112 | } | |
113 | ||
114 | pmap_set(WALLPROG, WALLVERS, IPPROTO_UDP, ntohs(sa.sin_port)); | |
115 | if (dup2(s, 0) < 0) { | |
116 | perror("dup2"); | |
117 | exit(1); | |
118 | } | |
119 | (void)pmap_unset(WALLPROG, WALLVERS); | |
120 | } | |
121 | ||
122 | (void)signal(SIGCHLD, killkids); | |
123 | ||
124 | transp = svcudp_create(sock); | |
125 | if (transp == NULL) { | |
126 | (void)fprintf(stderr, "cannot create udp service.\n"); | |
127 | exit(1); | |
128 | } | |
129 | if (!svc_register(transp, WALLPROG, WALLVERS, wallprog_1, proto)) { | |
130 | (void)fprintf(stderr, "unable to register (WALLPROG, WALLVERS, udp).\n"); | |
131 | exit(1); | |
132 | } | |
133 | svc_run(); | |
134 | (void)fprintf(stderr, "svc_run returned\n"); | |
135 | exit(1); | |
136 | ||
137 | } | |
138 | ||
139 | void possess() | |
140 | { | |
141 | daemon(0, 0); | |
142 | } | |
143 | ||
144 | void killkids() | |
145 | { | |
146 | while(wait4(-1, NULL, WNOHANG, NULL) > 0) | |
147 | ; | |
148 | } | |
149 | ||
150 | void *wallproc_wall_1(s) | |
151 | char **s; | |
152 | { | |
153 | /* fork, popen wall with special option, and send the message */ | |
154 | if (fork() == 0) { | |
155 | FILE *pfp; | |
156 | ||
157 | pfp = popen(WALL_CMD, "w"); | |
158 | if (pfp != NULL) { | |
159 | fprintf(pfp, "\007\007%s", *s); | |
160 | pclose(pfp); | |
161 | exit(0); | |
162 | } | |
163 | } | |
164 | } | |
165 | ||
166 | void | |
167 | wallprog_1(rqstp, transp) | |
168 | struct svc_req *rqstp; | |
169 | SVCXPRT *transp; | |
170 | { | |
171 | union { | |
172 | char *wallproc_wall_1_arg; | |
173 | } argument; | |
174 | char *result; | |
175 | bool_t (*xdr_argument)(), (*xdr_result)(); | |
176 | char *(*local)(); | |
177 | ||
178 | switch (rqstp->rq_proc) { | |
179 | case NULLPROC: | |
180 | (void)svc_sendreply(transp, xdr_void, (char *)NULL); | |
181 | goto leave; | |
182 | ||
183 | case WALLPROC_WALL: | |
184 | xdr_argument = xdr_wrapstring; | |
185 | xdr_result = xdr_void; | |
186 | local = (char *(*)()) wallproc_wall_1; | |
187 | break; | |
188 | ||
189 | default: | |
190 | svcerr_noproc(transp); | |
191 | goto leave; | |
192 | } | |
193 | bzero((char *)&argument, sizeof(argument)); | |
194 | if (!svc_getargs(transp, xdr_argument, &argument)) { | |
195 | svcerr_decode(transp); | |
196 | goto leave; | |
197 | } | |
198 | result = (*local)(&argument, rqstp); | |
199 | if (result != NULL && !svc_sendreply(transp, xdr_result, result)) { | |
200 | svcerr_systemerr(transp); | |
201 | } | |
202 | if (!svc_freeargs(transp, xdr_argument, &argument)) { | |
203 | (void)fprintf(stderr, "unable to free arguments\n"); | |
204 | exit(1); | |
205 | } | |
206 | leave: | |
207 | if (from_inetd) | |
208 | exit(0); | |
209 | } |