Annotation of src/usr.bin/rdist/rdist.c, Revision 1.4
1.4 ! millert 1: /* $OpenBSD: rdist.c,v 1.3 1996/06/26 05:38:17 deraadt Exp $ */
1.3 deraadt 2:
1.1 dm 3: /*
4: * Copyright (c) 1983 Regents of the University of California.
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. All advertising materials mentioning features or use of this software
16: * must display the following acknowledgement:
17: * This product includes software developed by the University of
18: * California, Berkeley and its contributors.
19: * 4. Neither the name of the University nor the names of its contributors
20: * may be used to endorse or promote products derived from this software
21: * without specific prior written permission.
22: *
23: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33: * SUCH DAMAGE.
34: */
35:
36: #ifndef lint
37: static char RCSid[] =
1.4 ! millert 38: "$OpenBSD: rdist.c,v 1.3 1996/06/26 05:38:17 deraadt Exp $";
1.1 dm 39:
40: static char sccsid[] = "@(#)main.c 5.1 (Berkeley) 6/6/85";
41:
42: static char copyright[] =
43: "@(#) Copyright (c) 1983 Regents of the University of California.\n\
44: All rights reserved.\n";
45: #endif /* not lint */
46:
47:
48: #include "defs.h"
49: #include "y.tab.h"
50: #include <netdb.h>
51: #include <sys/ioctl.h>
52:
53: /*
54: * Remote distribution program.
55: */
56:
57: char *distfile = NULL; /* Name of distfile to use */
58: int maxchildren = MAXCHILDREN; /* Max no of concurrent PIDs */
59: int nflag = 0; /* Say without doing */
60: long min_freespace = 0; /* Min filesys free space */
61: long min_freefiles = 0; /* Min filesys free # files */
62: FILE *fin = NULL; /* Input file pointer */
63: struct group *gr = NULL; /* Static area for getgrent */
64: char localmsglist[] = "stdout=all:notify=all:syslog=nerror,ferror";
65: char *remotemsglist = NULL;
66: char optchars[] = "A:a:bcd:DFf:hil:L:M:m:NnOo:p:P:qRrst:Vvwxy";
67: FILE *opendist();
68: char *path_rdistd = _PATH_RDISTD;
1.4 ! millert 69: char *path_remsh = NULL;
1.1 dm 70:
71: /*
72: * Add a hostname to the host list
73: */
74: static void addhostlist(name, hostlist)
75: char *name;
76: struct namelist **hostlist;
77: {
78: register struct namelist *ptr, *new;
79:
80: if (!name || !hostlist)
81: return;
82:
83: new = (struct namelist *) xmalloc(sizeof(struct namelist));
84: new->n_name = strdup(name);
85: new->n_next = NULL;
86:
87: if (*hostlist) {
88: for (ptr = *hostlist; ptr && ptr->n_next; ptr = ptr->n_next)
89: ;
90: ptr->n_next = new;
91: } else
92: *hostlist = new;
93: }
94:
95: main(argc, argv, envp)
96: int argc;
97: char *argv[];
98: char **envp;
99: {
100: struct namelist *hostlist = NULL;
101: register int x;
102: register char *cp;
103: int cmdargs = 0;
104: int c;
105:
106: /*
107: * We initialize progname here instead of init() because
108: * things in msgparseopts() need progname set.
109: */
110: setprogname(argv);
111:
112: if (cp = msgparseopts(localmsglist, TRUE)) {
113: error("Bad builtin log option (%s): %s.",
114: localmsglist, cp);
115: usage();
116: }
117:
118: if (init(argc, argv, envp) < 0)
119: exit(1);
120:
121: /*
122: * Be backwards compatible.
123: */
124: for (x = 1; x <= argc && argv[x]; x++) {
125: if (strcmp(argv[x], "-Server") != 0)
126: continue;
127: #if defined(_PATH_OLDRDIST)
128: message(MT_SYSLOG,
129: "Old rdist (-Server) requested; running %s",
130: _PATH_OLDRDIST);
131: (void) execl(_PATH_OLDRDIST, xbasename(_PATH_OLDRDIST),
132: "-Server", (char *)NULL);
133: fatalerr("Exec old rdist failed: %s: %s.",
134: _PATH_OLDRDIST, SYSERR);
135: #else /* !_PATH_OLDRDIST */
136: fatalerr("Old rdist not available.");
137: #endif /* _PATH_OLDRDIST */
138: exit(1);
139: }
140:
141: #if defined(DIRECT_RCMD)
142: if (becomeuser() != 0)
143: exit(1);
144: #else /* !DIRECT_RCMD */
145: /*
146: * Perform check to make sure we are not incorrectly installed
147: * setuid to root or anybody else.
148: */
149: if (getuid() != geteuid())
150: fatalerr("This version of rdist should not be installed setuid.");
151: #endif /* DIRECT_RCMD */
152:
153: while ((c = getopt(argc, argv, optchars)) != -1)
154: switch (c) {
155: case 'l':
156: if (cp = msgparseopts(optarg, TRUE)) {
157: error("Bad log option \"%s\": %s.", optarg,cp);
158: usage();
159: }
160: break;
161:
162: case 'L':
163: remotemsglist = strdup(optarg);
164: break;
165:
166: case 'A':
167: case 'a':
168: case 'M':
169: case 't':
170: if (!isdigit(*optarg)) {
171: error("\"%s\" is not a number.", optarg);
172: usage();
173: }
174: if (c == 'a')
175: min_freespace = atoi(optarg);
176: else if (c == 'A')
177: min_freefiles = atoi(optarg);
178: else if (c == 'M')
179: maxchildren = atoi(optarg);
180: else if (c == 't')
181: rtimeout = atoi(optarg);
182: break;
183:
184: case 'F':
185: do_fork = FALSE;
186: break;
187:
188: case 'f':
189: distfile = strdup(optarg);
190: if (distfile[0] == '-' && distfile[1] == CNULL)
191: fin = stdin;
192: break;
193:
194: case 'm':
195: addhostlist(optarg, &hostlist);
196: break;
197:
198: case 'd':
199: define(optarg);
200: break;
201:
202: case 'D':
203: debug = DM_ALL;
204: if (cp = msgparseopts("stdout=all,debug", TRUE)) {
205: error("Enable debug messages failed: %s.", cp);
206: usage();
207: }
208: break;
209:
210: case 'c':
211: cmdargs++;
212: break;
213:
214: case 'n':
215: nflag++;
216: break;
217:
218: case 'V':
219: printf("%s\n", getversion());
220: exit(0);
221:
222: case 'o':
223: if (parsedistopts(optarg, &options, TRUE)) {
224: error("Bad dist option string \"%s\".",
225: optarg);
226: usage();
227: }
228: break;
229:
230: case 'p':
231: if (!optarg) {
232: error("No path specified to \"-p\".");
233: usage();
234: }
235: path_rdistd = strdup(optarg);
236: break;
237:
238: case 'P':
239: if (!optarg) {
240: error("No path specified to \"-P\".");
241: usage();
242: }
243: if (cp = searchpath(optarg))
244: path_remsh = strdup(cp);
245: else {
246: error("No component of path \"%s\" exists.",
247: optarg);
248: usage();
249: }
250: break;
251:
252: /*
253: * These options are obsoleted by -o. They are
254: * provided only for backwards compatibility
255: */
256: case 'v': FLAG_ON(options, DO_VERIFY); break;
257: case 'N': FLAG_ON(options, DO_CHKNFS); break;
258: case 'O': FLAG_ON(options, DO_CHKREADONLY); break;
259: case 'q': FLAG_ON(options, DO_QUIET); break;
260: case 'b': FLAG_ON(options, DO_COMPARE); break;
261: case 'r': FLAG_ON(options, DO_NODESCEND); break;
262: case 'R': FLAG_ON(options, DO_REMOVE); break;
263: case 's': FLAG_ON(options, DO_SAVETARGETS); break;
264: case 'w': FLAG_ON(options, DO_WHOLE); break;
265: case 'y': FLAG_ON(options, DO_YOUNGER); break;
266: case 'h': FLAG_ON(options, DO_FOLLOW); break;
267: case 'i': FLAG_ON(options, DO_IGNLNKS); break;
268: case 'x': FLAG_ON(options, DO_NOEXEC); break;
269:
270: case '?':
271: default:
272: usage();
273: }
274:
275: if (debug) {
276: printf("%s\n", getversion());
277: msgprconfig();
278: }
279:
280: if (nflag && IS_ON(options, DO_VERIFY))
281: fatalerr(
282: "The -n flag and \"verify\" mode may not both be used.");
1.4 ! millert 283:
! 284: if (path_remsh == NULL)
! 285: path_remsh = getenv("RSH");
1.1 dm 286:
287: /*
288: * Don't fork children for nflag
289: */
290: if (nflag)
291: do_fork = 0;
292:
293: if (cmdargs)
294: docmdargs(realargc - optind, &realargv[optind]);
295: else {
296: if (fin == NULL)
297: fin = opendist(distfile);
298: (void) yyparse();
299: /*
300: * Need to keep stdin open for child processing later
301: */
302: if (fin != stdin)
303: (void) fclose(fin);
304: if (nerrs == 0)
305: docmds(hostlist, realargc-optind, &realargv[optind]);
306: }
307:
308: exit(nerrs != 0);
309: }
310:
311: /*
312: * Open a distfile
313: */
314: FILE *opendist(distfile)
315: char *distfile;
316: {
317: char *file = NULL;
318: FILE *fp;
319:
320: if (distfile == NULL) {
321: if (access("distfile", R_OK) == 0)
322: file = "distfile";
323: else if (access("Distfile", R_OK) == 0)
324: file = "Distfile";
325: } else {
326: /*
327: * Try to test to see if file is readable before running m4.
328: */
329: if (access(distfile, R_OK) != 0)
330: fatalerr("%s: Cannot access file: %s.",
331: distfile, SYSERR);
332: file = distfile;
333: }
334:
335: if (file == NULL)
336: fatalerr("No distfile found.");
337:
338: fp = fopen(file, "r");
339:
340: if (fp == NULL)
341: fatalerr("%s: open failed: %s.", file, SYSERR);
342:
343: return(fp);
344: }
345:
346: /*
347: * Print usage message and exit.
348: */
349: usage()
350: {
351: char *sopts = "cDFnv";
352:
353: (void) fprintf(stderr,
354: "Usage: %s [-%s] [-A <num>] [-a <num>] [-d var=value]\n",
355: progname, sopts);
356: (void) fprintf(stderr,
357: "\t[-f distfile] [-l <msgopt>] [-L <msgopt>] [-M <maxproc>]\n");
358: (void) fprintf(stderr,
359: "\t[-m host] [-o <distopts>] [-p <rdistd-cmd>] [-P <rsh-path>]\n");
360: (void) fprintf(stderr,
361: "\t[-t <timeout>] [target ...]\n");
362:
363: (void) fprintf(stderr,
364: "OR: %s [-%s] -c source [...] machine[:dest]\n",
365: progname, sopts);
366:
367: (void) fprintf(stderr, "OR: %s -V\n", progname);
368:
369: (void) fprintf(stderr, "\nThe values for <distopts> are:\n\t%s\n",
370: getdistoptlist());
371:
372: msgprusage();
373:
374: exit(1);
375: }
376:
377: /*
378: * rcp like interface for distributing files.
379: */
380: docmdargs(nargs, args)
381: int nargs;
382: char *args[];
383: {
384: register struct namelist *nl, *prev;
385: register char *cp;
386: struct namelist *files, *hosts;
387: struct subcmd *cmds;
388: char *dest;
389: static struct namelist tnl = { NULL, NULL };
390: int i;
391:
392: if (nargs < 2)
393: usage();
394:
395: prev = NULL;
396: files = NULL;
397: for (i = 0; i < nargs - 1; i++) {
398: nl = makenl(args[i]);
399: if (prev == NULL)
400: files = prev = nl;
401: else {
402: prev->n_next = nl;
403: prev = nl;
404: }
405: }
406:
407: cp = args[i];
408: if ((dest = strchr(cp, ':')) != NULL)
409: *dest++ = '\0';
410: tnl.n_name = cp;
411: hosts = expand(&tnl, E_ALL);
412: if (nerrs)
413: exit(1);
414:
415: if (dest == NULL || *dest == '\0')
416: cmds = NULL;
417: else {
418: cmds = makesubcmd(INSTALL);
419: cmds->sc_options = options;
420: cmds->sc_name = dest;
421: }
422:
423: debugmsg(DM_MISC, "docmdargs()\nfiles = %s", getnlstr(files));
424: debugmsg(DM_MISC, "host = %s", getnlstr(hosts));
425:
426: insert((char *)NULL, files, hosts, cmds);
427: docmds(0, (char **)NULL, 0, (char **)NULL);
428: }
429:
430: /*
431: * Get a list of NAME blocks (mostly for debugging).
432: */
433: extern char *getnlstr(nl)
434: register struct namelist *nl;
435: {
436: static char buf[16384];
437: register int count = 0, len = 0;
438:
439: (void) sprintf(buf, "(");
440:
441: while (nl != NULL) {
442: if (nl->n_name == NULL)
443: continue;
444: len += strlen(nl->n_name) + 2;
445: if (len >= sizeof(buf)) {
446: (void) strcpy(buf,
447: "getnlstr() Buffer not large enough");
448: return(buf);
449: }
450: ++count;
451: (void) strcat(buf, " ");
452: (void) strcat(buf, nl->n_name);
453: nl = nl->n_next;
454: }
455:
456: (void) strcat(buf, " )");
457:
458: return(buf);
459: }