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