source: trunk/athena/etc/track/track.c @ 14093

Revision 14093, 18.9 KB checked in by danw, 25 years ago (diff)
autoconfiscate
RevLine 
[233]1/*
[14093]2 *      $Id: track.c,v 4.25 1999-12-16 01:58:11 danw Exp $
[233]3 */
4
5#ifndef lint
[14093]6static char *rcsid_header_h = "$Id: track.c,v 4.25 1999-12-16 01:58:11 danw Exp $";
[13492]7#endif
[233]8
[1471]9#include "bellcore-copyright.h"
[233]10#include "mit-copyright.h"
11
12#include "track.h"
13
14char admin[WORDLEN] = DEF_ADM;          /* track administrator */
[919]15char workdir[LINELEN];                  /* working directory under src/dest
16                                         * root where slists, statfiles, etc.
17                                         * can be found */
[233]18char binarydir[LINELEN] = DEF_BINDIR;   /* directory in working dir to
19                                         * find executables */
20char fromroot[LINELEN] = DEF_FROMROOT;  /* Root directory for source */
[908]21char toroot[LINELEN] = DEF_TOROOT;      /* Root directory for destination */
22
23char lockpath[LINELEN];                 /* starting lock filename */
[1090]24char logfilepath[LINELEN] = DEF_LOG;    /* default log file */
25FILE *logfile = NULL;                   /* the logfile */
[908]26char subfilename[LINELEN] = DEF_SUB;    /* default subscription file */
27char subfilepath[LINELEN] = "";         /* alternate subscription file */
28char statfilepath[LINELEN];             /* pathname to statfile */
29FILE *statfile;                         /* the statfile! */
[12496]30char **statfilebufs;                    /* array of lines for sort() */
[908]31int cur_line;                           /* index into statfilebufs      */
[913]32unsigned maxlines = 0;                  /* max # lines in statfile buf array.
[908]33                                         * write_statline maintains maxlines */
[913]34unsigned stackmax = STACKMAX;           /* max depth of pathname-stack vars */
[908]35
[233]36char prgname[LINELEN];
37
38extern int errno;               /* global error number location */
39char errmsg[LINELEN];
40
[908]41int writeflag = 0;      /* if set, translate subscription list -> statfile,
42                         * rather than pulling files */
[233]43int parseflag = 0;      /* if set, just parse the subscription list */
44int forceflag = 0;      /* if set, will over-ride lock files */
[908]45int verboseflag = 0;    /* if set, files listed on stdout as they're updated */
[1075]46int cksumflag = 0;      /* if set, compare file checksums when updating */
[233]47int nopullflag = 0;     /* if set, find out the differences,
[908]48                         *         but don't pull anything */
[233]49int quietflag = 0;      /* if set, don't print non-fatal error messages */
50int interactive = 1;    /* if set, don't send errors via mail, print them */
51int uflag = NO_CLOBBER; /* if set, copy a older file on top of a newer one */
52int debug = 0;          /* if set, print debugging information */
[1176]53int ignore_prots = 0;   /* if set, don't use or set uid/gid/mode-bits */
[233]54int incl_devs = 0;      /* if set, include devices in update */
55
[1005]56/* initialize the global entry-counters with bad values,
57 * so that printmsg() can detect them.
58 */
59Entry entries[ ENTRYMAX];       /* Subscription list entries */
60int entrycnt = -1;              /* Number of entries */
61int entnum = -1;                /* Current entry number */
[233]62
[13492]63void cleanup(), readstat(), clearlocks(), writestat(), walk_trees();
64void get_arg(), justshow(), setuperr(), build_path(), openstat();
65void closestat();
66
[233]67main(argc,argv)
68int argc;
69char **argv;
70{
[908]71        char    scratch[LINELEN];
72        int     i;
[14093]73        struct sigaction sa;
[7811]74
[233]75        strcpy(prgname,argv[0]);
[908]76        strcpy(errmsg,"");
[233]77
78        umask(022);     /* set default umask for daemons */
79
[14093]80        sa.sa_flags = 0;
81        sigemptyset(&sa.sa_mask);
82        sa.sa_handler = cleanup;
[7811]83
[14093]84        sigaction( SIGINT, &sa, NULL);
85        sigaction( SIGHUP, &sa, NULL);
86        sigaction( SIGPIPE, &sa, NULL);
87
[233]88        for(i=1;i<argc;i++) {
[908]89                if (argv[i][0] != '-') {
90                        strcpy( subfilepath, argv[i]);
91                        continue;
[233]92                }
[908]93                switch (argv[i][1]) {
94                /* -F dirname
95                 *    Specify source "root" directory.
96                 */
97                case 'F':
[1005]98                        get_arg(scratch,argv,&i);
99                        if (*scratch != '/') {
[8321]100                                getcwd( fromroot, sizeof(fromroot));
[1005]101                                strcat( strcat( fromroot, "/"), scratch);
102                        }
[1181]103                        else if (! scratch[1]) *fromroot = '\0';
[1005]104                        else strcpy( fromroot, scratch);
[908]105                        break;
[1176]106
107                /* -I
108                 *    Ignore protections (uid,gid,mode) when tracking,
109                 *    except when creating a file: then, use remote prots.
110                 */
111                case 'I':
112                        ignore_prots = 1;
113                        break;
114
[908]115                /* -S stackmax
116                 *    Specify deeper path stacks
117                 */
118                case 'S':
119                        get_arg(scratch,argv,&i);
[913]120                        sscanf( scratch, "%d", &stackmax);
[908]121                        break;
[1176]122
[908]123                /* -T dirname
124                 *    Specify destination "root" directory.
125                 */
126                case 'T':
[1005]127                        get_arg(scratch,argv,&i);
128                        if (*scratch != '/') {
[8321]129                                getcwd( toroot, sizeof(toroot));
[1005]130                                strcat( strcat( toroot, "/"), scratch);
131                        }
[1181]132                        else if (! scratch[1]) *toroot = '\0';
[1005]133                        else strcpy( toroot, scratch);
[908]134                        break;
[1176]135
136                /* -W dirname
137                 *    Specify the working directory for
138                 *    accessing the subscription-list and statfile.
139                 */
140                case 'W':
141                        get_arg(workdir,argv,&i);
142                        break;
[1075]143                /* -c
144                 *    compare checksums of regular files, when updating.
145                 *    the checksums are used to detect file-system
146                 *    corruption.
147                 */
148                case 'c':
149                        cksumflag = 1;
150                        break;
[1176]151                /* -d
152                 *    Include devices in an update.
[908]153                 */
154                case 'd':
[1176]155                        incl_devs = 1;
[908]156                        break;
157                /* -f
158                 *    Force updating regardless of locks.
159                 */
160                case 'f':
161                        forceflag = 1;
162                        break;
[1176]163
[908]164                /* -m {user}
165                 *    Send mail to root/user instead of
166                 * displaying messages on the terminal.
167                 */
168                case 'm':
169                        interactive = 0;
170                        get_arg(admin,argv,&i);
171                        break;
172                /* -n
173                 *    Produce a list of files that need updating,
174                 * but don't actually do anything about them.
175                 */
176                case 'n':
177                        nopullflag = 1;
178                        verboseflag = 1;
179                        fprintf( stderr, "-n: what we WOULD do:\n");
180                        break;
[1075]181                /* -p
182                 *    Parse only.  Display a detailed list of the fields in the
183                 * subscription file.
184                 */
185                case 'p':
186                        parseflag = 1;
187                        break;
[908]188                /* -q
189                 *    Be quiet about warning messages.
190                 */
191                case 'q':
192                        quietflag = 1;
193                        break;
194                /* -s {pathname}
195                 *   use specified file as statfile,
196                 * or use stdio if pathname is "-".
197                 */
198                case 's':
199                        get_arg( statfilepath, argv, &i);
200                        break;
201                /* -u
202                 *    Copy over files regardless of which is newer.
203                 */
204                case 'u':
205                        uflag = DO_CLOBBER;
206                        break;
207                /* -v
208                 *    Explain what is going on verbosely.
209                 */
210                case 'v':
211                        verboseflag = 1;
212                        break;
213                /* -w
214                 *    Create a statfile.
215                 */
216                case 'w':
217                        writeflag = 1;
218                        break;
219                /* -x
220                 *    Display debugging information.
221                 */
222                case 'x':
223                        debug = 1;
224                        break;
225                /*
226                 * Something isn't right if we got this far...
227                 */
228                default:
229                        fprintf(stderr,"track error: bad option %s\n",argv[i]);
230                        break;
231                }
[233]232        }
233
[908]234        /*
235         * Set up nullmail interface if not an interactive session.
236         */
237        if (!interactive)
238                setuperr();
[1005]239
240        /* check for existence of root directories:
241         * we shouldn't create them, as they are likely to be remote,
242         * so that the user may have forgotten to attach them.
243         */
244        if ( *fromroot && access( fromroot, 0)) {
245                sprintf(errmsg,"can't access source root-directory %s\n",
246                        fromroot);
247                do_panic();
248        }
249        if ( !writeflag && *toroot && access( toroot, 0)) {
250                sprintf(errmsg,"can't access target root-directory %s\n",
251                        toroot);
252                do_panic();
253        }
[1176]254        build_path( fromroot, workdir, DEF_SLISTDIR, subfilepath);
255        build_path( fromroot, workdir, DEF_STATDIR, statfilepath);
[233]256
[919]257        fprintf( stderr, "using %s as subscription-list\n", subfilepath);
258        fprintf( stderr, "using %s as statfile\n",         statfilepath);
259
[233]260        /*
261        **      redirect yacc/lex i/o
262        */
[919]263        parseinit( opensubfile( subfilepath));
[233]264        if (yyparse()) {
[1090]265                strcpy(errmsg,"parse aborted.\n");
[233]266                do_panic();
267        }
268        if (debug)
269                printf("parse worked\n");
270
[1105]271        sort_entries();
272
[233]273        if (parseflag) {  /* -p: Just show the fields */
274                justshow();
275                cleanup();
276        }
277
[908]278        setlock();
[233]279
[919]280        openstat( statfilepath, writeflag);
[233]281
[1005]282        if ( writeflag)         /* -w: Write the exporting statfile */
[908]283                writestat();
[1243]284        else {
285                /* update in two passes: links & their parent-dirs first,
286                 * which frees up file-system space when links replace files,
287                 * then everything else. re-update dirs in second pass,
288                 * to facilitate statfile-traversal.
289                 */
290                readstat( "ld");
291                rewind( statfile);
292                readstat( "fdbc");
293        }
[908]294        closestat();
295
[233]296        clearlocks();
[1005]297        exit( 0);
[908]298}                       /* end of main() */
[233]299
[908]300#define pathtail( p) p[1+*(int*)p[CNT]]
[233]301
[13492]302void
[1251]303readstat( types) char *types; {
[1090]304        struct currentness rem_currency, *cmp_currency;
[1075]305        char statline[ LINELEN], *remname;
[908]306        char **from, **to, **cmp;
[1075]307        char *tail = NULL;
[233]308
[1005]309        from = initpath( fromroot);
310        to   = initpath(   toroot);
311        cmp  = initpath(   toroot);
[233]312
[1075]313        /* prime the path-stacks for dec_entry() to
314         * pop the "old" entry-names off.
315         */
316        pushpath( from, ""); pushpath( to, ""); pushpath( cmp, "");
317
[908]318        init_next_match();
[233]319
[1005]320        while ( NULL != fgets( statline, sizeof statline, statfile)) {
[1251]321
322                /* XXX : needs data-hiding work, but will do:
323                 *       only update what main tells us to in this pass.
324                 */
[8915]325                if ( ! strchr( types, *statline)) continue;
[1251]326
[908]327                /* extract the currency data from the statline:
328                 */
[1075]329                remname = dec_statfile( statline, &rem_currency);
[233]330
[1005]331                /* find the subscription entry corresponding to the
332                 * current pathname.
333                 * if we reach an entry which is lexicographically greater than
334                 * the current pathname, read statfile for the next pathname.
335                 * both entries[] & statfile must be sorted by sortkey!
[908]336                 */
[1005]337                if ( 0 >= ( entnum = get_next_match( remname))) continue;
[233]338
[1090]339                /* do a breadth-first search of the tree of entries,
340                 * to find the entry corresponding to remname:
341                 * for example, if /usr & /usr/bin are both entries,
342                 * they appear in that order in the entries[] array.
343                 * if remname is /usr/bin/foo, we want gettail() to
344                 * use /usr/bin's exception-list, not /usr's exception-list.
345                 * thus, /usr/bin is the "last match" for /usr/bin/foo.
346                 */
[1005]347                entnum = last_match( remname, entnum);
[233]348
[1090]349                tail = remname;
350                switch ( gettail( &tail, TYPE( rem_currency.sbuf), entnum)) {
351                case NORMALCASE: break;
352                case DONT_TRACK: continue;
353                case FORCE_LINK: fake_link( fromroot, remname, &rem_currency);
354                                 break;
355                default:         sprintf(errmsg,"bad value from gettail\n");
356                                 do_panic();
357                }
[1005]358
[1075]359                /* loosely, tail == remname - fromfile, as
360                 * long as tail isn't in the exception-list.
361                 * the string remname begins with the string from[ PATH]:
362                 * for example: remname =            /usr/bin/foo.
363                 *          from[ PATH] =            /usr/bin.
364                 *          from[ ROOT] = /mountpoint/usr/bin.
365                 * in this example, we get tail == "foo".
[908]366                 */
367
[1075]368                cmp_currency = dec_entry( entnum, from, to, cmp, tail);
[908]369
[1075]370                pushpath( to,  tail);
[1005]371                pushpath( from, tail);
[908]372
[1075]373                if ( ! update_file( cmp_currency, to,
374                                   &rem_currency, from))
375                        /* REWRITE:
376                        do_cmds( entries[entnum].cmdbuf, to[ ROOT])
377                         */
378                        ;
379                /* remove tail from each path:
[908]380                 */
[1075]381                poppath( to);
[1005]382                poppath( from);
[233]383        }
[14093]384        /* make sure that the file-systems' superblocks are up-to-date.
[1176]385         */
386        sync();
387        sleep(2);
[233]388}
389
390/*
391 * Set lock for subscriptionlist file.
392 */
393
394setlock()
395{
[908]396        sprintf( lockpath,"%s/%s.started", DEF_LOCKDIR, subfilename);
[233]397
[908]398        if ( access( lockpath, 0));
399        else if ( too_old( lockpath, LOCK_TIME) || forceflag) clearlocks();
400        else {
401                sprintf( errmsg, "lock set on %s--quitting\n", lockpath);
402                do_gripe();
403                exit(0);
[233]404        }
[1181]405        if ( close( creat( lockpath,220))) {
[908]406                sprintf( errmsg, "can't create lockfile %s\n", lockpath);
[233]407                do_panic();
408        }
[908]409        return(0);
[233]410}
411
412/*
413 * Erase those locks...
414 */
415
[13492]416void
[233]417clearlocks()
418{
[908]419        if ( !*lockpath) return;
420        if ( unlink( lockpath)) {
[1243]421                fprintf( stderr, "can't remove lockfile %s", lockpath);
422                perror( "system error is: ");
[908]423        }
424        else if ( verboseflag)
425                fprintf( stderr, "cleared lock %s\n",lockpath);
[233]426}
427
[908]428/* the array from[] is a set of pointers into a single pathname.
429 * it allows us to pass a parsed pathname along in walk_trees()'
430 * recursive descent of a directory.
431 * the ROOT component is the entire absolute pathname,
432 * including the mount-point, for use in file-system calls.
433 * the NAME component is the portable pathname, without the mount-point,
434 * as the file is described in the statfile.
435 * the TAIL component is everything that's added during the recursive descent,
436 * for comparison with the exception-list. TAIL lacks both mount-point &
437 * the fromfile name.
438 */
439
[233]440/*
441 * Act like a librarian and write out the statfile.
442 */
443
[13492]444void
[233]445writestat()
446{
[913]447        char **from, **cmp, **dummy = (char **) NULL;
[1075]448        struct currentness *entry_currency;
[233]449
[1005]450        from = initpath( fromroot);
451        cmp  = initpath( fromroot);
[233]452
[1075]453        /* prime the path-stacks for dec_entry() to
454         * pop the "old" entry-names off.
455         */
456        pushpath( from, ""); pushpath( cmp, "");
457
[909]458        for( entnum = 1; entnum < entrycnt; entnum++) {
[233]459
[908]460                /* dec_entry pushes pathname-qualification
[1005]461                 * onto the paths 'from' & 'cmp',
462                 * and pops when appropriate.
[908]463                 */
[1075]464                entry_currency = dec_entry( entnum, from, dummy, cmp, NULL);
[233]465
[11137]466                if (entries[entnum].islink) {
467                        fake_link( "", from[ NAME], entry_currency);
468                        write_statline( from, entry_currency);
[11179]469                        continue;
[11137]470                }
471
[1075]472                /* write_statline returns fromfile's true type,
473                 * regardless of cmpfile's type:
[908]474                 */
[1075]475                if      ( S_IFDIR != write_statline( from, entry_currency));
476                else if ( S_IFDIR != TYPE( entry_currency->sbuf))
[233]477
[1075]478                        walk_trees( from, dummy, entry_currency);
479                else    walk_trees( from, cmp,   entry_currency);
[233]480
[908]481                /* WARNING: walk_trees alters ALL of its arguments */
[1176]482                /* sort the statfile, and write it out
483                 * to the correct directory:
484                 */
[233]485        }
[1251]486        sort_stat();
[233]487}
488
[908]489/* if the current entry's fromfile is a directory, but its cmpfile isn't,
490 * put the same cmpstat in all of fromfile's contents' statlines.
491 * if cmpfile is a directory too, its subtree must parallel fromfile's subtree,
492 * and each statline reflects the one-to-one (not onto) mapping from
493 * fromfile's subtree to cmpfile's subtree:
494 * we take fromfile's subnode's pathname ( not including the prefix fromroot),
495 * and we take the stat from cmpfile's corresponding subnode.
[233]496 */
[13492]497void
[1075]498walk_trees( f, c, currency)
[908]499char *f[], *c[];
[1075]500struct currentness *currency;
[233]501{
502        DIR *dirp;
[5133]503        struct dirent *dp;
[1090]504        char *tail;
[233]505
[908]506        dirp = opendir( f[ ROOT]);
[233]507        if (!dirp) {
[908]508                sprintf(errmsg,"can't open directory %s\n", f[ ROOT]);
[233]509                do_gripe();
510                return;
511        }
512
[908]513        while( dp = readdir( dirp)) {
[12340]514                if (strcmp(dp->d_name, ".") == 0)
515                  continue;
516                if (strcmp(dp->d_name, "..") == 0)
517                  continue;
518
[908]519                if (! dp->d_ino) continue;    /* empty dir-block */
520
521                pushpath( f, dp->d_name);
522                pushpath( c, dp->d_name);
523
[1090]524                tail = f[ NAME];
525                switch ( gettail( &tail, 0, entnum)) {
526                case NORMALCASE: break;
527                case FORCE_LINK: fake_link( "", f[ NAME], currency);
528                                 write_statline( f, currency);
529                                 /* fall through to poppath() calls */
530                case DONT_TRACK: poppath( f);
531                                 poppath( c);
532                                 continue;
533                default:         sprintf(errmsg,"bad value from gettail\n");
534                                 do_panic();
535                }
536                /* normal case: tail isn't an exception or a forced link.
537                 */
538                if ( c && get_currentness( c, currency)) {
[11108]539                        sprintf(errmsg,"can't lstat comparison-file %s.\n",
540                                c[ ROOT]);
[1090]541                        do_panic();
542                }
[908]543                /* write_statline returns fromfile's type:
544                 */
[1075]545                else if ( S_IFDIR == write_statline( f, currency))
546                        walk_trees( f, c, currency);
[908]547
548                poppath( f);
549                poppath( c);
[233]550        }
551        closedir(dirp);
552}
553
554/*
[908]555 * Get a command line argument
[233]556 */
557
[13492]558void
[908]559get_arg(to,list,ptr)
560char *to,**list;
561int *ptr;
[233]562{
[908]563        int offset = 2;
564
565        if (strlen(list[*ptr]) == 2) {
566                (*ptr)++;
567                offset = 0;
[233]568        }
[908]569        strcpy(to,list[*ptr]+offset);
[233]570}
571
572/*
[908]573 * Log a message to the logfile.
[1090]574   UNUSED
[233]575
[908]576log(ptr)
[233]577char *ptr;
578{
[908]579        extern long time();
580        extern char *ctime();
581        static FILE *logfile = NULL;
582        char namebuf[LINELEN];
583        char timestring[LINELEN];
584        long timebuf;
[233]585
[908]586        if ( NULL == logfile) {
[919]587                sprintf( namebuf,"%s/%s",workdir,DEF_LOG);
[908]588                if( access( namebuf, 0))
589                        return;
590                if (NULL == (logfile = fopen( namebuf,"a"))) {
591                        sprintf(errmsg,"can't open log file %s",namebuf);
592                        do_panic();
[233]593                }
594        }
[908]595        timebuf = time(0);
596        strcpy(timestring,ctime(&timebuf));
597        timestring[ strlen(timestring)-1] = '\0';
598        fprintf(logfile,"%s %s %s\n",timestring,subfilename,ptr);
[233]599}
[908]600 */
[233]601
[908]602#undef ROOT
603
[233]604/*
605 * Execute shell commands
606 */
607
[13492]608void
[233]609do_cmds(cmds,local)
610char *cmds,*local;
611{
612        char *ptr,*nptr;
613        FILE *shell;
614
[908]615        if ( ! *cmds) return;
[233]616        ptr = cmds;
617
618        shell = popen(DEF_SHELL,"w");
619        if (!shell) {
620                sprintf(errmsg,"can't open shell %s\n",DEF_SHELL);
621                do_gripe();
622                return;
623        }
624
625        fprintf(shell,"chdir %s\n",toroot);
[908]626        fprintf(shell,"%sFILE=%s\n",DEF_SETCMD,local);
[233]627        fprintf(shell,"%sROOT=%s\n",DEF_SETCMD,toroot);
628
629        for (;;) {
[8915]630                nptr = strchr(ptr,'\n');
[233]631                if (nptr)
632                        *nptr = '\0';
633                fprintf(shell,"%s\n",ptr);
634                if (!nptr) {
635                        pclose(shell);
636                        return;
637                }
638                ptr = nptr+1;
639        }
640}
641/*
[908]642 * Show parsing.
[233]643 */
644
[13492]645void
[908]646justshow()
[233]647{
[1090]648        int i,j, size;
649        Entry *e;
650        List_element *p;
[233]651
[1090]652        fprintf( stderr, "subscription-list as parsed:\n\n");
653
654        for (i = 0; i <= entrycnt; i++) {
655                e = &entries[ i];
656                if ( ! e->fromfile) break;
[908]657                fprintf(stderr,
[11137]658                        "entry %d:\n\tislink-- %d\tfromfile-- %s\n",
[908]659                        i,
[11137]660                        e->islink,
[1090]661                        e->fromfile);
[908]662                fprintf(stderr,
[1090]663                        "\tcmpfile-- %s\n\ttofile-- %s\n\tpatterns--\n",
664                        e->cmpfile,
665                        e->tofile);
666                for( p = e->patterns; p ; p = NEXT( p))
[1176]667                    fprintf(stderr,"\t\t%s%s\n",
668                            FLAG( p) == FORCE_LINK ? "-> " : "",
669                            TEXT( p));
[1090]670                fprintf( stderr, "\texceptions--\n");
671                switch( SIGN( e->names.shift)) {
672                case -1:
673                    for( p = ( List_element *) e->names.table; p ; p = NEXT( p))
674                        fprintf(stderr,"\t\t%s%s\n",
675                                FLAG( p) == FORCE_LINK ? "-> " : "",
676                                TEXT( p));
677                    fprintf(stderr,
678                        "track didn't fully parse the exception-list.\n");
679                    fprintf(stderr,
680                        "the most-recently parsed exception was:\n%s%s\n",
681                        FLAG( e->names.table) == FORCE_LINK ? "-> " : "",
682                        TEXT( e->names.table));
683                    continue;
684                case 0: break;
685                case 1:
686                    size = (unsigned) 0x80000000 >> e->names.shift - 1;
687                    for( j = 0; j < size; j++)
688                    {
689                        if ( ! e->names.table[j]) continue;
690                        fprintf( stderr,"\t\t");
691                        for ( p = e->names.table[j]; p; p = NEXT( p))
692                            fprintf(stderr,"%s%s, ",
693                                    FLAG( p) == FORCE_LINK ? "-> " : "",
694                                    TEXT( p));
695                        fprintf( stderr,"\n");
696                    }
697                    break;
698                }
699                fprintf(stderr,"\tcommand-- %s\n",e->cmdbuf);
[233]700        }
701}
702
703/*
[908]704 *      redirect standard error output to mail to the administrator
705 *      use nullmail so that null messages won't get sent.
[233]706 */
707
[908]708/* REWORK */
[233]709
[13492]710void
[908]711setuperr()
[233]712{
[908]713        char msg[LINELEN];
714        FILE *tmp;
[233]715
[908]716        sprintf(msg,"%s/nullmail %s",binarydir,admin);
717        /*
718        **      start a process that will send mail to the adminstrator
719        */
720        if ((tmp = popen(msg,"w")) == NULL) {
721/*              sprintf( msg, "echo HELP track --%s %s", gargv[0],
722                        "can't execute nullmail cmd  > /dev/console");
723                system(msg); */
724                exit(1);
[233]725        }
[908]726        /*
727        **      now connect stderr to the pipe
728        */
729        if (dup2(fileno(tmp),2) ==  -1) {
730/*              sprintf( msg, "echo HELP track --%s %s", gargv[0],
731                        "can't dup stderr  > /dev/console");
732                system(msg); */
733                exit(1);
734        }
[233]735}
736
[13492]737void
[1176]738build_path( f, w, d, p) char *f, *w, *d, *p; {
739        static char buf[ LINELEN];
740
741        if ( ! strcmp( p, "-")) return;
742        /*
743         * Get the proper working directory,
744         * where the subscription-list & statfile are.
745         */
746        if ( *w) f = "";  /* don't add root-qualification to user's workdir */
747        else if ( *p) f = "."; /* don't use default workdir with user's filen */
748        else w = DEF_WORKDIR; /* default workdir, default filename */
749
750        if ( *p) d = "";
751        else strcpy( p, subfilename);
752
753        sprintf( buf, "%s%s%s%s/%s", f, w, *d ? "/" : "", d, p);
754        strcpy( p, buf);
755}
756
[908]757FILE *
[919]758opensubfile( path) char *path; {
[908]759        FILE *subfile;
[919]760        if ( ! ( subfile = fopen( path, "r"))) {
761                sprintf( errmsg, "Can't open subscriptionlist %s\n", path);
[908]762                do_panic();
763        }
764        return( subfile);
[233]765}
766
[13492]767void
[919]768openstat( path, write) char *path; int write;
[233]769{
[908]770        char *mode = write? "w"   : "r";
771        FILE *std =  write? stdout : stdin;
[233]772
[919]773        if ( ! strcmp( path, "-"))
[908]774                statfile = std;
[919]775        else if ( ! ( statfile = fopen( path, mode))) {
776                sprintf( errmsg, "can't open statfile %s\n", path);
[908]777                do_panic();
778        }
779}
[233]780
[13492]781void
[908]782closestat() {
783        if ( EOF == fclose( statfile)) {
784                sprintf( errmsg, "can't close %s\n", statfilepath);
[233]785                do_panic();
786        }
787}
788
[13492]789void
[908]790cleanup()
[233]791{
[908]792        clearlocks();
793        exit(0);
[233]794}
Note: See TracBrowser for help on using the repository browser.