17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate * with the License.
87c478bd9Sstevel@tonic-gate *
97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate * and limitations under the License.
137c478bd9Sstevel@tonic-gate *
147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate *
207c478bd9Sstevel@tonic-gate * CDDL HEADER END
217c478bd9Sstevel@tonic-gate */
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate * Copyright (c) 1995 Sun Microsystems, Inc. All Rights Reserved
247c478bd9Sstevel@tonic-gate *
257c478bd9Sstevel@tonic-gate * module:
267c478bd9Sstevel@tonic-gate * rules.c
277c478bd9Sstevel@tonic-gate *
287c478bd9Sstevel@tonic-gate * purpose:
297c478bd9Sstevel@tonic-gate * to read and write the rules file and manage rules lists
307c478bd9Sstevel@tonic-gate *
317c478bd9Sstevel@tonic-gate * contents:
327c478bd9Sstevel@tonic-gate * reading rules file
337c478bd9Sstevel@tonic-gate * read_rules
347c478bd9Sstevel@tonic-gate * (static) read_command
357c478bd9Sstevel@tonic-gate * writing rules file
367c478bd9Sstevel@tonic-gate * write_rules
377c478bd9Sstevel@tonic-gate * (static) rw_header, rw_base
387c478bd9Sstevel@tonic-gate * adding rules
397c478bd9Sstevel@tonic-gate * add_ignore, add_include
407c478bd9Sstevel@tonic-gate * (static) add_rule
417c478bd9Sstevel@tonic-gate * adding/checking restrictions
427c478bd9Sstevel@tonic-gate * add_restr, check_restr
437c478bd9Sstevel@tonic-gate */
44*63360950Smp204432 #pragma ident "%Z%%M% %I% %E% SMI"
457c478bd9Sstevel@tonic-gate
467c478bd9Sstevel@tonic-gate #include <stdio.h>
477c478bd9Sstevel@tonic-gate #include <stdlib.h>
487c478bd9Sstevel@tonic-gate #include <string.h>
497c478bd9Sstevel@tonic-gate #include <time.h>
507c478bd9Sstevel@tonic-gate #include <ctype.h>
517c478bd9Sstevel@tonic-gate
527c478bd9Sstevel@tonic-gate #include "filesync.h"
537c478bd9Sstevel@tonic-gate #include "database.h"
547c478bd9Sstevel@tonic-gate #include "messages.h"
557c478bd9Sstevel@tonic-gate #include "debug.h"
567c478bd9Sstevel@tonic-gate
577c478bd9Sstevel@tonic-gate /*
587c478bd9Sstevel@tonic-gate * routines:
597c478bd9Sstevel@tonic-gate */
607c478bd9Sstevel@tonic-gate static errmask_t rw_base(FILE *file, struct base *bp);
617c478bd9Sstevel@tonic-gate static errmask_t rw_header(FILE *file);
627c478bd9Sstevel@tonic-gate static errmask_t add_rule(struct base *, int, const char *);
637c478bd9Sstevel@tonic-gate static char *read_cmd(char *);
647c478bd9Sstevel@tonic-gate
657c478bd9Sstevel@tonic-gate /*
667c478bd9Sstevel@tonic-gate * globals
677c478bd9Sstevel@tonic-gate */
687c478bd9Sstevel@tonic-gate static int rules_added;
697c478bd9Sstevel@tonic-gate static int restr_added;
707c478bd9Sstevel@tonic-gate
717c478bd9Sstevel@tonic-gate /*
727c478bd9Sstevel@tonic-gate * locals
737c478bd9Sstevel@tonic-gate */
747c478bd9Sstevel@tonic-gate #define RULE_MAJOR 1 /* rules file format major rev */
757c478bd9Sstevel@tonic-gate #define RULE_MINOR 1 /* rules file format minor rev */
767c478bd9Sstevel@tonic-gate #define RULE_TAG "PACKINGRULES" /* magic string for rules files */
777c478bd9Sstevel@tonic-gate
787c478bd9Sstevel@tonic-gate /*
797c478bd9Sstevel@tonic-gate * routine:
807c478bd9Sstevel@tonic-gate * read_rules
817c478bd9Sstevel@tonic-gate *
827c478bd9Sstevel@tonic-gate * purpose:
837c478bd9Sstevel@tonic-gate * to read in the rules file
847c478bd9Sstevel@tonic-gate *
857c478bd9Sstevel@tonic-gate * parameters:
867c478bd9Sstevel@tonic-gate * name of rules file
877c478bd9Sstevel@tonic-gate *
887c478bd9Sstevel@tonic-gate * returns:
897c478bd9Sstevel@tonic-gate * error mask
907c478bd9Sstevel@tonic-gate *
917c478bd9Sstevel@tonic-gate * notes:
927c478bd9Sstevel@tonic-gate * later when I implement a proper (comment preserving) update
937c478bd9Sstevel@tonic-gate * function I'm going to wish I had figured out how to build the
947c478bd9Sstevel@tonic-gate * input functions for this function in a way that would make
957c478bd9Sstevel@tonic-gate * the more usable for that too.
967c478bd9Sstevel@tonic-gate */
977c478bd9Sstevel@tonic-gate errmask_t
read_rules(char * name)987c478bd9Sstevel@tonic-gate read_rules(char *name)
997c478bd9Sstevel@tonic-gate { FILE *file;
1007c478bd9Sstevel@tonic-gate errmask_t errs = 0;
1017c478bd9Sstevel@tonic-gate int flags;
1027c478bd9Sstevel@tonic-gate int major, minor;
1037c478bd9Sstevel@tonic-gate char *s, *s1, *s2;
1047c478bd9Sstevel@tonic-gate struct base *bp;
1057c478bd9Sstevel@tonic-gate char *errstr = "???";
1067c478bd9Sstevel@tonic-gate
1077c478bd9Sstevel@tonic-gate file = fopen(name, "r");
1087c478bd9Sstevel@tonic-gate if (file == NULL) {
1097c478bd9Sstevel@tonic-gate fprintf(stderr, gettext(ERR_open), gettext(TXT_rules),
1107c478bd9Sstevel@tonic-gate name);
1117c478bd9Sstevel@tonic-gate return (ERR_FILES);
1127c478bd9Sstevel@tonic-gate }
1137c478bd9Sstevel@tonic-gate
1147c478bd9Sstevel@tonic-gate lex_linenum = 0;
1157c478bd9Sstevel@tonic-gate
1167c478bd9Sstevel@tonic-gate if (opt_debug & DBG_FILES)
1177c478bd9Sstevel@tonic-gate fprintf(stderr, "FILE: READ RULES %s\n", name);
1187c478bd9Sstevel@tonic-gate
1197c478bd9Sstevel@tonic-gate bp = &omnibase; /* default base before any others */
1207c478bd9Sstevel@tonic-gate
1217c478bd9Sstevel@tonic-gate while (!feof(file)) {
1227c478bd9Sstevel@tonic-gate /* find the first token on the line */
1237c478bd9Sstevel@tonic-gate s = lex(file);
1247c478bd9Sstevel@tonic-gate
1257c478bd9Sstevel@tonic-gate /* skip blank lines and comments */
1267c478bd9Sstevel@tonic-gate if (s == 0 || *s == 0 || *s == '#' || *s == '*')
1277c478bd9Sstevel@tonic-gate continue;
1287c478bd9Sstevel@tonic-gate
1297c478bd9Sstevel@tonic-gate /* see if the first token is a known keyword */
1307c478bd9Sstevel@tonic-gate if (strcmp(s, "BASE") == 0) {
1317c478bd9Sstevel@tonic-gate
1327c478bd9Sstevel@tonic-gate /* get the source & destination tokens */
1337c478bd9Sstevel@tonic-gate errstr = gettext(TXT_srcdst);
1347c478bd9Sstevel@tonic-gate s1 = lex(0);
1357c478bd9Sstevel@tonic-gate if (s1 == 0)
1367c478bd9Sstevel@tonic-gate goto bad;
1377c478bd9Sstevel@tonic-gate s1 = strdup(s1);
1387c478bd9Sstevel@tonic-gate
1397c478bd9Sstevel@tonic-gate s2 = lex(0);
1407c478bd9Sstevel@tonic-gate if (s2 == 0)
1417c478bd9Sstevel@tonic-gate goto bad;
1427c478bd9Sstevel@tonic-gate s2 = strdup(s2);
1437c478bd9Sstevel@tonic-gate
1447c478bd9Sstevel@tonic-gate /* creat the new base pair */
1457c478bd9Sstevel@tonic-gate bp = add_base(s1, s2);
1467c478bd9Sstevel@tonic-gate bp->b_flags |= F_LISTED;
1477c478bd9Sstevel@tonic-gate
1487c478bd9Sstevel@tonic-gate free(s1);
1497c478bd9Sstevel@tonic-gate free(s2);
1507c478bd9Sstevel@tonic-gate continue;
1517c478bd9Sstevel@tonic-gate }
1527c478bd9Sstevel@tonic-gate
1537c478bd9Sstevel@tonic-gate if (strcmp(s, "LIST") == 0) {
1547c478bd9Sstevel@tonic-gate
1557c478bd9Sstevel@tonic-gate /* make sure we are associated with a real base */
1567c478bd9Sstevel@tonic-gate if (bp == &omnibase) {
1577c478bd9Sstevel@tonic-gate errstr = gettext(TXT_nobase);
1587c478bd9Sstevel@tonic-gate goto bad;
1597c478bd9Sstevel@tonic-gate }
1607c478bd9Sstevel@tonic-gate
1617c478bd9Sstevel@tonic-gate /* skip to the next token */
1627c478bd9Sstevel@tonic-gate s = lex(0);
1637c478bd9Sstevel@tonic-gate errstr = gettext(TXT_noargs);
1647c478bd9Sstevel@tonic-gate if (s == 0)
1657c478bd9Sstevel@tonic-gate goto bad;
1667c478bd9Sstevel@tonic-gate
1677c478bd9Sstevel@tonic-gate /* see if it is a program or a name */
1687c478bd9Sstevel@tonic-gate if (*s == '!') {
1697c478bd9Sstevel@tonic-gate errs |= add_rule(bp, R_PROGRAM,
1707c478bd9Sstevel@tonic-gate read_cmd(&s[1]));
1717c478bd9Sstevel@tonic-gate } else {
1727c478bd9Sstevel@tonic-gate do {
1737c478bd9Sstevel@tonic-gate flags = wildcards(s) ? R_WILD : 0;
1747c478bd9Sstevel@tonic-gate errs |= add_rule(bp, flags, s);
1757c478bd9Sstevel@tonic-gate s = lex(0);
1767c478bd9Sstevel@tonic-gate } while (s != 0);
1777c478bd9Sstevel@tonic-gate }
1787c478bd9Sstevel@tonic-gate continue;
1797c478bd9Sstevel@tonic-gate }
1807c478bd9Sstevel@tonic-gate
1817c478bd9Sstevel@tonic-gate if (strcmp(s, "IGNORE") == 0) {
1827c478bd9Sstevel@tonic-gate
1837c478bd9Sstevel@tonic-gate /* skip to the next token */
1847c478bd9Sstevel@tonic-gate s = lex(0);
1857c478bd9Sstevel@tonic-gate errstr = gettext(TXT_noargs);
1867c478bd9Sstevel@tonic-gate if (s == 0)
1877c478bd9Sstevel@tonic-gate goto bad;
1887c478bd9Sstevel@tonic-gate
1897c478bd9Sstevel@tonic-gate flags = R_IGNORE;
1907c478bd9Sstevel@tonic-gate
1917c478bd9Sstevel@tonic-gate /* see if it is a program or a name */
1927c478bd9Sstevel@tonic-gate if (*s == '!') {
1937c478bd9Sstevel@tonic-gate errs |= add_rule(bp, R_PROGRAM|flags,
1947c478bd9Sstevel@tonic-gate read_cmd(&s[1]));
1957c478bd9Sstevel@tonic-gate } else {
1967c478bd9Sstevel@tonic-gate do {
1977c478bd9Sstevel@tonic-gate if (wildcards(s))
1987c478bd9Sstevel@tonic-gate flags |= R_WILD;
1997c478bd9Sstevel@tonic-gate errs |= add_rule(bp, flags, s);
2007c478bd9Sstevel@tonic-gate s = lex(0);
2017c478bd9Sstevel@tonic-gate } while (s != 0);
2027c478bd9Sstevel@tonic-gate }
2037c478bd9Sstevel@tonic-gate continue;
2047c478bd9Sstevel@tonic-gate }
2057c478bd9Sstevel@tonic-gate
2067c478bd9Sstevel@tonic-gate if (strcmp(s, "VERSION") == 0 || strcmp(s, RULE_TAG) == 0) {
2077c478bd9Sstevel@tonic-gate s = lex(0);
2087c478bd9Sstevel@tonic-gate errstr = gettext(TXT_noargs);
2097c478bd9Sstevel@tonic-gate if (s == 0)
2107c478bd9Sstevel@tonic-gate goto bad;
2117c478bd9Sstevel@tonic-gate
2127c478bd9Sstevel@tonic-gate major = strtol(s, &s1, 10);
2137c478bd9Sstevel@tonic-gate errstr = gettext(TXT_badver);
2147c478bd9Sstevel@tonic-gate if (*s1 != '.')
2157c478bd9Sstevel@tonic-gate goto bad;
2167c478bd9Sstevel@tonic-gate minor = strtol(&s1[1], 0, 10);
2177c478bd9Sstevel@tonic-gate
2187c478bd9Sstevel@tonic-gate if (major != RULE_MAJOR || minor > RULE_MINOR) {
2197c478bd9Sstevel@tonic-gate fprintf(stderr, gettext(ERR_badver),
2207c478bd9Sstevel@tonic-gate major, minor, gettext(TXT_rules), name);
2217c478bd9Sstevel@tonic-gate errs |= ERR_FILES;
2227c478bd9Sstevel@tonic-gate }
2237c478bd9Sstevel@tonic-gate continue;
2247c478bd9Sstevel@tonic-gate }
2257c478bd9Sstevel@tonic-gate
2267c478bd9Sstevel@tonic-gate bad: /* log the error and continue processing to find others */
2277c478bd9Sstevel@tonic-gate fprintf(stderr, gettext(ERR_badinput),
2287c478bd9Sstevel@tonic-gate lex_linenum, errstr, name);
2297c478bd9Sstevel@tonic-gate errs |= ERR_FILES;
2307c478bd9Sstevel@tonic-gate }
2317c478bd9Sstevel@tonic-gate
2327c478bd9Sstevel@tonic-gate
2337c478bd9Sstevel@tonic-gate (void) fclose(file);
2347c478bd9Sstevel@tonic-gate return (errs);
2357c478bd9Sstevel@tonic-gate }
2367c478bd9Sstevel@tonic-gate
2377c478bd9Sstevel@tonic-gate /*
2387c478bd9Sstevel@tonic-gate * routine:
2397c478bd9Sstevel@tonic-gate * read_cmd
2407c478bd9Sstevel@tonic-gate *
2417c478bd9Sstevel@tonic-gate * purpose:
2427c478bd9Sstevel@tonic-gate * to lex a runnable command (! lines) into a buffer
2437c478bd9Sstevel@tonic-gate *
2447c478bd9Sstevel@tonic-gate * parameters:
2457c478bd9Sstevel@tonic-gate * first token
2467c478bd9Sstevel@tonic-gate *
2477c478bd9Sstevel@tonic-gate * returns:
2487c478bd9Sstevel@tonic-gate * pointer to a command line in a static buffer
2497c478bd9Sstevel@tonic-gate * (it is assumed the caller will copy it promptly)
2507c478bd9Sstevel@tonic-gate *
2517c478bd9Sstevel@tonic-gate * notes:
2527c478bd9Sstevel@tonic-gate * this is necessary because lex has already choped off
2537c478bd9Sstevel@tonic-gate * the first token for us
2547c478bd9Sstevel@tonic-gate */
read_cmd(char * s)2557c478bd9Sstevel@tonic-gate static char *read_cmd(char * s)
2567c478bd9Sstevel@tonic-gate {
2577c478bd9Sstevel@tonic-gate static char cmdbuf[ MAX_LINE ];
2587c478bd9Sstevel@tonic-gate
2597c478bd9Sstevel@tonic-gate cmdbuf[0] = 0;
2607c478bd9Sstevel@tonic-gate
2617c478bd9Sstevel@tonic-gate do {
2627c478bd9Sstevel@tonic-gate if (*s) {
2637c478bd9Sstevel@tonic-gate strcat(cmdbuf, s);
2647c478bd9Sstevel@tonic-gate strcat(cmdbuf, " ");
2657c478bd9Sstevel@tonic-gate }
2667c478bd9Sstevel@tonic-gate } while ((s = lex(0)) != 0);
2677c478bd9Sstevel@tonic-gate
2687c478bd9Sstevel@tonic-gate return (cmdbuf);
2697c478bd9Sstevel@tonic-gate }
2707c478bd9Sstevel@tonic-gate
2717c478bd9Sstevel@tonic-gate /*
2727c478bd9Sstevel@tonic-gate * routine:
2737c478bd9Sstevel@tonic-gate * write_rules
2747c478bd9Sstevel@tonic-gate *
2757c478bd9Sstevel@tonic-gate * purpose:
2767c478bd9Sstevel@tonic-gate * to rewrite the rules file, appending the new rules
2777c478bd9Sstevel@tonic-gate *
2787c478bd9Sstevel@tonic-gate * parameters:
2797c478bd9Sstevel@tonic-gate * name of output file
2807c478bd9Sstevel@tonic-gate *
2817c478bd9Sstevel@tonic-gate * returns:
2827c478bd9Sstevel@tonic-gate * error mask
2837c478bd9Sstevel@tonic-gate *
2847c478bd9Sstevel@tonic-gate */
2857c478bd9Sstevel@tonic-gate errmask_t
write_rules(char * name)2867c478bd9Sstevel@tonic-gate write_rules(char *name)
2877c478bd9Sstevel@tonic-gate { FILE *newfile;
2887c478bd9Sstevel@tonic-gate errmask_t errs = 0;
2897c478bd9Sstevel@tonic-gate struct base *bp;
2907c478bd9Sstevel@tonic-gate char tmpname[ MAX_PATH ];
2917c478bd9Sstevel@tonic-gate
2927c478bd9Sstevel@tonic-gate /* if no-touch is specified, we don't update files */
2937c478bd9Sstevel@tonic-gate if (opt_notouch || rules_added == 0)
2947c478bd9Sstevel@tonic-gate return (0);
2957c478bd9Sstevel@tonic-gate
2967c478bd9Sstevel@tonic-gate /* create a temporary output file */
2977c478bd9Sstevel@tonic-gate sprintf(tmpname, "%s-TMP", name);
2987c478bd9Sstevel@tonic-gate
2997c478bd9Sstevel@tonic-gate /* create our output file */
3007c478bd9Sstevel@tonic-gate newfile = fopen(tmpname, "w+");
3017c478bd9Sstevel@tonic-gate if (newfile == NULL) {
3027c478bd9Sstevel@tonic-gate fprintf(stderr, gettext(ERR_creat), gettext(TXT_rules),
3037c478bd9Sstevel@tonic-gate name);
3047c478bd9Sstevel@tonic-gate return (ERR_FILES);
3057c478bd9Sstevel@tonic-gate }
3067c478bd9Sstevel@tonic-gate
3077c478bd9Sstevel@tonic-gate if (opt_debug & DBG_FILES)
3087c478bd9Sstevel@tonic-gate fprintf(stderr, "FILE: UPDATE RULES %s\n", name);
3097c478bd9Sstevel@tonic-gate
3107c478bd9Sstevel@tonic-gate errs |= rw_header(newfile);
3117c478bd9Sstevel@tonic-gate errs |= rw_base(newfile, &omnibase);
3127c478bd9Sstevel@tonic-gate for (bp = bases; bp; bp = bp->b_next)
3137c478bd9Sstevel@tonic-gate errs |= rw_base(newfile, bp);
3147c478bd9Sstevel@tonic-gate
3157c478bd9Sstevel@tonic-gate if (ferror(newfile)) {
3167c478bd9Sstevel@tonic-gate fprintf(stderr, gettext(ERR_write), gettext(TXT_rules),
3177c478bd9Sstevel@tonic-gate tmpname);
3187c478bd9Sstevel@tonic-gate errs |= ERR_FILES;
3197c478bd9Sstevel@tonic-gate }
3207c478bd9Sstevel@tonic-gate
3217c478bd9Sstevel@tonic-gate if (fclose(newfile)) {
3227c478bd9Sstevel@tonic-gate fprintf(stderr, gettext(ERR_fclose), gettext(TXT_rules),
3237c478bd9Sstevel@tonic-gate tmpname);
3247c478bd9Sstevel@tonic-gate errs |= ERR_FILES;
3257c478bd9Sstevel@tonic-gate }
3267c478bd9Sstevel@tonic-gate
3277c478bd9Sstevel@tonic-gate /* now switch the new file for the old one */
3287c478bd9Sstevel@tonic-gate if (errs == 0)
3297c478bd9Sstevel@tonic-gate if (rename(tmpname, name) != 0) {
3307c478bd9Sstevel@tonic-gate fprintf(stderr, gettext(ERR_rename),
3317c478bd9Sstevel@tonic-gate gettext(TXT_rules), tmpname, name);
3327c478bd9Sstevel@tonic-gate errs |= ERR_FILES;
3337c478bd9Sstevel@tonic-gate }
3347c478bd9Sstevel@tonic-gate
3357c478bd9Sstevel@tonic-gate return (errs);
3367c478bd9Sstevel@tonic-gate }
3377c478bd9Sstevel@tonic-gate
3387c478bd9Sstevel@tonic-gate /*
3397c478bd9Sstevel@tonic-gate * routine:
3407c478bd9Sstevel@tonic-gate * rw_header
3417c478bd9Sstevel@tonic-gate *
3427c478bd9Sstevel@tonic-gate * purpose:
3437c478bd9Sstevel@tonic-gate * to write out a rules header
3447c478bd9Sstevel@tonic-gate *
3457c478bd9Sstevel@tonic-gate * parameters:
3467c478bd9Sstevel@tonic-gate * FILE* for the output file
3477c478bd9Sstevel@tonic-gate *
3487c478bd9Sstevel@tonic-gate * returns:
3497c478bd9Sstevel@tonic-gate * error mask
3507c478bd9Sstevel@tonic-gate *
3517c478bd9Sstevel@tonic-gate * notes:
3527c478bd9Sstevel@tonic-gate */
rw_header(FILE * file)3537c478bd9Sstevel@tonic-gate static errmask_t rw_header(FILE *file)
3547c478bd9Sstevel@tonic-gate {
3557c478bd9Sstevel@tonic-gate time_t now;
3567c478bd9Sstevel@tonic-gate struct tm *local;
3577c478bd9Sstevel@tonic-gate
3587c478bd9Sstevel@tonic-gate /* figure out what time it is */
3597c478bd9Sstevel@tonic-gate (void) time(&now);
3607c478bd9Sstevel@tonic-gate local = localtime(&now);
3617c478bd9Sstevel@tonic-gate
3627c478bd9Sstevel@tonic-gate fprintf(file, "%s %d.%d\n", RULE_TAG, RULE_MAJOR, RULE_MINOR);
3637c478bd9Sstevel@tonic-gate fprintf(file, "#\n");
3647c478bd9Sstevel@tonic-gate fprintf(file, "# filesync rules, last written by %s, %s",
3657c478bd9Sstevel@tonic-gate cuserid((char *) 0), asctime(local));
3667c478bd9Sstevel@tonic-gate fprintf(file, "#\n");
3677c478bd9Sstevel@tonic-gate
3687c478bd9Sstevel@tonic-gate return (0);
3697c478bd9Sstevel@tonic-gate }
3707c478bd9Sstevel@tonic-gate
3717c478bd9Sstevel@tonic-gate /*
3727c478bd9Sstevel@tonic-gate * routine:
3737c478bd9Sstevel@tonic-gate * rw_base
3747c478bd9Sstevel@tonic-gate *
3757c478bd9Sstevel@tonic-gate * purpose:
3767c478bd9Sstevel@tonic-gate * to write out the summary for one base-pair
3777c478bd9Sstevel@tonic-gate *
3787c478bd9Sstevel@tonic-gate * parameters:
3797c478bd9Sstevel@tonic-gate * FILE * for the output file
3807c478bd9Sstevel@tonic-gate *
3817c478bd9Sstevel@tonic-gate * returns:
3827c478bd9Sstevel@tonic-gate * error mask
3837c478bd9Sstevel@tonic-gate *
3847c478bd9Sstevel@tonic-gate * notes:
3857c478bd9Sstevel@tonic-gate */
rw_base(FILE * file,struct base * bp)3867c478bd9Sstevel@tonic-gate static errmask_t rw_base(FILE *file, struct base *bp)
3877c478bd9Sstevel@tonic-gate { struct rule *rp;
3887c478bd9Sstevel@tonic-gate
3897c478bd9Sstevel@tonic-gate fprintf(file, "\n");
3907c478bd9Sstevel@tonic-gate
3917c478bd9Sstevel@tonic-gate /* global rules don't appear within a base */
3927c478bd9Sstevel@tonic-gate if (bp->b_ident)
3937c478bd9Sstevel@tonic-gate fprintf(file, "BASE %s %s\n", noblanks(bp->b_src_spec),
3947c478bd9Sstevel@tonic-gate noblanks(bp->b_dst_spec));
3957c478bd9Sstevel@tonic-gate
3967c478bd9Sstevel@tonic-gate for (rp = bp->b_includes; rp; rp = rp->r_next)
3977c478bd9Sstevel@tonic-gate if (rp->r_flags & R_PROGRAM)
3987c478bd9Sstevel@tonic-gate fprintf(file, "LIST !%s\n", rp->r_file);
3997c478bd9Sstevel@tonic-gate else
4007c478bd9Sstevel@tonic-gate fprintf(file, "LIST %s\n", noblanks(rp->r_file));
4017c478bd9Sstevel@tonic-gate
4027c478bd9Sstevel@tonic-gate for (rp = bp->b_excludes; rp; rp = rp->r_next)
4037c478bd9Sstevel@tonic-gate if (rp->r_flags & R_PROGRAM)
4047c478bd9Sstevel@tonic-gate fprintf(file, "IGNORE !%s\n", rp->r_file);
4057c478bd9Sstevel@tonic-gate else
4067c478bd9Sstevel@tonic-gate fprintf(file, "IGNORE %s\n", noblanks(rp->r_file));
4077c478bd9Sstevel@tonic-gate
4087c478bd9Sstevel@tonic-gate return (0);
4097c478bd9Sstevel@tonic-gate }
4107c478bd9Sstevel@tonic-gate
4117c478bd9Sstevel@tonic-gate /*
4127c478bd9Sstevel@tonic-gate * routine:
4137c478bd9Sstevel@tonic-gate * add_rule
4147c478bd9Sstevel@tonic-gate *
4157c478bd9Sstevel@tonic-gate * purpose:
4167c478bd9Sstevel@tonic-gate * to add a new rule
4177c478bd9Sstevel@tonic-gate *
4187c478bd9Sstevel@tonic-gate * parameters:
4197c478bd9Sstevel@tonic-gate * pointer to list base
4207c478bd9Sstevel@tonic-gate * rule flags
4217c478bd9Sstevel@tonic-gate * associated name/arguments
4227c478bd9Sstevel@tonic-gate *
4237c478bd9Sstevel@tonic-gate * returns:
4247c478bd9Sstevel@tonic-gate * error flags
4257c478bd9Sstevel@tonic-gate *
4267c478bd9Sstevel@tonic-gate * notes:
4277c478bd9Sstevel@tonic-gate * we always copy the argument string because most of them
4287c478bd9Sstevel@tonic-gate * were read from a file and are just in a transient buffer
4297c478bd9Sstevel@tonic-gate */
add_rule(struct base * bp,int flags,const char * args)4307c478bd9Sstevel@tonic-gate static errmask_t add_rule(struct base *bp, int flags, const char *args)
4317c478bd9Sstevel@tonic-gate { struct rule *rp;
4327c478bd9Sstevel@tonic-gate struct rule **list;
4337c478bd9Sstevel@tonic-gate
4347c478bd9Sstevel@tonic-gate rp = malloc(sizeof (struct rule));
4357c478bd9Sstevel@tonic-gate if (rp == 0)
4367c478bd9Sstevel@tonic-gate nomem("rule struture");
4377c478bd9Sstevel@tonic-gate
4387c478bd9Sstevel@tonic-gate /* initialize the new base */
4397c478bd9Sstevel@tonic-gate memset((void *) rp, 0, sizeof (struct rule));
4407c478bd9Sstevel@tonic-gate rp->r_flags = flags;
4417c478bd9Sstevel@tonic-gate rp->r_file = strdup(args);
4427c478bd9Sstevel@tonic-gate
4437c478bd9Sstevel@tonic-gate /* figure out which list to put it on */
4447c478bd9Sstevel@tonic-gate if (flags&R_IGNORE)
4457c478bd9Sstevel@tonic-gate list = &bp->b_excludes;
4467c478bd9Sstevel@tonic-gate else if (flags&R_RESTRICT)
4477c478bd9Sstevel@tonic-gate list = &bp->b_restrictions;
4487c478bd9Sstevel@tonic-gate else
4497c478bd9Sstevel@tonic-gate list = &bp->b_includes;
4507c478bd9Sstevel@tonic-gate
4517c478bd9Sstevel@tonic-gate while (*list)
4527c478bd9Sstevel@tonic-gate list = &((*list)->r_next);
4537c478bd9Sstevel@tonic-gate *list = rp;
4547c478bd9Sstevel@tonic-gate
4557c478bd9Sstevel@tonic-gate if (flags & R_NEW)
4567c478bd9Sstevel@tonic-gate rules_added++;
4577c478bd9Sstevel@tonic-gate
4587c478bd9Sstevel@tonic-gate if (opt_debug & DBG_RULE) {
4597c478bd9Sstevel@tonic-gate fprintf(stderr, "RULE: base=%d, ", bp->b_ident);
4607c478bd9Sstevel@tonic-gate fprintf(stderr, "flags=%s, ",
4617c478bd9Sstevel@tonic-gate showflags(rflags, rp->r_flags));
4627c478bd9Sstevel@tonic-gate fprintf(stderr, "arg=%s\n", rp->r_file);
4637c478bd9Sstevel@tonic-gate }
4647c478bd9Sstevel@tonic-gate
4657c478bd9Sstevel@tonic-gate return (0);
4667c478bd9Sstevel@tonic-gate }
4677c478bd9Sstevel@tonic-gate
4687c478bd9Sstevel@tonic-gate /*
4697c478bd9Sstevel@tonic-gate * routine:
4707c478bd9Sstevel@tonic-gate * add_ignore, add_include
4717c478bd9Sstevel@tonic-gate *
4727c478bd9Sstevel@tonic-gate * purpose:
4737c478bd9Sstevel@tonic-gate * wrappers for add_rule that permit outsiders (like main.c)
4747c478bd9Sstevel@tonic-gate * not to know what is inside of a base, file, or list entry
4757c478bd9Sstevel@tonic-gate *
4767c478bd9Sstevel@tonic-gate * parameters:
4777c478bd9Sstevel@tonic-gate * base under which rules should be added
4787c478bd9Sstevel@tonic-gate * argument associated with rule
4797c478bd9Sstevel@tonic-gate *
4807c478bd9Sstevel@tonic-gate * returns:
4817c478bd9Sstevel@tonic-gate * error flags
4827c478bd9Sstevel@tonic-gate *
4837c478bd9Sstevel@tonic-gate * notes:
4847c478bd9Sstevel@tonic-gate * basically these routines figure out what the right
4857c478bd9Sstevel@tonic-gate * flags are for a rule, and what list to put it on,
4867c478bd9Sstevel@tonic-gate * and then call a common handler.
4877c478bd9Sstevel@tonic-gate */
4887c478bd9Sstevel@tonic-gate errmask_t
add_ignore(struct base * bp,char * name)4897c478bd9Sstevel@tonic-gate add_ignore(struct base *bp, char *name)
4907c478bd9Sstevel@tonic-gate { int flags = R_IGNORE | R_NEW;
4917c478bd9Sstevel@tonic-gate
4927c478bd9Sstevel@tonic-gate if (bp == 0)
4937c478bd9Sstevel@tonic-gate bp = &omnibase;
4947c478bd9Sstevel@tonic-gate
4957c478bd9Sstevel@tonic-gate if (wildcards(name))
4967c478bd9Sstevel@tonic-gate flags |= R_WILD;
4977c478bd9Sstevel@tonic-gate
4987c478bd9Sstevel@tonic-gate return (add_rule(bp, flags, name));
4997c478bd9Sstevel@tonic-gate }
5007c478bd9Sstevel@tonic-gate
5017c478bd9Sstevel@tonic-gate errmask_t
add_include(struct base * bp,char * name)5027c478bd9Sstevel@tonic-gate add_include(struct base *bp, char *name)
5037c478bd9Sstevel@tonic-gate { int flags = R_NEW;
5047c478bd9Sstevel@tonic-gate
5057c478bd9Sstevel@tonic-gate if (bp == 0)
5067c478bd9Sstevel@tonic-gate bp = &omnibase;
5077c478bd9Sstevel@tonic-gate
5087c478bd9Sstevel@tonic-gate if (wildcards(name))
5097c478bd9Sstevel@tonic-gate flags |= R_WILD;
5107c478bd9Sstevel@tonic-gate
5117c478bd9Sstevel@tonic-gate bp->b_flags |= F_LISTED;
5127c478bd9Sstevel@tonic-gate
5137c478bd9Sstevel@tonic-gate return (add_rule(bp, flags, name));
5147c478bd9Sstevel@tonic-gate }
5157c478bd9Sstevel@tonic-gate
5167c478bd9Sstevel@tonic-gate /*
5177c478bd9Sstevel@tonic-gate * routine:
5187c478bd9Sstevel@tonic-gate * add_restr
5197c478bd9Sstevel@tonic-gate *
5207c478bd9Sstevel@tonic-gate * purpose:
5217c478bd9Sstevel@tonic-gate * to add a restriction to a base
5227c478bd9Sstevel@tonic-gate *
5237c478bd9Sstevel@tonic-gate * parameters:
5247c478bd9Sstevel@tonic-gate * address of base
5257c478bd9Sstevel@tonic-gate * restriction string
5267c478bd9Sstevel@tonic-gate *
5277c478bd9Sstevel@tonic-gate * returns:
5287c478bd9Sstevel@tonic-gate * error mask
5297c478bd9Sstevel@tonic-gate *
5307c478bd9Sstevel@tonic-gate * notes:
5317c478bd9Sstevel@tonic-gate * a restriction is specified on the command line and
5327c478bd9Sstevel@tonic-gate * tells us to limit our analysis/reconcilation to
5337c478bd9Sstevel@tonic-gate * specified files and/or directories. We deal with
5347c478bd9Sstevel@tonic-gate * these by adding a restriction rule to any base that
5357c478bd9Sstevel@tonic-gate * looks like it might fit the restriction. We need to
5367c478bd9Sstevel@tonic-gate * treat this as a rule because the restriction string
5377c478bd9Sstevel@tonic-gate * may extend beyond the base directory and part-way into
5387c478bd9Sstevel@tonic-gate * its tree ... meaning that individual file names under
5397c478bd9Sstevel@tonic-gate * the base will have to be checked against the restriction.
5407c478bd9Sstevel@tonic-gate */
5417c478bd9Sstevel@tonic-gate errmask_t
add_restr(char * restr)5427c478bd9Sstevel@tonic-gate add_restr(char *restr)
5437c478bd9Sstevel@tonic-gate { const char *s;
5447c478bd9Sstevel@tonic-gate errmask_t errs = 0;
5457c478bd9Sstevel@tonic-gate struct base *bp;
5467c478bd9Sstevel@tonic-gate
5477c478bd9Sstevel@tonic-gate for (bp = bases; bp; bp = bp->b_next) {
5487c478bd9Sstevel@tonic-gate /*
5497c478bd9Sstevel@tonic-gate * see if this restriction could apply to this base.
5507c478bd9Sstevel@tonic-gate * It could match either the source or destination
5517c478bd9Sstevel@tonic-gate * directory name for this base. If it matches neither
5527c478bd9Sstevel@tonic-gate * then the restriction does not apply to this base.
5537c478bd9Sstevel@tonic-gate */
5547c478bd9Sstevel@tonic-gate s = prefix(restr, bp->b_src_name);
5557c478bd9Sstevel@tonic-gate if (s == 0)
5567c478bd9Sstevel@tonic-gate s = prefix(restr, bp->b_dst_name);
5577c478bd9Sstevel@tonic-gate if (s == 0)
5587c478bd9Sstevel@tonic-gate continue;
5597c478bd9Sstevel@tonic-gate
5607c478bd9Sstevel@tonic-gate /*
5617c478bd9Sstevel@tonic-gate * if there is more restriction string after the
5627c478bd9Sstevel@tonic-gate * base, we will need to note the remainder of the
5637c478bd9Sstevel@tonic-gate * string so that we can match individual files
5647c478bd9Sstevel@tonic-gate * against it.
5657c478bd9Sstevel@tonic-gate */
5667c478bd9Sstevel@tonic-gate if (*s == '/')
5677c478bd9Sstevel@tonic-gate s++;
5687c478bd9Sstevel@tonic-gate
5697c478bd9Sstevel@tonic-gate errs |= add_rule(bp, R_RESTRICT, s);
5707c478bd9Sstevel@tonic-gate restr_added++;
5717c478bd9Sstevel@tonic-gate }
5727c478bd9Sstevel@tonic-gate
5737c478bd9Sstevel@tonic-gate return (errs);
5747c478bd9Sstevel@tonic-gate }
5757c478bd9Sstevel@tonic-gate
5767c478bd9Sstevel@tonic-gate /*
5777c478bd9Sstevel@tonic-gate * routine:
5787c478bd9Sstevel@tonic-gate * check_restr
5797c478bd9Sstevel@tonic-gate *
5807c478bd9Sstevel@tonic-gate * purpose:
5817c478bd9Sstevel@tonic-gate * to see if an argument falls within restrictions
5827c478bd9Sstevel@tonic-gate *
5837c478bd9Sstevel@tonic-gate * parameters:
584*63360950Smp204432 * pointer to relevant base
5857c478bd9Sstevel@tonic-gate * file name
5867c478bd9Sstevel@tonic-gate *
5877c478bd9Sstevel@tonic-gate * returns:
5887c478bd9Sstevel@tonic-gate * TRUE name is within restrictions
5897c478bd9Sstevel@tonic-gate * FALSE name is outside of restrictions
5907c478bd9Sstevel@tonic-gate * MAYBE name is on the path to a restriction
5917c478bd9Sstevel@tonic-gate *
5927c478bd9Sstevel@tonic-gate * notes:
5937c478bd9Sstevel@tonic-gate * if no restrictions have been specified, we evaluate
5947c478bd9Sstevel@tonic-gate * everything. If any restrictions have been specified,
5957c478bd9Sstevel@tonic-gate * we process only files that match one of the restrictions.
5967c478bd9Sstevel@tonic-gate *
5977c478bd9Sstevel@tonic-gate * add_restr has ensured that if the restriction includes
5987c478bd9Sstevel@tonic-gate * a portion that must be matched by individual files under
5997c478bd9Sstevel@tonic-gate * the base, that the restriction rule will contain that
6007c478bd9Sstevel@tonic-gate * portion of the restriction which must be matched against
6017c478bd9Sstevel@tonic-gate * individual file names.
6027c478bd9Sstevel@tonic-gate */
6037c478bd9Sstevel@tonic-gate bool_t
check_restr(struct base * bp,const char * name)6047c478bd9Sstevel@tonic-gate check_restr(struct base *bp, const char *name)
6057c478bd9Sstevel@tonic-gate { struct rule *rp;
6067c478bd9Sstevel@tonic-gate
6077c478bd9Sstevel@tonic-gate /* if there are no restrictions, everything is OK */
6087c478bd9Sstevel@tonic-gate if (restr_added == 0)
6097c478bd9Sstevel@tonic-gate return (TRUE);
6107c478bd9Sstevel@tonic-gate
6117c478bd9Sstevel@tonic-gate /* now we have to run through the list */
6127c478bd9Sstevel@tonic-gate for (rp = bp->b_restrictions; rp; rp = rp->r_next) {
6137c478bd9Sstevel@tonic-gate /* see if current path is under the restriction */
6147c478bd9Sstevel@tonic-gate if (prefix(name, rp->r_file))
6157c478bd9Sstevel@tonic-gate return (TRUE);
6167c478bd9Sstevel@tonic-gate
6177c478bd9Sstevel@tonic-gate /* see if current path is on the way to restr */
6187c478bd9Sstevel@tonic-gate if (prefix(rp->r_file, name))
6197c478bd9Sstevel@tonic-gate /*
6207c478bd9Sstevel@tonic-gate * this is kinky, but walker really needs
6217c478bd9Sstevel@tonic-gate * to know the difference between a directory
6227c478bd9Sstevel@tonic-gate * that we are unreservedly scanning, and one
6237c478bd9Sstevel@tonic-gate * that we are scanning only to find something
6247c478bd9Sstevel@tonic-gate * beneath it.
6257c478bd9Sstevel@tonic-gate */
6267c478bd9Sstevel@tonic-gate return (MAYBE);
6277c478bd9Sstevel@tonic-gate }
6287c478bd9Sstevel@tonic-gate
6297c478bd9Sstevel@tonic-gate /*
6307c478bd9Sstevel@tonic-gate * there are restrictions in effect and this file doesn't seem
6317c478bd9Sstevel@tonic-gate * to meet any of them
6327c478bd9Sstevel@tonic-gate */
6337c478bd9Sstevel@tonic-gate if (opt_debug & DBG_RULE)
6347c478bd9Sstevel@tonic-gate fprintf(stderr, "RULE: FAIL RESTRICTION base=%d, file=%s\n",
6357c478bd9Sstevel@tonic-gate bp->b_ident, name);
6367c478bd9Sstevel@tonic-gate
6377c478bd9Sstevel@tonic-gate return (FALSE);
6387c478bd9Sstevel@tonic-gate }
639