]> git.saurik.com Git - apple/network_cmds.git/blob - yppush.tproj/yppush.c
3249369e6ab201333146af730591c64630cbff4e
[apple/network_cmds.git] / yppush.tproj / yppush.c
1 /*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25 /* $OpenBSD: yppush.c,v 1.10 1997/11/10 05:49:17 deraadt Exp $ */
26
27 /*
28 * Copyright (c) 1995 Mats O Jansson <moj@stacken.kth.se>
29 * All rights reserved.
30 *
31 * Redistribution and use in source and binary forms, with or without
32 * modification, are permitted provided that the following conditions
33 * are met:
34 * 1. Redistributions of source code must retain the above copyright
35 * notice, this list of conditions and the following disclaimer.
36 * 2. Redistributions in binary form must reproduce the above copyright
37 * notice, this list of conditions and the following disclaimer in the
38 * documentation and/or other materials provided with the distribution.
39 * 3. All advertising materials mentioning features or use of this software
40 * must display the following acknowledgement:
41 * This product includes software developed by Mats O Jansson
42 * 4. The name of the author may not be used to endorse or promote products
43 * derived from this software without specific prior written permission.
44 *
45 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
46 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
47 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
48 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
49 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
50 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
51 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
53 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
54 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
55 * SUCH DAMAGE.
56 */
57
58 #ifndef lint
59 static char rcsid[] = "$OpenBSD: yppush.c,v 1.10 1997/11/10 05:49:17 deraadt Exp $";
60 #endif /* not lint */
61
62 #include <sys/types.h>
63 #include <stdio.h>
64 #include <stdlib.h>
65 #include <unistd.h>
66 #include <string.h>
67 #include <rpc/rpc.h>
68 #include <rpc/xdr.h>
69 #include <rpcsvc/yp.h>
70 #include <rpcsvc/ypclnt.h>
71 #include <sys/stat.h>
72 #include <sys/resource.h>
73 #include <sys/signal.h>
74 #include <sys/wait.h>
75 #include <netdb.h>
76 #include <errno.h>
77 #include <fcntl.h>
78
79 #include "yplib_host.h"
80 #include "ypdef.h"
81 #include "ypdb.h"
82
83 int Verbose = 0;
84 char Domain[MAXHOSTNAMELEN], Map[255];
85 u_int32_t OrderNum;
86 char *master;
87
88 extern void yppush_xfrrespprog_1(struct svc_req *request, SVCXPRT *xprt);
89 extern bool_t xdr_ypreq_xfr(XDR *, struct ypreq_xfr *);
90
91 void
92 usage()
93 {
94 fprintf(stderr, "Usage:\n");
95 /*
96 fprintf(stderr, "\typpush [-d domainname] [-t seconds] [-p #paralleljobs] [-h host] [-v] mapname\n");
97 */
98 fprintf(stderr, "\typpush [-d domainname] [-h host] [-v] mapname\n");
99 exit(1);
100 }
101
102 void
103 _svc_run()
104 {
105 fd_set readfds;
106 struct timeval timeout;
107
108 timeout.tv_sec=60; timeout.tv_usec=0;
109
110 for(;;) {
111 readfds = svc_fdset;
112 switch (select(_rpc_dtablesize(), &readfds, (void *) 0,
113 (void *) 0, &timeout)) {
114 case -1:
115 if (errno == EINTR) {
116 continue;
117 }
118 perror("yppush: _svc_run: select failed");
119 return;
120 case 0:
121 fprintf(stderr, "yppush: Callback timed out.\n");
122 exit(0);
123 default:
124 svc_getreqset(&readfds);
125 }
126 }
127
128 }
129
130 void
131 req_xfr(pid, prog, transp, host, client)
132 pid_t pid;
133 u_int prog;
134 SVCXPRT *transp;
135 char *host;
136 CLIENT *client;
137 {
138 struct ypreq_xfr request;
139 struct timeval tv;
140
141 tv.tv_sec=0; tv.tv_usec=0;
142
143 request.map_parms.domain=(char *)&Domain;
144 request.map_parms.map=(char *)&Map;
145 request.map_parms.peer=master;
146 request.map_parms.ordernum=OrderNum;
147 request.transid=(u_int)pid;
148 request.prog=prog;
149 request.port=transp->xp_port;
150
151 if (Verbose)
152 printf("%d: %s(%u@%s) -> %s@%s\n",
153 request.transid,
154 request.map_parms.map,
155 request.map_parms.ordernum,
156 host,
157 request.map_parms.peer,
158 request.map_parms.domain);
159 switch (clnt_call(client, YPPROC_XFR, xdr_ypreq_xfr, &request,
160 xdr_void, NULL, tv)) {
161 case RPC_SUCCESS:
162 case RPC_TIMEDOUT:
163 break;
164 default:
165 clnt_perror(client, "yppush: Cannot call YPPROC_XFR");
166 kill(pid, SIGTERM);
167 }
168 }
169
170 void
171 push(inlen, indata)
172 int inlen;
173 char *indata;
174 {
175 char host[MAXHOSTNAMELEN];
176 CLIENT *client;
177 SVCXPRT *transp;
178 int sock = RPC_ANYSOCK;
179 u_int prog;
180 bool_t sts;
181 pid_t pid;
182 int status;
183 struct rusage res;
184
185 snprintf(host,sizeof host,"%*.*s" ,inlen ,inlen, indata);
186
187 client = clnt_create(host, YPPROG, YPVERS, "tcp");
188 if (client == NULL) {
189 if (Verbose)
190 fprintf(stderr,"Target Host: %s\n",host);
191 clnt_pcreateerror("yppush: Cannot create client");
192 return;
193 }
194
195 transp = svcudp_create(sock);
196 if (transp == NULL) {
197 fprintf(stderr, "yppush: Cannot create callback transport.\n");
198 return;
199 }
200 if (transp->xp_port >= IPPORT_RESERVED) {
201 SVC_DESTROY(transp);
202 fprintf(stderr, "yppush: Cannot allocate reserved port.\n");
203 return;
204 }
205
206 for (prog=0x40000000; prog<0x5fffffff; prog++) {
207 if (sts = svc_register(transp, prog, 1,
208 yppush_xfrrespprog_1, IPPROTO_UDP))
209 break;
210 }
211
212 if (!sts) {
213 fprintf(stderr, "yppush: Cannot register callback.\n");
214 return;
215 }
216
217 switch(pid=fork()) {
218 case -1:
219 fprintf(stderr, "yppush: Cannot fork.\n");
220 exit(1);
221 case 0:
222 _svc_run();
223 exit(0);
224 default:
225 close(transp->xp_sock);
226 transp->xp_sock = -1;
227 req_xfr(pid, prog, transp, host, client);
228 wait4(pid, &status, 0, &res);
229 svc_unregister(prog, 1);
230 if (client != NULL)
231 clnt_destroy(client);
232 /* XXX transp leak? */
233 }
234
235 }
236
237 int
238 pushit(instatus, inkey, inkeylen, inval, invallen, indata)
239 int instatus;
240 char *inkey;
241 int inkeylen;
242 char *inval;
243 int invallen;
244 char *indata;
245 {
246 if(instatus != YP_TRUE)
247 return instatus;
248 push(invallen, inval);
249 return 0;
250 }
251
252 int
253 main(argc, argv)
254 int argc;
255 char **argv;
256 {
257 struct ypall_callback ypcb;
258 extern char *optarg;
259 extern int optind;
260 char *domain,*map,*hostname,*parallel,*timeout;
261 int c, r, i;
262 char *ypmap = "ypservers";
263 CLIENT *client;
264 static char map_path[MAXPATHLEN];
265 struct stat finfo;
266 DBM *yp_databas;
267 char order_key[YP_LAST_LEN] = YP_LAST_KEY;
268 datum o;
269
270 yp_get_default_domain(&domain);
271 hostname = NULL;
272 /*
273 while( (c=getopt(argc, argv, "d:h:p:t:v?")) != -1)
274 */
275 while( (c=getopt(argc, argv, "d:h:v?")) != -1)
276 switch(c) {
277 case 'd':
278 domain = optarg;
279 break;
280 case 'h':
281 hostname = optarg;
282 break;
283 case 'p':
284 parallel = optarg;
285 break;
286 case 't':
287 timeout = optarg;
288 break;
289 case 'v':
290 Verbose = 1;
291 break;
292 case '?':
293 usage();
294 /*NOTREACHED*/
295 }
296
297 if(optind + 1 != argc )
298 usage();
299
300 map = argv[optind];
301
302 strncpy(Domain,domain,sizeof(Domain)-1);
303 Domain[sizeof(Domain)-1] = '\0';
304 strncpy(Map,map,sizeof(Map)-1);
305 Map[sizeof(Map)-1] = '\0';
306
307 /* Check domain */
308 snprintf(map_path,sizeof map_path,"%s/%s",YP_DB_PATH,domain);
309 if (!((stat(map_path, &finfo) == 0) &&
310 ((finfo.st_mode & S_IFMT) == S_IFDIR))) {
311 fprintf(stderr,"yppush: Map does not exist.\n");
312 exit(1);
313 }
314
315
316 /* Check map */
317 snprintf(map_path,sizeof map_path,"%s/%s/%s%s",
318 YP_DB_PATH,domain,Map,YPDB_SUFFIX);
319 if (!(stat(map_path, &finfo) == 0)) {
320 fprintf(stderr,"yppush: Map does not exist.\n");
321 exit(1);
322 }
323
324 snprintf(map_path,sizeof map_path,"%s/%s/%s",YP_DB_PATH,domain,Map);
325 yp_databas = ypdb_open(map_path,0,O_RDONLY);
326 OrderNum=0xffffffff;
327 if (yp_databas == 0) {
328 fprintf(stderr, "yppush: %s%s: Cannot open database\n",
329 map_path, YPDB_SUFFIX);
330 } else {
331 o.dptr = (char *) &order_key;
332 o.dsize = YP_LAST_LEN;
333 o=ypdb_fetch(yp_databas,o);
334 if (o.dptr == NULL) {
335 fprintf(stderr,
336 "yppush: %s: Cannot determine order number\n",
337 Map);
338 } else {
339 OrderNum=0;
340 for(i=0; i<o.dsize-1; i++) {
341 if (!isdigit(o.dptr[i])) {
342 OrderNum=0xffffffff;
343 }
344 }
345 if (OrderNum != 0) {
346 fprintf(stderr,
347 "yppush: %s: Invalid order number '%s'\n",
348 Map,
349 o.dptr);
350 } else {
351 OrderNum = atoi(o.dptr);
352 }
353 }
354 }
355
356
357 yp_bind(Domain);
358
359 r = yp_master(Domain, ypmap, &master);
360 if (r != 0) {
361 fprintf(stderr, "yppush: could not get ypservers map\n");
362 exit(1);
363 }
364
365 if (hostname != NULL) {
366 push(strlen(hostname), hostname);
367 } else {
368
369 if (Verbose) {
370 printf("Contacting master for ypservers (%s).\n", master);
371 }
372
373 client = yp_bind_host(master, YPPROG, YPVERS, 0, 1);
374
375 ypcb.foreach = pushit;
376 ypcb.data = NULL;
377
378 r = yp_all_host(client,Domain, ypmap, &ypcb);
379 }
380
381 exit(0);
382 }
383