blob: d9bcbcaf9ddeed4671de6ae436a2bd68b778c497 [file] [log] [blame]
aPieceka83b8e02023-06-07 15:25:16 +02001/**
2 * @file yl_opt.c
3 * @author Adam Piecek <piecek@cesnet.cz>
4 * @brief Settings options for the libyang context.
5 *
6 * Copyright (c) 2020 - 2023 CESNET, z.s.p.o.
7 *
8 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
13 */
14
15#define _GNU_SOURCE
16
17#include <assert.h>
18#include <errno.h>
19#include <getopt.h>
20#include <strings.h>
21
22#include "in.h" /* ly_in_free */
23
24#include "common.h"
25#include "yl_opt.h"
26
27struct cmdline_file *
28fill_cmdline_file(struct ly_set *set, struct ly_in *in, const char *path, LYD_FORMAT format)
29{
30 struct cmdline_file *rec;
31
32 rec = malloc(sizeof *rec);
33 if (!rec) {
34 YLMSG_E("Allocating memory for data file information failed.\n");
35 return NULL;
36 }
37 rec->in = in;
38 rec->path = path;
39 rec->format = format;
40
41 if (set && ly_set_add(set, rec, 1, NULL)) {
42 free(rec);
43 YLMSG_E("Storing data file information failed.\n");
44 return NULL;
45 }
46
47 return rec;
48}
49
50void
51free_cmdline_file_items(struct cmdline_file *rec)
52{
53 if (rec && rec->in) {
54 ly_in_free(rec->in, 1);
55 }
56}
57
58void
59free_cmdline_file(void *cmdline_file)
60{
61 struct cmdline_file *rec = (struct cmdline_file *)cmdline_file;
62
63 if (rec) {
64 free_cmdline_file_items(rec);
65 free(rec);
66 }
67}
68
69void
70yl_opt_erase(struct yl_opt *yo)
71{
72 ly_bool interactive;
73
74 interactive = yo->interactive;
75
76 /* data */
77 ly_set_erase(&yo->data_inputs, free_cmdline_file);
78 ly_in_free(yo->data_operational.in, 1);
79 ly_set_erase(&yo->data_xpath, NULL);
80
81 /* schema */
82 ly_set_erase(&yo->schema_features, free_features);
83 ly_set_erase(&yo->schema_modules, NULL);
84 free(yo->features_output);
85
86 /* context */
87 free(yo->searchpaths);
88
89 /* --reply-rpc */
90 ly_in_free(yo->reply_rpc.in, 1);
91
92 ly_out_free(yo->out, NULL, yo->out_stdout ? 0 : 1);
93
94 free_cmdline(yo->argv);
95
96 *yo = (const struct yl_opt) {
97 0
98 };
99 yo->interactive = interactive;
100}
101
aPiecek113e0f02023-06-09 08:47:48 +0200102int
103yl_opt_update_schema_out_format(const char *arg, struct yl_opt *yo)
104{
105 if (!strcasecmp(arg, "yang")) {
106 yo->schema_out_format = LYS_OUT_YANG;
107 yo->data_out_format = 0;
108 } else if (!strcasecmp(arg, "yin")) {
109 yo->schema_out_format = LYS_OUT_YIN;
110 yo->data_out_format = 0;
111 } else if (!strcasecmp(arg, "info")) {
112 yo->schema_out_format = LYS_OUT_YANG_COMPILED;
113 yo->data_out_format = 0;
114 } else if (!strcasecmp(arg, "tree")) {
115 yo->schema_out_format = LYS_OUT_TREE;
116 yo->data_out_format = 0;
117 } else {
118 return 1;
119 }
120
121 return 0;
122}
123
124int
125yl_opt_update_data_out_format(const char *arg, struct yl_opt *yo)
126{
127 if (!strcasecmp(arg, "xml")) {
128 yo->schema_out_format = 0;
129 yo->data_out_format = LYD_XML;
130 } else if (!strcasecmp(arg, "json")) {
131 yo->schema_out_format = 0;
132 yo->data_out_format = LYD_JSON;
133 } else if (!strcasecmp(arg, "lyb")) {
134 yo->schema_out_format = 0;
135 yo->data_out_format = LYD_LYB;
136 } else {
137 return 1;
138 }
139
140 return 0;
141}
142
143static int
144yl_opt_update_other_out_format(const char *arg, struct yl_opt *yo)
145{
146 if (!strcasecmp(arg, "feature-param")) {
147 yo->feature_param_format = 1;
148 } else {
149 return 1;
150 }
151
152 return 0;
153}
154
155int
156yl_opt_update_out_format(const char *arg, struct yl_opt *yo)
157{
158 if (!yl_opt_update_schema_out_format(arg, yo)) {
159 return 0;
160 }
161 if (!yl_opt_update_data_out_format(arg, yo)) {
162 return 0;
163 }
164 if (!yl_opt_update_other_out_format(arg, yo)) {
165 return 0;
166 }
167
168 YLMSG_E("Unknown output format %s\n", arg);
169 return 1;
170}
171
aPiecek3167f382023-06-09 09:23:10 +0200172int
173yl_opt_update_data_type(const char *arg, struct yl_opt *yo)
174{
175 if (!strcasecmp(arg, "config")) {
176 yo->data_parse_options |= LYD_PARSE_NO_STATE;
177 yo->data_validate_options |= LYD_VALIDATE_NO_STATE;
178 } else if (!strcasecmp(arg, "get")) {
179 yo->data_parse_options |= LYD_PARSE_ONLY;
180 } else if (!strcasecmp(arg, "getconfig") || !strcasecmp(arg, "get-config") || !strcasecmp(arg, "edit")) {
181 yo->data_parse_options |= LYD_PARSE_ONLY | LYD_PARSE_NO_STATE;
182 } else if (!strcasecmp(arg, "rpc") || !strcasecmp(arg, "action")) {
183 yo->data_type = LYD_TYPE_RPC_YANG;
184 } else if (!strcasecmp(arg, "nc-rpc")) {
185 yo->data_type = LYD_TYPE_RPC_NETCONF;
186 } else if (!strcasecmp(arg, "reply") || !strcasecmp(arg, "rpcreply")) {
187 yo->data_type = LYD_TYPE_REPLY_YANG;
188 } else if (!strcasecmp(arg, "nc-reply")) {
189 yo->data_type = LYD_TYPE_REPLY_NETCONF;
190 } else if (!strcasecmp(arg, "notif") || !strcasecmp(arg, "notification")) {
191 yo->data_type = LYD_TYPE_NOTIF_YANG;
192 } else if (!strcasecmp(arg, "nc-notif")) {
193 yo->data_type = LYD_TYPE_NOTIF_NETCONF;
194 } else if (!strcasecmp(arg, "data")) {
195 /* default option */
196 } else {
197 return 1;
198 }
199
200 return 0;
201}
202
aPiecek20cc2fe2023-06-09 09:32:28 +0200203int
204yo_opt_update_data_default(const char *arg, struct yl_opt *yo)
205{
206 if (!strcasecmp(arg, "all")) {
207 yo->data_print_options = (yo->data_print_options & ~LYD_PRINT_WD_MASK) | LYD_PRINT_WD_ALL;
208 } else if (!strcasecmp(arg, "all-tagged")) {
209 yo->data_print_options = (yo->data_print_options & ~LYD_PRINT_WD_MASK) | LYD_PRINT_WD_ALL_TAG;
210 } else if (!strcasecmp(arg, "trim")) {
211 yo->data_print_options = (yo->data_print_options & ~LYD_PRINT_WD_MASK) | LYD_PRINT_WD_TRIM;
212 } else if (!strcasecmp(arg, "implicit-tagged")) {
213 yo->data_print_options = (yo->data_print_options & ~LYD_PRINT_WD_MASK) | LYD_PRINT_WD_IMPL_TAG;
214 } else {
215 return 1;
216 }
217
218 return 0;
219}
220
aPieceka83b8e02023-06-07 15:25:16 +0200221void
222free_cmdline(char *argv[])
223{
224 if (argv) {
225 free(argv[0]);
226 free(argv);
227 }
228}
229
230int
231parse_cmdline(const char *cmdline, int *argc_p, char **argv_p[])
232{
233 int count;
234 char **vector;
235 char *ptr;
236 char qmark = 0;
237
238 assert(cmdline);
239 assert(argc_p);
240 assert(argv_p);
241
242 /* init */
243 optind = 0; /* reinitialize getopt() */
244 count = 1;
245 vector = malloc((count + 1) * sizeof *vector);
246 vector[0] = strdup(cmdline);
247
248 /* command name */
249 strtok(vector[0], " ");
250
251 /* arguments */
252 while ((ptr = strtok(NULL, " "))) {
253 size_t len;
254 void *r;
255
256 len = strlen(ptr);
257
258 if (qmark) {
259 /* still in quotated text */
260 /* remove NULL termination of the previous token since it is not a token,
261 * but a part of the quotation string */
262 ptr[-1] = ' ';
263
264 if ((ptr[len - 1] == qmark) && (ptr[len - 2] != '\\')) {
265 /* end of quotation */
266 qmark = 0;
267 /* shorten the argument by the terminating quotation mark */
268 ptr[len - 1] = '\0';
269 }
270 continue;
271 }
272
273 /* another token in cmdline */
274 ++count;
275 r = realloc(vector, (count + 1) * sizeof *vector);
276 if (!r) {
277 YLMSG_E("Memory allocation failed (%s:%d, %s).\n", __FILE__, __LINE__, strerror(errno));
278 free(vector);
279 return -1;
280 }
281 vector = r;
282 vector[count - 1] = ptr;
283
284 if ((ptr[0] == '"') || (ptr[0] == '\'')) {
285 /* remember the quotation mark to identify end of quotation */
286 qmark = ptr[0];
287
288 /* move the remembered argument after the quotation mark */
289 ++vector[count - 1];
290
291 /* check if the quotation is terminated within this token */
292 if ((ptr[len - 1] == qmark) && (ptr[len - 2] != '\\')) {
293 /* end of quotation */
294 qmark = 0;
295 /* shorten the argument by the terminating quotation mark */
296 ptr[len - 1] = '\0';
297 }
298 }
299 }
300 vector[count] = NULL;
301
302 *argc_p = count;
303 *argv_p = vector;
304
305 return 0;
306}