source: trunk/athena/etc/synctree/synctree.c @ 11280

Revision 11280, 17.3 KB checked in by ghudson, 27 years ago (diff)
Add -d flag to descend into an ignored directory.
RevLine 
[5292]1/* Copyright (C) 1988  Tim Shepard   All rights reserved. */
2
3#include <stdio.h>
4#include <sys/types.h>
[7221]5#include <sys/param.h>
6#include <unistd.h>
7#include <dirent.h>
[5292]8#include <sys/stat.h>
[7221]9
[5292]10#include <sys/time.h>
11#include <sys/resource.h>
[8465]12#include <string.h>
[5292]13#ifdef OLD
14#include <ndbm.h>
15#endif
[8465]16#include <errno.h>
[7943]17
[7221]18#ifdef SOLARIS
19#define NO_LINEBUF
20#endif
[5292]21#include "synctree.h"
22
23#ifndef DEBUG
24char *srcdir = "/server";
25char *dstdir = "";            /* effectively "/" */
26char *src_rule_file = ".rconf";
27char *dst_rule_file = ".rconf.local";
28char *date_db_name  = ".reconcile_dates";
[7943]29#else /* DEBUG */
[5292]30char *srcdir = "s";
31char *dstdir = "d";
32char *src_rule_file = ".rconf";
33char *dst_rule_file = ".rconf.local";
34#ifdef DATE
35char *date_db_name  = ".reconcile_dates";
36#endif
[7943]37#endif /* DEBUG */
[5292]38
39rule rules[MAXNRULES];
40unsigned int lastrule;
41unsigned int rflag = 0;
42
43int dodir();
44char *destination_pathname();
45
46int  verbosef = 1;
47int  nflag = 0;
48int  aflag = 0;
49char *afile;
50
51bool nosrcrules = FALSE;
52bool nodstrules = FALSE;
53uid_t uid, euid;
[7221]54#ifndef SOLARIS
[5292]55uid_t getuid(), geteuid();
[7221]56#endif
[5292]57void usage(arg0)
58     char *arg0;
59{
[11189]60  fprintf(stderr,"Usage: %s [-v] [-n] [-q] [-nosrcrules] [-nodstrules] [-s srcdir] [-d dstdir] [-a rules]\n",arg0);
[5292]61  exit(1);
62}
63
64main(argc, argv)
65     int argc;
66     char *argv[];
67{
68  int i;
69#ifndef NO_RLIMIT
70  struct rlimit rl;
71#endif
72
[9744]73#ifndef NO_LINEBUF
74  setlinebuf(stdout);
75#else
76  setvbuf(stdout,NULL,_IOLBF,BUFSIZ);
77#endif
78
[5292]79  uid = getuid();
80  euid = geteuid();
81
82#ifndef NO_RLIMIT
83  getrlimit(RLIMIT_DATA,&rl);
84  rl.rlim_cur = rl.rlim_max;
85  setrlimit(RLIMIT_DATA,&rl);
86
87  getrlimit(RLIMIT_STACK,&rl);
88  rl.rlim_cur = rl.rlim_max;
89  setrlimit(RLIMIT_STACK,&rl);
90#endif
91
92  i = 0;
93 
94  while (++i < argc)
95    {
96      if (argv[i][0] != '-') usage(argv[0]);
97
98      switch (argv[i][1]) {
99      case 's':
100        if (argv[i][2])
[10717]101          { srcdir = (char *) malloc(strlen(&argv[i][2])+1);
[5292]102            (void) strcpy(srcdir, &argv[i][2]);
103          }
104        else if (++i >= argc) usage(argv[0]);
105        else
[10717]106          { srcdir = (char *) malloc(strlen(&argv[i][0])+1);
[5292]107            (void) strcpy(srcdir, argv[i]);
108          }
109        break;
110
111      case 'd':
112        if (argv[i][2])
[10717]113          { dstdir = (char *) malloc(strlen(&argv[i][2])+1);
[5292]114            (void) strcpy(dstdir, &argv[i][2]);
115          }
116        else if (++i >= argc) usage(argv[0]);
117        else
[10717]118          { dstdir = (char *) malloc(strlen(&argv[i][0])+1);
[5292]119            (void) strcpy(dstdir, argv[i]);
120          }
121        if (strcmp(dstdir,"/") == 0)
122          dstdir[0] = '\0';
123        break;
124
125      case 'a':
126        if (argv[i][2])
[10717]127          { afile = (char *) malloc(strlen(&argv[i][2])+1);
[5292]128            (void) strcpy(afile, &argv[i][2]);
129          }
130        else if (++i >= argc) usage(argv[0]);
131        else
[10717]132          { afile = (char *) malloc(strlen(&argv[i][0])+1);
[5292]133            (void) strcpy(afile, argv[i]);
134          }
135        if (strcmp(afile,"/") == 0)
136          afile[0] = '\0';
137        aflag++;
138        break;
139
140      case 'v':
141        verbosef++;
142        break;
143      case 'q':
144        verbosef = 0;
145        break;
146      case 'n':
147        if (strcmp(&argv[i][1],"nosrcrules") == 0)
148          { nosrcrules = TRUE;
149            break;
150          }         
151        if (strcmp(&argv[i][1],"nodstrules") == 0)
152          { nodstrules = TRUE;
153            break;
154          }         
155        if (strcmp(&argv[i][1],"n") == 0)
156          { nflag = 1;
157            break;
158          }         
159        /* fall through to default */
160      default:
161        usage(argv[0]);
162      }
163    }
164     
165  (void) umask(0);
166
167  if (srcdir[0] != '/')
168    { char *p = srcdir;
[10717]169      srcdir = (char *) malloc(MAXPATHLEN);
[7221]170      if ((srcdir = getcwd(srcdir,MAXPATHLEN )) == NULL)
171        { perror("getcwd() failed");
172          fprintf(stderr,"exiting\n");
173          exit(1);
174        }
[5292]175      if ((strlen(srcdir) + strlen("/") + strlen(p) + 1) > MAXPATHLEN)
176        { fprintf(stderr,"full pathname is too long, exiting");
177          exit(1);
178        }
179      (void) strcat(srcdir,"/");
180      (void) strcat(srcdir,p);
181    }
182
183  if ((dstdir[0] != '/') && (dstdir[0] != '\0'))
184    { char *p = dstdir;
[10717]185      dstdir = (char *) malloc(MAXPATHLEN);
[7221]186      if ((dstdir = getcwd(dstdir, MAXPATHLEN)) == NULL)
187        { perror("getcwd() failed");
188          fprintf(stderr,"exiting\n");
189          exit(1);
190        }
[5292]191      if ((strlen(dstdir) + strlen("/") + strlen(p) + 1) > MAXPATHLEN)
192        { fprintf(stderr,"full pathname is too long, exiting");
193          exit(1);
194        }
[7221]195
[5292]196      (void) strcat(dstdir,"/");
197      (void) strcat(dstdir,p);
198    }
199
200
201  lastrule = 0;
202
203  /* The hardwired rules (number zero and number one):
204            map * $
205            ignore *
206
207            */
208
209  {
210      static char *mapdests[] = { "$", (char *)0 };
211
212      lstrule.type = R_MAP;
213      lstrule.u.u_map.globexp    = "*";
214      lstrule.u.u_map.file_types = TYPE_ALL;
215      lstrule.u.u_map.dests      = mapdests;
216  }
217  newrule();
218  lstrule.type = R_ACTION;
219  lstrule.u.u_action.type        = ACTION_IGNORE;
220  lstrule.u.u_action.globexp     = "*";
221  lstrule.u.u_action.file_types  = TYPE_ALL;
222  lstrule.u.u_action.options     = 0;
223
224  exit(dodir(srcdir,dstdir,""));
225}
226
227struct src {
[10511]228  char *name;
[5292]229  char *pathname;
230  struct stat stat;
231  unsigned int type;
232  int map_ruleno;
233  bool chased;
234  struct src *next;
235};
236
237struct targ {
238  char *pathname;
239  struct src *sp;
240  int action_ruleno;
241  bool updated; /* for when */
242  struct targ *next;
243};
244
245int dodir(src,dst,part)
246     char *src;
247     char *dst;
248     char *part;
249{
250    struct src srclist,*sp,*spp,*sppp;
251    struct targ targlist,*tp,*tpp,*tppp;
252    int i,j;
[8915]253    void *getmemt;
[5292]254    bool sorted;
255    DIR *dirp;
[5294]256    struct dirent *dp;
[5292]257    char *testpath;
258    struct stat teststat;
259
260    if (verbosef)
261        printf("processing %s\n", dst);
262 
263    srclist.next = 0;
264    targlist.next = 0;
265
[10717]266#define getmem(amt) (((getmemt = malloc(amt)) == NULL)? panic("dodir: bad return from malloc"), (void *) NULL : getmemt)
[5292]267#define newsrc(ptr)  (ptr = (struct src *)  getmem(sizeof(struct src)),  ptr->next=srclist.next,  srclist.next=ptr)
268#define newtarg(ptr) (ptr = (struct targ *) getmem(sizeof(struct targ)), ptr->next=targlist.next, targlist.next=ptr)
269#define allsrcs(ptr)  for (ptr=srclist.next; ptr!=NULL; ptr=ptr->next)
270#define alltargs(ptr) for (ptr=targlist.next; ptr!=NULL; ptr=ptr->next)
271
272    getrules(src,dst);
273 
274    /* read in source directory */
275    if ((dirp = opendir(src)) == NULL) {
[8465]276        fprintf(stderr, "Can't read directory %s: %s\n", src, strerror(errno));
[5292]277        return 1;
278    }
279    while ((dp = readdir(dirp)) != NULL) {
280        if (!strcmp(dp->d_name,".") || !strcmp(dp->d_name,".."))
281            continue;
282        newsrc(sp);
283        sp->pathname = (char *)0;
[10511]284        sp->name = (char *) getmem(strlen(dp->d_name) + 1);
285        strcpy(sp->name, dp->d_name);
[5292]286    }
287    closedir(dirp);
288
289    /* XXX */
290    /* read in target directory */
291    if ((rflag & RFLAG_SCAN_TARGET) && (dirp = opendir(dst))) {
292        testpath = (char *) getmem(strlen(src) + 66);
293        while ((dp = readdir(dirp)) != NULL) {
294            if (!strcmp(dp->d_name,".") || !strcmp(dp->d_name,".."))
295                continue;
296            strcpy(testpath,src);
297            strcat(testpath,"/");
298            strcat(testpath,dp->d_name);
299            if (lstat(testpath, &teststat)) {
300                newsrc(sp);
[10511]301                sp->name  = (char *) getmem(strlen(dp->d_name) + 1);
302                strcpy(sp->name, dp->d_name);
[5292]303
304                sp->pathname =
[10511]305                    (char *) getmem( strlen(src) + strlen(sp->name) + 2 );
[5292]306                strcpy(sp->pathname, testpath);
307            }
308        }
309        closedir(dirp);
310    }
311    /* XXX */
312
313    /* process each src */
314    allsrcs(sp) {
315
316        /*
317         * If sp->pathname is already set, it must be a virtual file,
318         * which indicates that the file only exists in the target
319         * directory.  We still wish to get the stats for such files,
320         * but we want to mark it as a virtual file, so we frob with
321         * the sp->type field.
322         */
323        if (!sp->pathname) {
324            sp->pathname =
[10511]325                (char *) getmem( strlen(src) + strlen(sp->name) + 2 );
[5292]326            (void) strcpy(sp->pathname,src);
327            (void) strcat(sp->pathname,"/");
[10511]328            (void) strcat(sp->pathname,sp->name);
[5292]329            /* get information about file */
330            if (lstat(sp->pathname,&(sp->stat)) < 0) {
[8465]331#define perror(problem, whatnext) printf("%s: %s: %s. %s\n", sp->pathname, problem, strerror(errno), whatnext)
[5292]332                perror("lstat() failed", "ignoring");
333                sp->map_ruleno = 0;
334                continue;
335            }
336
337            sp->type = 0;
338
339        } else {
340            char path[MAXPATHLEN];
341
342            (void) strcpy(path, dst);
343            (void) strcat(path, "/");
[10511]344            (void) strcat(path, sp->name);
[5292]345
346            if (lstat(path, &(sp->stat)) < 0) {
[8465]347#define perror(problem, whatnext) printf("%s: %s: %s. %s\n", sp->pathname, problem, strerror(errno), whatnext)
[5292]348                perror("lstat() failed", "ignoring");
349                sp->map_ruleno = 0;
350                continue;
351            }
352             
353            sp->type = TYPE_V;
354        }
355   
356        {
357            int mode = sp->stat.st_mode & S_IFMT;
358            switch(mode) {
359#define X(a,b) case a: \
360                if (verbosef > 1) printf("Found %s, mode %7.7o\n",sp->pathname,mode); \
361                    sp->type |= b; break
362                        X(S_IFDIR,TYPE_D);
363                X(S_IFCHR,TYPE_C);
364                X(S_IFBLK,TYPE_B);
365                X(S_IFREG,TYPE_R);
366                X(S_IFLNK,TYPE_L);
367                X(S_IFSOCK,TYPE_S);
368#undef X
369            default:
370                printf("%s: unknown type of src file: %7.7o, ignoring.\n",
371                       sp->pathname, mode);
372                sp->map_ruleno = 0;
373                continue;
374            }
375        }
376   
377        if ((sp->type == TYPE_L) &&
378            (findrule(sp->pathname,R_CHASE,sp->type,sp->pathname) > 0)) {
379            sp->chased = TRUE;
380            if (stat(sp->pathname,&(sp->stat)) < 0) {
381                perror("stat() after chase failed", "ignoring.");
382#undef perror
383                sp->map_ruleno = 0;
384                continue;
385            }
386            {
387                int mode = sp->stat.st_mode & S_IFMT;
388                switch (mode) {
389#define X(a,b) case a: sp->type = b ; break
390                    X(S_IFDIR,TYPE_D);
391                    X(S_IFCHR,TYPE_C);
392                    X(S_IFBLK,TYPE_B);
393                    X(S_IFREG,TYPE_R);
394                    X(S_IFLNK,TYPE_L);
395                    X(S_IFSOCK,TYPE_S);
396#undef X
397                default:
398                    printf("%s: unknown type of chased file: %7.7o, ignoring.\n",
399                           sp->pathname, mode);
400                    sp->map_ruleno = 0;
401                    continue;
402                }
403            }
404        } else {
405            sp->chased = FALSE;
406        }
407 
408        sp->map_ruleno = findrule(sp->pathname,R_MAP,sp->type,sp->pathname);
409
410        for (i = 0; rules[sp->map_ruleno].u.u_map.dests[i] != 0; i++) {
411            char *r;
412            newtarg(tp);
413            r = destination_pathname(dst,
[10511]414                                     sp->name,
[5292]415                                     rules[sp->map_ruleno].u.u_map.dests[i]);
416            tp->pathname = (char *) getmem(strlen(r)+1);
417            strcpy(tp->pathname,r);
418            tp->sp = sp;
419            if (verbosef > 2) printf("new targ: %s (from %s)\n",
420                                     tp->pathname, sp->pathname);
421
422        }
423    }
424    alltargs(tp) {
425        tp->action_ruleno =
426            findrule(tp->pathname,R_ACTION,tp->sp->type,tp->sp->pathname);
427        tp->updated = FALSE;
428    }
429
430    alltargs(tp) {
431        bool exists = FALSE;
432        bool chased = FALSE;
433        struct stat targstat;
434        unsigned int targtype;
435        time_t dbdate;
436        if (lstat(tp->pathname,&targstat) == 0) {
437            int mode = targstat.st_mode & S_IFMT;
438       
439            exists = TRUE;     
440            switch (mode) {
441#define X(a,b) case a: targtype = b ; break
442                X(S_IFDIR,TYPE_D);
443                X(S_IFCHR,TYPE_C);
444                X(S_IFBLK,TYPE_B);
445                X(S_IFREG,TYPE_R);
446                X(S_IFLNK,TYPE_L);
447                X(S_IFSOCK,TYPE_S);
448#undef X
449            }
450            if ((targtype == TYPE_L) &&
451                option_on(tp->action_ruleno, 'l')) {
452                if (stat(tp->pathname,&targstat) != 0) {
453                    /*** the link exists but its target does not */
454                    /*** hopefully, we can make it exist ..... */
455                    chased = TRUE;
456                    exists = FALSE;
457                } else {
458                    chased = TRUE;
459                    switch (targstat.st_mode & S_IFMT) {
460#define X(a,b) case a: targtype = b ; break
461                        X(S_IFDIR,TYPE_D);
462                        X(S_IFCHR,TYPE_C);
463                        X(S_IFBLK,TYPE_B);
464                        X(S_IFREG,TYPE_R);
465                        X(S_IFLNK,TYPE_L);
466                        X(S_IFSOCK,TYPE_S);
467#undef X
468                    }
469                }
470            }
471        }
472
473#define srcstat (tp->sp->stat)
474        /*      targstat */
475
476        /* "switch.c" knows only about what is defined or mentioned between here and where it is included */
477
478#define typeofaction (rules[tp->action_ruleno].u.u_action.type)
479#define pflag   (option_on(tp->action_ruleno,'p'))
480#define fflag   (option_on(tp->action_ruleno,'f'))
[11280]481#define dflag   (option_on(tp->action_ruleno,'d'))
[5292]482
483        /* modemask is not known to switch.c */
484#define modemask (pflag ? 07777 : 00777)
485
486#define srcname (tp->sp->pathname)
487#define srcdev  (int) (srcstat.st_rdev)
488#define srctype (tp->sp->type)
489#define srcuid  ((int) (srcstat.st_uid))
490
491#define targname (tp->pathname)
492#define targdev  (int) (targstat.st_rdev)
493#define targuid  ((int) (targstat.st_uid))
494#define targmode (int) (targstat.st_mode & modemask)
495#define tmark()  (tp->updated = TRUE)
496
497#define srcgid  ((gid_t) (srcstat.st_gid))
498#define targgid  ((gid_t) (targstat.st_gid))
499
500#if defined(_AIX) && defined(_IBMR2)
501#define srcmode (int)(srcstat.st_mode & ((srctype==TYPE_D) ? 07777 : modemask))
502#else
503#define srcmode (int)(srcstat.st_mode & modemask)
504#endif
505
506#define ERROR -1
507#define NODBDATE 0
508#define NODBDATE_P LOCAL                /* (forceupdatef? OUTOFDATE : LOCAL) */
509#define UPTODATE 1
510#define OUTOFDATE 2
511#define NEWERDATE 3
512#define LOCAL 4
513#define LOCAL_P LOCAL                   /* (forceupdatef? OUTOFDATE : LOCAL) */
514#define LOCALBUTOUTOFDATE 6
515#define LOCALBUTOUTOFDATE_P LOCAL       /* (forceupdatef? OUTOFDATE : LOCAL) */
516#define FIXMODE 6
517#define FIXOWNANDMODE 7
518
519#define filecheck3() \
520        ((srcstat.st_mtime > targstat.st_mtime) ? \
521         OUTOFDATE : \
522         ((srcstat.st_mtime < targstat.st_mtime) || \
523          (srcstat.st_size != targstat.st_size)) ? \
524         NEWERDATE : \
525         (pflag && ((srcuid != targuid) || (srcgid != targgid))) ? \
526         FIXOWNANDMODE : \
527         ((srcmode&modemask) != (targmode&modemask)) ? \
528         FIXMODE : \
529         UPTODATE)
530       
531#define dircheck() \
532        ((pflag && ((srcuid != targuid) || \
533                    ((srcgid >= 0) && (srcgid != targgid)))) \
534         ? FIXOWNANDMODE : \
[5346]535         (pflag && ((srcmode&modemask) != (targmode&modemask))) \
[5341]536         ? FIXMODE : UPTODATE)
[5292]537
538#define setdates() \
539        { time_t date = srcstat.st_mtime; \
540          struct timeval tv[2]; \
541          tv[0].tv_sec = tv[1].tv_sec = date; \
542          tv[0].tv_usec = tv[1].tv_usec = 0; \
543          (void) utimes(targname,tv); \
544          tmark(); \
545        }
546
547    if (verbosef > 2) {
548      printf("entering switch.c:  %s ----> %s\n", srcname, targname);
549      printf("              typeofaction   is %d\n", typeofaction);
550      printf("              pflag              is %d\n", pflag);
551      printf("              modemask       is %4.4o\n", modemask);
552      printf("              srcname            is %s\n", srcname);
553      printf("              srcmode            is %7.7o\n", srcstat.st_mode);
554      printf("              srcdev             is %4.4x\n", srcdev);
555      printf("              srctype            is %d\n", srctype);
556      printf("              srcuid             is %d\n", srcuid);
557      printf("              srcgid             is %d\n", srcgid);
558      printf("              targname       is %s\n", targname);
559      printf("              exists             is %d\n", exists);
560      if (exists) {
561        printf("              targmode   is %7.7o\n", targstat.st_mode);
562        printf("              targdev    is %4.4x\n", targdev);
563        printf("              targtype   is %d\n", targtype);
564        printf("              targuid    is %d\n", targuid);
565        printf("              targgid    is %d\n", targgid);
566      }
567      printf("\n");
568    }     
569
570#include "switch.c"
571  }
572 
573  /* do when rules */
574  alltargs(tp) {
575    if (tp->updated) {
576      void dowhenrule();
577      int whenruleno;
578      whenruleno = findrule(tp->pathname, R_WHEN, tp->sp->type, tp->sp->pathname);
579      if (whenruleno != -1)
580        dowhenrule(whenruleno, tp->pathname);
581    }
582  }
583
584    {
585        char * ptr = (char *)NULL;
586       
587        allsrcs(sp) {
[10717]588            free(ptr);
[5292]589            ptr = (char *) sp;
[10717]590            free(sp->pathname);
591            free(sp->name);
[5292]592        }
593        alltargs(tp) {
[10717]594            free(ptr);
[5292]595            ptr = (char *) tp;
[10717]596            free(tp->pathname);
[5292]597        }
[10717]598        free(ptr);
[5292]599    }
600   
601  poprules();
602  return 0;
603}
604
605char * destination_pathname(dstdir, sname, mapstring)
606     char *dstdir, *sname, *mapstring;
607{
608  static char buf[MAXPATHLEN];
609  register char *p,*bp,*sp;
610  register char *lastdot;
611  bp = buf;
612
613  if (verbosef>2) printf("destination_pathname(%s,%s,%s)\n",
614                         dstdir, sname, mapstring);
615
616  for (p = dstdir; *p != '\0'; p++) *bp++ = *p;
617
618  *bp++ = '/';
619
620  for (p = mapstring; *p != '\0'; p++) {
621    switch (*p) {
622    case '$':
623      lastdot = NULL;
624      for (sp = sname; *sp != '\0'; sp++)
625        if ((*bp++ = *sp) == '.')
626          lastdot = bp - 1;
627      p++;
628      switch(*p) {
629      default:
630        p--; continue;
631      case ':':
632        p++;
633        switch(*p) {
634        case '\0':
635          /***** maybe this should be an error */
636          p--; p--; continue;
637        case 'r':
638          if (lastdot)
639            bp = lastdot;
640          else
641            { ; /***** should be an error of some sort */ }
642          continue;
643        default:
644          /***** should be an error of some sort */
645          continue;
646        }
647      }
648      /*NOTREACHED*/
649    default:
650      *bp++ = *p;
651      continue;
652    }
653  }
654
655  *bp = '\0';
656 
657  if (verbosef>1) printf("destination_pathname returning %s\n",buf);
658
659  return buf;
660}
661
662
663void dowhenrule(ruleno, tname)
664     int ruleno;
665     char *tname;
666{
667    char *cp;
668    int pid;
669    char *shell, *arg1;
670    int pipefds[2];
671
672    if (rules[ruleno].type != R_WHEN)
673        panic("dowhenrule:  rule type is not R_WHEN");
674
675    switch(rules[ruleno].u.u_when.type) {
676    case WHEN_SH:
677        shell = "/bin/sh";
678        arg1  = "-s";
679        break;
680    case WHEN_CSH:
681        shell = "/bin/csh";
682        arg1  = "-fs";
683        break;
684    }
685   
686    if (pipe(pipefds) != 0)
687        epanic("dowhenrule:  pipe");
688
689    if (nflag == 0) {
690        pid = fork();
691   
692        if (pid == 0) {
693
694            cp = tname;
695            while (*cp != '\0') cp++;
696            while (*cp != '/') cp--;
697            *cp = '\0';
698            if (cp == tname)
699                chdir("/");
700            else
701                chdir(tname);
702            *cp = '/';
703
704            dup2(pipefds[0], 0);
705            execl(shell, shell, arg1, 0);
706            epanic("dowhenrule:  execl");
707        } else if (pid > 0) {
708            char **c;
709            FILE *f;
710
711            f = fdopen(pipefds[1],"w");
712            c = rules[ruleno].u.u_when.cmds;
713
714            while (*c) {
715                if (verbosef) printf("%c %s",
716                                     (rules[ruleno].u.u_when.type == WHEN_SH)
717                                     ? '$' : '%', *c);
718                fprintf(f,"%s\n", *(c++));
719            }
720            /* kludge killing the sh because I cannot figure out how to
721             * make it go away on end of file */
722            switch(rules[ruleno].u.u_when.type) {
723            case WHEN_SH:
724                fprintf(f,"kill $$\n");
725                break;
726            default:
727                break;
728            }
729            fclose(f);
730        } else if (pid < 0) {
731            epanic("dowhenrule: fork");
732        }
733    } else                              /* If noop */
734        {
735            char **c;
736            c = rules[ruleno].u.u_when.cmds;
737
738            while (*c) {
739                if (verbosef) printf("%c %s",
740                                     (rules[ruleno].u.u_when.type == WHEN_SH)? '$': '%',
741                                     *c);
742            }   
743        }
744}
745
Note: See TracBrowser for help on using the repository browser.