5.0-pre2 release
[linux_from_scratch.git] / lfscmd / src / lfscmd.c
blob6103cb85060c84a1440aca4f0c65f63e2deb8b9f
1 /*
2 * Copyright (C) 2003 Timothy Bauscher <timothy@linuxfromscratch.org>
3 */
5 #include <stdio.h>
6 #include <regex.h>
7 #include <sys/stat.h>
8 #include <unistd.h>
9 #include <stdlib.h>
11 #include "help.h"
12 #include "env.h"
13 #include "string.h"
14 #include "file.h"
15 #include "lfscmd.h"
17 int lfscmd (int argc, char **argv) {
18 xmlDocPtr doc;
19 xmlNodePtr node;
20 int c;
22 /* Set defaults */
23 lfs.exe = 0;
24 lfs.execute = 0;
25 lfs.file = 0;
26 lfs.title = 0;
27 lfs.status = 0;
28 lfs.query = NULL;
29 lfs.xmlfile = NULL;
31 while ((c = getopt (argc, argv, "fxteq:")) != -1)
32 switch(c)
34 case 'f':
35 lfs.file = 1;
36 break;
37 case 'x':
38 lfs.exe = 1;
39 break;
40 case 't':
41 lfs.title = 1;
42 break;
43 case 'e':
44 lfs.execute = 1;
45 break;
46 case 'q':
47 lfs.query = optarg;
48 break;
49 case '?':
50 default:
51 help(argv[0]);
54 /* Get xml file path */
55 lfs.xmlfile = argv[optind];
57 /* Validate arguments */
58 if (NULL == lfs.xmlfile
59 && NULL == (lfs.xmlfile=locate_book("LFSCMD_BOOK")))
60 help(argv[0]);
62 /* Setup the xml parser */
63 xmlSubstituteEntitiesDefault(1);
64 doc = xmlParseFile(lfs.xmlfile);
65 node = xmlDocGetRootElement(doc);
67 /* Check that the document is well-formed */
68 if (NULL == doc) error("Document not well-formed");
69 /* Check for an empty root element */
70 if (NULL == node) error("Empty root element");
72 return(lfscmd_parsexml(doc, node->children));
75 int lfscmd_parsexml (xmlDocPtr doc, xmlNodePtr node) {
76 regex_t reg;
78 /* Compile regex query */
79 if (NULL != lfs.query) {
80 if (regcomp(&reg, lfs.query, REG_NOSUB))
81 error("Regex is ill-formed: %s", lfs.query);
84 while (NULL != node)
86 /* Record page title */
87 if (string_comp("title", node->name)) {
88 lfs.sect = xmlNodeListGetString(doc, node->children, 1);
89 lfs.status = 1;
91 /* Determine filename by section id */
92 else if (string_comp("part", node->name)
93 || (string_len(node->name) >= 4
94 && string_comp("sect", string_snip(node->name, 0, 4)))) {
96 if (NULL != xmlGetProp(node, "id"))
97 lfs.fname = xmlGetProp(node, "id");
99 /* Display screen commands */
100 else if (string_comp("screen", node->name)
101 && string_comp("userinput", node->children->name)) {
103 /* Match title or section with query */
104 if (NULL != lfs.query) {
105 if (!regexec(&reg, lfs.sect, 0, NULL, 0)
106 || !regexec(&reg, lfs.fname, 0, NULL, 0))
107 lfscmd_parse_screen(doc, node->children);
109 else lfscmd_parse_screen(doc, node->children);
112 /* Recursively traverse the tree */
113 if (NULL != node->children)
114 lfscmd_parsexml(doc, node->children);
116 node = node->next;
118 return(0);
121 int lfscmd_parse_screen (xmlDocPtr doc, xmlNodePtr node) {
122 FILE *output = stdout;
124 if (NULL == lfs.fname) lfs.fname = "unknown";
125 if (NULL == lfs.sect) lfs.sect = "unknown";
127 /* Append output to file */
128 if (1 == lfs.file) output=write_file(lfs.fname, "a");
130 /* Output new page title */
131 if (1 == lfs.status && 1 == lfs.title) {
132 fprintf(output, "\n\n### %s: %s ###\n", lfs.fname, lfs.sect);
133 lfs.status = 0;
136 /* Output screen commands and content */
137 while (NULL != node)
139 /* Output content outside of "userinput" */
140 if (string_comp("text", node->name)) {
141 if (NULL != (lfs.cmd = node->content)) {
142 if (1 == lfs.execute) system(lfs.cmd);
143 else fprintf(output, "%s", lfs.cmd);
147 /* Output commands */
148 else if (string_comp("userinput", node->name))
150 /* Strip double ampersands */
151 if (NULL != (lfs.cmd = xmlNodeListGetString(doc, node->children, 1))) {
153 if (1 == lfs.execute)
154 system(string_strip(lfs.cmd, "&&"));
155 else
156 fprintf(output, "%s", string_strip(lfs.cmd, "&&"));
159 /* Properly deal with BLFS commands of the form <screen><userinput><command> */
160 if (string_comp("command", node->children->name))
162 xmlNodePtr command_node = node->children;
164 while (NULL != command_node)
166 if (NULL != (lfs.cmd = xmlNodeListGetString(doc, command_node->children, 1)))
168 if (1 == lfs.execute)
170 system(string_strip(lfs.cmd, "&&"));
172 else
174 fprintf(output, "%s", string_strip(lfs.cmd, "&&"));
177 command_node = command_node->next;
183 node = node->next;
186 /* Output trailing space */
187 fprintf(output, "\n");
189 /* Close file */
190 if (1 == lfs.file) {
191 fclose(output);
193 /* Make file executable */
194 if (1 == lfs.exe) chmod(lfs.fname, 00755);
196 return(1);