diff options
author | wollman <wollman@FreeBSD.org> | 1995-04-24 21:04:35 +0000 |
---|---|---|
committer | wollman <wollman@FreeBSD.org> | 1995-04-24 21:04:35 +0000 |
commit | a90da0ca41b1694b5b2cf38b7c36f912ad28b19e (patch) | |
tree | 980263aed3bcc058801d9292608a3f1b083db5eb /usr.sbin/tzsetup | |
parent | b75b8fba1b9063ee1f4f26a3c5e5d25503c71650 (diff) | |
download | FreeBSD-src-a90da0ca41b1694b5b2cf38b7c36f912ad28b19e.zip FreeBSD-src-a90da0ca41b1694b5b2cf38b7c36f912ad28b19e.tar.gz |
Grand new all-singing, dialog-wielding tzsetup(8). Still needs a man page.
Diffstat (limited to 'usr.sbin/tzsetup')
-rw-r--r-- | usr.sbin/tzsetup/Makefile | 20 | ||||
-rw-r--r-- | usr.sbin/tzsetup/grok.pl | 76 | ||||
-rw-r--r-- | usr.sbin/tzsetup/main.c | 265 | ||||
-rw-r--r-- | usr.sbin/tzsetup/tzmenu.c | 178 | ||||
-rw-r--r-- | usr.sbin/tzsetup/tzsetup.h | 55 |
5 files changed, 588 insertions, 6 deletions
diff --git a/usr.sbin/tzsetup/Makefile b/usr.sbin/tzsetup/Makefile index 6959dcb..0e316ef 100644 --- a/usr.sbin/tzsetup/Makefile +++ b/usr.sbin/tzsetup/Makefile @@ -1,12 +1,20 @@ -# $Id$ +# $Id: Makefile,v 1.1 1994/09/13 23:01:57 wollman Exp $ -NOPROG= tzsetup +PROG= tzsetup NOMAN= +SRCS= main.c tzmenu.c menus.c +CFLAGS+= -I. -I${.CURDIR} +CLEANFILES+= menus.c +LDADD+= -ldialog -lncurses -lmytinfo +DPADD+= ${LIBDIALOG} ${LIBNCURSES} ${LIBMYTINFO} -all depend: +Z= ${.CURDIR}/../../share/zoneinfo +.PATH: ${Z} -beforeinstall: - $(INSTALL) -c -m $(BINMODE) -o $(BINOWN) -g $(BINGRP) \ - ${.CURDIR}/tzsetup.sh ${DESTDIR}${BINDIR}/tzsetup +ZF= africa antarctica asia australasia europe northamerica southamerica + +menus.c: grok.pl ${ZF} + perl ${.CURDIR}/grok.pl `for a in ${ZF}; do echo ${Z}/$$a; done` \ + > ${.TARGET} .include <bsd.prog.mk> diff --git a/usr.sbin/tzsetup/grok.pl b/usr.sbin/tzsetup/grok.pl new file mode 100644 index 0000000..434554f --- /dev/null +++ b/usr.sbin/tzsetup/grok.pl @@ -0,0 +1,76 @@ +# -*- Perl -*- + +%reg_ctry = (); +%ctry_files = (); +%file_descrs = (); + +while(<>) { + next if(!/^\# ZONE-DESCR/); + chop; + split; + + shift(@_); shift(@_); # get rid of # ZONE-DESCR + + # Now $_[0] is region, $_[1] is filename, $_[2] is country, + # and @_[3 .. $#_] is the description + $reg = $_[0]; + $file = $_[1]; + $ctry = $_[2]; + $descr = join(' ', @_[3 .. $#_]); + + if($reg_ctry{$reg} =~ /$ctry/) { + # do nothing + } else { + $reg_ctry{$reg} = $ctry . "," . $reg_ctry{$reg}; + } + + $ctry_files{$ctry} .= ",$reg/$file"; + $file_descrs{"$reg/$file"} = $descr; +} + +print "/* This file automatically generated. */\n"; +print "#include \"tzsetup.h\"\n"; + +foreach $ctry (sort keys %ctry_files) { + print "const char *files_$ctry\[\] = {\n"; + $ctry_files{$ctry} =~ s/^,//; + foreach $file (sort {$file_descrs{$a} cmp $file_descrs{$b}} + split(/,/, $ctry_files{$ctry})) { + print "\t\"$file\",\n"; + } + print "\t0 };\n"; + print "const char *menu_$ctry\[\] = {\n"; + $i = 0; + + foreach $file (sort {$file_descrs{$a} cmp $file_descrs{$b}} + split(/,/, $ctry_files{$ctry})) { + $i++; + print "\t\"$i\", \"$file_descrs{$file}\",\n"; + } + print "\t0, 0 };\n"; + + print "struct country $ctry = { files_$ctry, menu_$ctry, $i };\n"; +} + +foreach $reg (sort keys %reg_ctry) { + print "\nstruct country *menu_$reg\[\] = {\n"; + $reg_ctry{$reg} =~ s/,$//; + foreach $ctry (sort split(/,/, $reg_ctry{$reg})) { + print "\t&$ctry,\n"; + } + + print "\t0 };\n"; + print "const char *name_$reg\[\] = {\n"; + $i = 0; + foreach $ctry (sort split(/,/, $reg_ctry{$reg})) { + $i++; + $ctry =~ s/_/ /g; + print "\t\"$i\", \"$ctry\",\n"; + } + print "\t0, 0 };\n"; + + print "struct region $reg = { menu_$reg, name_$reg, $i };\n"; +} + +exit 0; + diff --git a/usr.sbin/tzsetup/main.c b/usr.sbin/tzsetup/main.c new file mode 100644 index 0000000..bfdd1e1 --- /dev/null +++ b/usr.sbin/tzsetup/main.c @@ -0,0 +1,265 @@ +/* + * Copyright 1995 Massachusetts Institute of Technology + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby + * granted, provided that both the above copyright notice and this + * permission notice appear in all copies, that both the above + * copyright notice and this permission notice appear in all + * supporting documentation, and that the name of M.I.T. not be used + * in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. M.I.T. makes + * no representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied + * warranty. + * + * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS + * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT + * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +static const char rcsid[] = + "$Id$"; + +#include <stdio.h> +#include <ncurses.h> +#include <dialog.h> +#include <limits.h> +#include <time.h> +#include <stdlib.h> +#include <errno.h> + +#include "tzsetup.h" + +#define PATH_LOCALTIME "/etc/localtime" +#define PATH_WALL_CMOS_CLOCK "/etc/wall_cmos_clock" +#define PATH_ZONEINFO "/usr/share/zoneinfo" + +static int set_time(); + +enum cmos { CMOS_UTC, CMOS_LOCAL, CMOS_LEAVE } cmos_state = CMOS_LEAVE; +static int time_adjust = 0; +static enum cmos cmos(enum cmos); +static void fiddle_cmos(void); + +int +main(void) +{ + const char *tz; + + init_dialog(); + if (set_time() != 0) { + end_dialog(); + exit(1); + } + + tz = tzmenu(); + + fiddle_cmos(); + + dialog_notify("Reboot the machine for changes to take effect.\n"); + end_dialog(); + + fprintf(stderr, + "Now reboot your computer for the changes to take effect.\n"); + return tz ? 0 : 1; +} + +static int +set_time(void) +{ + unsigned char result[_POSIX2_LINE_MAX]; + unsigned char buf2[_POSIX2_LINE_MAX]; + static struct tm usertm, systm; + time_t usertime, systime; + long diff; + int rv; + + /* + * If /etc/wall_cmos_clock exists, or if there is already a timezone + * file installed, then just leave it alone and don't ask the user + * what time it is (because the system clock is already in POSIX + * time so we don't need to adjust anything later on). + */ + time(&systime); + systm = *localtime(&systime); + if (systm.tm_zone[0] + || access(PATH_WALL_CMOS_CLOCK, 0) == 0) { + cmos_state = CMOS_LEAVE; + return 0; + } + + usertm = systm; + usertm.tm_isdst = -1; + + result[0] = '\0'; + + while(1) { + rv = dialog_inputbox("Checking current time", + "Please enter the current local time" + " using 24-hour style,\n" + "in the form HH:MM", + 8, 78, result); + if (rv != 0) + return 1; + + if (result[0]) { + if (sscanf(result, "%d:%d:%d", &usertm.tm_hour, + &usertm.tm_min, + &usertm.tm_sec) < 2) { + snprintf(buf2, sizeof buf2, + "Invalid time format: %s", result); + dialog_notify(buf2); + continue; + } + usertime = mktime(&usertm); + if (usertime == (time_t)-1) { + snprintf(buf2, sizeof buf2, + "Unreasonable time: %s", result); + dialog_notify(buf2); + continue; + } + + diff = usertime - systime; + if (labs(diff) > 15*60) { + cmos_state = cmos(CMOS_LOCAL); + if (diff > 0) { + time_adjust = ((diff + 15*60)/30*60 + * 30*60); + } else { + time_adjust = ((diff - 15*60)/30*60 + * 30*60); + } + } else { + cmos_state = cmos(CMOS_UTC); + time_adjust = 0; + } + break; + } + } + return 0; +} + +static unsigned char *cmos_list[] = { + "1", "CMOS clock is set to local time", + "2", "CMOS clock is set to Universal time (UTC)", + "3", "I'm not sure, leave it alone" +}; + +static enum cmos +cmos(enum cmos state) +{ + int rv, sel = 0; + unsigned char buf[_POSIX2_LINE_MAX]; + unsigned char result[_POSIX2_LINE_MAX]; + + snprintf(buf, sizeof buf, "%s seems most likely", + state == CMOS_UTC ? "UTC" : "local time"); + + rv = dialog_menu("CMOS clock in local time or UTC", + buf, 12, 78, 3, 3, cmos_list, result, &sel, 0); + if (rv == 0) { + return sel; + } else { + return state; + } +} + +static void +fiddle_cmos(void) +{ + FILE *fp; + + switch(cmos_state) { + case CMOS_LEAVE: + case CMOS_UTC: + break; + case CMOS_LOCAL: + fp = fopen(PATH_WALL_CMOS_CLOCK, "w"); + if(fp) { + fclose(fp); + } /* xxx should have error message */ + } +} + + +int +setzone(const char *zone) +{ + time_t systime; + struct tm *tm; + char msg[_POSIX2_LINE_MAX]; + int rv; + FILE *ifp, *ofp; + + snprintf(msg, sizeof msg, "TZ=%s", zone); + putenv(msg); + tzset(); + time(&systime); + systime += time_adjust; + tm = localtime(&systime); + + snprintf(msg, sizeof msg, + "Does %02d:%02d:%02d %d.%d.%04d %s look reasonable?", + tm->tm_hour, tm->tm_min, tm->tm_sec, tm->tm_mday, tm->tm_mon, + tm->tm_year + 1900, tm->tm_zone); + + rv = dialog_yesno("Verifying timezone selection", + msg, -1, -1); + if (rv) + return 1; + + snprintf(msg, sizeof msg, PATH_ZONEINFO "/%s", zone); + ifp = fopen(msg, "r"); + if (!ifp) { + snprintf(msg, sizeof msg, + "Could not open " PATH_ZONEINFO "/%s: %s", + zone, strerror(errno)); + dialog_notify(msg); + return 1; + } + + ofp = fopen(PATH_LOCALTIME, "w"); + if (!ofp) { + snprintf(msg, sizeof msg, "Could not open " PATH_LOCALTIME + ": %s", strerror(errno)); + dialog_notify(msg); + fclose(ifp); + return 1; + } + + while((rv = fread(msg, 1, sizeof msg, ifp)) > 0) { + int rv2; + if((rv2 = fwrite(msg, 1, rv, ofp)) != rv) { + snprintf(msg, sizeof msg, + "Could not write " PATH_LOCALTIME ": %s", + strerror(errno)); +out: + dialog_notify(msg); + fclose(ifp); + fclose(ofp); + unlink(PATH_LOCALTIME); + return 1; + } + } + if (rv < 0) { + snprintf(msg, sizeof msg, "Could not read timezone file: %s", + strerror(errno)); + goto out; + } + + fclose(ifp); + fclose(ofp); + snprintf(msg, sizeof msg, "Installed timezone file %s", zone); + dialog_notify(msg); + return 0; +} diff --git a/usr.sbin/tzsetup/tzmenu.c b/usr.sbin/tzsetup/tzmenu.c new file mode 100644 index 0000000..c27c417 --- /dev/null +++ b/usr.sbin/tzsetup/tzmenu.c @@ -0,0 +1,178 @@ +/* + * Copyright 1995 Massachusetts Institute of Technology + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby + * granted, provided that both the above copyright notice and this + * permission notice appear in all copies, that both the above + * copyright notice and this permission notice appear in all + * supporting documentation, and that the name of M.I.T. not be used + * in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. M.I.T. makes + * no representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied + * warranty. + * + * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS + * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT + * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +static const char rcsid[] = + "$Id$"; + +#include <stdio.h> +#include <ncurses.h> +#include <dialog.h> +#include <limits.h> + +#include "tzsetup.h" + +static const char *regmenu[] = { + "1", "Africa", + "2", "Asia", + "3", "Atlantic Ocean islands", + "4", "Australia", + "5", "Europe (including Russia)", + "6", "Indian Ocean islands", + "7", "North and South America", + "8", "Pacific Ocean islands" +}; + +static struct region *regions[] = { + &Africa, + &Asia, + &Atlantic, + &Australia, + &Europe, + &Indian, + &America, + &Pacific +}; + +#define NREGIONS 8 + +static const char *country_menu(const struct region *, const char *); + +const char * +tzmenu(void) +{ + unsigned char rbuf[_POSIX2_LINE_MAX]; + int rv; + int item = 0; + int sc = 0; + const char *res; + + while(1) { + dialog_clear(); + rv = dialog_menu("Timezone Selector", + "Select a region", + NREGIONS + 6, + 78, + NREGIONS, + NREGIONS, + (unsigned char **)regmenu, + rbuf, + &item, + &sc); + + + if (rv != 0) { + return 0; + } + + res = country_menu(regions[item], + regmenu[2 * item + 1]); + + if (res) + return res; + } +} + +static const char *location_menu(const struct country *, const char *); + +static const char * +country_menu(const struct region *reg, const char *name) +{ + unsigned char rbuf[_POSIX2_LINE_MAX]; + unsigned char title[_POSIX2_LINE_MAX]; + int rv; + int item = 0; + int sc = 0; + const char *res; + + snprintf(title, sizeof title, "Timezone Selector - %s", name); + + while(1) { + dialog_clear(); + rv = dialog_menu(title, "Select a country", + reg->r_count > 18 ? 24 : reg->r_count + 6, + 78, + reg->r_count > 18 ? 18 : reg->r_count, + reg->r_count, + (unsigned char **)reg->r_menu, + rbuf, + &item, + &sc); + + + if (rv != 0) { + return 0; + } + + sscanf(rbuf, "%d", &rv); + + res = location_menu(reg->r_ctrylist[rv - 1], + reg->r_menu[2 * (rv - 1) + 1]); + + if (res) + return res; + } +} + +static const char * +location_menu(const struct country *ctry, const char *name) +{ + unsigned char rbuf[_POSIX2_LINE_MAX]; + unsigned char title[_POSIX2_LINE_MAX]; + int rv; + int item = 0; + int sc = 0; + const char *res; + + snprintf(title, sizeof title, "Timezone Selector - %s", name); + + while(1) { + dialog_clear(); + rv = dialog_menu(title, "Select a location", + ctry->c_count + 6, + 78, + ctry->c_count, + ctry->c_count, + (unsigned char **)ctry->c_menu, + rbuf, + &item, + &sc); + + + if (rv != 0) { + return 0; + } + + + rv = setzone(ctry->c_filelist[item]); + + if (rv == 0) + return ctry->c_filelist[item]; + } +} + diff --git a/usr.sbin/tzsetup/tzsetup.h b/usr.sbin/tzsetup/tzsetup.h new file mode 100644 index 0000000..ab8731b --- /dev/null +++ b/usr.sbin/tzsetup/tzsetup.h @@ -0,0 +1,55 @@ +/* + * Copyright 1995 Massachusetts Institute of Technology + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby + * granted, provided that both the above copyright notice and this + * permission notice appear in all copies, that both the above + * copyright notice and this permission notice appear in all + * supporting documentation, and that the name of M.I.T. not be used + * in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. M.I.T. makes + * no representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied + * warranty. + * + * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS + * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT + * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id$ + */ + +struct country { + const char **c_filelist; + const char **c_menu; + int c_count; +}; + +struct region { + struct country **r_ctrylist; + const char **r_menu; + int r_count; +}; + +extern struct region Africa; /* all of Africa */ +extern struct region America; /* North and South America */ +extern struct region Asia; /* all of Asia */ +extern struct region Atlantic; /* Atlantic Ocean islands */ +extern struct region Australia; /* Australia */ +extern struct region Europe; /* all of Europe including Russia */ +extern struct region Indian; /* Indian Ocean islands */ +extern struct region Pacific; /* Pacific Ocean islands */ + +extern int setzone(const char *); +extern const char *tzmenu(void); + |