blob: 1e5eb396c70602b17eb4598c9423c85b634fb8e3 [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
102void
103free_cmdline(char *argv[])
104{
105 if (argv) {
106 free(argv[0]);
107 free(argv);
108 }
109}
110
111int
112parse_cmdline(const char *cmdline, int *argc_p, char **argv_p[])
113{
114 int count;
115 char **vector;
116 char *ptr;
117 char qmark = 0;
118
119 assert(cmdline);
120 assert(argc_p);
121 assert(argv_p);
122
123 /* init */
124 optind = 0; /* reinitialize getopt() */
125 count = 1;
126 vector = malloc((count + 1) * sizeof *vector);
127 vector[0] = strdup(cmdline);
128
129 /* command name */
130 strtok(vector[0], " ");
131
132 /* arguments */
133 while ((ptr = strtok(NULL, " "))) {
134 size_t len;
135 void *r;
136
137 len = strlen(ptr);
138
139 if (qmark) {
140 /* still in quotated text */
141 /* remove NULL termination of the previous token since it is not a token,
142 * but a part of the quotation string */
143 ptr[-1] = ' ';
144
145 if ((ptr[len - 1] == qmark) && (ptr[len - 2] != '\\')) {
146 /* end of quotation */
147 qmark = 0;
148 /* shorten the argument by the terminating quotation mark */
149 ptr[len - 1] = '\0';
150 }
151 continue;
152 }
153
154 /* another token in cmdline */
155 ++count;
156 r = realloc(vector, (count + 1) * sizeof *vector);
157 if (!r) {
158 YLMSG_E("Memory allocation failed (%s:%d, %s).\n", __FILE__, __LINE__, strerror(errno));
159 free(vector);
160 return -1;
161 }
162 vector = r;
163 vector[count - 1] = ptr;
164
165 if ((ptr[0] == '"') || (ptr[0] == '\'')) {
166 /* remember the quotation mark to identify end of quotation */
167 qmark = ptr[0];
168
169 /* move the remembered argument after the quotation mark */
170 ++vector[count - 1];
171
172 /* check if the quotation is terminated within this token */
173 if ((ptr[len - 1] == qmark) && (ptr[len - 2] != '\\')) {
174 /* end of quotation */
175 qmark = 0;
176 /* shorten the argument by the terminating quotation mark */
177 ptr[len - 1] = '\0';
178 }
179 }
180 }
181 vector[count] = NULL;
182
183 *argc_p = count;
184 *argv_p = vector;
185
186 return 0;
187}