Subject: Non strict REQUIRE/BEFORE in rcorder(8)
To: None <tech-userlevel@netbsd.org, current-users@netbsd.org>
From: Mike M. Volokhov <mishka@apk.od.ua>
List: current-users
Date: 05/20/2004 17:28:31
Greetings!
In http://mail-index.NetBSD.org/tech-userlevel/2004/02/04/0001.html I've
wrote about useful extension for rcorder(8), which will made possible
non-strict BEFORE/REQUIRE dependencies.
Accordingly to Jason Thorpe's proposition about using special keywords
instead of using special marks for values (see
http://mail-index.NetBSD.org/tech-userlevel/2004/02/04/0002.html), I
decide to implement this strategy in rcorder(8). Now, for providing non
strict dependencies just use "OPT-REQUIRE" and "OPT-BEFORE" keywords.
The "REQUIRE" and "BEFORE" keywords may be used in the same file as
well. For example:
# PROVIDE: avdaemon
# PROVIDE: mail sendmail
# PROVIDE: avmilter
# OPT-REQUIRE: avdaemon
# OPT-BEFORE: sendmail
And if all sendmail, AV daemon, and AV filter will be installed on three
separate hosts, there are no errors will be produced for "avmilter"
script.
Please see a patch below. Shortly said, I've expand structures for
require/before lists within "optional" flag. Thus, we can choose how to
handle non available dependencies.
Any comments are welcome.
--
Mishka.
Index: rcorder.c
===================================================================
RCS file: /cvsroot/src/sbin/rcorder/rcorder.c,v
retrieving revision 1.12
diff -u -r1.12 rcorder.c
--- rcorder.c 13 Oct 2003 14:22:20 -0000 1.12
+++ rcorder.c 20 May 2004 14:06:03 -0000
@@ -81,12 +81,18 @@
#define REQUIRE_LEN (sizeof(REQUIRE_STR) - 1)
#define REQUIRES_STR "# REQUIRES:"
#define REQUIRES_LEN (sizeof(REQUIRES_STR) - 1)
+#define OPT_REQUIRE_STR "# OPT-REQUIRE:"
+#define OPT_REQUIRE_LEN (sizeof(OPT_REQUIRE_STR) - 1)
+#define OPT_REQUIRES_STR "# OPT-REQUIRES:"
+#define OPT_REQUIRES_LEN (sizeof(OPT_REQUIRES_STR) - 1)
#define PROVIDE_STR "# PROVIDE:"
#define PROVIDE_LEN (sizeof(PROVIDE_STR) - 1)
#define PROVIDES_STR "# PROVIDES:"
#define PROVIDES_LEN (sizeof(PROVIDES_STR) - 1)
#define BEFORE_STR "# BEFORE:"
#define BEFORE_LEN (sizeof(BEFORE_STR) - 1)
+#define OPT_BEFORE_STR "# OPT-BEFORE:"
+#define OPT_BEFORE_LEN (sizeof(OPT_BEFORE_STR) - 1)
#define KEYWORD_STR "# KEYWORD:"
#define KEYWORD_LEN (sizeof(KEYWORD_STR) - 1)
#define KEYWORDS_STR "# KEYWORDS:"
@@ -122,11 +128,13 @@
};
struct f_reqnode {
+ int optional;
Hash_Entry *entry;
f_reqnode *next;
};
struct strnodelist {
+ int optional;
filenode *node;
strnodelist *next;
char s[1];
@@ -156,8 +164,10 @@
void parse_line(filenode *, char *, void (*)(filenode *, char *));
filenode *filenode_new(char *);
void add_require(filenode *, char *);
+void add_opt_require(filenode *, char *);
void add_provide(filenode *, char *);
void add_before(filenode *, char *);
+void add_opt_before(filenode *, char *);
void add_keyword(filenode *, char *);
void insert_before(void);
Hash_Entry *make_fake_provision(filenode *);
@@ -227,6 +237,7 @@
strnodelist *ent;
ent = emalloc(sizeof *ent + strlen(s));
+ ent->optional = RESET;
ent->node = fnode;
strcpy(ent->s, s);
ent->next = *listp;
@@ -285,6 +296,18 @@
rnode->entry = entry;
rnode->next = fnode->req_list;
fnode->req_list = rnode;
+ fnode->req_list->optional = RESET;
+}
+
+/*
+ * add an optional requirement to a filenode.
+ */
+void
+add_opt_require(filenode *fnode, char *s)
+{
+
+ add_require(fnode, s);
+ fnode->req_list->optional = SET;
}
/*
@@ -376,6 +399,16 @@
strnode_add(&bl_list, s, fnode);
}
+/*
+ * put the OPT-BEFORE: lines to a list and handle them later.
+ */
+void
+add_opt_before(filenode *fnode, char *s)
+{
+
+ add_before(fnode, s);
+ bl_list->optional = SET;
+}
/*
* add a key to a filenode.
@@ -411,6 +444,7 @@
FILE *fp;
char *buf;
int require_flag, provide_flag, before_flag, keyword_flag;
+ int opt_require_flag, opt_before_flag;
enum { BEFORE_PARSING, PARSING, PARSING_DONE } state;
filenode *node;
char delims[3] = { '\\', '\\', '\0' };
@@ -444,16 +478,23 @@
for (state = BEFORE_PARSING; state != PARSING_DONE &&
(buf = fparseln(fp, NULL, NULL, delims, 0)) != NULL; free(buf)) {
require_flag = provide_flag = before_flag = keyword_flag = 0;
+ opt_require_flag = opt_before_flag = 0;
if (strncmp(REQUIRE_STR, buf, REQUIRE_LEN) == 0)
require_flag = REQUIRE_LEN;
else if (strncmp(REQUIRES_STR, buf, REQUIRES_LEN) == 0)
require_flag = REQUIRES_LEN;
+ else if (strncmp(OPT_REQUIRE_STR, buf, OPT_REQUIRE_LEN) == 0)
+ opt_require_flag = OPT_REQUIRE_LEN;
+ else if (strncmp(OPT_REQUIRES_STR, buf, OPT_REQUIRES_LEN) == 0)
+ opt_require_flag = OPT_REQUIRES_LEN;
else if (strncmp(PROVIDE_STR, buf, PROVIDE_LEN) == 0)
provide_flag = PROVIDE_LEN;
else if (strncmp(PROVIDES_STR, buf, PROVIDES_LEN) == 0)
provide_flag = PROVIDES_LEN;
else if (strncmp(BEFORE_STR, buf, BEFORE_LEN) == 0)
before_flag = BEFORE_LEN;
+ else if (strncmp(OPT_BEFORE_STR, buf, OPT_BEFORE_LEN) == 0)
+ opt_before_flag = OPT_BEFORE_LEN;
else if (strncmp(KEYWORD_STR, buf, KEYWORD_LEN) == 0)
keyword_flag = KEYWORD_LEN;
else if (strncmp(KEYWORDS_STR, buf, KEYWORDS_LEN) == 0)
@@ -467,10 +508,14 @@
state = PARSING;
if (require_flag)
parse_line(node, buf + require_flag, add_require);
+ else if (opt_require_flag)
+ parse_line(node, buf+opt_require_flag, add_opt_require);
else if (provide_flag)
parse_line(node, buf + provide_flag, add_provide);
else if (before_flag)
- parse_line(node, buf + before_flag, add_before);
+ parse_line(node, buf + before_flag, add_before);
+ else if (opt_before_flag)
+ parse_line(node, buf + opt_before_flag, add_opt_before);
else if (keyword_flag)
parse_line(node, buf + keyword_flag, add_keyword);
}
@@ -538,8 +583,16 @@
fake_prov_entry = make_fake_provision(bl_list->node);
entry = Hash_CreateEntry(provide_hash, bl_list->s, &new);
- if (new == 1)
- warnx("file `%s' is before unknown provision `%s'", bl_list->node->filename, bl_list->s);
+ if (new == 1) {
+ if (bl_list->optional == SET) {
+ DPRINTF((stderr,
+ "unresolved OPT-BEFORE `%s' in file `%s'\n",
+ bl_list->s, bl_list->node->filename));
+ } else {
+ warnx("file `%s' is before unknown provision `%s'",
+ bl_list->node->filename, bl_list->s);
+ }
+ }
for (pnode = Hash_GetValue(entry); pnode; pnode = pnode->next) {
if (pnode->head)
@@ -596,10 +649,17 @@
head = Hash_GetValue(entry);
if (head == NULL) {
- warnx("requirement `%s' in file `%s' has no providers.",
- Hash_GetKey(entry), filename);
- exit_code = 1;
- return;
+ if (rnode->optional == SET) {
+ DPRINTF((stderr,
+ "unresolved OPT-REQUIRE `%s' in file `%s'\n",
+ Hash_GetKey(entry), filename));
+ return;
+ } else {
+ warnx("requirement `%s' in file `%s' has no providers.",
+ Hash_GetKey(entry), filename);
+ exit_code = 1;
+ return;
+ }
}
/* return if the requirement is already satisfied. */