# 2.11BSD#431 - /usr/src/ucb/rdist/docmd.c

##### Functions

    closeconn         X
    cmptime           X
    doarrow           X
    docmds            X
    dodcolon          X
    except            X
    inlist            X
    lostconn          X
    makeconn          X
    notify            X
    okname            X
    rcmptime          X

##### Variables

    env               X
    lastmod           X
    subcmds           X

       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

- in line 75, 180, 238

cmptime defined in line 357; used 2 times

- in line 342, 436

doarrow defined in line 81; used 1 times

- in line 66

docmds defined in line 26; used 2 times

- in /usr/src/ucb/rdist/main.c line 187, 252

dodcolon defined in line 292; used 1 times

- in line 69

except defined in line 540; used 3 times

- in line 365
- in /usr/src/ucb/rdist/server.c line 278, 1105

inlist defined in line 525; used 1 times

- in /usr/src/ucb/rdist/server.c line 466

lostconn defined in line 257; used 9 times

- in line 21, 107, 222-226(2)
- in /usr/src/ucb/rdist/server.c line 547, 1091, 1136, 1452, 1483

makeconn defined in line 163; used 1 times

- in line 108

notify defined in line 448; used 2 times

- in line 145, 349

okname defined in line 265; used 1 times

- in line 194

rcmptime defined in line 405; used 1 times

- in line 393

#### Defined variables

env defined in line 18; used 2 times

- in line 105, 262

lastmod defined in line 285; used 3 times

- in line 320, 349, 401

sccsid defined in line 8; never used
subcmds defined in line 17; used 3 times

- in line 100, 319, 549

Last modified: 1995-05-10 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 2174 |