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