Added a few comments here and there
[linux_from_scratch.git] / lfscmd / src / lfscmd.c
blob7bb0af369268d04e355efb6d22e42f13d62f968e
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 struct LFSCMD options;
19 int lfscmd (int argc, char **argv)
21 xmlDocPtr doc;
22 xmlNodePtr node;
23 int c;
24 char* xmlfile;
26 /* Set defaults */
27 options.exe = 0;
28 options.execute = 0;
29 options.file = 0;
30 options.title = 0;
31 options.strip_amp = 0;
32 options.query = NULL;
33 //options.xmlfile = NULL;
35 while ((c = getopt (argc, argv, "fxteq:a")) != -1)
36 switch (c)
38 case 'f':
39 options.file = 1;
40 break;
41 case 'x':
42 options.exe = 1;
43 break;
44 case 't':
45 options.title = 1;
46 break;
47 case 'e':
48 options.execute = 1;
49 break;
50 case 'q':
51 options.query = optarg;
52 break;
53 case 'a':
54 options.strip_amp = 1;
55 break;
56 case '?':
57 default:
58 help(argv[0]);
61 /* Get xml file path */
62 xmlfile = argv[optind];
64 /* Validate arguments */
65 if (NULL == xmlfile
66 && NULL == (xmlfile=locate_book("LFSCMD_BOOK")))
67 help(argv[0]);
69 /* Setup the xml parser */
70 xmlSubstituteEntitiesDefault(1);
71 doc = xmlParseFile(xmlfile);
72 node = xmlDocGetRootElement(doc);
74 /* Check that the document is well-formed */
75 if (NULL == doc) error("Document not well-formed");
76 /* Check for an empty root element */
77 if (NULL == node) error("Empty root element");
79 return(lfscmd_parsexml("unknown", "unknown", doc, node->children));
82 int lfscmd_parsexml (char* sect, char* fname, xmlDocPtr doc, xmlNodePtr node)
84 regex_t reg;
85 FILE *output = stdout;
86 int title_shown = 0;
88 /* Compile regex query */
89 if (NULL != options.query)
91 if (regcomp(&reg, options.query, REG_NOSUB))
92 error("Regex is ill-formed: %s", options.query);
95 while (NULL != node)
97 /* Record page title */
98 if (string_comp("title", node->name))
100 sect = xmlNodeListGetString(doc, node->children, 1);
101 title_shown = 0;
103 /* Determine filename by section id */
104 else if (string_comp("part", node->name)
105 || (string_len(node->name) >= 4
106 && string_comp("sect", string_snip(node->name, 0, 4))))
108 if (NULL != xmlGetProp(node, "id"))
109 fname = xmlGetProp(node, "id");
112 /* Display screen commands */
113 else if (string_comp("screen", node->name)
114 && string_comp("userinput", node->children->name))
116 /* Match title or section with query */
117 if (NULL != options.query)
119 if (!regexec(&reg, sect, 0, NULL, 0)
120 || !regexec(&reg, fname, 0, NULL, 0))
122 /* Append output to file */
123 if (options.file)
124 output=write_file(fname, "a");
126 /* Output new page title */
127 if (options.title && !title_shown)
129 fprintf(output, "\n\n### %s: %s ###\n", fname, sect);
130 title_shown = 1;
132 lfscmd_parse_screen(output, doc, node->children);
135 else
137 /* Append output to file */
138 if (options.file)
139 output=write_file(fname, "a");
141 /* Output new page title */
142 if (options.title && !title_shown)
144 fprintf(output, "\n\n### %s: %s ###\n", fname, sect);
145 title_shown = 1;
147 lfscmd_parse_screen(output, doc, node->children);
149 /* Close file */
150 if (options.file)
152 fclose(output);
154 /* Make file executable */
155 if (options.exe)
156 chmod(fname, 00755);
160 /* Recursively traverse the tree */
161 if (NULL != node->children)
162 lfscmd_parsexml(sect, fname, doc, node->children);
164 node = node->next;
166 return(0);
169 static void output_cmd(FILE* output, char* cmd)
171 if (options.execute)
172 system(options.strip_amp ? string_strip(cmd, " &&") : cmd);
173 else
174 fprintf(output, "%s", options.strip_amp ? string_strip(cmd, " &&") : cmd);
177 int lfscmd_parse_command(FILE* output, xmlDocPtr doc, xmlNodePtr node)
179 char* cmd;
181 while (NULL != node)
183 /* Output content outside of "command" */
184 if (string_comp("text", node->name))
186 if (NULL != (cmd = node->content))
188 output_cmd(output, cmd);
192 if (NULL != (cmd = xmlNodeListGetString(doc, node->children, 1)))
194 output_cmd(output, cmd);
197 node = node->next;
199 return 1;
202 int lfscmd_parse_userinput(FILE* output, xmlDocPtr doc, xmlNodePtr node)
204 char* cmd;
206 /* Output userinput commands and content */
207 while (NULL != node)
209 /* Properly deal with BLFS commands of the form <screen><userinput><command> */
210 if (string_comp("command", node->name))
212 lfscmd_parse_command(output, doc, node->children);
214 else if (NULL != (cmd = xmlNodeListGetString(doc, node, 1)))
216 output_cmd(output, cmd);
219 node = node->next;
222 return 1;
225 int lfscmd_parse_screen (FILE* output, xmlDocPtr doc, xmlNodePtr node)
227 char* cmd;
229 /* Output screen commands and content */
230 while (NULL != node)
232 /* Output content outside of "userinput" */
233 if (string_comp("text", node->name))
235 if (NULL != (cmd = node->content))
237 output_cmd(output, cmd);
241 /* Output commands */
242 else if (string_comp("userinput", node->name))
244 lfscmd_parse_userinput(output, doc, node->children);
247 node = node->next;
250 /* Output trailing space */
251 fprintf(output, "\n");
253 return(1);