1 /* $NetBSD: main.c,v 1.17 2004/07/13 12:06:35 wiz 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\n\ 35 The Regents of the University of California. All rights reserved.\n"); 36 #endif /* not lint */ 37 38 #ifndef lint 39 #if 0 40 static char sccsid[] = "@(#)main.c 8.1 (Berkeley) 6/9/93"; 41 #else 42 __RCSID("$NetBSD: main.c,v 1.17 2004/07/13 12:06:35 wiz 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 60 char *distfile = NULL; 61 #define _RDIST_TMP "/rdistXXXXXX" 62 char tempfile[sizeof _PATH_TMP + sizeof _RDIST_TMP + 1]; 63 char *tempname; 64 65 int debug; /* debugging flag */ 66 int nflag; /* NOP flag, just print commands without executing */ 67 int qflag; /* Quiet. Don't print messages */ 68 int options; /* global options */ 69 int iamremote; /* act as remote server for transfering files */ 70 71 FILE *fin = NULL; /* input file pointer */ 72 int rem = -1; /* file descriptor to remote source/sink process */ 73 char host[MAXHOSTNAMELEN + 1]; /* host name */ 74 int nerrs; /* number of errors while sending/receiving */ 75 char user[34]; /* user's name */ 76 char homedir[PATH_MAX]; /* user's home directory */ 77 uid_t userid; /* user's user ID */ 78 gid_t groupid; /* user's group ID */ 79 80 struct passwd *pw; /* pointer to static area used by getpwent */ 81 struct group *gr; /* pointer to static area used by getgrent */ 82 83 int main(int, char **); 84 static void usage(void); 85 static void docmdargs(int, char *[]); 86 87 int 88 main(int argc, char **argv) 89 { 90 char *arg; 91 int cmdargs = 0; 92 char *dhosts[NHOSTS], **hp = dhosts; 93 int fd; 94 95 pw = getpwuid(userid = getuid()); 96 if (pw == NULL) { 97 fprintf(stderr, "%s: Who are you?\n", argv[0]); 98 exit(1); 99 } 100 strlcpy(user, pw->pw_name, sizeof(user)); 101 strlcpy(homedir, pw->pw_dir, sizeof(homedir)); 102 groupid = pw->pw_gid; 103 gethostname(host, sizeof(host)); 104 host[sizeof(host) - 1] = '\0'; 105 strlcpy(tempfile, _PATH_TMP, sizeof(tempfile)); 106 strlcat(tempfile, _RDIST_TMP, sizeof(tempfile)); 107 if ((tempname = strrchr(tempfile, '/')) != 0) 108 tempname++; 109 else 110 tempname = tempfile; 111 112 while (--argc > 0) { 113 if ((arg = *++argv)[0] != '-') 114 break; 115 if (!strcmp(arg, "-Server")) 116 iamremote++; 117 else while (*++arg) 118 switch (*arg) { 119 case 'f': 120 if (--argc <= 0) 121 usage(); 122 distfile = *++argv; 123 if (distfile[0] == '-' && distfile[1] == '\0') 124 fin = stdin; 125 break; 126 127 case 'm': 128 if (--argc <= 0) 129 usage(); 130 if (hp >= &dhosts[NHOSTS-2]) { 131 fprintf(stderr, "rdist: too many destination hosts\n"); 132 exit(1); 133 } 134 *hp++ = *++argv; 135 break; 136 137 case 'd': 138 if (--argc <= 0) 139 usage(); 140 define(*++argv); 141 break; 142 143 case 'D': 144 debug++; 145 break; 146 147 case 'c': 148 cmdargs++; 149 break; 150 151 case 'n': 152 if (options & VERIFY) { 153 printf("rdist: -n overrides -v\n"); 154 options &= ~VERIFY; 155 } 156 nflag++; 157 break; 158 159 case 'q': 160 qflag++; 161 break; 162 163 case 'b': 164 options |= COMPARE; 165 break; 166 167 case 'R': 168 options |= REMOVE; 169 break; 170 171 case 'v': 172 if (nflag) { 173 printf("rdist: -n overrides -v\n"); 174 break; 175 } 176 options |= VERIFY; 177 break; 178 179 case 'w': 180 options |= WHOLE; 181 break; 182 183 case 'y': 184 options |= YOUNGER; 185 break; 186 187 case 'h': 188 options |= FOLLOW; 189 break; 190 191 case 'i': 192 options |= IGNLNKS; 193 break; 194 195 default: 196 usage(); 197 } 198 } 199 *hp = NULL; 200 201 seteuid(userid); 202 fd = mkstemp(tempfile); 203 if (fd == -1) 204 err(1, "could not make a temporary file"); 205 close (fd); 206 207 if (iamremote) { 208 server(); 209 unlink(tempfile); 210 exit(nerrs != 0); 211 } 212 213 if (cmdargs) 214 docmdargs(argc, argv); 215 else { 216 if (fin == NULL) { 217 if (distfile == NULL) { 218 if ((fin = fopen("distfile","r")) == NULL) 219 fin = fopen("Distfile", "r"); 220 } else 221 fin = fopen(distfile, "r"); 222 if (fin == NULL) { 223 perror(distfile ? distfile : "distfile"); 224 unlink(tempfile); 225 exit(1); 226 } 227 } 228 yyparse(); 229 if (nerrs == 0) 230 docmds(dhosts, argc, argv); 231 } 232 233 unlink(tempfile); 234 exit(nerrs != 0); 235 } 236 237 static void 238 usage(void) 239 { 240 241 (void)fprintf(stderr, 242 "usage: %s [-bDhinqRvwy] [-d var=value] [-f distfile] [-m host] " 243 "[name ...]\n" 244 "or : %s [-bDhinqRvwy] -c name ... [login@]host[:dest]\n", 245 getprogname(), getprogname()); 246 exit(1); 247 } 248 249 /* 250 * rcp like interface for distributing files. 251 */ 252 static void 253 docmdargs(int nargs, char **args) 254 { 255 struct namelist *nl, *prev; 256 char *cp; 257 struct namelist *files, *hosts; 258 struct subcmd *cmds; 259 char *dest; 260 static struct namelist tnl = { NULL, NULL }; 261 int i; 262 263 if (nargs < 2) 264 usage(); 265 266 files = NULL; 267 prev = NULL; 268 for (i = 0; i < nargs - 1; i++) { 269 nl = makenl(args[i]); 270 if (prev == NULL) 271 files = prev = nl; 272 else { 273 prev->n_next = nl; 274 prev = nl; 275 } 276 } 277 278 cp = args[i]; 279 if ((dest = strchr(cp, ':')) != NULL) 280 *dest++ = '\0'; 281 tnl.n_name = cp; 282 hosts = expand(&tnl, E_ALL); 283 if (nerrs) 284 return; 285 286 if (dest == NULL || *dest == '\0') 287 cmds = NULL; 288 else { 289 cmds = makesubcmd(INSTALL); 290 cmds->sc_options = options; 291 cmds->sc_name = dest; 292 } 293 294 if (debug) { 295 printf("docmdargs()\nfiles = "); 296 prnames(files); 297 printf("hosts = "); 298 prnames(hosts); 299 } 300 insert(NULL, files, hosts, cmds); 301 docmds(NULL, 0, NULL); 302 } 303 304 /* 305 * Print a list of NAME blocks (mostly for debugging). 306 */ 307 void 308 prnames(struct namelist *nl) 309 { 310 printf("( "); 311 while (nl != NULL) { 312 printf("%s ", nl->n_name); 313 nl = nl->n_next; 314 } 315 printf(")\n"); 316 } 317