1 /*
2 Copyright 2021 Northern.tech AS
3
4 This file is part of CFEngine 3 - written and maintained by Northern.tech AS.
5
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; version 3.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
18
19 To the extent this program is licensed as part of the Enterprise
20 versions of CFEngine, the applicable Commercial Open Source License
21 (COSL) may apply to this file if you as a licensee so wish it. See
22 included file COSL.txt.
23 */
24
25 #include <parser.h>
26 #include <parser_state.h>
27
28 #include <misc_lib.h>
29 #include <file_lib.h>
30 #include <cleanup.h>
31
32 #include <errno.h>
33
34 int yyparse(void);
35
36 ParserState PARSER_STATE = { 0 }; /* GLOBAL_X */
37
38 extern FILE *yyin;
39
ParserStateReset(ParserState * p,bool discard)40 static void ParserStateReset(ParserState *p, bool discard)
41 {
42 assert(p != NULL);
43 p->agent_type = AGENT_TYPE_COMMON;
44 p->warnings = PARSER_WARNING_ALL;
45 p->policy = NULL;
46
47 int i = CF_MAX_NESTING;
48 while (i-- > 0) /* Clear stacks from top down */
49 {
50 if (discard)
51 {
52 free(p->currentfnid[i]);
53 RlistDestroy(p->giveargs[i]);
54 FnCallDestroy(p->currentfncall[i]);
55 }
56 else
57 {
58 assert(!p->currentfnid[i]);
59 assert(!p->giveargs[i]);
60 assert(!p->currentfncall[i]);
61 }
62 p->currentfnid[i] = NULL;
63 p->giveargs[i] = NULL;
64 p->currentfncall[i] = NULL;
65 }
66
67 free(p->current_line);
68 p->current_line = NULL;
69 p->line_no = 1;
70 p->line_pos = 1;
71 p->error_count = 0;
72 p->warning_count = 0;
73 p->list_nesting = 0;
74 p->arg_nesting = 0;
75
76 free(p->current_namespace);
77 p->current_namespace = xstrdup("default");
78
79 p->currentid[0] = '\0';
80 if (p->currentstring)
81 {
82 free(p->currentstring);
83 }
84 p->currentstring = NULL;
85 p->currenttype[0] = '\0';
86 if (p->currentclasses)
87 {
88 free(p->currentclasses);
89 }
90 p->currentclasses = NULL;
91 p->currentRlist = NULL;
92 p->currentpromise = NULL;
93 p->currentbody = NULL;
94 if (p->promiser)
95 {
96 free(p->promiser);
97 }
98 p->promiser = NULL;
99 p->blockid[0] = '\0';
100 p->blocktype[0] = '\0';
101 RvalDestroy(p->rval);
102 p->rval = RvalNew(NULL, RVAL_TYPE_NOPROMISEE);
103 }
104
ParserStateClean(ParserState * p)105 static void ParserStateClean(ParserState *p)
106 {
107 free(p->current_namespace);
108 p->current_namespace = NULL;
109 }
110
ParserParseFile(AgentType agent_type,const char * path,unsigned int warnings,unsigned int warnings_error)111 Policy *ParserParseFile(AgentType agent_type, const char *path, unsigned int warnings, unsigned int warnings_error)
112 {
113 ParserStateReset(&PARSER_STATE, false);
114
115 PARSER_STATE.agent_type = agent_type;
116 PARSER_STATE.policy = PolicyNew();
117
118 PARSER_STATE.warnings = warnings;
119 PARSER_STATE.warnings_error = warnings_error;
120
121 strlcpy(PARSER_STATE.filename, path, CF_MAXVARSIZE);
122
123 yyin = safe_fopen(path, "rt");
124 if (yyin == NULL)
125 {
126 Log(LOG_LEVEL_ERR, "While opening file '%s' for parsing. (fopen: %s)", path, GetErrorStr());
127 DoCleanupAndExit(EXIT_FAILURE);
128 }
129
130 while (!feof(yyin))
131 {
132 yyparse();
133
134 if (ferror(yyin))
135 {
136 perror("cfengine");
137 DoCleanupAndExit(EXIT_FAILURE);
138 }
139 }
140
141 fclose(yyin);
142
143 if (PARSER_STATE.error_count > 0)
144 {
145 PolicyDestroy(PARSER_STATE.policy);
146 ParserStateReset(&PARSER_STATE, true);
147 ParserStateClean(&PARSER_STATE);
148 return NULL;
149 }
150
151 Policy *policy = PARSER_STATE.policy;
152 ParserStateReset(&PARSER_STATE, false);
153 ParserStateClean(&PARSER_STATE);
154 return policy;
155 }
156
ParserWarningFromString(const char * warning_str)157 int ParserWarningFromString(const char *warning_str)
158 {
159 if (strcmp("deprecated", warning_str) == 0)
160 {
161 return PARSER_WARNING_DEPRECATED;
162 }
163 else if (strcmp("removed", warning_str) == 0)
164 {
165 return PARSER_WARNING_REMOVED;
166 }
167 else if (strcmp("all", warning_str) == 0)
168 {
169 return PARSER_WARNING_ALL;
170 }
171 else
172 {
173 return -1;
174 }
175 }
176
ParserWarningToString(unsigned int warning)177 const char *ParserWarningToString(unsigned int warning)
178 {
179 switch (warning)
180 {
181 case PARSER_WARNING_DEPRECATED:
182 return "deprecated";
183 case PARSER_WARNING_REMOVED:
184 return "removed";
185
186 default:
187 ProgrammingError("Invalid parser warning: %u", warning);
188 }
189 }
190