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