|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1983 Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * Redistribution and use in source and binary forms are permitted ! 6: * provided that the above copyright notice and this paragraph are ! 7: * duplicated in all such forms and that any documentation, ! 8: * advertising materials, and other materials related to such ! 9: * distribution and use acknowledge that the software was developed ! 10: * by the University of California, Berkeley. The name of the ! 11: * University may not be used to endorse or promote products derived ! 12: * from this software without specific prior written permission. ! 13: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR ! 14: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED ! 15: * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 16: */ ! 17: ! 18: #ifndef lint ! 19: static char sccsid[] = "@(#)docmd.c 5.3 (Berkeley) 6/29/88"; ! 20: #endif /* not lint */ ! 21: ! 22: #include "defs.h" ! 23: #include <setjmp.h> ! 24: #include <netdb.h> ! 25: ! 26: #ifndef RDIST ! 27: #define RDIST "/usr/ucb/rdist" ! 28: #endif ! 29: ! 30: FILE *lfp; /* log file for recording files updated */ ! 31: struct subcmd *subcmds; /* list of sub-commands for current cmd */ ! 32: jmp_buf env; ! 33: ! 34: int cleanup(); ! 35: int lostconn(); ! 36: ! 37: /* ! 38: * Do the commands in cmds (initialized by yyparse). ! 39: */ ! 40: docmds(dhosts, argc, argv) ! 41: char **dhosts; ! 42: int argc; ! 43: char **argv; ! 44: { ! 45: register struct cmd *c; ! 46: register struct namelist *f; ! 47: register char **cpp; ! 48: extern struct cmd *cmds; ! 49: ! 50: signal(SIGHUP, cleanup); ! 51: signal(SIGINT, cleanup); ! 52: signal(SIGQUIT, cleanup); ! 53: signal(SIGTERM, cleanup); ! 54: ! 55: for (c = cmds; c != NULL; c = c->c_next) { ! 56: if (dhosts != NULL && *dhosts != NULL) { ! 57: for (cpp = dhosts; *cpp; cpp++) ! 58: if (strcmp(c->c_name, *cpp) == 0) ! 59: goto fndhost; ! 60: continue; ! 61: } ! 62: fndhost: ! 63: if (argc) { ! 64: for (cpp = argv; *cpp; cpp++) { ! 65: if (c->c_label != NULL && ! 66: strcmp(c->c_label, *cpp) == 0) { ! 67: cpp = NULL; ! 68: goto found; ! 69: } ! 70: for (f = c->c_files; f != NULL; f = f->n_next) ! 71: if (strcmp(f->n_name, *cpp) == 0) ! 72: goto found; ! 73: } ! 74: continue; ! 75: } else ! 76: cpp = NULL; ! 77: found: ! 78: switch (c->c_type) { ! 79: case ARROW: ! 80: doarrow(cpp, c->c_files, c->c_name, c->c_cmds); ! 81: break; ! 82: case DCOLON: ! 83: dodcolon(cpp, c->c_files, c->c_name, c->c_cmds); ! 84: break; ! 85: default: ! 86: fatal("illegal command type %d\n", c->c_type); ! 87: } ! 88: } ! 89: closeconn(); ! 90: } ! 91: ! 92: /* ! 93: * Process commands for sending files to other machines. ! 94: */ ! 95: doarrow(filev, files, rhost, cmds) ! 96: char **filev; ! 97: struct namelist *files; ! 98: char *rhost; ! 99: struct subcmd *cmds; ! 100: { ! 101: register struct namelist *f; ! 102: register struct subcmd *sc; ! 103: register char **cpp; ! 104: int n, ddir, opts = options; ! 105: ! 106: if (debug) ! 107: printf("doarrow(%x, %s, %x)\n", files, rhost, cmds); ! 108: ! 109: if (files == NULL) { ! 110: error("no files to be updated\n"); ! 111: return; ! 112: } ! 113: ! 114: subcmds = cmds; ! 115: ddir = files->n_next != NULL; /* destination is a directory */ ! 116: if (nflag) ! 117: printf("updating host %s\n", rhost); ! 118: else { ! 119: if (setjmp(env)) ! 120: goto done; ! 121: signal(SIGPIPE, lostconn); ! 122: if (!makeconn(rhost)) ! 123: return; ! 124: if ((lfp = fopen(tmpfile, "w")) == NULL) { ! 125: fatal("cannot open %s\n", tmpfile); ! 126: exit(1); ! 127: } ! 128: } ! 129: for (f = files; f != NULL; f = f->n_next) { ! 130: if (filev) { ! 131: for (cpp = filev; *cpp; cpp++) ! 132: if (strcmp(f->n_name, *cpp) == 0) ! 133: goto found; ! 134: if (!nflag) ! 135: (void) fclose(lfp); ! 136: continue; ! 137: } ! 138: found: ! 139: n = 0; ! 140: for (sc = cmds; sc != NULL; sc = sc->sc_next) { ! 141: if (sc->sc_type != INSTALL) ! 142: continue; ! 143: n++; ! 144: install(f->n_name, sc->sc_name, ! 145: sc->sc_name == NULL ? 0 : ddir, sc->sc_options); ! 146: opts = sc->sc_options; ! 147: } ! 148: if (n == 0) ! 149: install(f->n_name, NULL, 0, options); ! 150: } ! 151: done: ! 152: if (!nflag) { ! 153: (void) signal(SIGPIPE, cleanup); ! 154: (void) fclose(lfp); ! 155: lfp = NULL; ! 156: } ! 157: for (sc = cmds; sc != NULL; sc = sc->sc_next) ! 158: if (sc->sc_type == NOTIFY) ! 159: notify(tmpfile, rhost, sc->sc_args, 0); ! 160: if (!nflag) { ! 161: (void) unlink(tmpfile); ! 162: for (; ihead != NULL; ihead = ihead->nextp) { ! 163: free(ihead); ! 164: if ((opts & IGNLNKS) || ihead->count == 0) ! 165: continue; ! 166: log(lfp, "%s: Warning: missing links\n", ! 167: ihead->pathname); ! 168: } ! 169: } ! 170: } ! 171: ! 172: /* ! 173: * Create a connection to the rdist server on the machine rhost. ! 174: */ ! 175: makeconn(rhost) ! 176: char *rhost; ! 177: { ! 178: register char *ruser, *cp; ! 179: static char *cur_host = NULL; ! 180: static int port = -1; ! 181: char tuser[20]; ! 182: int n; ! 183: extern char user[]; ! 184: extern int userid; ! 185: ! 186: if (debug) ! 187: printf("makeconn(%s)\n", rhost); ! 188: ! 189: if (cur_host != NULL && rem >= 0) { ! 190: if (strcmp(cur_host, rhost) == 0) ! 191: return(1); ! 192: closeconn(); ! 193: } ! 194: cur_host = rhost; ! 195: cp = index(rhost, '@'); ! 196: if (cp != NULL) { ! 197: char c = *cp; ! 198: ! 199: *cp = '\0'; ! 200: strncpy(tuser, rhost, sizeof(tuser)-1); ! 201: *cp = c; ! 202: rhost = cp + 1; ! 203: ruser = tuser; ! 204: if (*ruser == '\0') ! 205: ruser = user; ! 206: else if (!okname(ruser)) ! 207: return(0); ! 208: } else ! 209: ruser = user; ! 210: if (!qflag) ! 211: printf("updating host %s\n", rhost); ! 212: (void) sprintf(buf, "%s -Server%s", RDIST, qflag ? " -q" : ""); ! 213: if (port < 0) { ! 214: struct servent *sp; ! 215: ! 216: if ((sp = getservbyname("shell", "tcp")) == NULL) ! 217: fatal("shell/tcp: unknown service"); ! 218: port = sp->s_port; ! 219: } ! 220: ! 221: if (debug) { ! 222: printf("port = %d, luser = %s, ruser = %s\n", ntohs(port), user, ruser); ! 223: printf("buf = %s\n", buf); ! 224: } ! 225: ! 226: fflush(stdout); ! 227: setreuid(userid, 0); ! 228: rem = rcmd(&rhost, port, user, ruser, buf, 0); ! 229: setreuid(0, userid); ! 230: if (rem < 0) ! 231: return(0); ! 232: cp = buf; ! 233: if (read(rem, cp, 1) != 1) ! 234: lostconn(); ! 235: if (*cp == 'V') { ! 236: do { ! 237: if (read(rem, cp, 1) != 1) ! 238: lostconn(); ! 239: } while (*cp++ != '\n' && cp < &buf[BUFSIZ]); ! 240: *--cp = '\0'; ! 241: cp = buf; ! 242: n = 0; ! 243: while (*cp >= '0' && *cp <= '9') ! 244: n = (n * 10) + (*cp++ - '0'); ! 245: if (*cp == '\0' && n == VERSION) ! 246: return(1); ! 247: error("connection failed: version numbers don't match (local %d, remote %d)\n", VERSION, n); ! 248: } else ! 249: error("connection failed: version numbers don't match\n"); ! 250: closeconn(); ! 251: return(0); ! 252: } ! 253: ! 254: /* ! 255: * Signal end of previous connection. ! 256: */ ! 257: closeconn() ! 258: { ! 259: if (debug) ! 260: printf("closeconn()\n"); ! 261: ! 262: if (rem >= 0) { ! 263: (void) write(rem, "\2\n", 2); ! 264: (void) close(rem); ! 265: rem = -1; ! 266: } ! 267: } ! 268: ! 269: lostconn() ! 270: { ! 271: if (iamremote) ! 272: cleanup(); ! 273: log(lfp, "rdist: lost connection\n"); ! 274: longjmp(env, 1); ! 275: } ! 276: ! 277: okname(name) ! 278: register char *name; ! 279: { ! 280: register char *cp = name; ! 281: register int c; ! 282: ! 283: do { ! 284: c = *cp; ! 285: if (c & 0200) ! 286: goto bad; ! 287: if (!isalpha(c) && !isdigit(c) && c != '_' && c != '-') ! 288: goto bad; ! 289: cp++; ! 290: } while (*cp); ! 291: return(1); ! 292: bad: ! 293: error("invalid user name %s\n", name); ! 294: return(0); ! 295: } ! 296: ! 297: time_t lastmod; ! 298: FILE *tfp; ! 299: extern char target[], *tp; ! 300: ! 301: /* ! 302: * Process commands for comparing files to time stamp files. ! 303: */ ! 304: dodcolon(filev, files, stamp, cmds) ! 305: char **filev; ! 306: struct namelist *files; ! 307: char *stamp; ! 308: struct subcmd *cmds; ! 309: { ! 310: register struct subcmd *sc; ! 311: register struct namelist *f; ! 312: register char **cpp; ! 313: struct timeval tv[2]; ! 314: struct timezone tz; ! 315: struct stat stb; ! 316: ! 317: if (debug) ! 318: printf("dodcolon()\n"); ! 319: ! 320: if (files == NULL) { ! 321: error("no files to be updated\n"); ! 322: return; ! 323: } ! 324: if (stat(stamp, &stb) < 0) { ! 325: error("%s: %s\n", stamp, sys_errlist[errno]); ! 326: return; ! 327: } ! 328: if (debug) ! 329: printf("%s: %d\n", stamp, stb.st_mtime); ! 330: ! 331: subcmds = cmds; ! 332: lastmod = stb.st_mtime; ! 333: if (nflag || (options & VERIFY)) ! 334: tfp = NULL; ! 335: else { ! 336: if ((tfp = fopen(tmpfile, "w")) == NULL) { ! 337: error("%s: %s\n", stamp, sys_errlist[errno]); ! 338: return; ! 339: } ! 340: (void) gettimeofday(&tv[0], &tz); ! 341: tv[1] = tv[0]; ! 342: (void) utimes(stamp, tv); ! 343: } ! 344: ! 345: for (f = files; f != NULL; f = f->n_next) { ! 346: if (filev) { ! 347: for (cpp = filev; *cpp; cpp++) ! 348: if (strcmp(f->n_name, *cpp) == 0) ! 349: goto found; ! 350: continue; ! 351: } ! 352: found: ! 353: tp = NULL; ! 354: cmptime(f->n_name); ! 355: } ! 356: ! 357: if (tfp != NULL) ! 358: (void) fclose(tfp); ! 359: for (sc = cmds; sc != NULL; sc = sc->sc_next) ! 360: if (sc->sc_type == NOTIFY) ! 361: notify(tmpfile, NULL, sc->sc_args, lastmod); ! 362: if (!nflag && !(options & VERIFY)) ! 363: (void) unlink(tmpfile); ! 364: } ! 365: ! 366: /* ! 367: * Compare the mtime of file to the list of time stamps. ! 368: */ ! 369: cmptime(name) ! 370: char *name; ! 371: { ! 372: struct stat stb; ! 373: ! 374: if (debug) ! 375: printf("cmptime(%s)\n", name); ! 376: ! 377: if (except(name)) ! 378: return; ! 379: ! 380: if (nflag) { ! 381: printf("comparing dates: %s\n", name); ! 382: return; ! 383: } ! 384: ! 385: /* ! 386: * first time cmptime() is called? ! 387: */ ! 388: if (tp == NULL) { ! 389: if (exptilde(target, name) == NULL) ! 390: return; ! 391: tp = name = target; ! 392: while (*tp) ! 393: tp++; ! 394: } ! 395: if (access(name, 4) < 0 || stat(name, &stb) < 0) { ! 396: error("%s: %s\n", name, sys_errlist[errno]); ! 397: return; ! 398: } ! 399: ! 400: switch (stb.st_mode & S_IFMT) { ! 401: case S_IFREG: ! 402: break; ! 403: ! 404: case S_IFDIR: ! 405: rcmptime(&stb); ! 406: return; ! 407: ! 408: default: ! 409: error("%s: not a plain file\n", name); ! 410: return; ! 411: } ! 412: ! 413: if (stb.st_mtime > lastmod) ! 414: log(tfp, "new: %s\n", name); ! 415: } ! 416: ! 417: rcmptime(st) ! 418: struct stat *st; ! 419: { ! 420: register DIR *d; ! 421: register struct direct *dp; ! 422: register char *cp; ! 423: char *otp; ! 424: int len; ! 425: ! 426: if (debug) ! 427: printf("rcmptime(%x)\n", st); ! 428: ! 429: if ((d = opendir(target)) == NULL) { ! 430: error("%s: %s\n", target, sys_errlist[errno]); ! 431: return; ! 432: } ! 433: otp = tp; ! 434: len = tp - target; ! 435: while (dp = readdir(d)) { ! 436: if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) ! 437: continue; ! 438: if (len + 1 + strlen(dp->d_name) >= BUFSIZ - 1) { ! 439: error("%s/%s: Name too long\n", target, dp->d_name); ! 440: continue; ! 441: } ! 442: tp = otp; ! 443: *tp++ = '/'; ! 444: cp = dp->d_name; ! 445: while (*tp++ = *cp++) ! 446: ; ! 447: tp--; ! 448: cmptime(target); ! 449: } ! 450: closedir(d); ! 451: tp = otp; ! 452: *tp = '\0'; ! 453: } ! 454: ! 455: /* ! 456: * Notify the list of people the changes that were made. ! 457: * rhost == NULL if we are mailing a list of changes compared to at time ! 458: * stamp file. ! 459: */ ! 460: notify(file, rhost, to, lmod) ! 461: char *file, *rhost; ! 462: register struct namelist *to; ! 463: time_t lmod; ! 464: { ! 465: register int fd, len; ! 466: FILE *pf, *popen(); ! 467: struct stat stb; ! 468: ! 469: if ((options & VERIFY) || to == NULL) ! 470: return; ! 471: if (!qflag) { ! 472: printf("notify "); ! 473: if (rhost) ! 474: printf("@%s ", rhost); ! 475: prnames(to); ! 476: } ! 477: if (nflag) ! 478: return; ! 479: ! 480: if ((fd = open(file, 0)) < 0) { ! 481: error("%s: %s\n", file, sys_errlist[errno]); ! 482: return; ! 483: } ! 484: if (fstat(fd, &stb) < 0) { ! 485: error("%s: %s\n", file, sys_errlist[errno]); ! 486: (void) close(fd); ! 487: return; ! 488: } ! 489: if (stb.st_size == 0) { ! 490: (void) close(fd); ! 491: return; ! 492: } ! 493: /* ! 494: * Create a pipe to mailling program. ! 495: */ ! 496: pf = popen(MAILCMD, "w"); ! 497: if (pf == NULL) { ! 498: error("notify: \"%s\" failed\n", MAILCMD); ! 499: (void) close(fd); ! 500: return; ! 501: } ! 502: /* ! 503: * Output the proper header information. ! 504: */ ! 505: fprintf(pf, "From: rdist (Remote distribution program)\n"); ! 506: fprintf(pf, "To:"); ! 507: if (!any('@', to->n_name) && rhost != NULL) ! 508: fprintf(pf, " %s@%s", to->n_name, rhost); ! 509: else ! 510: fprintf(pf, " %s", to->n_name); ! 511: to = to->n_next; ! 512: while (to != NULL) { ! 513: if (!any('@', to->n_name) && rhost != NULL) ! 514: fprintf(pf, ", %s@%s", to->n_name, rhost); ! 515: else ! 516: fprintf(pf, ", %s", to->n_name); ! 517: to = to->n_next; ! 518: } ! 519: putc('\n', pf); ! 520: if (rhost != NULL) ! 521: fprintf(pf, "Subject: files updated by rdist from %s to %s\n", ! 522: host, rhost); ! 523: else ! 524: fprintf(pf, "Subject: files updated after %s\n", ctime(&lmod)); ! 525: putc('\n', pf); ! 526: ! 527: while ((len = read(fd, buf, BUFSIZ)) > 0) ! 528: (void) fwrite(buf, 1, len, pf); ! 529: (void) close(fd); ! 530: (void) pclose(pf); ! 531: } ! 532: ! 533: /* ! 534: * Return true if name is in the list. ! 535: */ ! 536: inlist(list, file) ! 537: struct namelist *list; ! 538: char *file; ! 539: { ! 540: register struct namelist *nl; ! 541: ! 542: for (nl = list; nl != NULL; nl = nl->n_next) ! 543: if (!strcmp(file, nl->n_name)) ! 544: return(1); ! 545: return(0); ! 546: } ! 547: ! 548: /* ! 549: * Return TRUE if file is in the exception list. ! 550: */ ! 551: except(file) ! 552: char *file; ! 553: { ! 554: register struct subcmd *sc; ! 555: register struct namelist *nl; ! 556: ! 557: if (debug) ! 558: printf("except(%s)\n", file); ! 559: ! 560: for (sc = subcmds; sc != NULL; sc = sc->sc_next) { ! 561: if (sc->sc_type != EXCEPT && sc->sc_type != PATTERN) ! 562: continue; ! 563: for (nl = sc->sc_args; nl != NULL; nl = nl->n_next) { ! 564: if (sc->sc_type == EXCEPT) { ! 565: if (!strcmp(file, nl->n_name)) ! 566: return(1); ! 567: continue; ! 568: } ! 569: re_comp(nl->n_name); ! 570: if (re_exec(file) > 0) ! 571: return(1); ! 572: } ! 573: } ! 574: return(0); ! 575: } ! 576: ! 577: char * ! 578: colon(cp) ! 579: register char *cp; ! 580: { ! 581: ! 582: while (*cp) { ! 583: if (*cp == ':') ! 584: return(cp); ! 585: if (*cp == '/') ! 586: return(0); ! 587: cp++; ! 588: } ! 589: return(0); ! 590: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.