1/* $NetBSD: main.c,v 1.19 2008/07/21 14:19:25 lukem Exp $ */ 2 3/* 4 * Copyright (c) 1983, 1993 5 * The Regents of the University of California. 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. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32#include <sys/cdefs.h> 33#ifndef lint 34__COPYRIGHT("@(#) Copyright (c) 1983, 1993\ 35 The Regents of the University of California. All rights reserved."); 36#endif /* not lint */ 37 38#ifndef lint 39#if 0 40static char sccsid[] = "@(#)main.c 8.1 (Berkeley) 6/9/93"; 41#else 42__RCSID("$NetBSD: main.c,v 1.19 2008/07/21 14:19:25 lukem Exp $"); 43#endif 44#endif /* not lint */ 45 46#include <sys/types.h> 47 48#include <err.h> 49#include <errno.h> 50#include <pwd.h> 51 52#include "defs.h" 53 54#define NHOSTS 100 55 56/* 57 * Remote distribution program. 58 */ 59 60char *distfile = NULL; 61#define _RDIST_TMP "/rdistXXXXXX" 62char tempfile[sizeof _PATH_TMP + sizeof _RDIST_TMP + 1]; 63char *tempname; 64 65int debug; /* debugging flag */ 66int nflag; /* NOP flag, just print commands without executing */ 67int qflag; /* Quiet. Don't print messages */ 68int options; /* global options */ 69int iamremote; /* act as remote server for transfering files */ 70 71FILE *fin = NULL; /* input file pointer */ 72int rem = -1; /* file descriptor to remote source/sink process */ 73char host[MAXHOSTNAMELEN + 1]; /* host name */ 74int nerrs; /* number of errors while sending/receiving */ 75char user[34]; /* user's name */ 76char homedir[PATH_MAX]; /* user's home directory */ 77uid_t userid; /* user's user ID */ 78gid_t groupid; /* user's group ID */ 79 80struct passwd *pw; /* pointer to static area used by getpwent */ 81struct group *gr; /* pointer to static area used by getgrent */ 82 83__dead static void usage(void); 84static void docmdargs(int, char *[]); 85 86int 87main(int argc, char **argv) 88{ 89 char *arg; 90 int cmdargs = 0; 91 char *dhosts[NHOSTS], **hp = dhosts; 92 int fd; 93 94 pw = getpwuid(userid = getuid()); 95 if (pw == NULL) { 96 fprintf(stderr, "%s: Who are you?\n", argv[0]); 97 exit(1); 98 } 99 strlcpy(user, pw->pw_name, sizeof(user)); 100 strlcpy(homedir, pw->pw_dir, sizeof(homedir)); 101 groupid = pw->pw_gid; 102 gethostname(host, sizeof(host)); 103 host[sizeof(host) - 1] = '\0'; 104 strlcpy(tempfile, _PATH_TMP, sizeof(tempfile)); 105 strlcat(tempfile, _RDIST_TMP, sizeof(tempfile)); 106 if ((tempname = strrchr(tempfile, '/')) != 0) 107 tempname++; 108 else 109 tempname = tempfile; 110 111 while (--argc > 0) { 112 if ((arg = *++argv)[0] != '-') 113 break; 114 if (!strcmp(arg, "-Server")) 115 iamremote++; 116 else while (*++arg) 117 switch (*arg) { 118 case 'f': 119 if (--argc <= 0) 120 usage(); 121 distfile = *++argv; 122 if (distfile[0] == '-' && distfile[1] == '\0') 123 fin = stdin; 124 break; 125 126 case 'm': 127 if (--argc <= 0) 128 usage(); 129 if (hp >= &dhosts[NHOSTS-2]) { 130 fprintf(stderr, "rdist: too many destination hosts\n"); 131 exit(1); 132 } 133 *hp++ = *++argv; 134 break; 135 136 case 'd': 137 if (--argc <= 0) 138 usage(); 139 define(*++argv); 140 break; 141 142 case 'D': 143 debug++; 144 break; 145 146 case 'c': 147 cmdargs++; 148 break; 149 150 case 'n': 151 if (options & VERIFY) { 152 printf("rdist: -n overrides -v\n"); 153 options &= ~VERIFY; 154 } 155 nflag++; 156 break; 157 158 case 'q': 159 qflag++; 160 break; 161 162 case 'b': 163 options |= COMPARE; 164 break; 165 166 case 'R': 167 options |= REMOVE; 168 break; 169 170 case 'v': 171 if (nflag) { 172 printf("rdist: -n overrides -v\n"); 173 break; 174 } 175 options |= VERIFY; 176 break; 177 178 case 'w': 179 options |= WHOLE; 180 break; 181 182 case 'y': 183 options |= YOUNGER; 184 break; 185 186 case 'h': 187 options |= FOLLOW; 188 break; 189 190 case 'i': 191 options |= IGNLNKS; 192 break; 193 194 default: 195 usage(); 196 } 197 } 198 *hp = NULL; 199 200 seteuid(userid); 201 fd = mkstemp(tempfile); 202 if (fd == -1) 203 err(1, "could not make a temporary file"); 204 close (fd); 205 206 if (iamremote) { 207 server(); 208 unlink(tempfile); 209 exit(nerrs != 0); 210 } 211 212 if (cmdargs) 213 docmdargs(argc, argv); 214 else { 215 if (fin == NULL) { 216 if (distfile == NULL) { 217 if ((fin = fopen("distfile","r")) == NULL) 218 fin = fopen("Distfile", "r"); 219 } else 220 fin = fopen(distfile, "r"); 221 if (fin == NULL) { 222 perror(distfile ? distfile : "distfile"); 223 unlink(tempfile); 224 exit(1); 225 } 226 } 227 yyparse(); 228 if (nerrs == 0) 229 docmds(dhosts, argc, argv); 230 } 231 232 unlink(tempfile); 233 exit(nerrs != 0); 234} 235 236static void 237usage(void) 238{ 239 240 (void)fprintf(stderr, 241 "usage: %s [-bDhinqRvwy] [-d var=value] [-f distfile] [-m host] " 242 "[name ...]\n" 243 "or : %s [-bDhinqRvwy] -c name ... [login@]host[:dest]\n", 244 getprogname(), getprogname()); 245 exit(1); 246} 247 248/* 249 * rcp like interface for distributing files. 250 */ 251static void 252docmdargs(int nargs, char **args) 253{ 254 struct namelist *nl, *prev; 255 char *cp; 256 struct namelist *files, *hosts; 257 struct subcmd *cmds; 258 char *dest; 259 static struct namelist tnl = { NULL, NULL }; 260 int i; 261 262 if (nargs < 2) 263 usage(); 264 265 files = NULL; 266 prev = NULL; 267 for (i = 0; i < nargs - 1; i++) { 268 nl = makenl(args[i]); 269 if (prev == NULL) 270 files = prev = nl; 271 else { 272 prev->n_next = nl; 273 prev = nl; 274 } 275 } 276 277 cp = args[i]; 278 if ((dest = strchr(cp, ':')) != NULL) 279 *dest++ = '\0'; 280 tnl.n_name = cp; 281 hosts = expand(&tnl, E_ALL); 282 if (nerrs) 283 return; 284 285 if (dest == NULL || *dest == '\0') 286 cmds = NULL; 287 else { 288 cmds = makesubcmd(INSTALL); 289 cmds->sc_options = options; 290 cmds->sc_name = dest; 291 } 292 293 if (debug) { 294 printf("docmdargs()\nfiles = "); 295 prnames(files); 296 printf("hosts = "); 297 prnames(hosts); 298 } 299 insert(NULL, files, hosts, cmds); 300 docmds(NULL, 0, NULL); 301 freenl(files); 302 freenl(hosts); 303 freesubcmd(cmds); 304} 305 306/* 307 * Print a list of NAME blocks (mostly for debugging). 308 */ 309void 310prnames(struct namelist *nl) 311{ 312 printf("( "); 313 while (nl != NULL) { 314 printf("%s ", nl->n_name); 315 nl = nl->n_next; 316 } 317 printf(")\n"); 318} 319