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_button *ipmi_clear_b;
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;
109 struct nc_widget_label *http_proxy_l;
110 struct nc_widget_textbox *http_proxy_f;
111 struct nc_widget_label *https_proxy_l;
112 struct nc_widget_textbox *https_proxy_f;
114 struct nc_widget_label *allow_write_l;
115 struct nc_widget_select *allow_write_f;
116 struct nc_widget_label *boot_console_l;
117 struct nc_widget_select *boot_console_f;
118 struct nc_widget_label *manual_console_l;
119 struct nc_widget_label *current_console_l;
121 struct nc_widget_label *net_override_l;
122 struct nc_widget_label *safe_mode;
123 struct nc_widget_button *ok_b;
124 struct nc_widget_button *help_b;
125 struct nc_widget_button *cancel_b;
129 static struct config_screen *config_screen_from_scr(struct nc_scr *scr)
131 struct config_screen *config_screen;
133 assert(scr->sig == pb_config_screen_sig);
134 config_screen = (struct config_screen *)
135 ((char *)scr - (size_t)&((struct config_screen *)0)->scr);
136 assert(config_screen->scr.sig == pb_config_screen_sig);
137 return config_screen;
140 static void pad_refresh(struct config_screen *screen)
142 int y, x, rows, cols;
144 getmaxyx(screen->scr.sub_ncw, rows, cols);
145 getbegyx(screen->scr.sub_ncw, y, x);
147 prefresh(screen->pad, screen->scroll_y, 0, y, x, rows, cols);
150 static void config_screen_process_key(struct nc_scr *scr, int key)
152 struct config_screen *screen = config_screen_from_scr(scr);
155 handled = widgetset_process_key(screen->widgetset, key);
164 screen->show_help = true;
170 screen->on_exit(screen->cui);
172 } else if (screen->show_help) {
173 screen->show_help = false;
174 screen->need_redraw = true;
175 cui_show_help(screen->cui, _("System Configuration"),
178 } else if (handled && !screen->show_subset) {
183 static void config_screen_resize(struct nc_scr *scr)
185 struct config_screen *screen = config_screen_from_scr(scr);
189 static int config_screen_unpost(struct nc_scr *scr)
191 struct config_screen *screen = config_screen_from_scr(scr);
192 widgetset_unpost(screen->widgetset);
196 struct nc_scr *config_screen_scr(struct config_screen *screen)
201 static int screen_process_form(struct config_screen *screen)
203 const struct system_info *sysinfo = screen->cui->sysinfo;
204 enum net_conf_type net_conf_type;
205 struct interface_config *iface;
206 bool allow_write, autoboot;
208 struct config *config;
209 int i, n_boot_opts, rc;
210 unsigned int *order, idx;
213 config = config_copy(screen, screen->cui->config);
215 talloc_free(config->autoboot_opts);
216 config->n_autoboot_opts = 0;
218 n_boot_opts = widget_subset_get_order(config, &order,
219 screen->widgets.boot_order_f);
221 autoboot = widget_select_get_value(screen->widgets.autoboot_f);
222 config->autoboot_enabled = autoboot && n_boot_opts;
224 config->n_autoboot_opts = n_boot_opts;
225 config->autoboot_opts = talloc_array(config, struct autoboot_option,
228 for (i = 0; i < n_boot_opts; i++) {
229 if (order[i] < sysinfo->n_blockdevs) {
231 config->autoboot_opts[i].boot_type = BOOT_DEVICE_UUID;
232 config->autoboot_opts[i].uuid = talloc_strdup(config,
233 sysinfo->blockdevs[order[i]]->uuid);
234 } else if(order[i] < (sysinfo->n_blockdevs + sysinfo->n_interfaces)) {
236 order[i] -= sysinfo->n_blockdevs;
237 config->autoboot_opts[i].boot_type = BOOT_DEVICE_UUID;
238 mac_str(sysinfo->interfaces[order[i]]->hwaddr,
239 sysinfo->interfaces[order[i]]->hwaddr_size,
241 config->autoboot_opts[i].uuid = talloc_strdup(config, mac);
244 order[i] -= (sysinfo->n_blockdevs + sysinfo->n_interfaces);
245 config->autoboot_opts[i].boot_type = BOOT_DEVICE_TYPE;
246 config->autoboot_opts[i].type = order[i];
250 str = widget_textbox_get_value(screen->widgets.timeout_f);
254 x = strtoul(str, &end, 10);
255 if (!errno && end != str)
256 config->autoboot_timeout_sec = x;
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 talloc_free(config->http_proxy);
338 talloc_free(config->https_proxy);
339 str = widget_textbox_get_value(screen->widgets.http_proxy_f);
340 config->http_proxy = talloc_strdup(config, str);
341 str = widget_textbox_get_value(screen->widgets.https_proxy_f);
342 config->https_proxy = talloc_strdup(config, str);
344 allow_write = widget_select_get_value(screen->widgets.allow_write_f);
345 if (allow_write != config->allow_writes)
346 config->allow_writes = allow_write;
348 if (config->n_consoles && !config->manual_console) {
349 idx = widget_select_get_value(screen->widgets.boot_console_f);
350 if (!config->boot_console) {
351 config->boot_console = talloc_strdup(config,
352 config->consoles[idx]);
353 } else if (strncmp(config->boot_console, config->consoles[idx],
354 strlen(config->boot_console)) != 0) {
355 talloc_free(config->boot_console);
356 config->boot_console = talloc_strdup(config,
357 config->consoles[idx]);
361 config->safe_mode = false;
362 rc = cui_send_config(screen->cui, config);
366 pb_log("cui_send_config failed!\n");
368 pb_debug("config sent!\n");
373 static void ok_click(void *arg)
375 struct config_screen *screen = arg;
376 if (screen_process_form(screen))
377 /* errors are written to the status line, so we'll need
379 wrefresh(screen->scr.main_ncw);
384 static void help_click(void *arg)
386 struct config_screen *screen = arg;
387 screen->show_help = true;
390 static void cancel_click(void *arg)
392 struct config_screen *screen = arg;
396 static void ipmi_clear_click(void *arg)
398 struct config_screen *screen = arg;
399 struct config *config;
402 config = config_copy(screen, screen->cui->config);
403 config->ipmi_bootdev = IPMI_BOOTDEV_INVALID;
404 config->safe_mode = false;
406 rc = cui_send_config(screen->cui, config);
410 pb_log("cui_send_config failed!\n");
412 pb_debug("config sent!\n");
416 static int layout_pair(struct config_screen *screen, int y,
417 struct nc_widget_label *label,
418 struct nc_widget *field)
420 struct nc_widget *label_w = widget_label_base(label);
421 widget_move(label_w, y, screen->label_x);
422 widget_move(field, y, screen->field_x);
423 return max(widget_height(label_w), widget_height(field));
426 static void config_screen_layout_widgets(struct config_screen *screen)
428 struct nc_widget *wl, *wf, *wh;
433 /* currently, the longest label we have is the DNS-servers
434 * widget, so layout our screen based on that */
435 help_x = screen->field_x + 2 +
436 widget_width(widget_textbox_base(screen->widgets.dns_f));
438 wl = widget_label_base(screen->widgets.autoboot_l);
439 widget_set_visible(wl, true);
440 widget_move(wl, y, screen->label_x);
442 wf = widget_select_base(screen->widgets.autoboot_f);
443 widget_set_visible(wf, true);
444 widget_move(wf, y, screen->field_x);
445 y += widget_height(wf);
447 show = screen->autoboot_enabled;
452 wl = widget_label_base(screen->widgets.boot_order_l);
453 widget_set_visible(wl, show);
454 widget_move(wl, y, screen->label_x);
456 wf = widget_subset_base(screen->widgets.boot_order_f);
457 widget_move(wf, y, screen->field_x);
458 wl = widget_label_base(screen->widgets.boot_empty_l);
459 widget_move(wl, y, screen->field_x);
461 if (widget_subset_height(screen->widgets.boot_order_f)) {
462 widget_set_visible(wl, false);
463 widget_set_visible(wf, show);
464 y += show ? widget_height(wf) : 0;
466 widget_set_visible(wl, show);
467 widget_set_visible(wf, false);
473 widget_move(widget_button_base(screen->widgets.boot_add_b),
474 y++, screen->field_x);
475 widget_move(widget_button_base(screen->widgets.boot_any_b),
476 y++, screen->field_x);
477 widget_move(widget_button_base(screen->widgets.boot_none_b),
481 wf = widget_button_base(screen->widgets.boot_add_b);
482 if (widget_subset_n_inactive(screen->widgets.boot_order_f) && show)
483 widget_set_visible(wf, true);
485 widget_set_visible(wf, false);
490 widget_set_visible(widget_button_base(screen->widgets.boot_any_b), show);
491 widget_set_visible(widget_button_base(screen->widgets.boot_none_b), show);
493 wf = widget_textbox_base(screen->widgets.timeout_f);
494 wl = widget_label_base(screen->widgets.timeout_l);
495 wh = widget_label_base(screen->widgets.timeout_help_l);
496 widget_set_visible(wl, screen->autoboot_enabled);
497 widget_set_visible(wf, screen->autoboot_enabled);
498 widget_set_visible(wh, screen->autoboot_enabled);
499 if (screen->autoboot_enabled) {
500 widget_set_visible(wh, screen->autoboot_enabled);
501 widget_move(wl, y, screen->label_x);
502 widget_move(wf, y, screen->field_x);
503 widget_move(wh, y, screen->field_x + widget_width(wf) + 1);
508 if (screen->ipmi_override) {
509 wl = widget_label_base(screen->widgets.ipmi_type_l);
510 widget_set_visible(wl, true);
511 widget_move(wl, y, screen->label_x);
514 wl = widget_label_base(screen->widgets.ipmi_clear_l);
515 wf = widget_button_base(screen->widgets.ipmi_clear_b);
516 widget_set_visible(wl, true);
517 widget_set_visible(wf, true);
518 widget_move(wl, y, screen->label_x);
519 widget_move(wf, y, screen->field_x);
525 y += layout_pair(screen, y, screen->widgets.network_l,
526 widget_select_base(screen->widgets.network_f));
530 /* conditionally show iface select */
531 wl = widget_label_base(screen->widgets.iface_l);
532 wf = widget_select_base(screen->widgets.iface_f);
534 show = screen->net_conf_type == NET_CONF_TYPE_DHCP_ONE ||
535 screen->net_conf_type == NET_CONF_TYPE_STATIC;
537 widget_set_visible(wl, show);
538 widget_set_visible(wf, show);
541 y += layout_pair(screen, y, screen->widgets.iface_l, wf) + 1;
543 /* conditionally show static IP params */
544 show = screen->net_conf_type == NET_CONF_TYPE_STATIC;
546 wl = widget_label_base(screen->widgets.ip_addr_l);
547 wf = widget_textbox_base(screen->widgets.ip_addr_f);
548 widget_set_visible(wl, show);
549 widget_set_visible(wf, show);
550 x = screen->field_x + widget_width(wf) + 1;
553 layout_pair(screen, y, screen->widgets.ip_addr_l, wf);
555 wl = widget_label_base(screen->widgets.ip_mask_l);
556 wf = widget_textbox_base(screen->widgets.ip_mask_f);
557 widget_set_visible(wl, show);
558 widget_set_visible(wf, show);
561 widget_move(wl, y, x);
562 widget_move(wf, y, x + 2);
565 /* help for IP/mask */
566 wh = widget_label_base(screen->widgets.ip_addr_mask_help_l);
567 widget_set_visible(wh, show);
569 widget_move(wh, y, help_x);
573 wl = widget_label_base(screen->widgets.gateway_l);
574 wf = widget_textbox_base(screen->widgets.gateway_f);
575 wh = widget_label_base(screen->widgets.gateway_help_l);
576 widget_set_visible(wl, show);
577 widget_set_visible(wf, show);
578 widget_set_visible(wh, show);
581 layout_pair(screen, y, screen->widgets.gateway_l, wf);
582 widget_move(wh, y, help_x);
586 wl = widget_label_base(screen->widgets.url_l);
587 wf = widget_textbox_base(screen->widgets.url_f);
588 wh = widget_label_base(screen->widgets.url_help_l);
589 widget_set_visible(wl, show);
590 widget_set_visible(wf, show);
591 widget_set_visible(wh, show);
594 layout_pair(screen, y, screen->widgets.url_l, wf);
595 widget_move(wh, y, help_x);
599 wh = widget_label_base(screen->widgets.dns_help_l);
600 layout_pair(screen, y, screen->widgets.dns_l,
601 widget_textbox_base(screen->widgets.dns_f));
602 widget_move(wh, y, help_x);
605 /* we show the DNS/DHCP help if we're configuring DHCP */
606 show = screen->net_conf_type != NET_CONF_TYPE_STATIC;
607 wl = widget_label_base(screen->widgets.dns_dhcp_help_l);
608 widget_set_visible(wl, show);
610 widget_move(wl, y, screen->field_x);
614 wf = widget_textbox_base(screen->widgets.http_proxy_f);
615 layout_pair(screen, y, screen->widgets.http_proxy_l, wf);
617 wf = widget_textbox_base(screen->widgets.https_proxy_f);
618 layout_pair(screen, y, screen->widgets.https_proxy_l, wf);
623 layout_pair(screen, y, screen->widgets.allow_write_l,
624 widget_select_base(screen->widgets.allow_write_f));
625 y += widget_height(widget_select_base(screen->widgets.allow_write_f));
629 if (screen->widgets.manual_console_l) {
630 layout_pair(screen, y++, screen->widgets.boot_console_l,
631 widget_label_base(screen->widgets.manual_console_l));
632 widget_move(widget_label_base(screen->widgets.current_console_l),
634 widget_set_visible(widget_select_base(
635 screen->widgets.boot_console_f), false);
637 } else if (widget_height(widget_select_base(screen->widgets.boot_console_f))) {
638 layout_pair(screen, y, screen->widgets.boot_console_l,
639 widget_select_base(screen->widgets.boot_console_f));
640 y += widget_height(widget_select_base(screen->widgets.boot_console_f));
641 widget_move(widget_label_base(screen->widgets.current_console_l),
645 widget_set_visible(widget_label_base(
646 screen->widgets.boot_console_l), false);
647 widget_set_visible(widget_select_base(
648 screen->widgets.boot_console_f), false);
649 widget_set_visible(widget_label_base(
650 screen->widgets.current_console_l), false);
653 if (screen->net_override) {
654 widget_move(widget_label_base(screen->widgets.net_override_l),
656 widget_set_visible(widget_label_base(screen->widgets.net_override_l),
661 if (screen->cui->config->safe_mode) {
662 widget_move(widget_label_base(screen->widgets.safe_mode),
664 widget_set_visible(widget_label_base(screen->widgets.safe_mode),
669 widget_move(widget_button_base(screen->widgets.ok_b),
671 widget_move(widget_button_base(screen->widgets.help_b),
672 y, screen->field_x + 14);
673 widget_move(widget_button_base(screen->widgets.cancel_b),
674 y, screen->field_x + 28);
677 static void config_screen_network_change(void *arg, int value)
679 struct config_screen *screen = arg;
680 screen->net_conf_type = value;
681 widgetset_unpost(screen->widgetset);
682 config_screen_layout_widgets(screen);
683 widgetset_post(screen->widgetset);
686 static void config_screen_boot_order_change(void *arg, int value)
689 struct config_screen *screen = arg;
690 widgetset_unpost(screen->widgetset);
691 config_screen_layout_widgets(screen);
692 widgetset_post(screen->widgetset);
695 static void config_screen_autoboot_change(void *arg, int value)
697 struct config_screen *screen = arg;
698 screen->autoboot_enabled = !!value;
699 widgetset_unpost(screen->widgetset);
700 config_screen_layout_widgets(screen);
701 widgetset_post(screen->widgetset);
704 static void config_screen_add_device(void *arg)
706 struct config_screen *screen = arg;
708 screen->show_subset = true;
709 cui_show_subset(screen->cui, _("Select a boot device to add"),
710 screen->widgets.boot_order_f);
713 static void config_screen_autoboot_none(void *arg)
715 struct config_screen *screen = arg;
716 struct nc_widget_subset *subset = screen->widgets.boot_order_f;
718 widget_subset_clear_active(subset);
720 widgetset_unpost(screen->widgetset);
721 config_screen_layout_widgets(screen);
722 widgetset_post(screen->widgetset);
725 static void config_screen_autoboot_any(void *arg)
727 struct config_screen *screen = arg;
728 const struct system_info *sysinfo = screen->cui->sysinfo;
729 struct nc_widget_subset *subset = screen->widgets.boot_order_f;
732 widget_subset_clear_active(subset);
734 idx = sysinfo->n_blockdevs + sysinfo->n_interfaces + DEVICE_TYPE_ANY;
736 widget_subset_make_active(screen->widgets.boot_order_f, idx);
738 screen->autoboot_enabled = true;
740 widgetset_unpost(screen->widgetset);
741 config_screen_layout_widgets(screen);
742 widgetset_post(screen->widgetset);
745 static void config_screen_update_subset(void *arg,
746 struct nc_widget_subset *subset, int idx)
748 struct config_screen *screen = arg;
751 widget_subset_make_active(subset, idx);
752 if (!screen->autoboot_enabled)
753 screen->autoboot_enabled = true;
754 config_screen_layout_widgets(screen);
757 static struct interface_config *first_active_interface(
758 const struct config *config)
762 for (i = 0; i < config->network.n_interfaces; i++) {
763 if (config->network.interfaces[i]->ignore)
765 return config->network.interfaces[i];
770 static enum net_conf_type find_net_conf_type(const struct config *config)
772 struct interface_config *ifcfg;
774 ifcfg = first_active_interface(config);
777 return NET_CONF_TYPE_DHCP_ALL;
779 else if (ifcfg->method == CONFIG_METHOD_DHCP)
780 return NET_CONF_TYPE_DHCP_ONE;
782 else if (ifcfg->method == CONFIG_METHOD_STATIC)
783 return NET_CONF_TYPE_STATIC;
786 return NET_CONF_TYPE_DHCP_ALL;
789 static void config_screen_setup_empty(struct config_screen *screen)
791 widget_new_label(screen->widgetset, 2, screen->field_x,
792 _("Waiting for configuration data..."));
793 screen->widgets.cancel_b = widget_new_button(screen->widgetset,
794 4, screen->field_x, 9, _("Cancel"),
795 cancel_click, screen);
798 static int find_autoboot_idx(const struct system_info *sysinfo,
799 struct autoboot_option *opt)
803 if (opt->boot_type == BOOT_DEVICE_TYPE)
804 return sysinfo->n_blockdevs + sysinfo->n_interfaces + opt->type;
806 for (i = 0; i < sysinfo->n_blockdevs; i++) {
807 if (!strcmp(sysinfo->blockdevs[i]->uuid, opt->uuid))
811 for (i = 0; i < sysinfo->n_interfaces; i++) {
812 struct interface_info *info = sysinfo->interfaces[i];
815 mac_str(info->hwaddr, info->hwaddr_size, mac, sizeof(mac));
817 if (!strcmp(mac, opt->uuid))
818 return sysinfo->n_blockdevs + i;
824 static void config_screen_setup_widgets(struct config_screen *screen,
825 const struct config *config,
826 const struct system_info *sysinfo)
828 struct nc_widgetset *set = screen->widgetset;
829 struct interface_config *ifcfg;
830 char *str, *ip, *mask, *gw, *url, *tty, *label;
831 enum net_conf_type type;
833 int add_len, clear_len, any_len, min_len = 20;
836 build_assert(sizeof(screen->widgets) / sizeof(struct widget *)
839 type = screen->net_conf_type;
840 ifcfg = first_active_interface(config);
842 screen->autoboot_enabled = config->autoboot_enabled;
844 screen->widgets.autoboot_l = widget_new_label(set, 0, 0,
846 screen->widgets.autoboot_f = widget_new_select(set, 0, 0,
847 COLS - screen->field_x - 1);
849 widget_select_add_option(screen->widgets.autoboot_f, 0, _("Disabled"),
850 !screen->autoboot_enabled);
851 widget_select_add_option(screen->widgets.autoboot_f, 1, _("Enabled"),
852 screen->autoboot_enabled);
854 widget_select_on_change(screen->widgets.autoboot_f,
855 config_screen_autoboot_change, screen);
857 add_len = max(min_len, strncols(_("Add Device")));
858 clear_len = max(min_len, strncols(_("Clear")));
859 any_len = max(min_len, strncols(_("Clear & Boot Any")));
861 screen->widgets.boot_add_b = widget_new_button(set, 0, 0, add_len,
863 config_screen_add_device, screen);
865 screen->widgets.boot_none_b = widget_new_button(set, 0, 0, clear_len,
867 config_screen_autoboot_none, screen);
869 screen->widgets.boot_any_b = widget_new_button(set, 0, 0, any_len,
870 _("Clear & Boot Any"),
871 config_screen_autoboot_any, screen);
873 screen->widgets.boot_order_l = widget_new_label(set, 0, 0,
875 screen->widgets.boot_order_f = widget_new_subset(set, 0, 0,
876 COLS - screen->field_x,
877 config_screen_update_subset);
878 screen->widgets.boot_empty_l = widget_new_label(set, 0, 0,
881 widget_subset_on_change(screen->widgets.boot_order_f,
882 config_screen_boot_order_change, screen);
884 for (i = 0; i < sysinfo->n_blockdevs; i++) {
885 struct blockdev_info *bd = sysinfo->blockdevs[i];
887 label = talloc_asprintf(screen, _("disk: %s [uuid: %s]"),
890 widget_subset_add_option(screen->widgets.boot_order_f, label);
893 for (i = 0; i < sysinfo->n_interfaces; i++) {
894 struct interface_info *info = sysinfo->interfaces[i];
897 mac_str(info->hwaddr, info->hwaddr_size, mac, sizeof(mac));
899 label = talloc_asprintf(screen, _("net: %s [mac: %s]"),
902 widget_subset_add_option(screen->widgets.boot_order_f, label);
905 for (i = DEVICE_TYPE_NETWORK; i < DEVICE_TYPE_UNKNOWN; i++) {
907 if (i == DEVICE_TYPE_ANY)
908 label = talloc_asprintf(screen, _("Any Device"));
910 label = talloc_asprintf(screen, _("Any %s device"),
911 device_type_display_name(i));
913 widget_subset_add_option(screen->widgets.boot_order_f, label);
916 for (i = 0; i < config->n_autoboot_opts; i++) {
917 struct autoboot_option *opt = &config->autoboot_opts[i];
920 idx = find_autoboot_idx(sysinfo, opt);
923 widget_subset_make_active(screen->widgets.boot_order_f,
926 if (opt->boot_type == BOOT_DEVICE_TYPE)
927 pb_log("%s: Unknown autoboot option: %d\n",
928 __func__, opt->type);
930 pb_log("%s: Unknown autoboot UUID: %s\n",
931 __func__, opt->uuid);
936 str = talloc_asprintf(screen, "%d", config->autoboot_timeout_sec);
937 screen->widgets.timeout_l = widget_new_label(set, 0, 0, _("Timeout:"));
938 screen->widgets.timeout_f = widget_new_textbox(set, 0, 0, 5, str);
939 screen->widgets.timeout_help_l = widget_new_label(set, 0, 0,
942 widget_textbox_set_fixed_size(screen->widgets.timeout_f);
943 widget_textbox_set_validator_integer(screen->widgets.timeout_f, 0, 999);
945 if (config->ipmi_bootdev) {
946 label = talloc_asprintf(screen,
947 _("%s IPMI boot option: %s"),
948 config->ipmi_bootdev_persistent ?
949 _("Persistent") : _("Temporary"),
950 ipmi_bootdev_display_name(config->ipmi_bootdev));
951 screen->widgets.ipmi_type_l = widget_new_label(set, 0, 0,
953 screen->widgets.ipmi_clear_l = widget_new_label(set, 0, 0,
955 screen->widgets.ipmi_clear_b = widget_new_button(set, 0, 0,
956 strncols(_("Clear IPMI override now")) + 10,
957 _("Clear IPMI override now"),
958 ipmi_clear_click, screen);
959 screen->ipmi_override = true;
962 screen->widgets.network_l = widget_new_label(set, 0, 0, _("Network:"));
963 screen->widgets.network_f = widget_new_select(set, 0, 0,
964 COLS - screen->field_x - 1);
966 widget_select_add_option(screen->widgets.network_f,
967 NET_CONF_TYPE_DHCP_ALL,
968 _("DHCP on all active interfaces"),
969 type == NET_CONF_TYPE_DHCP_ALL);
970 widget_select_add_option(screen->widgets.network_f,
971 NET_CONF_TYPE_DHCP_ONE,
972 _("DHCP on a specific interface"),
973 type == NET_CONF_TYPE_DHCP_ONE);
974 widget_select_add_option(screen->widgets.network_f,
975 NET_CONF_TYPE_STATIC,
976 _("Static IP configuration"),
977 type == NET_CONF_TYPE_STATIC);
979 widget_select_on_change(screen->widgets.network_f,
980 config_screen_network_change, screen);
982 screen->widgets.iface_l = widget_new_label(set, 0, 0, _("Device:"));
983 screen->widgets.iface_f = widget_new_select(set, 0, 0, 50);
985 for (i = 0; i < sysinfo->n_interfaces; i++) {
986 struct interface_info *info = sysinfo->interfaces[i];
987 char str[50], mac[20];
990 is_default = ifcfg && !memcmp(ifcfg->hwaddr, info->hwaddr,
991 sizeof(ifcfg->hwaddr));
993 mac_str(info->hwaddr, info->hwaddr_size, mac, sizeof(mac));
994 snprintf(str, sizeof(str), "%s [%s, %s]", info->name, mac,
995 info->link ? _("link up") : _("link down"));
997 widget_select_add_option(screen->widgets.iface_f,
1001 url = gw = ip = mask = NULL;
1002 if (ifcfg && ifcfg->method == CONFIG_METHOD_STATIC) {
1005 str = talloc_strdup(screen, ifcfg->static_config.address);
1006 sep = strchr(str, '/');
1013 gw = ifcfg->static_config.gateway;
1014 url = ifcfg->static_config.url;
1017 screen->net_override = ifcfg && ifcfg->override;
1018 if (screen->net_override) {
1019 screen->widgets.net_override_l = widget_new_label(set, 0, 0,
1020 _("Network Override Active! 'OK' will overwrite interface config"));
1023 screen->widgets.ip_addr_l = widget_new_label(set, 0, 0, _("IP/mask:"));
1024 screen->widgets.ip_addr_f = widget_new_textbox(set, 0, 0, 16, ip);
1025 screen->widgets.ip_mask_l = widget_new_label(set, 0, 0, "/");
1026 screen->widgets.ip_mask_f = widget_new_textbox(set, 0, 0, 3, mask);
1027 screen->widgets.ip_addr_mask_help_l =
1028 widget_new_label(set, 0, 0, _("(eg. 192.168.0.10 / 24)"));
1030 widget_textbox_set_fixed_size(screen->widgets.ip_addr_f);
1031 widget_textbox_set_fixed_size(screen->widgets.ip_mask_f);
1032 widget_textbox_set_validator_ipv4(screen->widgets.ip_addr_f);
1033 widget_textbox_set_validator_integer(screen->widgets.ip_mask_f, 1, 31);
1035 screen->widgets.gateway_l = widget_new_label(set, 0, 0, _("Gateway:"));
1036 screen->widgets.gateway_f = widget_new_textbox(set, 0, 0, 16, gw);
1037 screen->widgets.gateway_help_l =
1038 widget_new_label(set, 0, 0, _("(eg. 192.168.0.1)"));
1040 widget_textbox_set_fixed_size(screen->widgets.gateway_f);
1041 widget_textbox_set_validator_ipv4(screen->widgets.gateway_f);
1043 screen->widgets.url_l = widget_new_label(set, 0, 0, _("URL:"));
1044 screen->widgets.url_f = widget_new_textbox(set, 0, 0, 32, url);
1045 screen->widgets.url_help_l =
1046 widget_new_label(set, 0, 0, _("(eg. tftp://)"));
1048 str = talloc_strdup(screen, "");
1049 for (i = 0; i < config->network.n_dns_servers; i++) {
1050 str = talloc_asprintf_append(str, "%s%s",
1051 (i == 0) ? "" : " ",
1052 config->network.dns_servers[i]);
1055 screen->widgets.dns_l = widget_new_label(set, 0, 0,
1056 _("DNS Server(s):"));
1057 screen->widgets.dns_f = widget_new_textbox(set, 0, 0, 32, str);
1058 screen->widgets.dns_help_l =
1059 widget_new_label(set, 0, 0, _("(eg. 192.168.0.2)"));
1061 widget_textbox_set_validator_ipv4_multi(screen->widgets.dns_f);
1063 screen->widgets.dns_dhcp_help_l = widget_new_label(set, 0, 0,
1064 _("(if not provided by DHCP server)"));
1066 screen->widgets.http_proxy_l = widget_new_label(set, 0, 0,
1068 screen->widgets.http_proxy_f = widget_new_textbox(set, 0, 0, 32,
1069 config->http_proxy);
1070 screen->widgets.https_proxy_l = widget_new_label(set, 0, 0,
1072 screen->widgets.https_proxy_f = widget_new_textbox(set, 0, 0, 32,
1073 config->https_proxy);
1075 if (config->safe_mode)
1076 screen->widgets.safe_mode = widget_new_label(set, 0, 0,
1077 _("Selecting 'OK' will exit safe mode"));
1079 screen->widgets.allow_write_l = widget_new_label(set, 0, 0,
1081 screen->widgets.allow_write_f = widget_new_select(set, 0, 0,
1082 COLS - screen->field_x - 1);
1084 widget_select_add_option(screen->widgets.allow_write_f, 0,
1085 _("Prevent all writes to disk"),
1086 !config->allow_writes);
1088 widget_select_add_option(screen->widgets.allow_write_f, 1,
1089 _("Allow bootloader scripts to modify disks"),
1090 config->allow_writes);
1092 screen->widgets.boot_console_l = widget_new_label(set, 0, 0,
1093 _("Boot console:"));
1094 screen->widgets.boot_console_f = widget_new_select(set, 0, 0,
1095 COLS - screen->field_x - 1);
1097 for (i = 0; i < config->n_consoles; i++){
1098 found = config->boot_console &&
1099 strncmp(config->boot_console, config->consoles[i],
1100 strlen(config->boot_console)) == 0;
1101 widget_select_add_option(screen->widgets.boot_console_f, i,
1102 config->consoles[i], found);
1105 if (config->manual_console) {
1106 label = talloc_asprintf(screen, _("Manually set: '%s'"),
1107 config->boot_console);
1108 screen->widgets.manual_console_l = widget_new_label(set, 0, 0, label);
1111 tty = talloc_asprintf(screen, _("Current interface: %s"),
1112 ttyname(STDIN_FILENO));
1113 screen->widgets.current_console_l = widget_new_label(set, 0 , 0, tty);
1115 screen->widgets.ok_b = widget_new_button(set, 0, 0, 10, _("OK"),
1117 screen->widgets.help_b = widget_new_button(set, 0, 0, 10, _("Help"),
1118 help_click, screen);
1119 screen->widgets.cancel_b = widget_new_button(set, 0, 0, 10, _("Cancel"),
1120 cancel_click, screen);
1123 static void config_screen_widget_focus(struct nc_widget *widget, void *arg)
1125 struct config_screen *screen = arg;
1126 int w_y, w_height, w_focus, s_max, adjust;
1128 w_height = widget_height(widget);
1129 w_focus = widget_focus_y(widget);
1130 w_y = widget_y(widget) + w_focus;
1131 s_max = getmaxy(screen->scr.sub_ncw) - 1;
1133 if (w_y < screen->scroll_y)
1134 screen->scroll_y = w_y;
1136 else if (w_y + screen->scroll_y + 1 > s_max) {
1137 /* Fit as much of the widget into the screen as possible */
1138 adjust = min(s_max - 1, w_height - w_focus);
1139 if (w_y + adjust >= screen->scroll_y + s_max)
1140 screen->scroll_y = max(0, 1 + w_y + adjust - s_max);
1144 pad_refresh(screen);
1147 static void config_screen_draw(struct config_screen *screen,
1148 const struct config *config,
1149 const struct system_info *sysinfo)
1151 bool repost = false;
1154 /* The size of the pad we'll need depends on the number of interfaces.
1156 * We use N_FIELDS (which is quite conservative, as some fields share
1157 * a line) as a base, then:
1158 * - add 6 (as the network select & boot device select fields take 3
1160 * - add n_interfaces for every field in the network select field, and
1161 * - add (n_blockdevs + n_interfaces) for every field in the boot device
1164 height = N_FIELDS + 6;
1166 height += sysinfo->n_interfaces;
1167 height += (sysinfo->n_blockdevs + sysinfo->n_interfaces);
1169 if (!screen->pad || getmaxy(screen->pad) < height) {
1171 delwin(screen->pad);
1172 screen->pad = newpad(height, COLS + 10);
1175 if (screen->widgetset) {
1176 widgetset_unpost(screen->widgetset);
1177 talloc_free(screen->widgetset);
1181 screen->widgetset = widgetset_create(screen, screen->scr.main_ncw,
1183 widgetset_set_widget_focus(screen->widgetset,
1184 config_screen_widget_focus, screen);
1186 if (!config || !sysinfo) {
1187 config_screen_setup_empty(screen);
1189 screen->net_conf_type = find_net_conf_type(config);
1190 config_screen_setup_widgets(screen, config, sysinfo);
1191 config_screen_layout_widgets(screen);
1195 widgetset_post(screen->widgetset);
1198 void config_screen_update(struct config_screen *screen,
1199 const struct config *config,
1200 const struct system_info *sysinfo)
1202 if (screen->cui->current != config_screen_scr(screen)) {
1203 screen->need_update = true;
1207 config_screen_draw(screen, config, sysinfo);
1208 pad_refresh(screen);
1211 static int config_screen_post(struct nc_scr *scr)
1213 struct config_screen *screen = config_screen_from_scr(scr);
1214 screen->show_subset = false;
1216 if (screen->need_update) {
1217 config_screen_draw(screen, screen->cui->config,
1218 screen->cui->sysinfo);
1219 screen->need_update = false;
1221 widgetset_post(screen->widgetset);
1224 nc_scr_frame_draw(scr);
1225 if (screen->need_redraw) {
1226 redrawwin(scr->main_ncw);
1227 screen->need_redraw = false;
1229 wrefresh(screen->scr.main_ncw);
1230 pad_refresh(screen);
1234 static int config_screen_destroy(void *arg)
1236 struct config_screen *screen = arg;
1238 delwin(screen->pad);
1242 struct config_screen *config_screen_init(struct cui *cui,
1243 const struct config *config,
1244 const struct system_info *sysinfo,
1245 void (*on_exit)(struct cui *))
1247 struct config_screen *screen;
1249 screen = talloc_zero(cui, struct config_screen);
1250 talloc_set_destructor(screen, config_screen_destroy);
1251 nc_scr_init(&screen->scr, pb_config_screen_sig, 0,
1252 cui, config_screen_process_key,
1253 config_screen_post, config_screen_unpost,
1254 config_screen_resize);
1257 screen->on_exit = on_exit;
1258 screen->need_redraw = false;
1259 screen->need_update = false;
1260 screen->label_x = 2;
1261 screen->field_x = 17;
1263 screen->ipmi_override = false;
1264 screen->show_subset = false;
1266 screen->scr.frame.ltitle = talloc_strdup(screen,
1267 _("Petitboot System Configuration"));
1268 screen->scr.frame.rtitle = NULL;
1269 screen->scr.frame.help = talloc_strdup(screen,
1270 _("tab=next, shift+tab=previous, x=exit, h=help"));
1271 nc_scr_frame_draw(&screen->scr);
1273 scrollok(screen->scr.sub_ncw, true);
1275 config_screen_draw(screen, config, sysinfo);