1 #include <nm_core.h>
2 #include <nm_utils.h>
3 #include <nm_string.h>
4 #include <nm_vector.h>
5 #include <nm_window.h>
6 #include <nm_machine.h>
7 #include <nm_cfg_file.h>
8
9 #include <sys/wait.h>
10
nm_mach_arch(const nm_mach_t * p)11 static inline nm_str_t *nm_mach_arch(const nm_mach_t *p)
12 {
13 return (nm_str_t *)&p->arch;
14 }
nm_mach_def(const nm_mach_t * p)15 static inline nm_str_t *nm_mach_def(const nm_mach_t *p)
16 {
17 return (nm_str_t *)&p->def;
18 }
nm_mach_list(const nm_mach_t * p)19 static inline nm_vect_t **nm_mach_list(const nm_mach_t *p)
20 {
21 return (nm_vect_t **)&p->list;
22 }
23
24 static nm_vect_t nm_machs = NM_INIT_VECT;
25
26 static void nm_mach_init(void);
27 static void nm_mach_get_data(const char *arch);
28 static nm_vect_t *nm_mach_parse(const nm_str_t *buf, nm_str_t *def);
29
nm_mach_init(void)30 static void nm_mach_init(void)
31 {
32 const nm_vect_t *archs = &nm_cfg_get()->qemu_targets;
33
34 for (size_t n = 0; n < archs->n_memb; n++)
35 nm_mach_get_data(((char **) archs->data)[n]);
36
37 if (nm_cfg_get()->debug) {
38 nm_debug("\n");
39 for (size_t n = 0; n < nm_machs.n_memb; n++) {
40 nm_vect_t *v = *nm_mach_list(nm_machs.data[n]);
41 nm_debug("Get machine list for %s (default: %s)\n",
42 nm_mach_arch(nm_machs.data[n])->data,
43 nm_mach_def(nm_machs.data[n])->data);
44
45 for (size_t m = 0; m < v->n_memb; m++) {
46 nm_debug(">> mach: %s\n", (char *) v->data[m]);
47 }
48 }
49 }
50 }
51
nm_mach_get(const nm_str_t * arch)52 const char **nm_mach_get(const nm_str_t *arch)
53 {
54 const char **v = NULL;
55
56 if (nm_machs.data == NULL)
57 nm_mach_init();
58
59 for (size_t n = 0; n < nm_machs.n_memb; n++) {
60 if (nm_str_cmp_ss(nm_machs.data[n], arch) == NM_OK) {
61 v = (const char **) (*nm_mach_list(nm_machs.data[n]))->data;
62 break;
63 }
64 }
65
66 return v;
67 }
68
nm_mach_get_default(const nm_str_t * arch)69 const char *nm_mach_get_default(const nm_str_t *arch)
70 {
71 const char *def = NULL;
72
73 if (nm_machs.data == NULL)
74 nm_mach_init();
75
76 for (size_t n = 0; n < nm_machs.n_memb; n++) {
77 if (nm_str_cmp_ss(nm_machs.data[n], arch) == NM_OK) {
78 def = nm_mach_def(nm_machs.data[n])->data;
79 break;
80 }
81 }
82
83 return def;
84 }
85
nm_mach_free(void)86 void nm_mach_free(void)
87 {
88 for (size_t n = 0; n < nm_machs.n_memb; n++)
89 nm_vect_free(*nm_mach_list(nm_machs.data[n]), NULL);
90
91 nm_vect_free(&nm_machs, nm_mach_vect_free_mlist_cb);
92 }
93
nm_mach_get_data(const char * arch)94 static void nm_mach_get_data(const char *arch)
95 {
96 nm_str_t buf = NM_INIT_STR;
97 nm_vect_t argv = NM_INIT_VECT;
98 nm_str_t answer = NM_INIT_STR;
99 nm_mach_t mach_list = NM_INIT_MLIST;
100
101 nm_str_alloc_text(&mach_list.arch, arch);
102
103 nm_str_format(&buf, "%s/qemu-system-%s",
104 nm_cfg_get()->qemu_bin_path.data, arch);
105 nm_vect_insert(&argv, buf.data, buf.len + 1, NULL);
106
107 nm_vect_insert_cstr(&argv, "-M");
108 nm_vect_insert_cstr(&argv, "help");
109
110 nm_vect_end_zero(&argv);
111 if (nm_spawn_process(&argv, &answer) != NM_OK) {
112 nm_str_t warn_msg = NM_INIT_STR;
113 nm_str_format(&warn_msg,
114 _("Cannot get mach for %-6s . Error was logged"), arch);
115 nm_warn(warn_msg.data);
116 nm_str_free(&warn_msg);
117 goto out;
118 }
119
120 nm_str_trunc(&buf, 0);
121 mach_list.list = nm_mach_parse(&answer, &buf);
122 nm_str_copy(&mach_list.def, &buf);
123
124 nm_vect_insert(&nm_machs, &mach_list,
125 sizeof(mach_list), nm_mach_vect_ins_mlist_cb);
126 out:
127 nm_str_free(&buf);
128 nm_vect_free(&argv, NULL);
129 nm_str_free(&answer);
130 nm_str_free(&mach_list.arch);
131 nm_str_free(&mach_list.def);
132 }
133
nm_mach_parse(const nm_str_t * buf,nm_str_t * def)134 static nm_vect_t *nm_mach_parse(const nm_str_t *buf, nm_str_t *def)
135 {
136 if(!buf || !buf->data)
137 return NULL;
138
139 const char *bufp = buf->data;
140 int lookup_mach = 1;
141 nm_str_t mach = NM_INIT_STR;
142 nm_vect_t *v;
143
144 v = nm_calloc(1, sizeof(nm_vect_t));
145
146 /* skip first line */
147 while (*bufp != '\n')
148 bufp++;
149
150 bufp++;
151
152 while (*bufp != '\0') {
153 if (lookup_mach && (!isblank(*bufp))) {
154 nm_str_add_char_opt(&mach, *bufp);
155 } else if (lookup_mach && (isblank(*bufp))) {
156 lookup_mach = 0;
157 }
158
159 if (!lookup_mach && (*bufp == '\n')) {
160 nm_str_t item = NM_INIT_STR;
161
162 nm_str_copy(&item, &mach);
163 nm_vect_insert(v, item.data, item.len + 1, NULL);
164 nm_str_trunc(&mach, 0);
165 lookup_mach = 1;
166
167 /* search and save default machine */
168 if (!def->len) {
169 const char *tmpp = bufp;
170 size_t def_len = 0;
171
172 while (!isblank(*tmpp) && (tmpp != buf->data)) {
173 tmpp--;
174 def_len++;
175 }
176
177 if (!strncmp(tmpp + 1, "(default)", def_len - 1))
178 nm_str_copy(def, &item);
179 }
180
181 nm_str_free(&item);
182 }
183
184 bufp++;
185 }
186
187 nm_vect_end_zero(v);
188
189 nm_str_free(&mach);
190
191 return v;
192 }
193
nm_mach_vect_ins_mlist_cb(void * unit_p,const void * ctx)194 void nm_mach_vect_ins_mlist_cb(void *unit_p, const void *ctx)
195 {
196 nm_str_copy(nm_mach_arch(unit_p), nm_mach_arch(ctx));
197 nm_str_copy(nm_mach_def(unit_p), nm_mach_def(ctx));
198 memcpy(nm_mach_list(unit_p), nm_mach_list(ctx), sizeof(nm_vect_t *));
199 }
200
nm_mach_vect_free_mlist_cb(void * unit_p)201 void nm_mach_vect_free_mlist_cb(void *unit_p)
202 {
203 nm_str_free(nm_mach_arch(unit_p));
204 nm_str_free(nm_mach_def(unit_p));
205 free(*nm_mach_list(unit_p));
206 }
207
208 /* vim:set ts=4 sw=4: */
209