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: }

Defined functions

closeconn defined in line 246; used 3 times
cmptime defined in line 358; used 2 times
colon defined in line 566; never used
doarrow defined in line 84; used 1 times
  • in line 69
docmds defined in line 29; used 2 times
dodcolon defined in line 293; used 1 times
  • in line 72
except defined in line 540; used 3 times
inlist defined in line 525; used 1 times
lostconn defined in line 258; used 9 times
makeconn defined in line 164; used 1 times
notify defined in line 449; used 2 times
okname defined in line 266; used 1 times
rcmptime defined in line 406; used 1 times

Defined variables

env defined in line 21; used 2 times
sccsid defined in line 8; never used
subcmds defined in line 20; used 3 times

Defined macros

RDIST defined in line 16; used 2 times
Last modified: 1986-03-10
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1735
Valid CSS Valid XHTML 1.0 Strict