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