8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / cmd-inet / usr.bin / rdist / main.c
blobd346f46277427d3ca71e59af8a94037819733399
1 /*
2 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
4 */
6 /*
7 * Copyright (c) 1983 Regents of the University of California.
8 * All rights reserved.
10 * Redistribution and use in source and binary forms are permitted
11 * provided that the above copyright notice and this paragraph are
12 * duplicated in all such forms and that any documentation,
13 * advertising materials, and other materials related to such
14 * distribution and use acknowledge that the software was developed
15 * by the University of California, Berkeley. The name of the
16 * University may not be used to endorse or promote products derived
17 * from this software without specific prior written permission.
20 #include "defs.h"
21 #include <string.h>
22 #include <syslog.h>
23 #include <k5-int.h>
24 #include <krb5defs.h>
25 #include <priv_utils.h>
27 #define NHOSTS 100
30 * Remote distribution program.
33 char *distfile = NULL;
34 char Tmpfile[] = "/tmp/rdistXXXXXX";
35 char *tmpname = &Tmpfile[5];
37 int debug; /* debugging flag */
38 int nflag; /* NOP flag, just print commands without executing */
39 int qflag; /* Quiet. Don't print messages */
40 int options; /* global options */
41 int iamremote; /* act as remote server for transfering files */
43 FILE *fin = NULL; /* input file pointer */
44 int rem = -1; /* file descriptor to remote source/sink process */
45 char host[32]; /* host name */
46 int nerrs; /* number of errors while sending/receiving */
47 char user[10]; /* user's name */
48 char homedir[128]; /* user's home directory */
49 char buf[RDIST_BUFSIZ]; /* general purpose buffer */
51 struct passwd *pw; /* pointer to static area used by getpwent */
52 struct group *gr; /* pointer to static area used by getgrent */
54 char des_inbuf[2 * RDIST_BUFSIZ]; /* needs to be > largest read size */
55 char des_outbuf[2 * RDIST_BUFSIZ]; /* needs to be > largest write size */
56 krb5_data desinbuf, desoutbuf;
57 krb5_encrypt_block eblock; /* eblock for encrypt/decrypt */
58 krb5_context bsd_context = NULL;
59 krb5_auth_context auth_context;
60 krb5_creds *cred;
61 char *krb_cache = NULL;
62 krb5_flags authopts;
63 krb5_error_code status;
64 enum kcmd_proto kcmd_proto = KCMD_NEW_PROTOCOL;
66 int encrypt_flag = 0; /* Flag set when encryption is used */
67 int krb5auth_flag = 0; /* Flag set, when KERBEROS is enabled */
68 static profile_options_boolean autologin_option[] = {
69 { "autologin", &krb5auth_flag, 0 },
70 { NULL, NULL, 0 }
72 static int no_krb5auth_flag = 0;
74 int debug_port = 0;
76 int retval = 0;
77 char *krb_realm = NULL;
79 /* Flag set, if -PN / -PO is specified */
80 static boolean_t rcmdoption_done = B_FALSE;
82 static int encrypt_done = 0; /* Flag set, if -x is specified */
83 profile_options_boolean option[] = {
84 { "encrypt", &encrypt_flag, 0 },
85 { NULL, NULL, 0 }
88 static char *rcmdproto = NULL;
89 profile_option_strings rcmdversion[] = {
90 { "rcmd_protocol", &rcmdproto, 0 },
91 { NULL, NULL, 0 }
94 char *realmdef[] = { "realms", NULL, "rdist", NULL };
95 char *appdef[] = { "appdefaults", "rdist", NULL };
97 static void usage(void);
98 static char *prtype(int t);
99 static void prsubcmd(struct subcmd *s);
100 static void docmdargs(int nargs, char *args[]);
101 void prnames();
102 void prcmd();
105 main(argc, argv)
106 int argc;
107 char *argv[];
109 register char *arg;
110 int cmdargs = 0;
111 char *dhosts[NHOSTS], **hp = dhosts;
113 (void) setlocale(LC_ALL, "");
115 pw = getpwuid(getuid());
116 if (pw == NULL) {
117 (void) fprintf(stderr, gettext("%s: Who are you?\n"), argv[0]);
118 exit(1);
120 strncpy(user, pw->pw_name, sizeof (user));
121 user[sizeof (user) - 1] = '\0';
122 strncpy(homedir, pw->pw_dir, sizeof (homedir));
123 homedir[sizeof (homedir) - 1] = '\0';
124 gethostname(host, sizeof (host));
126 while (--argc > 0) {
127 if ((arg = *++argv)[0] != '-')
128 break;
129 if ((strcmp(arg, "-Server") == 0))
130 iamremote++;
131 else while (*++arg) {
132 if (strncmp(*argv, "-PO", 3) == 0) {
133 if (rcmdoption_done == B_TRUE) {
134 (void) fprintf(stderr, gettext("rdist: "
135 "Only one of -PN "
136 "and -PO allowed.\n"));
137 usage();
139 kcmd_proto = KCMD_OLD_PROTOCOL;
140 krb5auth_flag++;
141 rcmdoption_done = B_TRUE;
142 break;
144 if (strncmp(*argv, "-PN", 3) == 0) {
145 if (rcmdoption_done == B_TRUE) {
146 (void) fprintf(stderr, gettext("rdist: "
147 "Only one of -PN "
148 "and -PO allowed.\n"));
149 usage();
151 kcmd_proto = KCMD_NEW_PROTOCOL;
152 krb5auth_flag++;
153 rcmdoption_done = B_TRUE;
154 break;
157 switch (*arg) {
158 #ifdef DEBUG
159 case 'p':
160 if (--argc <= 0)
161 usage();
162 debug_port = htons(atoi(*++argv));
163 break;
164 #endif /* DEBUG */
165 case 'k':
166 if (--argc <= 0) {
167 (void) fprintf(stderr, gettext("rdist: "
168 "-k flag must be followed with "
169 " a realm name.\n"));
170 exit(1);
172 if ((krb_realm = strdup(*++argv)) == NULL) {
173 (void) fprintf(stderr, gettext("rdist: "
174 "Cannot malloc.\n"));
175 exit(1);
177 krb5auth_flag++;
178 break;
180 case 'K':
181 no_krb5auth_flag++;
182 break;
184 case 'a':
185 krb5auth_flag++;
186 break;
188 case 'x':
189 encrypt_flag++;
190 encrypt_done++;
191 krb5auth_flag++;
192 break;
194 case 'f':
195 if (--argc <= 0)
196 usage();
197 distfile = *++argv;
198 if (distfile[0] == '-' && distfile[1] == '\0')
199 fin = stdin;
200 break;
202 case 'm':
203 if (--argc <= 0)
204 usage();
205 if (hp >= &dhosts[NHOSTS-2]) {
206 (void) fprintf(stderr, gettext("rdist:"
207 " too many destination"
208 " hosts\n"));
209 exit(1);
211 *hp++ = *++argv;
212 break;
214 case 'd':
215 if (--argc <= 0)
216 usage();
217 define(*++argv);
218 break;
220 case 'D':
221 debug++;
222 break;
224 case 'c':
225 cmdargs++;
226 break;
228 case 'n':
229 if (options & VERIFY) {
230 printf("rdist: -n overrides -v\n");
231 options &= ~VERIFY;
233 nflag++;
234 break;
236 case 'q':
237 qflag++;
238 break;
240 case 'b':
241 options |= COMPARE;
242 break;
244 case 'R':
245 options |= REMOVE;
246 break;
248 case 'v':
249 if (nflag) {
250 printf("rdist: -n overrides -v\n");
251 break;
253 options |= VERIFY;
254 break;
256 case 'w':
257 options |= WHOLE;
258 break;
260 case 'y':
261 options |= YOUNGER;
262 break;
264 case 'h':
265 options |= FOLLOW;
266 break;
268 case 'i':
269 options |= IGNLNKS;
270 break;
272 default:
273 usage();
277 *hp = NULL;
279 mktemp(Tmpfile);
282 * if the user disables krb5 on the cmdline (-K), then skip
283 * all krb5 setup.
285 * if the user does not disable krb5 or enable krb5 on the
286 * cmdline, check krb5.conf to see if it should be enabled.
289 if (no_krb5auth_flag) {
290 krb5auth_flag = 0;
291 encrypt_flag = 0;
292 } else if (!krb5auth_flag) {
293 /* is autologin set in krb5.conf? */
294 status = krb5_init_context(&bsd_context);
295 /* don't sweat failure here */
296 if (!status) {
298 * note that the call to profile_get_options_boolean
299 * with autologin_option can affect value of
300 * krb5auth_flag
302 (void) profile_get_options_boolean(bsd_context->profile,
303 appdef,
304 autologin_option);
308 if (krb5auth_flag > 0) {
309 if (!bsd_context) {
310 status = krb5_init_context(&bsd_context);
311 if (status) {
312 com_err("rdist", status,
313 gettext("while initializing krb5"));
314 exit(1);
318 /* Set up des buffers */
319 desinbuf.data = des_inbuf;
320 desoutbuf.data = des_outbuf;
321 desinbuf.length = sizeof (des_inbuf);
322 desoutbuf.length = sizeof (des_outbuf);
325 * Get our local realm to look up local realm options.
327 status = krb5_get_default_realm(bsd_context, &realmdef[1]);
328 if (status) {
329 com_err("rdist", status,
330 gettext("while getting default realm"));
331 exit(1);
334 * See if encryption should be done for this realm
336 profile_get_options_boolean(bsd_context->profile, realmdef,
337 option);
339 * Check the appdefaults section
341 profile_get_options_boolean(bsd_context->profile, appdef,
342 option);
343 profile_get_options_string(bsd_context->profile, appdef,
344 rcmdversion);
346 if ((encrypt_done > 0) || (encrypt_flag > 0)) {
347 if (krb5_privacy_allowed() == TRUE) {
348 encrypt_flag++;
349 } else {
350 (void) fprintf(stderr, gettext("rdist: "
351 "Encryption not supported.\n"));
352 exit(1);
356 if ((rcmdoption_done == B_FALSE) && (rcmdproto != NULL)) {
357 if (strncmp(rcmdproto, "rcmdv2", 6) == 0) {
358 kcmd_proto = KCMD_NEW_PROTOCOL;
359 } else if (strncmp(rcmdproto, "rcmdv1", 6) == 0) {
360 kcmd_proto = KCMD_OLD_PROTOCOL;
361 } else {
362 (void) fprintf(stderr, gettext("Unrecognized "
363 "KCMD protocol (%s)"), rcmdproto);
364 exit(1);
369 if (iamremote) {
370 setreuid(getuid(), getuid());
371 server();
372 exit(nerrs != 0);
374 if (__init_suid_priv(0, PRIV_NET_PRIVADDR, NULL) == -1) {
375 (void) fprintf(stderr,
376 "rdist needs to run with sufficient privilege\n");
377 exit(1);
380 if (cmdargs)
381 docmdargs(argc, argv);
382 else {
383 if (fin == NULL) {
384 if (distfile == NULL) {
385 if ((fin = fopen("distfile", "r")) == NULL)
386 fin = fopen("Distfile", "r");
387 } else
388 fin = fopen(distfile, "r");
389 if (fin == NULL) {
390 perror(distfile ? distfile : "distfile");
391 exit(1);
394 yyparse();
395 if (nerrs == 0)
396 docmds(dhosts, argc, argv);
399 return (nerrs != 0);
402 static void
403 usage()
405 printf(gettext("Usage: rdist [-nqbhirvwyDax] [-PN / -PO] "
406 #ifdef DEBUG
407 "[-p port] "
408 #endif /* DEBUG */
409 "[-k realm] [-f distfile] [-d var=value] [-m host] [file ...]\n"));
410 printf(gettext("or: rdist [-nqbhirvwyDax] [-PN / -PO] [-p port] "
411 "[-k realm] -c source [...] machine[:dest]\n"));
412 exit(1);
416 * rcp like interface for distributing files.
418 static void
419 docmdargs(nargs, args)
420 int nargs;
421 char *args[];
423 register struct namelist *nl, *prev;
424 register char *cp;
425 struct namelist *files, *hosts;
426 struct subcmd *cmds;
427 char *dest;
428 static struct namelist tnl = { NULL, NULL };
429 int i;
431 if (nargs < 2)
432 usage();
434 prev = NULL;
435 for (i = 0; i < nargs - 1; i++) {
436 nl = makenl(args[i]);
437 if (prev == NULL)
438 files = prev = nl;
439 else {
440 prev->n_next = nl;
441 prev = nl;
445 cp = args[i];
446 if ((dest = index(cp, ':')) != NULL)
447 *dest++ = '\0';
448 tnl.n_name = cp;
449 hosts = expand(&tnl, E_ALL);
450 if (nerrs)
451 exit(1);
453 if (dest == NULL || *dest == '\0')
454 cmds = NULL;
455 else {
456 cmds = makesubcmd(INSTALL);
457 cmds->sc_options = options;
458 cmds->sc_name = dest;
461 if (debug) {
462 printf("docmdargs()\nfiles = ");
463 prnames(files);
464 printf("hosts = ");
465 prnames(hosts);
467 insert(NULL, files, hosts, cmds);
468 docmds(NULL, 0, NULL);
472 * Print a list of NAME blocks (mostly for debugging).
474 void
475 prnames(nl)
476 register struct namelist *nl;
478 printf("( ");
479 while (nl != NULL) {
480 printf("%s ", nl->n_name);
481 nl = nl->n_next;
483 printf(")\n");
486 void
487 prcmd(c)
488 struct cmd *c;
490 extern char *prtype();
492 while (c) {
493 printf("c_type %s, c_name %s, c_label %s, c_files ",
494 prtype(c->c_type), c->c_name,
495 c->c_label? c->c_label : "NULL");
496 prnames(c->c_files);
497 prsubcmd(c->c_cmds);
498 c = c->c_next;
502 static void
503 prsubcmd(s)
504 struct subcmd *s;
506 extern char *prtype();
507 extern char *proptions();
509 while (s) {
510 printf("sc_type %s, sc_options %d%s, sc_name %s, sc_args ",
511 prtype(s->sc_type),
512 s->sc_options, proptions(s->sc_options),
513 s->sc_name ? s->sc_name : "NULL");
514 prnames(s->sc_args);
515 s = s->sc_next;
519 char *
520 prtype(t)
521 int t;
523 switch (t) {
524 case EQUAL:
525 return ("EQUAL");
526 case LP:
527 return ("LP");
528 case RP:
529 return ("RP");
530 case SM:
531 return ("SM");
532 case ARROW:
533 return ("ARROW");
534 case COLON:
535 return ("COLON");
536 case DCOLON:
537 return ("DCOLON");
538 case NAME:
539 return ("NAME");
540 case STRING:
541 return ("STRING");
542 case INSTALL:
543 return ("INSTALL");
544 case NOTIFY:
545 return ("NOTIFY");
546 case EXCEPT:
547 return ("EXCEPT");
548 case PATTERN:
549 return ("PATTERN");
550 case SPECIAL:
551 return ("SPECIAL");
552 case OPTION:
553 return ("OPTION");
555 return (NULL);
558 char *
559 proptions(o)
560 int o;
562 return (printb((unsigned short) o, OBITS));
565 char *
566 printb(v, bits)
567 register char *bits;
568 register unsigned short v;
570 register int i, any = 0;
571 register char c;
572 char *p = buf;
574 bits++;
575 if (bits) {
577 *p++ = '<';
578 while ((i = *bits++) != 0) {
579 if (v & (1 << (i-1))) {
580 if (any)
581 *p++ = ',';
582 any = 1;
583 for (; (c = *bits) > 32; bits++)
584 *p++ = c;
585 } else
586 for (; *bits > 32; bits++)
589 *p++ = '>';
592 *p = '\0';
593 return (buf);