1 #include <nm_core.h>
2 #include <nm_form.h>
3 #include <nm_menu.h>
4 #include <nm_utils.h>
5 #include <nm_string.h>
6 #include <nm_vector.h>
7 #include <nm_window.h>
8 #include <nm_network.h>
9 #include <nm_svg_map.h>
10 #include <nm_database.h>
11 #include <nm_cfg_file.h>
12 #include <nm_lan_settings.h>
13 
14 #if defined (NM_OS_LINUX)
15 
16 const char NM_LC_LAN_FORM_LNAME[] = "Name";
17 const char NM_LC_LAN_FORM_RNAME[] = "Peer name";
18 
19 static void nm_lan_init_main_windows(bool redraw);
20 static void nm_lan_init_add_windows(nm_form_t *form);
21 static size_t nm_lan_labels_setup();
22 static void nm_lan_add_veth(void);
23 static void nm_lan_del_veth(const nm_str_t *name);
24 static void nm_lan_up_veth(const nm_str_t *name);
25 static void nm_lan_down_veth(const nm_str_t *name);
26 static void nm_lan_veth_info(const nm_str_t *name);
27 static int nm_lan_add_get_data(nm_str_t *ln, nm_str_t *rn);
28 
29 enum {
30     NM_LAN_LBL_LNAME = 0, NM_LAN_FLD_LNAME,
31     NM_LAN_LBL_RNAME, NM_LAN_FLD_RNAME,
32     NM_LAN_FLD_COUNT
33 };
34 
35 static nm_field_t *fields_lan[NM_LAN_FLD_COUNT + 1];
36 
37 #if defined (NM_WITH_NETWORK_MAP)
38 const char *nm_form_svg_state[] = {
39     "UP",
40     "DOWN",
41     "ALL",
42     NULL
43 };
44 
45 const char *nm_form_svg_layout[] = {
46     "neato",
47     "dot",
48     NULL
49 };
50 
51 const char NM_LC_SVG_FORM_PATH[] = "Export path";
52 const char NM_LC_SVG_FORM_TYPE[] = "State";
53 const char NM_LC_SVG_FORM_LAYT[] = "Layout";
54 const char NM_LC_SVG_FORM_GROUP[] = "Group";
55 
56 static void nm_svg_init_windows(nm_form_t *form);
57 static void nm_svg_fields_setup();
58 static size_t nm_svg_labels_setup();
59 static void nm_lan_export_svg(const nm_vect_t *veths);
60 
61 enum {
62     NM_SVG_LBL_PATH = 0, NM_SVG_FLD_PATH,
63     NM_SVG_LBL_TYPE, NM_SVG_FLD_TYPE,
64     NM_SVG_LBL_LAYT, NM_SVG_FLD_LAYT,
65     NM_SVG_LBL_GROUP, NM_SVG_FLD_GROUP,
66     NM_SVG_FLD_COUNT
67 };
68 
69 static nm_field_t *fields_svg[NM_SVG_FLD_COUNT + 1];
70 #endif /* NM_WITH_NETWORK_MAP */
71 
nm_lan_init_main_windows(bool redraw)72 static void nm_lan_init_main_windows(bool redraw)
73 {
74     if (redraw) {
75         nm_form_window_init();
76     } else {
77         werase(action_window);
78         werase(help_window);
79         werase(side_window);
80     }
81 
82     nm_init_help_lan();
83     nm_init_action(_(NM_MSG_LAN));
84     nm_init_side_lan();
85 
86     nm_print_veth_menu(NULL, 1);
87 }
88 
nm_lan_init_add_windows(nm_form_t * form)89 static void nm_lan_init_add_windows(nm_form_t *form)
90 {
91     if (form) {
92         nm_form_window_init();
93         nm_form_data_t *form_data = (nm_form_data_t *)form_userptr(form);
94         if(form_data)
95             form_data->parent_window = action_window;
96     } else {
97         werase(action_window);
98         werase(help_window);
99     }
100 
101     nm_init_help_edit();
102     nm_init_action(_(NM_MSG_ADD_VETH));
103     nm_init_side_lan();
104 
105     nm_print_veth_menu(NULL, 1);
106 }
107 
nm_lan_settings(void)108 void nm_lan_settings(void)
109 {
110     int ch = 0, regen_data = 1, renew_status = 0;
111     nm_str_t query = NM_INIT_STR;
112     nm_vect_t veths = NM_INIT_VECT;
113     nm_vect_t veths_list = NM_INIT_VECT;
114     nm_menu_data_t veths_data = NM_INIT_MENU_DATA;
115     size_t veth_list_len, old_hl;
116 
117     veth_list_len = old_hl = 0;
118 
119     nm_lan_create_veth(NM_FALSE);
120 
121     nm_lan_init_main_windows(false);
122 
123     do {
124         if (ch == NM_KEY_QUESTION) {
125             nm_lan_help();
126         } else if (ch == NM_KEY_A) {
127             nm_lan_add_veth();
128             regen_data = 1;
129             old_hl = veths_data.highlight;
130         } else if (ch == NM_KEY_R) {
131             if (veths.n_memb > 0) {
132                 nm_lan_del_veth(nm_vect_item_name_cur(&veths_data));
133                 regen_data = 1;
134                 old_hl = veths_data.highlight;
135 
136                 if (veths_data.item_first != 0) {
137                     veths_data.item_first--;
138                     veths_data.item_last--;
139                 }
140                 werase(side_window);
141                 nm_init_side_lan();
142             }
143         } else if (ch == NM_KEY_D) {
144             if (veths.n_memb > 0) {
145                 nm_lan_down_veth(nm_vect_item_name_cur(&veths_data));
146                 renew_status = 1;
147             }
148         } else if (ch == NM_KEY_U) {
149             if (veths.n_memb > 0) {
150                 nm_lan_up_veth(nm_vect_item_name_cur(&veths_data));
151                 renew_status = 1;
152             }
153         }
154 #if defined (NM_WITH_NETWORK_MAP)
155         else if (ch == NM_KEY_E) {
156             if (veths.n_memb > 0)
157                 nm_lan_export_svg(&veths);
158         }
159 #endif
160 
161         if (regen_data) {
162             nm_vect_free(&veths_list, NULL);
163             nm_vect_free(&veths, nm_str_vect_free_cb);
164             nm_db_select(NM_LAN_GET_VETH_SQL, &veths);
165             veth_list_len = (getmaxy(side_window) - 4);
166 
167             veths_data.highlight = 1;
168 
169             if (old_hl > 1) {
170                 if (veths.n_memb < old_hl)
171                     veths_data.highlight = (old_hl - 1);
172                 else
173                     veths_data.highlight = old_hl;
174                 old_hl = 0;
175             }
176 
177             if (veth_list_len < veths.n_memb)
178                 veths_data.item_last = veth_list_len;
179             else
180                 veths_data.item_last = veth_list_len = veths.n_memb;
181 
182             for (size_t n = 0; n < veths.n_memb; n++) {
183                 nm_menu_item_t veth = NM_INIT_MENU_ITEM;
184                 veth.name = (nm_str_t *) nm_vect_at(&veths, n);
185                 nm_vect_insert(&veths_list, &veth, sizeof(veth), NULL);
186             }
187 
188             veths_data.v = &veths_list;
189 
190             regen_data = 0;
191             renew_status = 1;
192         }
193 
194         if (veths.n_memb > 0) {
195             nm_menu_scroll(&veths_data, veth_list_len, ch);
196             werase(action_window);
197             nm_init_action(_(NM_MSG_LAN));
198             nm_print_veth_menu(&veths_data, renew_status);
199             nm_lan_veth_info(nm_vect_item_name_cur(&veths_data));
200 
201             if (renew_status)
202                 renew_status = 0;
203         } else {
204             werase(action_window);
205             nm_init_action(_(NM_MSG_LAN));
206         }
207 
208         if (redraw_window) {
209             nm_lan_init_main_windows(true);
210 
211             veth_list_len = (getmaxy(side_window) - 4);
212             /* TODO save last pos */
213             if (veth_list_len < veths.n_memb) {
214                 veths_data.item_last = veth_list_len;
215                 veths_data.item_first = 0;
216                 veths_data.highlight = 1;
217             } else {
218                 veths_data.item_last = veth_list_len = veths.n_memb;
219             }
220 
221             redraw_window = 0;
222         }
223     } while ((ch = wgetch(action_window)) != NM_KEY_Q);
224 
225     werase(side_window);
226     werase(help_window);
227     nm_init_help_main();
228     nm_vect_free(&veths, nm_str_vect_free_cb);
229     nm_vect_free(&veths_list, NULL);
230     nm_str_free(&query);
231 }
232 
nm_lan_add_veth(void)233 static void nm_lan_add_veth(void)
234 {
235     nm_form_data_t *form_data = NULL;
236     nm_form_t *form = NULL;
237     nm_str_t l_name = NM_INIT_STR;
238     nm_str_t r_name = NM_INIT_STR;
239     nm_str_t query = NM_INIT_STR;
240     size_t msg_len;
241 
242     nm_lan_init_add_windows(NULL);
243 
244     msg_len = nm_lan_labels_setup();
245 
246     form_data = nm_form_data_new(
247         action_window, nm_lan_init_add_windows, msg_len, NM_LAN_FLD_COUNT / 2, NM_TRUE);
248 
249     if (nm_form_data_update(form_data, 0, 0) != NM_OK)
250         goto out;
251 
252     for (size_t n = 0; n < NM_LAN_FLD_COUNT; n++) {
253         switch (n) {
254             case NM_LAN_FLD_LNAME:
255                 fields_lan[n] = nm_field_regexp_new(
256                     n / 2, form_data, "^[a-zA-Z0-9_-]{1,15} *$");
257                 break;
258             case NM_LAN_FLD_RNAME:
259                 fields_lan[n] = nm_field_regexp_new(
260                     n / 2, form_data, "^[a-zA-Z0-9_-]{1,15} *$");
261                 break;
262             default:
263                 fields_lan[n] = nm_field_label_new(n / 2, form_data);
264                 break;
265         }
266     }
267     fields_lan[NM_LAN_FLD_COUNT] = NULL;
268 
269     nm_lan_labels_setup();
270     nm_fields_unset_status(fields_lan);
271 
272     form = nm_form_new(form_data, fields_lan);
273     nm_form_post(form);
274 
275     if (nm_form_draw(&form) != NM_OK)
276         goto out;
277 
278     if (nm_lan_add_get_data(&l_name, &r_name) != NM_OK)
279         goto out;
280 
281     nm_net_add_veth(&l_name, &r_name);
282     nm_net_link_up(&l_name);
283     nm_net_link_up(&r_name);
284 
285     nm_str_format(&query, NM_LAN_ADD_VETH_SQL, l_name.data, r_name.data);
286     nm_db_edit(query.data);
287 
288 out:
289     wtimeout(action_window, -1);
290     werase(help_window);
291     nm_init_help_lan();
292     nm_form_free(form);
293     nm_form_data_free(form_data);
294     nm_fields_free(fields_lan);
295     nm_str_free(&l_name);
296     nm_str_free(&r_name);
297     nm_str_free(&query);
298 }
299 
nm_lan_labels_setup()300 static size_t nm_lan_labels_setup()
301 {
302     nm_str_t buf = NM_INIT_STR;
303     size_t max_label_len = 0;
304     size_t msg_len = 0;
305 
306     for (size_t n = 0; n < NM_LAN_FLD_COUNT; n++) {
307         switch (n) {
308         case NM_LAN_LBL_LNAME:
309             nm_str_format(&buf, "%s", _(NM_LC_LAN_FORM_LNAME));
310             break;
311         case NM_LAN_LBL_RNAME:
312             nm_str_format(&buf, "%s", _(NM_LC_LAN_FORM_RNAME));
313             break;
314         default:
315             continue;
316         }
317 
318         msg_len = mbstowcs(NULL, buf.data, buf.len);
319         if (msg_len > max_label_len)
320             max_label_len = msg_len;
321 
322         if (fields_lan[n])
323             set_field_buffer(fields_lan[n], 0, buf.data);
324     }
325 
326     nm_str_free(&buf);
327     return max_label_len;
328 }
329 
nm_lan_add_get_data(nm_str_t * ln,nm_str_t * rn)330 static int nm_lan_add_get_data(nm_str_t *ln, nm_str_t *rn)
331 {
332     int rc;
333     nm_str_t query = NM_INIT_STR;
334     nm_vect_t err = NM_INIT_VECT;
335     nm_vect_t names = NM_INIT_VECT;
336 
337     nm_get_field_buf(fields_lan[NM_LAN_FLD_LNAME], ln);
338     nm_get_field_buf(fields_lan[NM_LAN_FLD_RNAME], rn);
339 
340     nm_form_check_datap(_("Name"), ln, err);
341     nm_form_check_datap(_("Peer name"), rn, err);
342 
343     if ((rc = nm_print_empty_fields(&err)) == NM_ERR) {
344         nm_vect_free(&err, NULL);
345         goto out;
346     }
347 
348     nm_str_format(&query, NM_LAN_CHECK_NAME_SQL, ln->data, ln->data);
349     nm_db_select(query.data, &names);
350     if (names.n_memb > 0) {
351         nm_warn(_(NM_MSG_NAME_BUSY));
352         rc = NM_ERR;
353         goto out;
354     }
355 
356     nm_str_format(&query, NM_LAN_CHECK_NAME_SQL, rn->data, rn->data);
357     nm_db_select(query.data, &names);
358     if (names.n_memb > 0) {
359         nm_warn(_(NM_MSG_NAME_BUSY));
360         rc = NM_ERR;
361         goto out;
362     }
363 
364     if (nm_str_cmp_ss(ln, rn) == NM_OK) {
365         nm_warn(_(NM_MSG_NAME_DIFF));
366         rc = NM_ERR;
367     }
368 
369 out:
370     nm_vect_free(&names, nm_str_vect_free_cb);
371     nm_str_free(&query);
372     return rc;
373 }
374 
nm_lan_del_veth(const nm_str_t * name)375 static void nm_lan_del_veth(const nm_str_t *name)
376 {
377     nm_str_t lname = NM_INIT_STR;
378     nm_str_t rname = NM_INIT_STR;
379     nm_str_t query = NM_INIT_STR;
380 
381     nm_lan_parse_name(name, &lname, &rname);
382     nm_net_del_iface(&lname);
383 
384     nm_str_format(&query, NM_LAN_DEL_VETH_SQL, lname.data);
385     nm_db_edit(query.data);
386 
387     nm_str_format(&query, NM_LAN_VETH_DEP_SQL, lname.data, rname.data);
388     nm_db_edit(query.data);
389 
390     nm_str_free(&lname);
391     nm_str_free(&rname);
392     nm_str_free(&query);
393 }
394 
nm_lan_up_veth(const nm_str_t * name)395 static void nm_lan_up_veth(const nm_str_t *name)
396 {
397     nm_str_t lname = NM_INIT_STR;
398     nm_str_t rname = NM_INIT_STR;
399 
400     nm_lan_parse_name(name, &lname, &rname);
401 
402     nm_net_link_up(&lname);
403     nm_net_link_up(&rname);
404 
405     nm_str_free(&lname);
406     nm_str_free(&rname);
407 }
408 
nm_lan_down_veth(const nm_str_t * name)409 static void nm_lan_down_veth(const nm_str_t *name)
410 {
411     nm_str_t lname = NM_INIT_STR;
412     nm_str_t rname = NM_INIT_STR;
413 
414     nm_lan_parse_name(name, &lname, &rname);
415 
416     nm_net_link_down(&lname);
417     nm_net_link_down(&rname);
418 
419     nm_str_free(&lname);
420     nm_str_free(&rname);
421 }
422 
nm_lan_veth_info(const nm_str_t * name)423 static void nm_lan_veth_info(const nm_str_t *name)
424 {
425     chtype ch1, ch2;
426     size_t y = 3, x = 2;
427     size_t cols, rows;
428     nm_str_t rname = NM_INIT_STR;
429     nm_str_t query = NM_INIT_STR;
430     nm_str_t buf = NM_INIT_STR;
431     nm_vect_t ifs = NM_INIT_VECT;
432 
433     ch1 = ch2 = 0;
434     getmaxyx(action_window, rows, cols);
435     nm_lan_parse_name(name, &buf, &rname);
436 
437     nm_str_format(&query, NM_LAN_VETH_INF_SQL, buf.data);
438     nm_db_select(query.data, &ifs);
439 
440     nm_str_add_char(&buf, ':');
441     if (ifs.n_memb > 0)
442         for (size_t n = 0; n < ifs.n_memb; n++)
443             nm_str_append_format(&buf, " %s", nm_vect_str_ctx(&ifs, n));
444     else
445         nm_str_add_text(&buf, _(" [none]"));
446 
447     NM_PR_VM_INFO();
448     nm_str_trunc(&buf, 0);
449 
450     nm_vect_free(&ifs, nm_str_vect_free_cb);
451     nm_str_copy(&buf, &rname);
452 
453     nm_str_format(&query, NM_LAN_VETH_INF_SQL, buf.data);
454     nm_db_select(query.data, &ifs);
455 
456     nm_str_add_char(&buf, ':');
457     if (ifs.n_memb > 0)
458         for (size_t n = 0; n < ifs.n_memb; n++)
459             nm_str_append_format(&buf, " %s", nm_vect_str_ctx(&ifs, n));
460     else
461         nm_str_add_text(&buf, _(" [none]"));
462     NM_PR_VM_INFO();
463 
464     nm_vect_free(&ifs, nm_str_vect_free_cb);
465     nm_str_free(&rname);
466     nm_str_free(&query);
467 
468     nm_str_free(&buf);
469 }
470 
nm_lan_parse_name(const nm_str_t * name,nm_str_t * ln,nm_str_t * rn)471 void nm_lan_parse_name(const nm_str_t *name, nm_str_t *ln, nm_str_t *rn)
472 {
473     nm_str_t name_copy = NM_INIT_STR;
474     char *cp = NULL;
475 
476     nm_str_copy(&name_copy, name);
477 
478     if (rn != NULL) {
479         cp = strchr(name_copy.data, '>');
480         nm_str_alloc_text(rn, ++cp);
481         cp = NULL;
482     }
483 
484     cp = strchr(name_copy.data, '<');
485     if (cp) {
486         *cp = '\0';
487         nm_str_alloc_text(ln, name_copy.data);
488     }
489 
490     nm_str_free(&name_copy);
491 }
492 
nm_lan_create_veth(int info)493 void nm_lan_create_veth(int info)
494 {
495     nm_vect_t veths = NM_INIT_VECT;
496     size_t veth_count, veth_created = 0;
497 
498     nm_db_select(NM_GET_VETH_SQL, &veths);
499     veth_count = veths.n_memb / 2;
500 
501     for (size_t n = 0; n < veth_count; n++) {
502         size_t idx_shift = n * 2;
503         const nm_str_t *l_name = nm_vect_str(&veths, idx_shift);
504         const nm_str_t *r_name = nm_vect_str(&veths, idx_shift + 1);
505 
506         if (info)
507             printf("Checking \"%s <-> %s\"...", l_name->data, r_name->data);
508 
509         if (nm_net_iface_exists(l_name) != NM_OK) {
510             if (info)
511                 printf("\t[not found]\n");
512 
513             nm_net_add_veth(l_name, r_name);
514             nm_net_link_up(l_name);
515             nm_net_link_up(r_name);
516 
517             veth_created++;
518         } else {
519             if (info)
520                 printf("\t[found]\n");
521         }
522     }
523 
524     if (info && !veth_created)
525         printf("Nothing to do.\n");
526     else if (info && veth_created)
527         printf("%zu VETH interface[s] was created.\n", veth_created);
528 
529     nm_vect_free(&veths, nm_str_vect_free_cb);
530 }
531 
532 #if defined (NM_WITH_NETWORK_MAP)
nm_svg_init_windows(nm_form_t * form)533 static void nm_svg_init_windows(nm_form_t *form)
534 {
535     if (form) {
536         nm_form_window_init();
537         nm_form_data_t *form_data = (nm_form_data_t *)form_userptr(form);
538         if (form_data)
539             form_data->parent_window = action_window;
540     } else {
541         werase(action_window);
542         werase(help_window);
543     }
544 
545     nm_init_help_export();
546     nm_init_action(_(NM_MSG_EXPORT_MAP));
547     nm_init_side_lan();
548 
549     nm_print_veth_menu(NULL, 1);
550 }
551 
nm_lan_export_svg(const nm_vect_t * veths)552 static void nm_lan_export_svg(const nm_vect_t *veths)
553 {
554     nm_form_data_t *form_data = NULL;
555     nm_form_t *form = NULL;
556     nm_vect_t err = NM_INIT_VECT;
557     nm_str_t path = NM_INIT_STR;
558     nm_str_t type = NM_INIT_STR;
559     nm_str_t layout = NM_INIT_STR;
560     nm_str_t group = NM_INIT_STR;
561     int state = NM_SVG_STATE_ALL;
562     char **states = (char **) nm_form_svg_state;
563     size_t msg_len;
564 
565     nm_svg_init_windows(NULL);
566 
567     msg_len = nm_svg_labels_setup();
568 
569     form_data = nm_form_data_new(
570         action_window, nm_svg_init_windows, msg_len, NM_SVG_FLD_COUNT / 2, NM_TRUE);
571 
572     if (nm_form_data_update(form_data, 0, 0) != NM_OK)
573         goto out;
574 
575     for (size_t n = 0; n < NM_SVG_FLD_COUNT; n++) {
576         switch (n) {
577             case NM_SVG_FLD_PATH:
578                 fields_svg[n] = nm_field_regexp_new(n / 2, form_data, "^/.*");
579                 break;
580             case NM_SVG_FLD_TYPE:
581                 fields_svg[n] = nm_field_enum_new(
582                     n / 2, form_data, nm_form_svg_state, false, false);
583                 break;
584             case NM_SVG_FLD_LAYT:
585                 fields_svg[n] = nm_field_enum_new(
586                     n / 2, form_data, nm_form_svg_layout, false, false);
587                 break;
588             case NM_SVG_FLD_GROUP:
589                 fields_svg[n] = nm_field_default_new(n / 2, form_data);
590                 break;
591             default:
592                 fields_svg[n] = nm_field_label_new(n / 2, form_data);
593                 break;
594         }
595     }
596     fields_svg[NM_SVG_FLD_COUNT] = NULL;
597 
598     nm_svg_labels_setup();
599     nm_svg_fields_setup();
600     nm_fields_unset_status(fields_svg);
601 
602     form = nm_form_new(form_data, fields_svg);
603     nm_form_post(form);
604 
605     if (nm_form_draw(&form) != NM_OK)
606         goto out;
607 
608     nm_get_field_buf(fields_svg[NM_SVG_FLD_PATH], &path);
609     nm_get_field_buf(fields_svg[NM_SVG_FLD_TYPE], &type);
610     nm_get_field_buf(fields_svg[NM_SVG_FLD_LAYT], &layout);
611     nm_get_field_buf(fields_svg[NM_SVG_FLD_GROUP], &group);
612     nm_form_check_data(_(NM_LC_SVG_FORM_PATH), path, err);
613     nm_form_check_data(_(NM_LC_SVG_FORM_TYPE), type, err);
614     nm_form_check_data(_(NM_LC_SVG_FORM_LAYT), layout, err);
615 
616     if (nm_print_empty_fields(&err) == NM_ERR) {
617         nm_vect_free(&err, NULL);
618         goto out;
619     }
620 
621     for (size_t n = 0; *states; n++, states++) {
622         if (nm_str_cmp_st(&type, *states) == NM_OK) {
623             state = n;
624             break;
625         }
626     }
627 
628     nm_svg_map(path.data, veths, state, &layout, &group);
629 
630 out:
631     wtimeout(action_window, -1);
632     werase(help_window);
633     nm_init_help_lan();
634     nm_init_action(_(NM_MSG_LAN));
635     nm_str_free(&path);
636     nm_str_free(&type);
637     nm_str_free(&layout);
638     nm_str_free(&group);
639     nm_form_free(form);
640     nm_form_data_free(form_data);
641     nm_fields_free(fields_svg);
642 }
643 
nm_svg_fields_setup()644 static void nm_svg_fields_setup()
645 {
646     nm_vect_t vgroup = NM_INIT_VECT;
647     const char **groups;
648     nm_field_type_args_t groups_args = {0};
649 
650     nm_db_select(NM_GET_GROUPS_SQL, &vgroup);
651     groups = nm_calloc(vgroup.n_memb + 1, sizeof(char *));
652     for (size_t n = 0; n < vgroup.n_memb; n++)
653         groups[n] = strdup(nm_vect_str_ctx(&vgroup, n));
654     groups[vgroup.n_memb] = NULL;
655 
656     groups_args.enum_arg.strings = groups;
657     groups_args.enum_arg.case_sens = false;
658     groups_args.enum_arg.uniq_match = false;
659 
660     nm_set_field_type(fields_svg[NM_SVG_FLD_GROUP], NM_FIELD_ENUM, groups_args);
661 
662     set_field_buffer(fields_svg[NM_SVG_FLD_TYPE], 0, nm_form_svg_state[0]);
663     set_field_buffer(fields_svg[NM_SVG_FLD_LAYT], 0, nm_form_svg_layout[0]);
664 
665     if (vgroup.n_memb == 1) {
666         field_opts_off(fields_svg[NM_SVG_FLD_GROUP], O_ACTIVE);
667     }
668 
669     nm_vect_free(&vgroup, nm_str_vect_free_cb);
670 }
671 
nm_svg_labels_setup()672 static size_t nm_svg_labels_setup()
673 {
674     nm_str_t buf = NM_INIT_STR;
675     size_t max_label_len = 0;
676     size_t msg_len = 0;
677 
678     for (size_t n = 0; n < NM_SVG_FLD_COUNT; n++) {
679         switch (n) {
680         case NM_SVG_LBL_PATH:
681             nm_str_format(&buf, "%s", _(NM_LC_SVG_FORM_PATH));
682             break;
683         case NM_SVG_LBL_TYPE:
684             nm_str_format(&buf, "%s", _(NM_LC_SVG_FORM_TYPE));
685             break;
686         case NM_SVG_LBL_LAYT:
687             nm_str_format(&buf, "%s", _(NM_LC_SVG_FORM_LAYT));
688             break;
689         case NM_SVG_LBL_GROUP:
690             nm_str_format(&buf, "%s", _(NM_LC_SVG_FORM_GROUP));
691             break;
692         default:
693             continue;
694         }
695 
696         msg_len = mbstowcs(NULL, buf.data, buf.len);
697         if (msg_len > max_label_len)
698             max_label_len = msg_len;
699 
700         if (fields_svg[n])
701             set_field_buffer(fields_svg[n], 0, buf.data);
702     }
703 
704     nm_str_free(&buf);
705     return max_label_len;
706 }
707 
708 #endif /* NM_WITH_NETWORK_MAP */
709 #endif /* NM_OS_LINUX */
710 /* vim:set ts=4 sw=4: */
711