2 * Copyright (C) 2013 IBM Corporation
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 #if defined(HAVE_CONFIG_H)
26 #include <pb-config/pb-config.h>
27 #include <talloc/talloc.h>
28 #include <types/types.h>
30 #include <i18n/i18n.h>
33 #include "nc-config.h"
34 #include "nc-widgets.h"
38 extern struct help_text config_help_text;
41 NET_CONF_TYPE_DHCP_ALL,
42 NET_CONF_TYPE_DHCP_ONE,
46 struct config_screen {
49 struct nc_widgetset *widgetset;
58 void (*on_exit)(struct cui *);
66 enum net_conf_type net_conf_type;
68 bool autoboot_enabled;
73 struct nc_widget_label *autoboot_l;
74 struct nc_widget_select *autoboot_f;
75 struct nc_widget_label *boot_order_l;
76 struct nc_widget_subset *boot_order_f;
77 struct nc_widget_label *boot_empty_l;
78 struct nc_widget_button *boot_add_b;
79 struct nc_widget_button *boot_none_b;
80 struct nc_widget_button *boot_any_b;
81 struct nc_widget_textbox *timeout_f;
82 struct nc_widget_label *timeout_l;
83 struct nc_widget_label *timeout_help_l;
85 struct nc_widget_label *ipmi_type_l;
86 struct nc_widget_label *ipmi_clear_l;
87 struct nc_widget_checkbox *ipmi_clear_cb;
89 struct nc_widget_label *network_l;
90 struct nc_widget_select *network_f;
92 struct nc_widget_label *iface_l;
93 struct nc_widget_select *iface_f;
94 struct nc_widget_label *ip_addr_l;
95 struct nc_widget_textbox *ip_addr_f;
96 struct nc_widget_label *ip_mask_l;
97 struct nc_widget_textbox *ip_mask_f;
98 struct nc_widget_label *ip_addr_mask_help_l;
99 struct nc_widget_label *gateway_l;
100 struct nc_widget_textbox *gateway_f;
101 struct nc_widget_label *gateway_help_l;
102 struct nc_widget_label *url_l;
103 struct nc_widget_textbox *url_f;
104 struct nc_widget_label *url_help_l;
105 struct nc_widget_label *dns_l;
106 struct nc_widget_textbox *dns_f;
107 struct nc_widget_label *dns_dhcp_help_l;
108 struct nc_widget_label *dns_help_l;
110 struct nc_widget_label *allow_write_l;
111 struct nc_widget_select *allow_write_f;
112 struct nc_widget_label *boot_console_l;
113 struct nc_widget_select *boot_console_f;
114 struct nc_widget_label *current_console_l;
116 struct nc_widget_label *net_override_l;
117 struct nc_widget_label *safe_mode;
118 struct nc_widget_button *ok_b;
119 struct nc_widget_button *help_b;
120 struct nc_widget_button *cancel_b;
124 static struct config_screen *config_screen_from_scr(struct nc_scr *scr)
126 struct config_screen *config_screen;
128 assert(scr->sig == pb_config_screen_sig);
129 config_screen = (struct config_screen *)
130 ((char *)scr - (size_t)&((struct config_screen *)0)->scr);
131 assert(config_screen->scr.sig == pb_config_screen_sig);
132 return config_screen;
135 static void pad_refresh(struct config_screen *screen)
137 int y, x, rows, cols;
139 getmaxyx(screen->scr.sub_ncw, rows, cols);
140 getbegyx(screen->scr.sub_ncw, y, x);
142 prefresh(screen->pad, screen->scroll_y, 0, y, x, rows, cols);
145 static void config_screen_process_key(struct nc_scr *scr, int key)
147 struct config_screen *screen = config_screen_from_scr(scr);
150 handled = widgetset_process_key(screen->widgetset, key);
159 screen->show_help = true;
165 screen->on_exit(screen->cui);
167 } else if (screen->show_help) {
168 screen->show_help = false;
169 screen->need_redraw = true;
170 cui_show_help(screen->cui, _("System Configuration"),
173 } else if (handled && !screen->show_subset) {
178 static void config_screen_resize(struct nc_scr *scr)
180 struct config_screen *screen = config_screen_from_scr(scr);
184 static int config_screen_unpost(struct nc_scr *scr)
186 struct config_screen *screen = config_screen_from_scr(scr);
187 widgetset_unpost(screen->widgetset);
191 struct nc_scr *config_screen_scr(struct config_screen *screen)
196 static int screen_process_form(struct config_screen *screen)
198 const struct system_info *sysinfo = screen->cui->sysinfo;
199 enum net_conf_type net_conf_type;
200 struct interface_config *iface;
201 bool allow_write, autoboot;
203 struct config *config;
204 int i, n_boot_opts, rc;
205 unsigned int *order, idx;
208 config = config_copy(screen, screen->cui->config);
210 talloc_free(config->autoboot_opts);
211 config->n_autoboot_opts = 0;
213 n_boot_opts = widget_subset_get_order(config, &order,
214 screen->widgets.boot_order_f);
216 autoboot = widget_select_get_value(screen->widgets.autoboot_f);
217 config->autoboot_enabled = autoboot && n_boot_opts;
219 config->n_autoboot_opts = n_boot_opts;
220 config->autoboot_opts = talloc_array(config, struct autoboot_option,
223 for (i = 0; i < n_boot_opts; i++) {
224 if (order[i] < sysinfo->n_blockdevs) {
226 config->autoboot_opts[i].boot_type = BOOT_DEVICE_UUID;
227 config->autoboot_opts[i].uuid = talloc_strdup(config,
228 sysinfo->blockdevs[order[i]]->uuid);
229 } else if(order[i] < (sysinfo->n_blockdevs + sysinfo->n_interfaces)) {
231 order[i] -= sysinfo->n_blockdevs;
232 config->autoboot_opts[i].boot_type = BOOT_DEVICE_UUID;
233 mac_str(sysinfo->interfaces[order[i]]->hwaddr,
234 sysinfo->interfaces[order[i]]->hwaddr_size,
236 config->autoboot_opts[i].uuid = talloc_strdup(config, mac);
239 order[i] -= (sysinfo->n_blockdevs + sysinfo->n_interfaces);
240 config->autoboot_opts[i].boot_type = BOOT_DEVICE_TYPE;
241 config->autoboot_opts[i].type = order[i];
245 str = widget_textbox_get_value(screen->widgets.timeout_f);
249 x = strtoul(str, &end, 10);
250 if (!errno && end != str)
251 config->autoboot_timeout_sec = x;
254 if (screen->ipmi_override)
255 if (widget_checkbox_get_value(screen->widgets.ipmi_clear_cb))
256 config->ipmi_bootdev = IPMI_BOOTDEV_INVALID;
259 net_conf_type = widget_select_get_value(screen->widgets.network_f);
261 /* if we don't have any network interfaces, prevent per-interface
263 if (sysinfo->n_interfaces == 0)
264 net_conf_type = NET_CONF_TYPE_DHCP_ALL;
266 if (net_conf_type == NET_CONF_TYPE_DHCP_ALL) {
267 config->network.n_interfaces = 0;
270 iface = talloc_zero(config, struct interface_config);
271 config->network.n_interfaces = 1;
272 config->network.interfaces = talloc_array(config,
273 struct interface_config *, 1);
274 config->network.interfaces[0] = iface;
276 /* copy hwaddr (from the sysinfo interface data) to
277 * the configuration */
278 idx = widget_select_get_value(screen->widgets.iface_f);
279 memcpy(iface->hwaddr, sysinfo->interfaces[idx]->hwaddr,
280 sizeof(iface->hwaddr));
283 if (net_conf_type == NET_CONF_TYPE_DHCP_ONE) {
284 iface->method = CONFIG_METHOD_DHCP;
287 if (net_conf_type == NET_CONF_TYPE_STATIC) {
288 char *ip, *mask, *gateway, *url;
290 ip = widget_textbox_get_value(screen->widgets.ip_addr_f);
291 mask = widget_textbox_get_value(screen->widgets.ip_mask_f);
292 gateway = widget_textbox_get_value(screen->widgets.gateway_f);
293 url = widget_textbox_get_value(screen->widgets.url_f);
295 if (!ip || !*ip || !mask || !*mask) {
296 screen->scr.frame.status =
297 _("No IP / mask values are set");
298 nc_scr_frame_draw(&screen->scr);
303 iface->method = CONFIG_METHOD_STATIC;
304 iface->static_config.address = talloc_asprintf(iface, "%s/%s",
306 iface->static_config.gateway = talloc_strdup(iface, gateway);
307 iface->static_config.url = talloc_strdup(iface, url);
310 str = widget_textbox_get_value(screen->widgets.dns_f);
311 talloc_free(config->network.dns_servers);
312 config->network.dns_servers = NULL;
313 config->network.n_dns_servers = 0;
315 if (str && strlen(str)) {
320 dns = strtok_r(str, " \t", &tmp);
325 i = config->network.n_dns_servers++;
326 config->network.dns_servers = talloc_realloc(config,
327 config->network.dns_servers,
329 config->network.n_dns_servers);
330 config->network.dns_servers[i] =
331 talloc_strdup(config, dns);
337 allow_write = widget_select_get_value(screen->widgets.allow_write_f);
338 if (allow_write != config->allow_writes)
339 config->allow_writes = allow_write;
341 if (config->n_consoles) {
342 idx = widget_select_get_value(screen->widgets.boot_console_f);
343 if (!config->boot_console) {
344 config->boot_console = talloc_strdup(config,
345 config->consoles[idx]);
346 } else if (strncmp(config->boot_console, config->consoles[idx],
347 strlen(config->boot_console)) != 0) {
348 talloc_free(config->boot_console);
349 config->boot_console = talloc_strdup(config,
350 config->consoles[idx]);
354 config->safe_mode = false;
355 rc = cui_send_config(screen->cui, config);
359 pb_log("cui_send_config failed!\n");
361 pb_debug("config sent!\n");
366 static void ok_click(void *arg)
368 struct config_screen *screen = arg;
369 if (screen_process_form(screen))
370 /* errors are written to the status line, so we'll need
372 wrefresh(screen->scr.main_ncw);
377 static void help_click(void *arg)
379 struct config_screen *screen = arg;
380 screen->show_help = true;
383 static void cancel_click(void *arg)
385 struct config_screen *screen = arg;
389 static int layout_pair(struct config_screen *screen, int y,
390 struct nc_widget_label *label,
391 struct nc_widget *field)
393 struct nc_widget *label_w = widget_label_base(label);
394 widget_move(label_w, y, screen->label_x);
395 widget_move(field, y, screen->field_x);
396 return max(widget_height(label_w), widget_height(field));
399 static void config_screen_layout_widgets(struct config_screen *screen)
401 struct nc_widget *wl, *wf, *wh;
406 /* currently, the longest label we have is the DNS-servers
407 * widget, so layout our screen based on that */
408 help_x = screen->field_x + 2 +
409 widget_width(widget_textbox_base(screen->widgets.dns_f));
411 wl = widget_label_base(screen->widgets.autoboot_l);
412 widget_set_visible(wl, true);
413 widget_move(wl, y, screen->label_x);
415 wf = widget_select_base(screen->widgets.autoboot_f);
416 widget_set_visible(wf, true);
417 widget_move(wf, y, screen->field_x);
418 y += widget_height(wf);
420 show = screen->autoboot_enabled;
425 wl = widget_label_base(screen->widgets.boot_order_l);
426 widget_set_visible(wl, show);
427 widget_move(wl, y, screen->label_x);
429 wf = widget_subset_base(screen->widgets.boot_order_f);
430 widget_move(wf, y, screen->field_x);
431 wl = widget_label_base(screen->widgets.boot_empty_l);
432 widget_move(wl, y, screen->field_x);
434 if (widget_subset_height(screen->widgets.boot_order_f)) {
435 widget_set_visible(wl, false);
436 widget_set_visible(wf, show);
437 y += show ? widget_height(wf) : 0;
439 widget_set_visible(wl, show);
440 widget_set_visible(wf, false);
446 widget_move(widget_button_base(screen->widgets.boot_add_b),
447 y++, screen->field_x);
448 widget_move(widget_button_base(screen->widgets.boot_any_b),
449 y++, screen->field_x);
450 widget_move(widget_button_base(screen->widgets.boot_none_b),
454 wf = widget_button_base(screen->widgets.boot_add_b);
455 if (widget_subset_n_inactive(screen->widgets.boot_order_f) && show)
456 widget_set_visible(wf, true);
458 widget_set_visible(wf, false);
463 widget_set_visible(widget_button_base(screen->widgets.boot_any_b), show);
464 widget_set_visible(widget_button_base(screen->widgets.boot_none_b), show);
466 wf = widget_textbox_base(screen->widgets.timeout_f);
467 wl = widget_label_base(screen->widgets.timeout_l);
468 wh = widget_label_base(screen->widgets.timeout_help_l);
469 widget_set_visible(wl, screen->autoboot_enabled);
470 widget_set_visible(wf, screen->autoboot_enabled);
471 widget_set_visible(wh, screen->autoboot_enabled);
472 if (screen->autoboot_enabled) {
473 widget_set_visible(wh, screen->autoboot_enabled);
474 widget_move(wl, y, screen->label_x);
475 widget_move(wf, y, screen->field_x);
476 widget_move(wh, y, screen->field_x + widget_width(wf) + 1);
481 if (screen->ipmi_override) {
482 wl = widget_label_base(screen->widgets.ipmi_type_l);
483 widget_set_visible(wl, true);
484 widget_move(wl, y, screen->label_x);
487 wl = widget_label_base(screen->widgets.ipmi_clear_l);
488 wf = widget_checkbox_base(screen->widgets.ipmi_clear_cb);
489 widget_set_visible(wl, true);
490 widget_set_visible(wf, true);
491 widget_move(wl, y, screen->label_x);
492 widget_move(wf, y, screen->field_x);
498 y += layout_pair(screen, y, screen->widgets.network_l,
499 widget_select_base(screen->widgets.network_f));
503 /* conditionally show iface select */
504 wl = widget_label_base(screen->widgets.iface_l);
505 wf = widget_select_base(screen->widgets.iface_f);
507 show = screen->net_conf_type == NET_CONF_TYPE_DHCP_ONE ||
508 screen->net_conf_type == NET_CONF_TYPE_STATIC;
510 widget_set_visible(wl, show);
511 widget_set_visible(wf, show);
514 y += layout_pair(screen, y, screen->widgets.iface_l, wf) + 1;
516 /* conditionally show static IP params */
517 show = screen->net_conf_type == NET_CONF_TYPE_STATIC;
519 wl = widget_label_base(screen->widgets.ip_addr_l);
520 wf = widget_textbox_base(screen->widgets.ip_addr_f);
521 widget_set_visible(wl, show);
522 widget_set_visible(wf, show);
523 x = screen->field_x + widget_width(wf) + 1;
526 layout_pair(screen, y, screen->widgets.ip_addr_l, wf);
528 wl = widget_label_base(screen->widgets.ip_mask_l);
529 wf = widget_textbox_base(screen->widgets.ip_mask_f);
530 widget_set_visible(wl, show);
531 widget_set_visible(wf, show);
534 widget_move(wl, y, x);
535 widget_move(wf, y, x + 2);
538 /* help for IP/mask */
539 wh = widget_label_base(screen->widgets.ip_addr_mask_help_l);
540 widget_set_visible(wh, show);
542 widget_move(wh, y, help_x);
546 wl = widget_label_base(screen->widgets.gateway_l);
547 wf = widget_textbox_base(screen->widgets.gateway_f);
548 wh = widget_label_base(screen->widgets.gateway_help_l);
549 widget_set_visible(wl, show);
550 widget_set_visible(wf, show);
551 widget_set_visible(wh, show);
554 layout_pair(screen, y, screen->widgets.gateway_l, wf);
555 widget_move(wh, y, help_x);
559 wl = widget_label_base(screen->widgets.url_l);
560 wf = widget_textbox_base(screen->widgets.url_f);
561 wh = widget_label_base(screen->widgets.url_help_l);
562 widget_set_visible(wl, show);
563 widget_set_visible(wf, show);
564 widget_set_visible(wh, show);
567 layout_pair(screen, y, screen->widgets.url_l, wf);
568 widget_move(wh, y, help_x);
572 wh = widget_label_base(screen->widgets.dns_help_l);
573 layout_pair(screen, y, screen->widgets.dns_l,
574 widget_textbox_base(screen->widgets.dns_f));
575 widget_move(wh, y, help_x);
578 /* we show the DNS/DHCP help if we're configuring DHCP */
579 show = screen->net_conf_type != NET_CONF_TYPE_STATIC;
580 wl = widget_label_base(screen->widgets.dns_dhcp_help_l);
581 widget_set_visible(wl, show);
583 widget_move(wl, y, screen->field_x);
589 layout_pair(screen, y, screen->widgets.allow_write_l,
590 widget_select_base(screen->widgets.allow_write_f));
591 y += widget_height(widget_select_base(screen->widgets.allow_write_f));
595 if (widget_height(widget_select_base(screen->widgets.boot_console_f))) {
596 layout_pair(screen, y, screen->widgets.boot_console_l,
597 widget_select_base(screen->widgets.boot_console_f));
598 y += widget_height(widget_select_base(screen->widgets.boot_console_f));
599 widget_move(widget_label_base(screen->widgets.current_console_l),
603 widget_set_visible(widget_label_base(
604 screen->widgets.boot_console_l), false);
605 widget_set_visible(widget_select_base(
606 screen->widgets.boot_console_f), false);
607 widget_set_visible(widget_label_base(
608 screen->widgets.current_console_l), false);
611 if (screen->net_override) {
612 widget_move(widget_label_base(screen->widgets.net_override_l),
614 widget_set_visible(widget_label_base(screen->widgets.net_override_l),
619 if (screen->cui->config->safe_mode) {
620 widget_move(widget_label_base(screen->widgets.safe_mode),
622 widget_set_visible(widget_label_base(screen->widgets.safe_mode),
627 widget_move(widget_button_base(screen->widgets.ok_b),
629 widget_move(widget_button_base(screen->widgets.help_b),
630 y, screen->field_x + 14);
631 widget_move(widget_button_base(screen->widgets.cancel_b),
632 y, screen->field_x + 28);
635 static void config_screen_network_change(void *arg, int value)
637 struct config_screen *screen = arg;
638 screen->net_conf_type = value;
639 widgetset_unpost(screen->widgetset);
640 config_screen_layout_widgets(screen);
641 widgetset_post(screen->widgetset);
644 static void config_screen_boot_order_change(void *arg, int value)
647 struct config_screen *screen = arg;
648 widgetset_unpost(screen->widgetset);
649 config_screen_layout_widgets(screen);
650 widgetset_post(screen->widgetset);
653 static void config_screen_autoboot_change(void *arg, int value)
655 struct config_screen *screen = arg;
656 screen->autoboot_enabled = !!value;
657 widgetset_unpost(screen->widgetset);
658 config_screen_layout_widgets(screen);
659 widgetset_post(screen->widgetset);
662 static void config_screen_add_device(void *arg)
664 struct config_screen *screen = arg;
666 screen->show_subset = true;
667 cui_show_subset(screen->cui, _("Select a boot device to add"),
668 screen->widgets.boot_order_f);
671 static void config_screen_autoboot_none(void *arg)
673 struct config_screen *screen = arg;
674 struct nc_widget_subset *subset = screen->widgets.boot_order_f;
676 widget_subset_clear_active(subset);
678 widgetset_unpost(screen->widgetset);
679 config_screen_layout_widgets(screen);
680 widgetset_post(screen->widgetset);
683 static void config_screen_autoboot_any(void *arg)
685 struct config_screen *screen = arg;
686 const struct system_info *sysinfo = screen->cui->sysinfo;
687 struct nc_widget_subset *subset = screen->widgets.boot_order_f;
690 widget_subset_clear_active(subset);
692 idx = sysinfo->n_blockdevs + sysinfo->n_interfaces + DEVICE_TYPE_ANY;
694 widget_subset_make_active(screen->widgets.boot_order_f, idx);
696 screen->autoboot_enabled = true;
698 widgetset_unpost(screen->widgetset);
699 config_screen_layout_widgets(screen);
700 widgetset_post(screen->widgetset);
703 static void config_screen_update_subset(void *arg,
704 struct nc_widget_subset *subset, int idx)
706 struct config_screen *screen = arg;
709 widget_subset_make_active(subset, idx);
710 if (!screen->autoboot_enabled)
711 screen->autoboot_enabled = true;
712 config_screen_layout_widgets(screen);
715 static struct interface_config *first_active_interface(
716 const struct config *config)
720 for (i = 0; i < config->network.n_interfaces; i++) {
721 if (config->network.interfaces[i]->ignore)
723 return config->network.interfaces[i];
728 static enum net_conf_type find_net_conf_type(const struct config *config)
730 struct interface_config *ifcfg;
732 ifcfg = first_active_interface(config);
735 return NET_CONF_TYPE_DHCP_ALL;
737 else if (ifcfg->method == CONFIG_METHOD_DHCP)
738 return NET_CONF_TYPE_DHCP_ONE;
740 else if (ifcfg->method == CONFIG_METHOD_STATIC)
741 return NET_CONF_TYPE_STATIC;
744 return NET_CONF_TYPE_DHCP_ALL;
747 static void config_screen_setup_empty(struct config_screen *screen)
749 widget_new_label(screen->widgetset, 2, screen->field_x,
750 _("Waiting for configuration data..."));
751 screen->widgets.cancel_b = widget_new_button(screen->widgetset,
752 4, screen->field_x, 9, _("Cancel"),
753 cancel_click, screen);
756 static int find_autoboot_idx(const struct system_info *sysinfo,
757 struct autoboot_option *opt)
761 if (opt->boot_type == BOOT_DEVICE_TYPE)
762 return sysinfo->n_blockdevs + sysinfo->n_interfaces + opt->type;
764 for (i = 0; i < sysinfo->n_blockdevs; i++) {
765 if (!strcmp(sysinfo->blockdevs[i]->uuid, opt->uuid))
769 for (i = 0; i < sysinfo->n_interfaces; i++) {
770 struct interface_info *info = sysinfo->interfaces[i];
773 mac_str(info->hwaddr, info->hwaddr_size, mac, sizeof(mac));
775 if (!strcmp(mac, opt->uuid))
776 return sysinfo->n_blockdevs + i;
782 static void config_screen_setup_widgets(struct config_screen *screen,
783 const struct config *config,
784 const struct system_info *sysinfo)
786 struct nc_widgetset *set = screen->widgetset;
787 struct interface_config *ifcfg;
788 char *str, *ip, *mask, *gw, *url, *tty;
789 enum net_conf_type type;
791 int add_len, clear_len, any_len, min_len = 20;
794 build_assert(sizeof(screen->widgets) / sizeof(struct widget *)
797 type = screen->net_conf_type;
798 ifcfg = first_active_interface(config);
800 screen->autoboot_enabled = config->autoboot_enabled;
802 screen->widgets.autoboot_l = widget_new_label(set, 0, 0,
804 screen->widgets.autoboot_f = widget_new_select(set, 0, 0,
805 COLS - screen->field_x - 1);
807 widget_select_add_option(screen->widgets.autoboot_f, 0, _("Disabled"),
808 !screen->autoboot_enabled);
809 widget_select_add_option(screen->widgets.autoboot_f, 1, _("Enabled"),
810 screen->autoboot_enabled);
812 widget_select_on_change(screen->widgets.autoboot_f,
813 config_screen_autoboot_change, screen);
815 add_len = max(min_len, strncols(_("Add Device")));
816 clear_len = max(min_len, strncols(_("Clear")));
817 any_len = max(min_len, strncols(_("Clear & Boot Any")));
819 screen->widgets.boot_add_b = widget_new_button(set, 0, 0, add_len,
821 config_screen_add_device, screen);
823 screen->widgets.boot_none_b = widget_new_button(set, 0, 0, clear_len,
825 config_screen_autoboot_none, screen);
827 screen->widgets.boot_any_b = widget_new_button(set, 0, 0, any_len,
828 _("Clear & Boot Any"),
829 config_screen_autoboot_any, screen);
831 screen->widgets.boot_order_l = widget_new_label(set, 0, 0,
833 screen->widgets.boot_order_f = widget_new_subset(set, 0, 0,
834 COLS - screen->field_x,
835 config_screen_update_subset);
836 screen->widgets.boot_empty_l = widget_new_label(set, 0, 0,
839 widget_subset_on_change(screen->widgets.boot_order_f,
840 config_screen_boot_order_change, screen);
842 for (i = 0; i < sysinfo->n_blockdevs; i++) {
843 struct blockdev_info *bd = sysinfo->blockdevs[i];
846 label = talloc_asprintf(screen, _("disk: %s [uuid: %s]"),
849 widget_subset_add_option(screen->widgets.boot_order_f, label);
852 for (i = 0; i < sysinfo->n_interfaces; i++) {
853 struct interface_info *info = sysinfo->interfaces[i];
854 char *label, mac[20];
856 mac_str(info->hwaddr, info->hwaddr_size, mac, sizeof(mac));
858 label = talloc_asprintf(screen, _("net: %s [mac: %s]"),
861 widget_subset_add_option(screen->widgets.boot_order_f, label);
864 for (i = DEVICE_TYPE_NETWORK; i < DEVICE_TYPE_UNKNOWN; i++) {
867 if (i == DEVICE_TYPE_ANY)
868 label = talloc_asprintf(screen, _("Any Device"));
870 label = talloc_asprintf(screen, _("Any %s device"),
871 device_type_display_name(i));
873 widget_subset_add_option(screen->widgets.boot_order_f, label);
876 for (i = 0; i < config->n_autoboot_opts; i++) {
877 struct autoboot_option *opt = &config->autoboot_opts[i];
880 idx = find_autoboot_idx(sysinfo, opt);
883 widget_subset_make_active(screen->widgets.boot_order_f,
886 if (opt->boot_type == BOOT_DEVICE_TYPE)
887 pb_log("%s: Unknown autoboot option: %d\n",
888 __func__, opt->type);
890 pb_log("%s: Unknown autoboot UUID: %s\n",
891 __func__, opt->uuid);
896 str = talloc_asprintf(screen, "%d", config->autoboot_timeout_sec);
897 screen->widgets.timeout_l = widget_new_label(set, 0, 0, _("Timeout:"));
898 screen->widgets.timeout_f = widget_new_textbox(set, 0, 0, 5, str);
899 screen->widgets.timeout_help_l = widget_new_label(set, 0, 0,
902 widget_textbox_set_fixed_size(screen->widgets.timeout_f);
903 widget_textbox_set_validator_integer(screen->widgets.timeout_f, 0, 999);
905 if (config->ipmi_bootdev) {
906 char *label = talloc_asprintf(screen,
907 _("%s IPMI boot option: %s"),
908 config->ipmi_bootdev_persistent ?
909 "Persistent" : "Temporary",
910 ipmi_bootdev_display_name(config->ipmi_bootdev));
911 screen->widgets.ipmi_type_l = widget_new_label(set, 0, 0,
913 screen->widgets.ipmi_clear_l = widget_new_label(set, 0, 0,
915 screen->widgets.ipmi_clear_cb = widget_new_checkbox(set, 0, 0,
917 screen->ipmi_override = true;
920 screen->widgets.network_l = widget_new_label(set, 0, 0, _("Network:"));
921 screen->widgets.network_f = widget_new_select(set, 0, 0,
922 COLS - screen->field_x - 1);
924 widget_select_add_option(screen->widgets.network_f,
925 NET_CONF_TYPE_DHCP_ALL,
926 _("DHCP on all active interfaces"),
927 type == NET_CONF_TYPE_DHCP_ALL);
928 widget_select_add_option(screen->widgets.network_f,
929 NET_CONF_TYPE_DHCP_ONE,
930 _("DHCP on a specific interface"),
931 type == NET_CONF_TYPE_DHCP_ONE);
932 widget_select_add_option(screen->widgets.network_f,
933 NET_CONF_TYPE_STATIC,
934 _("Static IP configuration"),
935 type == NET_CONF_TYPE_STATIC);
937 widget_select_on_change(screen->widgets.network_f,
938 config_screen_network_change, screen);
940 screen->widgets.iface_l = widget_new_label(set, 0, 0, _("Device:"));
941 screen->widgets.iface_f = widget_new_select(set, 0, 0, 50);
943 for (i = 0; i < sysinfo->n_interfaces; i++) {
944 struct interface_info *info = sysinfo->interfaces[i];
945 char str[50], mac[20];
948 is_default = ifcfg && !memcmp(ifcfg->hwaddr, info->hwaddr,
949 sizeof(ifcfg->hwaddr));
951 mac_str(info->hwaddr, info->hwaddr_size, mac, sizeof(mac));
952 snprintf(str, sizeof(str), "%s [%s, %s]", info->name, mac,
953 info->link ? _("link up") : _("link down"));
955 widget_select_add_option(screen->widgets.iface_f,
959 url = gw = ip = mask = NULL;
960 if (ifcfg && ifcfg->method == CONFIG_METHOD_STATIC) {
963 str = talloc_strdup(screen, ifcfg->static_config.address);
964 sep = strchr(str, '/');
971 gw = ifcfg->static_config.gateway;
972 url = ifcfg->static_config.url;
975 screen->net_override = ifcfg && ifcfg->override;
976 if (screen->net_override) {
977 screen->widgets.net_override_l = widget_new_label(set, 0, 0,
978 _("Network Override Active! 'OK' will overwrite interface config"));
981 screen->widgets.ip_addr_l = widget_new_label(set, 0, 0, _("IP/mask:"));
982 screen->widgets.ip_addr_f = widget_new_textbox(set, 0, 0, 16, ip);
983 screen->widgets.ip_mask_l = widget_new_label(set, 0, 0, "/");
984 screen->widgets.ip_mask_f = widget_new_textbox(set, 0, 0, 3, mask);
985 screen->widgets.ip_addr_mask_help_l =
986 widget_new_label(set, 0, 0, _("(eg. 192.168.0.10 / 24)"));
988 widget_textbox_set_fixed_size(screen->widgets.ip_addr_f);
989 widget_textbox_set_fixed_size(screen->widgets.ip_mask_f);
990 widget_textbox_set_validator_ipv4(screen->widgets.ip_addr_f);
991 widget_textbox_set_validator_integer(screen->widgets.ip_mask_f, 1, 31);
993 screen->widgets.gateway_l = widget_new_label(set, 0, 0, _("Gateway:"));
994 screen->widgets.gateway_f = widget_new_textbox(set, 0, 0, 16, gw);
995 screen->widgets.gateway_help_l =
996 widget_new_label(set, 0, 0, _("(eg. 192.168.0.1)"));
998 widget_textbox_set_fixed_size(screen->widgets.gateway_f);
999 widget_textbox_set_validator_ipv4(screen->widgets.gateway_f);
1001 screen->widgets.url_l = widget_new_label(set, 0, 0, _("URL:"));
1002 screen->widgets.url_f = widget_new_textbox(set, 0, 0, 32, url);
1003 screen->widgets.url_help_l =
1004 widget_new_label(set, 0, 0, _("(eg. tftp://)"));
1006 str = talloc_strdup(screen, "");
1007 for (i = 0; i < config->network.n_dns_servers; i++) {
1008 str = talloc_asprintf_append(str, "%s%s",
1009 (i == 0) ? "" : " ",
1010 config->network.dns_servers[i]);
1013 screen->widgets.dns_l = widget_new_label(set, 0, 0,
1014 _("DNS Server(s):"));
1015 screen->widgets.dns_f = widget_new_textbox(set, 0, 0, 32, str);
1016 screen->widgets.dns_help_l =
1017 widget_new_label(set, 0, 0, _("(eg. 192.168.0.2)"));
1019 widget_textbox_set_validator_ipv4_multi(screen->widgets.dns_f);
1021 screen->widgets.dns_dhcp_help_l = widget_new_label(set, 0, 0,
1022 _("(if not provided by DHCP server)"));
1024 if (config->safe_mode)
1025 screen->widgets.safe_mode = widget_new_label(set, 0, 0,
1026 _("Selecting 'OK' will exit safe mode"));
1028 screen->widgets.allow_write_l = widget_new_label(set, 0, 0,
1030 screen->widgets.allow_write_f = widget_new_select(set, 0, 0,
1031 COLS - screen->field_x - 1);
1033 widget_select_add_option(screen->widgets.allow_write_f, 0,
1034 _("Prevent all writes to disk"),
1035 !config->allow_writes);
1037 widget_select_add_option(screen->widgets.allow_write_f, 1,
1038 _("Allow bootloader scripts to modify disks"),
1039 config->allow_writes);
1041 screen->widgets.boot_console_l = widget_new_label(set, 0, 0,
1042 _("Boot console:"));
1043 screen->widgets.boot_console_f = widget_new_select(set, 0, 0,
1044 COLS - screen->field_x - 1);
1046 for (i = 0; i < config->n_consoles; i++){
1047 found = config->boot_console &&
1048 strncmp(config->boot_console, config->consoles[i],
1049 strlen(config->boot_console)) == 0;
1050 widget_select_add_option(screen->widgets.boot_console_f, i,
1051 config->consoles[i], found);
1054 tty = talloc_asprintf(screen, _("Current interface: %s"),
1055 ttyname(STDIN_FILENO));
1056 screen->widgets.current_console_l = widget_new_label(set, 0 , 0, tty);
1058 screen->widgets.ok_b = widget_new_button(set, 0, 0, 10, _("OK"),
1060 screen->widgets.help_b = widget_new_button(set, 0, 0, 10, _("Help"),
1061 help_click, screen);
1062 screen->widgets.cancel_b = widget_new_button(set, 0, 0, 10, _("Cancel"),
1063 cancel_click, screen);
1066 static void config_screen_widget_focus(struct nc_widget *widget, void *arg)
1068 struct config_screen *screen = arg;
1069 int w_y, w_height, w_focus, s_max, adjust;
1071 w_height = widget_height(widget);
1072 w_focus = widget_focus_y(widget);
1073 w_y = widget_y(widget) + w_focus;
1074 s_max = getmaxy(screen->scr.sub_ncw) - 1;
1076 if (w_y < screen->scroll_y)
1077 screen->scroll_y = w_y;
1079 else if (w_y + screen->scroll_y + 1 > s_max) {
1080 /* Fit as much of the widget into the screen as possible */
1081 adjust = min(s_max - 1, w_height - w_focus);
1082 if (w_y + adjust >= screen->scroll_y + s_max)
1083 screen->scroll_y = max(0, 1 + w_y + adjust - s_max);
1087 pad_refresh(screen);
1090 static void config_screen_draw(struct config_screen *screen,
1091 const struct config *config,
1092 const struct system_info *sysinfo)
1094 bool repost = false;
1097 /* The size of the pad we'll need depends on the number of interfaces.
1099 * We use N_FIELDS (which is quite conservative, as some fields share
1100 * a line) as a base, then:
1101 * - add 6 (as the network select & boot device select fields take 3
1103 * - add n_interfaces for every field in the network select field, and
1104 * - add (n_blockdevs + n_interfaces) for every field in the boot device
1107 height = N_FIELDS + 6;
1109 height += sysinfo->n_interfaces;
1110 height += (sysinfo->n_blockdevs + sysinfo->n_interfaces);
1112 if (!screen->pad || getmaxy(screen->pad) < height) {
1114 delwin(screen->pad);
1115 screen->pad = newpad(height, COLS + 10);
1118 if (screen->widgetset) {
1119 widgetset_unpost(screen->widgetset);
1120 talloc_free(screen->widgetset);
1124 screen->widgetset = widgetset_create(screen, screen->scr.main_ncw,
1126 widgetset_set_widget_focus(screen->widgetset,
1127 config_screen_widget_focus, screen);
1129 if (!config || !sysinfo) {
1130 config_screen_setup_empty(screen);
1132 screen->net_conf_type = find_net_conf_type(config);
1133 config_screen_setup_widgets(screen, config, sysinfo);
1134 config_screen_layout_widgets(screen);
1138 widgetset_post(screen->widgetset);
1141 void config_screen_update(struct config_screen *screen,
1142 const struct config *config,
1143 const struct system_info *sysinfo)
1145 if (screen->cui->current != config_screen_scr(screen)) {
1146 screen->need_update = true;
1150 config_screen_draw(screen, config, sysinfo);
1151 pad_refresh(screen);
1154 static int config_screen_post(struct nc_scr *scr)
1156 struct config_screen *screen = config_screen_from_scr(scr);
1157 screen->show_subset = false;
1159 if (screen->need_update) {
1160 config_screen_draw(screen, screen->cui->config,
1161 screen->cui->sysinfo);
1162 screen->need_update = false;
1164 widgetset_post(screen->widgetset);
1167 nc_scr_frame_draw(scr);
1168 if (screen->need_redraw) {
1169 redrawwin(scr->main_ncw);
1170 screen->need_redraw = false;
1172 wrefresh(screen->scr.main_ncw);
1173 pad_refresh(screen);
1177 static int config_screen_destroy(void *arg)
1179 struct config_screen *screen = arg;
1181 delwin(screen->pad);
1185 struct config_screen *config_screen_init(struct cui *cui,
1186 const struct config *config,
1187 const struct system_info *sysinfo,
1188 void (*on_exit)(struct cui *))
1190 struct config_screen *screen;
1192 screen = talloc_zero(cui, struct config_screen);
1193 talloc_set_destructor(screen, config_screen_destroy);
1194 nc_scr_init(&screen->scr, pb_config_screen_sig, 0,
1195 cui, config_screen_process_key,
1196 config_screen_post, config_screen_unpost,
1197 config_screen_resize);
1200 screen->on_exit = on_exit;
1201 screen->need_redraw = false;
1202 screen->need_update = false;
1203 screen->label_x = 2;
1204 screen->field_x = 17;
1206 screen->ipmi_override = false;
1207 screen->show_subset = false;
1209 screen->scr.frame.ltitle = talloc_strdup(screen,
1210 _("Petitboot System Configuration"));
1211 screen->scr.frame.rtitle = NULL;
1212 screen->scr.frame.help = talloc_strdup(screen,
1213 _("tab=next, shift+tab=previous, x=exit, h=help"));
1214 nc_scr_frame_draw(&screen->scr);
1216 scrollok(screen->scr.sub_ncw, true);
1218 config_screen_draw(screen, config, sysinfo);