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

Defined functions

closeconn defined in line 245; used 3 times
cmptime defined in line 357; used 2 times
doarrow defined in line 81; used 1 times
  • in line 66
docmds defined in line 26; used 2 times
dodcolon defined in line 292; used 1 times
  • in line 69
except defined in line 540; used 3 times
inlist defined in line 525; used 1 times
lostconn defined in line 257; used 9 times
makeconn defined in line 163; used 1 times
notify defined in line 448; used 2 times
okname defined in line 265; used 1 times
rcmptime defined in line 405; used 1 times

Defined variables

env defined in line 18; used 2 times
lastmod defined in line 285; used 3 times
sccsid defined in line 8; never used
subcmds defined in line 17; used 3 times
Last modified: 1995-05-10
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1001
Valid CSS Valid XHTML 1.0 Strict