blob: 46887fca7eb95a35455fed7436e3b6af02e2b9be [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
aPieceka83b8e02023-06-07 15:25:16 +0200172void
173free_cmdline(char *argv[])
174{
175 if (argv) {
176 free(argv[0]);
177 free(argv);
178 }
179}
180
181int
182parse_cmdline(const char *cmdline, int *argc_p, char **argv_p[])
183{
184 int count;
185 char **vector;
186 char *ptr;
187 char qmark = 0;
188
189 assert(cmdline);
190 assert(argc_p);
191 assert(argv_p);
192
193 /* init */
194 optind = 0; /* reinitialize getopt() */
195 count = 1;
196 vector = malloc((count + 1) * sizeof *vector);
197 vector[0] = strdup(cmdline);
198
199 /* command name */
200 strtok(vector[0], " ");
201
202 /* arguments */
203 while ((ptr = strtok(NULL, " "))) {
204 size_t len;
205 void *r;
206
207 len = strlen(ptr);
208
209 if (qmark) {
210 /* still in quotated text */
211 /* remove NULL termination of the previous token since it is not a token,
212 * but a part of the quotation string */
213 ptr[-1] = ' ';
214
215 if ((ptr[len - 1] == qmark) && (ptr[len - 2] != '\\')) {
216 /* end of quotation */
217 qmark = 0;
218 /* shorten the argument by the terminating quotation mark */
219 ptr[len - 1] = '\0';
220 }
221 continue;
222 }
223
224 /* another token in cmdline */
225 ++count;
226 r = realloc(vector, (count + 1) * sizeof *vector);
227 if (!r) {
228 YLMSG_E("Memory allocation failed (%s:%d, %s).\n", __FILE__, __LINE__, strerror(errno));
229 free(vector);
230 return -1;
231 }
232 vector = r;
233 vector[count - 1] = ptr;
234
235 if ((ptr[0] == '"') || (ptr[0] == '\'')) {
236 /* remember the quotation mark to identify end of quotation */
237 qmark = ptr[0];
238
239 /* move the remembered argument after the quotation mark */
240 ++vector[count - 1];
241
242 /* check if the quotation is terminated within this token */
243 if ((ptr[len - 1] == qmark) && (ptr[len - 2] != '\\')) {
244 /* end of quotation */
245 qmark = 0;
246 /* shorten the argument by the terminating quotation mark */
247 ptr[len - 1] = '\0';
248 }
249 }
250 }
251 vector[count] = NULL;
252
253 *argc_p = count;
254 *argv_p = vector;
255
256 return 0;
257}