From caa284ac57b7aa84ccca35e2d9a3f5086ed333b3 Mon Sep 17 00:00:00 2001 From: hubertf Date: Tue, 15 Aug 2000 01:08:00 +0000 Subject: [PATCH] * Add timezone-setting menu to sysinst, offering all timezones from (/mnt)/usr/share/zoneinfo in a listbox, and setting (/mnt)/etc/localtime accordingly. * Adjust for the needed menuc change un run.c's log_flip() and script_flip() functions. Related PRs: 5777 sysinst does not offer to tweak /etc/localtime 8099 changing the default time zone is non-obvious 9910 sysinst doesn't ask about setting timezone --- distrib/utils/sysinst/defs.h | 3 +- distrib/utils/sysinst/install.c | 4 +- distrib/utils/sysinst/menus.mi.en | 6 +- distrib/utils/sysinst/msg.mi.en | 11 +- distrib/utils/sysinst/run.c | 10 +- distrib/utils/sysinst/util.c | 165 +++++++++++++++++++++++++++++- 6 files changed, 189 insertions(+), 10 deletions(-) diff --git a/distrib/utils/sysinst/defs.h b/distrib/utils/sysinst/defs.h index e914c168a714..23382bfc2cf9 100644 --- a/distrib/utils/sysinst/defs.h +++ b/distrib/utils/sysinst/defs.h @@ -1,4 +1,4 @@ -/* $NetBSD: defs.h,v 1.54 2000/07/24 10:52:28 itojun Exp $ */ +/* $NetBSD: defs.h,v 1.55 2000/08/15 01:08:00 hubertf Exp $ */ /* * Copyright 1997 Piermont Information Systems Inc. @@ -328,6 +328,7 @@ void make_ramdisk_dir __P((const char *path)); void ask_verbose_dist __P((void)); int get_and_unpack_sets(msg success_msg, msg failure_msg); int sanity_check __P((void)); +int set_timezone __P((void)); /* from target.c */ int must_mount_root __P((void)); diff --git a/distrib/utils/sysinst/install.c b/distrib/utils/sysinst/install.c index 26c6cfea085a..753744b1d0bb 100644 --- a/distrib/utils/sysinst/install.c +++ b/distrib/utils/sysinst/install.c @@ -1,4 +1,4 @@ -/* $NetBSD: install.c,v 1.19 1999/06/22 06:57:00 cgd Exp $ */ +/* $NetBSD: install.c,v 1.20 2000/08/15 01:08:00 hubertf Exp $ */ /* * Copyright 1997 Piermont Information Systems Inc. @@ -125,6 +125,8 @@ do_install() if (get_and_unpack_sets(MSG_instcomplete, MSG_abortinst) != 0) return; + set_timezone(); + sanity_check(); md_cleanup_install(); diff --git a/distrib/utils/sysinst/menus.mi.en b/distrib/utils/sysinst/menus.mi.en index b436c39bc935..af558b36a107 100644 --- a/distrib/utils/sysinst/menus.mi.en +++ b/distrib/utils/sysinst/menus.mi.en @@ -1,4 +1,4 @@ -/* $NetBSD: menus.mi.en,v 1.42 2000/07/06 20:25:26 jhawk Exp $ */ +/* $NetBSD: menus.mi.en,v 1.43 2000/08/15 01:08:00 hubertf Exp $ */ /* * Copyright 1997 Piermont Information Systems Inc. @@ -77,6 +77,10 @@ menu utility, title "NetBSD-@@VERSION@@ Utilities", exit; option "Run /bin/sh", action (endwin) { system("/bin/sh"); }; /* option "test", action { run_prog(0, 1, NULL, "/bin/pwd"); }; */ + option "Set timezone", + action { + set_timezone(); + }; option "Configure network", action { extern int network_up; diff --git a/distrib/utils/sysinst/msg.mi.en b/distrib/utils/sysinst/msg.mi.en index b387b0909cb0..dac8943281e3 100644 --- a/distrib/utils/sysinst/msg.mi.en +++ b/distrib/utils/sysinst/msg.mi.en @@ -1,4 +1,4 @@ -/* $NetBSD: msg.mi.en,v 1.64 2000/08/10 17:06:02 hubertf Exp $ */ +/* $NetBSD: msg.mi.en,v 1.65 2000/08/15 01:08:00 hubertf Exp $ */ /* * Copyright 1997 Piermont Information Systems Inc. @@ -748,3 +748,12 @@ of this partition to the new NetBSD-only partition type?} message continue {Continue?} +message choose_timezone +{Please choose the timezone that fits you best from the list below. +Press RETURN to select an entry, press 'x' followed by RETURN to quit +the timezone selection. + + Default: %s + Selected: %s + Local time: %s %s +} diff --git a/distrib/utils/sysinst/run.c b/distrib/utils/sysinst/run.c index d86f5d43990c..9f6b9daae82c 100644 --- a/distrib/utils/sysinst/run.c +++ b/distrib/utils/sysinst/run.c @@ -1,4 +1,4 @@ -/* $NetBSD: run.c,v 1.30 2000/04/14 21:46:11 thorpej Exp $ */ +/* $NetBSD: run.c,v 1.31 2000/08/15 01:08:00 hubertf Exp $ */ /* * Copyright 1997 Piermont Information Systems Inc. @@ -72,8 +72,8 @@ */ char* va_prog_cmdstr __P((const char *cmd, va_list ap)); int launch_subwin __P((WINDOW *actionwin, char **args, struct winsize win, int display)); -int log_flip __P((void)); -int script_flip __P((void)); +int log_flip __P((menudesc *)); +int script_flip __P((menudesc *)); #define BUFSIZE 4096 @@ -103,7 +103,7 @@ do_logging(void) } int -log_flip(void) +log_flip(menudesc *m) { time_t tloc; @@ -129,7 +129,7 @@ log_flip(void) } int -script_flip(void) +script_flip(menudesc *m) { time_t tloc; diff --git a/distrib/utils/sysinst/util.c b/distrib/utils/sysinst/util.c index 08ef75e254f1..a956f67043d9 100644 --- a/distrib/utils/sysinst/util.c +++ b/distrib/utils/sysinst/util.c @@ -1,4 +1,4 @@ -/* $NetBSD: util.c,v 1.51 2000/06/18 13:40:41 hubertf Exp $ */ +/* $NetBSD: util.c,v 1.52 2000/08/15 01:08:00 hubertf Exp $ */ /* * Copyright 1997 Piermont Information Systems Inc. @@ -47,6 +47,7 @@ #include #include #include +#include #include "defs.h" #include "md.h" #include "msg_defs.h" @@ -899,3 +900,165 @@ int askyesno(int reverse) refresh(); return(found); } + +/* + * Some globals to pass things back from callbacks + */ +static char zoneinfo_dir[STRSIZE]; +static char *tz_selected; /* timezonename (relative to share/zoneinfo */ +static char *tz_default; /* UTC, or whatever /etc/localtime points to */ +static char tz_env[STRSIZE]; + +/* + * Callback from timezone menu + */ +static int +set_timezone_select(menudesc *m) +{ + time_t t; + + if (m) + tz_selected = m->opts[m->cursel].opt_name; + snprintf(tz_env, sizeof(tz_env), "%s/%s", + zoneinfo_dir, tz_selected); + setenv("TZ", tz_env, 1); + t = time(NULL); + msg_display(MSG_choose_timezone, + tz_default, tz_selected, ctime(&t), localtime(&t)->tm_zone); + return 0; +} + +/* + * Alarm-handler to update example-display + */ +static void +timezone_sig(int sig) +{ + set_timezone_select(NULL); + alarm(1); +} + +/* + * Choose from the files in usr/share/zoneinfo and set etc/localtime + */ +int +set_timezone() +{ + char localtime_link[STRSIZE]; + char localtime_target[STRSIZE]; + int rc; + time_t t; + sig_t oldalrm; + FTS *tree; + FTSENT *entry; + int rval; + char *argv[2]; + int skip; + struct stat sb; + int nfiles, n; + int menu_no; + menu_ent *tz_menu; + + oldalrm=signal(SIGALRM, timezone_sig); + alarm(1); + + strncpy(zoneinfo_dir, target_expand("/usr/share/zoneinfo"), STRSIZE); + strncpy(localtime_link, target_expand("/etc/localtime"), STRSIZE); + + /* Add sanity check that /mnt/usr/share/zoneinfo contains + * something useful */ + + rc = readlink(localtime_link, localtime_target, + sizeof(localtime_target)); + if (rc < 0) { + endwin(); + printf("readlink(\"%s\")\n", localtime_link); + exit (1); + } + localtime_target[rc] = '\0'; + + tz_default = strchr(strstr(localtime_target, "zoneinfo"), '/')+1; + tz_selected=tz_default; + snprintf(tz_env, sizeof(tz_env), "%s/%s", + zoneinfo_dir, tz_selected); + setenv("TZ", tz_env, 1); + t = time(NULL); + msg_display(MSG_choose_timezone, + tz_default, tz_selected, ctime(&t), localtime(&t)->tm_zone); + + skip = strlen(zoneinfo_dir); + argv[0] = zoneinfo_dir; + argv[1] = NULL; + if (!(tree = fts_open(argv, FTS_LOGICAL, NULL))) { + endwin(); + fprintf(stderr, "ftsopen failed\n"); + exit(1); + } + for (nfiles = 0; (entry = fts_read(tree)) != NULL;) { + stat(entry->fts_accpath, &sb); + if (S_ISREG(sb.st_mode)) + nfiles++; + } + if (errno) { + endwin(); + fprintf(stderr, "fts_read\n"); + exit(1); + } + (void)fts_close(tree); + + tz_menu = malloc(nfiles * sizeof(struct menu_ent)); + if (tz_menu == NULL) { + endwin(); + fprintf(stderr, "malloc nfiles*menu_ent\n"); + exit(1); + } + + if (!(tree = fts_open(argv, FTS_LOGICAL, NULL))) { + endwin(); + fprintf(stderr, "ftsopen failed\n"); + exit(1); + } + n=0; + for (rval=0; (entry = fts_read(tree)) != NULL; ) { + + stat(entry->fts_accpath, &sb); + if (S_ISREG(sb.st_mode)) { + tz_menu[n].opt_name = strdup(entry->fts_accpath+skip+1); + tz_menu[n].opt_menu = OPT_NOMENU; + tz_menu[n].opt_flags = 0; + tz_menu[n].opt_action = set_timezone_select; + + n++; + } + } + if (errno) { + endwin(); + fprintf(stderr, "fts_read\n"); + exit(1); + } + (void)fts_close(tree); + + menu_no = new_menu(NULL, tz_menu, nfiles, 23, 9, + 12, 32, MC_SCROLL|MC_NOSHORTCUT, NULL, NULL, + "\nPlease consult the install documents."); + if (menu_no < 0) { + endwin(); + (void) fprintf(stderr, "Dynamic menu creation failed.\n"); + exit(1); + } + process_menu(menu_no); + + free_menu(menu_no); + for(n=0; n < nfiles; n++) + free(tz_menu[n].opt_name); + free(tz_menu); + + signal(SIGALRM, SIG_IGN); + + snprintf(localtime_target, sizeof(localtime_target), + "/usr/share/zoneinfo/%s", tz_selected); + unlink(localtime_link); + symlink(localtime_target, localtime_link); + + return 1; +}