From owner-svn-src-all@FreeBSD.ORG Fri Dec 16 23:44:16 2011 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 91EC9106564A; Fri, 16 Dec 2011 23:44:16 +0000 (UTC) (envelope-from dougb@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 7E8CA8FC15; Fri, 16 Dec 2011 23:44:16 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id pBGNiGmw032764; Fri, 16 Dec 2011 23:44:16 GMT (envelope-from dougb@svn.freebsd.org) Received: (from dougb@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id pBGNiGbN032761; Fri, 16 Dec 2011 23:44:16 GMT (envelope-from dougb@svn.freebsd.org) Message-Id: <201112162344.pBGNiGbN032761@svn.freebsd.org> From: Doug Barton Date: Fri, 16 Dec 2011 23:44:16 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-7@freebsd.org X-SVN-Group: stable-7 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r228608 - stable/7/usr.sbin/tzsetup X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 16 Dec 2011 23:44:16 -0000 Author: dougb Date: Fri Dec 16 23:44:16 2011 New Revision: 228608 URL: http://svn.freebsd.org/changeset/base/228608 Log: MFC: r179530 - Replace rcsid with __FBSDID. - Remove paths.h and embed it in the source. - Remove stale alpha support. - Clean up compiler warnings and fix style(9) bugs. Not MFC'ed by: jkim MFC: r195339 Add a new options (-s) that, when specified, skips the question about adjusting the clock to UTC. That avoids to write on /etc/wall_cmos_clock which is useful in some cases (example: host user in a jail). Not MFC'ed by: attilio MFC: r198254 When tzsetup is run as non-root and the "CMOS clock question on UTC" is answered as No, it would abort without properly ending the dialog session. Not MFC'ed by: edwin MFC: r198267 Instead of having to know which timezone was picked last time, you now can run "tzsetup -r" which will reinstall the last choice. This data is recorded in /var/db/zoneinfo. Not MFC'ed by: edwin MFC: r198350 - Add support for chrooted installs. - Add examples to the man-page. Not MFC'ed by: edwin MFC: r208830 When there is a problem with writing, also bail out. Not MFC'ed by: edwin MFC: r208831 Add comment that this value is unused. It is obvious that it isn't used, but both clang and Coverity talk about it. Not MFC'ed by: edwin MFC: r209190 Use literal format strings. Found by clang. Not MFC'ed by: emaste MFC: r210243 Fix support for chrooted installs. Not MFC'ed by: nork While mentored by: imp MFC: r220172 Add a menu entry for UTC in the main menu. Not MFC'ed by: edwin MFC: r222139 - add missing options and arguments to program's usage() and sync it with manpage's SYNOPSIS - generally clean up a manpage's formatting Not MFC'ed by: ru MFC: r227011 If the user is moving from any other time zone to UTC we need to delete any old /var/db/zoneinfo file that may exist so that tzsetup -r does the right thing. Deleted: stable/7/usr.sbin/tzsetup/paths.h Modified: stable/7/usr.sbin/tzsetup/tzsetup.8 stable/7/usr.sbin/tzsetup/tzsetup.c Directory Properties: stable/7/usr.sbin/tzsetup/ (props changed) Modified: stable/7/usr.sbin/tzsetup/tzsetup.8 ============================================================================== --- stable/7/usr.sbin/tzsetup/tzsetup.8 Fri Dec 16 23:43:58 2011 (r228607) +++ stable/7/usr.sbin/tzsetup/tzsetup.8 Fri Dec 16 23:44:16 2011 (r228608) @@ -23,7 +23,8 @@ .\" SUCH DAMAGE. .\" .\" $FreeBSD$ -.Dd September 05, 2009 +.\" +.Dd October 21, 2009 .Dt TZSETUP 8 .Os .Sh NAME @@ -31,8 +32,9 @@ .Nd set local timezone .Sh SYNOPSIS .Nm -.Op Fl ns -.Op Ar default +.Op Fl nrs +.Op Fl C Ar chroot_directory +.Op Ar zoneinfo_file | zoneinfo_name .Sh DESCRIPTION The .Nm @@ -49,17 +51,27 @@ the hardware clock does not keep .Pp The following option is available: .Bl -tag -offset indent -width Fl +.It Fl C Ar chroot_directory +Open all files and directories relative to +.Ar chroot_directory . .It Fl n Do not create or copy files. +.It Fl r +Reinstall the zoneinfo file installed last time. +The name is obtained from +.Pa /var/db/zoneinfo . .It Fl s Skip the initial question about adjusting the clock if not set to .Tn UTC . .El .Pp -It is possible to short-circuit the menu system by specifying a -.Ar default -on the command line; this is intended mainly for pre-configured -installation scripts. +It is possible to short-circuit the menu system by specifying the +location of a +.Ar zoneinfo_file +or the name of the +.Ar zoneinfo_name +on the command line; this is intended mainly for pre-configured installation +scripts or people who know which zoneinfo they want to install. .Sh TIMEZONE DATABASE The contents of the timezone database are indexed by .Pa /usr/share/zoneinfo/zone.tab . @@ -91,12 +103,12 @@ The source code to the database contains many additional comments and documentation references for the historically minded. .Sh FILES -.Bl -tag -width /usr/share/zoneinfo/zone.tab -compact +.Bl -tag -width ".Pa /usr/share/zoneinfo/zone.tab" -compact .It Pa /etc/localtime current time zone file .It Pa /etc/wall_cmos_clock see -.Xr adjkerntz 8 . +.Xr adjkerntz 8 .It Pa /usr/share/misc/iso3166 mapping of .Tn ISO @@ -105,7 +117,27 @@ mapping of directory for zoneinfo files .It Pa /usr/share/zoneinfo/zone.tab mapping of timezone file to country and location +.It Pa /var/db/zoneinfo +saved name of the timezone file installed last .El +.Sh EXAMPLES +Normal usage, to select the right zoneinfo file via the dialog-based +user interface: +.Dl tzsetup +.Pp +Install the file +.Pa /usr/share/zoneinfo/Australia/Sydney : +.Dl "tzsetup /usr/share/zoneinfo/Australia/Sydney" +.Pp +Install the zoneinfo file for Australia/Sydney, assumed to be located +in +.Pa /usr/share/zoneinfo : +.Dl "tzsetup Australia/Sydney" +.Pp +After a reinstall of the zoneinfo files, you can reinstall the +latest installed zoneinfo file (as specified in +.Pa /var/db/zoneinfo ) : +.Dl "tzsetup -r" .Sh SEE ALSO .Xr date 1 , .Xr adjtime 2 , Modified: stable/7/usr.sbin/tzsetup/tzsetup.c ============================================================================== --- stable/7/usr.sbin/tzsetup/tzsetup.c Fri Dec 16 23:43:58 2011 (r228607) +++ stable/7/usr.sbin/tzsetup/tzsetup.c Fri Dec 16 23:44:16 2011 (r228608) @@ -12,7 +12,7 @@ * 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 @@ -32,12 +32,9 @@ * files provided in newer tzdata releases. */ -#ifndef lint -static const char rcsid[] = - "$FreeBSD$"; -#endif /* not lint */ +#include +__FBSDID("$FreeBSD$"); -#include #include #include #include @@ -48,112 +45,145 @@ static const char rcsid[] = #include #include +#include #include #include -#include "paths.h" +#define _PATH_ZONETAB "/usr/share/zoneinfo/zone.tab" +#define _PATH_ISO3166 "/usr/share/misc/iso3166" +#define _PATH_ZONEINFO "/usr/share/zoneinfo" +#define _PATH_LOCALTIME "/etc/localtime" +#define _PATH_DB "/var/db/zoneinfo" +#define _PATH_WALL_CMOS_CLOCK "/etc/wall_cmos_clock" + +static char path_zonetab[MAXPATHLEN], path_iso3166[MAXPATHLEN], + path_zoneinfo[MAXPATHLEN], path_localtime[MAXPATHLEN], + path_db[MAXPATHLEN], path_wall_cmos_clock[MAXPATHLEN]; static int reallydoit = 1; - -static int continent_country_menu(dialogMenuItem *); -static int set_zone_multi(dialogMenuItem *); -static int set_zone_whole_country(dialogMenuItem *); -static int set_zone_menu(dialogMenuItem *); +static int reinstall = 0; +static int usedialog = 1; +static char *chrootenv = NULL; + +static void usage(void); +static int confirm_zone(const char *filename); +static int continent_country_menu(dialogMenuItem *); +static int install_zoneinfo_file(const char *zoneinfo_file); +static int set_zone_multi(dialogMenuItem *); +static int set_zone_whole_country(dialogMenuItem *); +static int set_zone_menu(dialogMenuItem *); +static int set_zone_utc(void); struct continent { dialogMenuItem *menu; - int nitems; - int ch; - int sc; + int nitems; + int ch; + int sc; }; -static struct continent africa, america, antarctica, arctic, asia, atlantic; -static struct continent australia, europe, indian, pacific; +static struct continent africa, america, antarctica, arctic, asia, atlantic; +static struct continent australia, europe, indian, pacific, utc; static struct continent_names { - char *name; + const char *name; struct continent *continent; } continent_names[] = { - { "Africa", &africa }, { "America", &america }, - { "Antarctica", &antarctica }, { "Arctic", &arctic }, - { "Asia", &asia }, - { "Atlantic", &atlantic }, { "Australia", &australia }, - { "Europe", &europe }, { "Indian", &indian }, { "Pacific", &pacific } + { "Africa", &africa }, + { "America", &america }, + { "Antarctica", &antarctica }, + { "Arctic", &arctic }, + { "Asia", &asia }, + { "Atlantic", &atlantic }, + { "Australia", &australia }, + { "Europe", &europe }, + { "Indian", &indian }, + { "Pacific", &pacific }, + { "UTC", &utc } }; -static dialogMenuItem continents[] = { - { "1", "Africa", 0, continent_country_menu, 0, &africa }, - { "2", "America -- North and South", 0, continent_country_menu, 0, - &america }, - { "3", "Antarctica", 0, continent_country_menu, 0, &antarctica }, - { "4", "Arctic Ocean", 0, continent_country_menu, 0, &arctic }, - { "5", "Asia", 0, continent_country_menu, 0, &asia }, - { "6", "Atlantic Ocean", 0, continent_country_menu, 0, &atlantic }, - { "7", "Australia", 0, continent_country_menu, 0, &australia }, - { "8", "Europe", 0, continent_country_menu, 0, &europe }, - { "9", "Indian Ocean", 0, continent_country_menu, 0, &indian }, - { "0", "Pacific Ocean", 0, continent_country_menu, 0, &pacific } +static struct continent_items { + char prompt[2]; + char title[30]; +} continent_items[] = { + { "1", "Africa" }, + { "2", "America -- North and South" }, + { "3", "Antarctica" }, + { "4", "Arctic Ocean" }, + { "5", "Asia" }, + { "6", "Atlantic Ocean" }, + { "7", "Australia" }, + { "8", "Europe" }, + { "9", "Indian Ocean" }, + { "0", "Pacific Ocean" }, + { "a", "UTC" } }; -#define NCONTINENTS (int)((sizeof continents)/(sizeof continents[0])) -#define OCEANP(x) ((x) == 3 || (x) == 5 || (x) == 8 || (x) == 9) + +#define NCONTINENTS \ + (int)((sizeof(continent_items)) / (sizeof(continent_items[0]))) +static dialogMenuItem continents[NCONTINENTS]; + +#define OCEANP(x) ((x) == 3 || (x) == 5 || (x) == 8 || (x) == 9) static int continent_country_menu(dialogMenuItem *continent) { - int rv; + char title[64], prompt[64]; struct continent *contp = continent->data; - char title[256]; - int isocean = OCEANP(continent - continents); - int menulen; + int isocean = OCEANP(continent - continents); + int menulen; + int rv; + + if (strcmp(continent->title, "UTC") == 0) + return set_zone_utc(); /* Short cut -- if there's only one country, don't post a menu. */ if (contp->nitems == 1) return (contp->menu[0].fire(&contp->menu[0])); /* It's amazing how much good grammar really matters... */ - if (!isocean) - snprintf(title, sizeof title, "Countries in %s", - continent->title); - else - snprintf(title, sizeof title, "Islands and groups in the %s", - continent->title); + if (!isocean) { + snprintf(title, sizeof(title), "Countries in %s", + continent->title); + snprintf(prompt, sizeof(prompt), "Select a country or region"); + } else { + snprintf(title, sizeof(title), "Islands and groups in the %s", + continent->title); + snprintf(prompt, sizeof(prompt), "Select an island or group"); + } menulen = contp->nitems < 16 ? contp->nitems : 16; - rv = dialog_menu(title, (isocean ? "Select an island or group" - : "Select a country or region"), -1, -1, menulen, - -contp->nitems, contp->menu, 0, &contp->ch, - &contp->sc); + rv = dialog_menu(title, prompt, -1, -1, menulen, -contp->nitems, + contp->menu, 0, &contp->ch, &contp->sc); if (rv == 0) - return DITEM_LEAVE_MENU; - return DITEM_RECREATE; + return (DITEM_LEAVE_MENU); + return (DITEM_RECREATE); } static struct continent * find_continent(const char *name) { - int i; + int i; - for (i = 0; i < NCONTINENTS; i++) { + for (i = 0; i < NCONTINENTS; i++) if (strcmp(name, continent_names[i].name) == 0) - return continent_names[i].continent; - } - return 0; + return (continent_names[i].continent); + return (0); } struct country { - char *name; - char *tlc; - int nzones; - char *filename; /* use iff nzones < 0 */ - struct continent *continent; /* use iff nzones < 0 */ - TAILQ_HEAD(, zone) zones; /* use iff nzones > 0 */ - dialogMenuItem *submenu; /* use iff nzones > 0 */ + char *name; + char *tlc; + int nzones; + char *filename; /* use iff nzones < 0 */ + struct continent *continent; /* use iff nzones < 0 */ + TAILQ_HEAD(, zone) zones; /* use iff nzones > 0 */ + dialogMenuItem *submenu; /* use iff nzones > 0 */ }; struct zone { TAILQ_ENTRY(zone) link; - char *descr; - char *filename; + char *descr; + char *filename; struct continent *continent; }; @@ -162,9 +192,10 @@ struct zone { * of the two-letter variety, so we just size this array to suit. * Beats worrying about dynamic allocation. */ -#define NCOUNTRIES (26*26) +#define NCOUNTRIES (26 * 26) static struct country countries[NCOUNTRIES]; -#define CODE2INT(s) ((s[0] - 'A') * 26 + (s[1] - 'A')) + +#define CODE2INT(s) ((s[0] - 'A') * 26 + (s[1] - 'A')) /* * Read the ISO 3166 country code database in _PATH_ISO3166 @@ -173,21 +204,21 @@ static struct country countries[NCOUNTRI static void read_iso3166_table(void) { - FILE *fp; - char *s, *t, *name; - size_t len; - int lineno; - struct country *cp; + FILE *fp; + struct country *cp; + size_t len; + char *s, *t, *name; + int lineno; - fp = fopen(_PATH_ISO3166, "r"); + fp = fopen(path_iso3166, "r"); if (!fp) - err(1, _PATH_ISO3166); + err(1, "%s", path_iso3166); lineno = 0; while ((s = fgetln(fp, &len)) != 0) { lineno++; if (s[len - 1] != '\n') - errx(1, _PATH_ISO3166 ":%d: invalid format", lineno); + errx(1, "%s:%d: invalid format", path_iso3166, lineno); s[len - 1] = '\0'; if (s[0] == '#' || strspn(s, " \t") == len - 1) continue; @@ -195,26 +226,25 @@ read_iso3166_table(void) /* Isolate the two-letter code. */ t = strsep(&s, "\t"); if (t == 0 || strlen(t) != 2) - errx(1, _PATH_ISO3166 ":%d: invalid format", lineno); + errx(1, "%s:%d: invalid format", path_iso3166, lineno); if (t[0] < 'A' || t[0] > 'Z' || t[1] < 'A' || t[1] > 'Z') - errx(1, _PATH_ISO3166 ":%d: invalid code `%s'", - lineno, t); + errx(1, "%s:%d: invalid code `%s'", path_iso3166, + lineno, t); /* Now skip past the three-letter and numeric codes. */ - name = strsep(&s, "\t"); /* 3-let */ + name = strsep(&s, "\t"); /* 3-let */ if (name == 0 || strlen(name) != 3) - errx(1, _PATH_ISO3166 ":%d: invalid format", lineno); - name = strsep(&s, "\t"); /* numeric */ + errx(1, "%s:%d: invalid format", path_iso3166, lineno); + name = strsep(&s, "\t"); /* numeric */ if (name == 0 || strlen(name) != 3) - errx(1, _PATH_ISO3166 ":%d: invalid format", lineno); + errx(1, "%s:%d: invalid format", path_iso3166, lineno); name = s; cp = &countries[CODE2INT(t)]; if (cp->name) - errx(1, _PATH_ISO3166 - ":%d: country code `%s' multiply defined: %s", - lineno, t, cp->name); + errx(1, "%s:%d: country code `%s' multiply defined: %s", + path_iso3166, lineno, t, cp->name); cp->name = strdup(name); if (cp->name == NULL) errx(1, "malloc failed"); @@ -228,28 +258,28 @@ read_iso3166_table(void) static void add_zone_to_country(int lineno, const char *tlc, const char *descr, - const char *file, struct continent *cont) + const char *file, struct continent *cont) { - struct zone *zp; - struct country *cp; + struct zone *zp; + struct country *cp; if (tlc[0] < 'A' || tlc[0] > 'Z' || tlc[1] < 'A' || tlc[1] > 'Z') - errx(1, _PATH_ZONETAB ":%d: country code `%s' invalid", - lineno, tlc); + errx(1, "%s:%d: country code `%s' invalid", path_zonetab, + lineno, tlc); cp = &countries[CODE2INT(tlc)]; if (cp->name == 0) - errx(1, _PATH_ZONETAB ":%d: country code `%s' unknown", - lineno, tlc); + errx(1, "%s:%d: country code `%s' unknown", path_zonetab, + lineno, tlc); if (descr) { if (cp->nzones < 0) - errx(1, _PATH_ZONETAB - ":%d: conflicting zone definition", lineno); + errx(1, "%s:%d: conflicting zone definition", + path_zonetab, lineno); - zp = malloc(sizeof *zp); + zp = malloc(sizeof(*zp)); if (zp == 0) - errx(1, "malloc(%lu)", (unsigned long)sizeof *zp); + errx(1, "malloc(%zu)", sizeof(*zp)); if (cp->nzones == 0) TAILQ_INIT(&cp->zones); @@ -265,11 +295,11 @@ add_zone_to_country(int lineno, const ch cp->nzones++; } else { if (cp->nzones > 0) - errx(1, _PATH_ZONETAB - ":%d: zone must have description", lineno); + errx(1, "%s:%d: zone must have description", + path_zonetab, lineno); if (cp->nzones < 0) - errx(1, _PATH_ZONETAB - ":%d: zone multiply defined", lineno); + errx(1, "%s:%d: zone multiply defined", + path_zonetab, lineno); cp->nzones = -1; cp->filename = strdup(file); if (cp->filename == NULL) @@ -289,13 +319,13 @@ compare_countries(const void *xa, const const struct country *a = xa, *b = xb; if (a->name == 0 && b->name == 0) - return 0; + return (0); if (a->name == 0 && b->name != 0) - return 1; + return (1); if (b->name == 0) - return -1; + return (-1); - return strcmp(a->name, b->name); + return (strcmp(a->name, b->name)); } /* @@ -305,51 +335,51 @@ compare_countries(const void *xa, const static void sort_countries(void) { - qsort(countries, NCOUNTRIES, sizeof countries[0], compare_countries); + + qsort(countries, NCOUNTRIES, sizeof(countries[0]), compare_countries); } static void read_zones(void) { - FILE *fp; - char *line; - size_t len; - int lineno; - char *tlc, *coord, *file, *descr, *p; - char contbuf[16]; + char contbuf[16]; + FILE *fp; struct continent *cont; + size_t len; + char *line, *tlc, *coord, *file, *descr, *p; + int lineno; - fp = fopen(_PATH_ZONETAB, "r"); + fp = fopen(path_zonetab, "r"); if (!fp) - err(1, _PATH_ZONETAB); + err(1, "%s", path_zonetab); lineno = 0; while ((line = fgetln(fp, &len)) != 0) { lineno++; if (line[len - 1] != '\n') - errx(1, _PATH_ZONETAB ":%d: invalid format", lineno); + errx(1, "%s:%d: invalid format", path_zonetab, lineno); line[len - 1] = '\0'; if (line[0] == '#') continue; tlc = strsep(&line, "\t"); if (strlen(tlc) != 2) - errx(1, _PATH_ZONETAB ":%d: invalid country code `%s'", - lineno, tlc); - coord = strsep(&line, "\t"); + errx(1, "%s:%d: invalid country code `%s'", + path_zonetab, lineno, tlc); + coord = strsep(&line, "\t"); /* Unused */ file = strsep(&line, "\t"); p = strchr(file, '/'); if (p == 0) - errx(1, _PATH_ZONETAB ":%d: invalid zone name `%s'", - lineno, file); + errx(1, "%s:%d: invalid zone name `%s'", path_zonetab, + lineno, file); contbuf[0] = '\0'; strncat(contbuf, file, p - file); cont = find_continent(contbuf); if (!cont) - errx(1, _PATH_ZONETAB ":%d: invalid region `%s'", - lineno, contbuf); + errx(1, "%s:%d: invalid region `%s'", path_zonetab, + lineno, contbuf); - descr = (line && *line) ? line : 0; + descr = (line != NULL && *line != '\0') ? line : NULL; add_zone_to_country(lineno, tlc, descr, file, cont); } @@ -359,11 +389,11 @@ read_zones(void) static void make_menus(void) { - struct country *cp; - struct zone *zp, *zp2; + struct country *cp; + struct zone *zp, *zp2; struct continent *cont; - dialogMenuItem *dmi; - int i; + dialogMenuItem *dmi; + int i; /* * First, count up all the countries in each continent/ocean. @@ -380,8 +410,8 @@ make_menus(void) TAILQ_FOREACH(zp, &cp->zones, link) { cont = zp->continent; for (zp2 = TAILQ_FIRST(&cp->zones); - zp2->continent != cont; - zp2 = TAILQ_NEXT(zp2, link)) + zp2->continent != cont; + zp2 = TAILQ_NEXT(zp2, link)) ; if (zp2 == zp) zp->continent->nitems++; @@ -390,17 +420,22 @@ make_menus(void) } /* - * Now allocate memory for the country menus. We set - * nitems back to zero so that we can use it for counting - * again when we actually build the menus. + * Now allocate memory for the country menus and initialize + * continent menus. We set nitems back to zero so that we can + * use it for counting again when we actually build the menus. */ + memset(continents, 0, sizeof(continents)); for (i = 0; i < NCONTINENTS; i++) { continent_names[i].continent->menu = - malloc(sizeof(dialogMenuItem) * - continent_names[i].continent->nitems); + malloc(sizeof(dialogMenuItem) * + continent_names[i].continent->nitems); if (continent_names[i].continent->menu == 0) errx(1, "malloc for continent menu"); continent_names[i].continent->nitems = 0; + continents[i].prompt = continent_items[i].prompt; + continents[i].title = continent_items[i].title; + continents[i].fire = continent_country_menu; + continents[i].data = continent_names[i].continent; } /* @@ -413,25 +448,23 @@ make_menus(void) continue; if (cp->nzones < 0) { dmi = &cp->continent->menu[cp->continent->nitems]; - memset(dmi, 0, sizeof *dmi); - asprintf(&dmi->prompt, "%d", - ++cp->continent->nitems); + memset(dmi, 0, sizeof(*dmi)); + asprintf(&dmi->prompt, "%d", ++cp->continent->nitems); dmi->title = cp->name; dmi->checked = 0; dmi->fire = set_zone_whole_country; dmi->selected = 0; dmi->data = cp; } else { - cp->submenu = malloc(cp->nzones * sizeof *dmi); + cp->submenu = malloc(cp->nzones * sizeof(*dmi)); if (cp->submenu == 0) errx(1, "malloc for submenu"); cp->nzones = 0; TAILQ_FOREACH(zp, &cp->zones, link) { cont = zp->continent; dmi = &cp->submenu[cp->nzones]; - memset(dmi, 0, sizeof *dmi); - asprintf(&dmi->prompt, "%d", - ++cp->nzones); + memset(dmi, 0, sizeof(*dmi)); + asprintf(&dmi->prompt, "%d", ++cp->nzones); dmi->title = zp->descr; dmi->checked = 0; dmi->fire = set_zone_multi; @@ -439,14 +472,14 @@ make_menus(void) dmi->data = zp; for (zp2 = TAILQ_FIRST(&cp->zones); - zp2->continent != cont; - zp2 = TAILQ_NEXT(zp2, link)) + zp2->continent != cont; + zp2 = TAILQ_NEXT(zp2, link)) ; if (zp2 != zp) continue; dmi = &cont->menu[cont->nitems]; - memset(dmi, 0, sizeof *dmi); + memset(dmi, 0, sizeof(*dmi)); asprintf(&dmi->prompt, "%d", ++cont->nitems); dmi->title = cp->name; dmi->checked = 0; @@ -461,202 +494,288 @@ make_menus(void) static int set_zone_menu(dialogMenuItem *dmi) { - int rv; - char buf[256]; - struct country *cp = dmi->data; - int menulen; - - snprintf(buf, sizeof buf, "%s Time Zones", cp->name); + char title[64], prompt[64]; + struct country *cp = dmi->data; + int menulen; + int rv; + + snprintf(title, sizeof(title), "%s Time Zones", cp->name); + snprintf(prompt, sizeof(prompt), + "Select a zone which observes the same time as your locality."); menulen = cp->nzones < 16 ? cp->nzones : 16; - rv = dialog_menu(buf, "Select a zone which observes the same time as " - "your locality.", -1, -1, menulen, -cp->nzones, - cp->submenu, 0, 0, 0); + rv = dialog_menu(title, prompt, -1, -1, menulen, -cp->nzones, + cp->submenu, 0, 0, 0); if (rv != 0) - return DITEM_RECREATE; - return DITEM_LEAVE_MENU; + return (DITEM_RECREATE); + return (DITEM_LEAVE_MENU); +} + +int +set_zone_utc(void) +{ + if (!confirm_zone(NULL)) + return (DITEM_FAILURE | DITEM_RECREATE); + + return (install_zoneinfo_file(NULL)); } static int -install_zone_file(const char *filename) +install_zoneinfo_file(const char *zoneinfo_file) { - struct stat sb; - int fd1, fd2; - int copymode; - char *msg; - ssize_t len; - char buf[1024]; + char buf[1024]; + char title[64], prompt[64]; + struct stat sb; + ssize_t len; + int fd1, fd2, copymode; - if (lstat(_PATH_LOCALTIME, &sb) < 0) + if (lstat(path_localtime, &sb) < 0) { /* Nothing there yet... */ copymode = 1; - else if(S_ISLNK(sb.st_mode)) + } else if (S_ISLNK(sb.st_mode)) copymode = 0; else copymode = 1; #ifdef VERBOSE if (copymode) - asprintf(&msg, "Copying %s to " _PATH_LOCALTIME, filename); + snprintf(prompt, sizeof(prompt), + "Copying %s to %s", zoneinfo_file, path_localtime); else - asprintf(&msg, "Creating symbolic link " _PATH_LOCALTIME - " to %s", filename); - - dialog_notify(msg); - free(msg); + snprintf(prompt, sizeof(prompt), + "Creating symbolic link %s to %s", + path_localtime, + zoneinfo_file == NULL ? "(UTC)" : zoneinfo_file); + if (usedialog) + dialog_notify(prompt); + else + fprintf(stderr, "%s\n", prompt); #endif if (reallydoit) { + if (zoneinfo_file == NULL) { + if (unlink(path_localtime) < 0 && errno != ENOENT) { + snprintf(title, sizeof(title), "Error"); + snprintf(prompt, sizeof(prompt), + "Could not delete %s: %s", path_localtime, + strerror(errno)); + if (usedialog) + dialog_mesgbox(title, prompt, 8, 72); + else + fprintf(stderr, "%s\n", prompt); + + return (DITEM_FAILURE | DITEM_RECREATE); + } + if (unlink(path_db) < 0 && errno != ENOENT) { + snprintf(title, sizeof(title), "Error"); + snprintf(prompt, sizeof(prompt), + "Could not delete %s: %s", path_db, + strerror(errno)); + if (usedialog) + dialog_mesgbox(title, prompt, 8, 72); + else + fprintf(stderr, "%s\n", prompt); + + return (DITEM_FAILURE | DITEM_RECREATE); + } + return (DITEM_LEAVE_MENU); + } + if (copymode) { - fd1 = open(filename, O_RDONLY, 0); + fd1 = open(zoneinfo_file, O_RDONLY, 0); if (fd1 < 0) { - asprintf(&msg, "Could not open %s: %s", - filename, strerror(errno)); - dialog_mesgbox("Error", msg, 8, 72); - free(msg); - return DITEM_FAILURE | DITEM_RECREATE; + snprintf(title, sizeof(title), "Error"); + snprintf(prompt, sizeof(prompt), + "Could not open %s: %s", zoneinfo_file, + strerror(errno)); + if (usedialog) + dialog_mesgbox(title, prompt, 8, 72); + else + fprintf(stderr, "%s\n", prompt); + return (DITEM_FAILURE | DITEM_RECREATE); } - unlink(_PATH_LOCALTIME); - fd2 = open(_PATH_LOCALTIME, - O_CREAT|O_EXCL|O_WRONLY, - S_IRUSR|S_IRGRP|S_IROTH); + unlink(path_localtime); + fd2 = open(path_localtime, O_CREAT | O_EXCL | O_WRONLY, + S_IRUSR | S_IRGRP | S_IROTH); if (fd2 < 0) { - asprintf(&msg, "Could not open " - _PATH_LOCALTIME ": %s", - strerror(errno)); - dialog_mesgbox("Error", msg, 8, 72); - free(msg); - return DITEM_FAILURE | DITEM_RECREATE; + snprintf(title, sizeof(title), "Error"); + snprintf(prompt, sizeof(prompt), + "Could not open %s: %s", + path_localtime, strerror(errno)); + if (usedialog) + dialog_mesgbox(title, prompt, 8, 72); + else + fprintf(stderr, "%s\n", prompt); + return (DITEM_FAILURE | DITEM_RECREATE); } - while ((len = read(fd1, buf, sizeof buf)) > 0) - len = write(fd2, buf, len); + while ((len = read(fd1, buf, sizeof(buf))) > 0) + if ((len = write(fd2, buf, len)) < 0) + break; if (len == -1) { - asprintf(&msg, "Error copying %s to " - _PATH_LOCALTIME ": %s", - filename, strerror(errno)); - dialog_mesgbox("Error", msg, 8, 72); - free(msg); + snprintf(title, sizeof(title), "Error"); + snprintf(prompt, sizeof(prompt), + "Error copying %s to %s %s", zoneinfo_file, + path_localtime, strerror(errno)); + if (usedialog) + dialog_mesgbox(title, prompt, 8, 72); + else + fprintf(stderr, "%s\n", prompt); /* Better to leave none than a corrupt one. */ - unlink(_PATH_LOCALTIME); - return DITEM_FAILURE | DITEM_RECREATE; + unlink(path_localtime); + return (DITEM_FAILURE | DITEM_RECREATE); } close(fd1); close(fd2); } else { - if (access(filename, R_OK) != 0) { - asprintf(&msg, "Cannot access %s: %s", - filename, strerror(errno)); - dialog_mesgbox("Error", msg, 8, 72); - free(msg); - return DITEM_FAILURE | DITEM_RECREATE; - } - unlink(_PATH_LOCALTIME); - if (symlink(filename, _PATH_LOCALTIME) < 0) { - asprintf(&msg, "Cannot create symbolic link " - _PATH_LOCALTIME " to %s: %s", - filename, strerror(errno)); - dialog_mesgbox("Error", msg, 8, 72); - free(msg); - return DITEM_FAILURE | DITEM_RECREATE; + if (access(zoneinfo_file, R_OK) != 0) { + snprintf(title, sizeof(title), "Error"); + snprintf(prompt, sizeof(prompt), + "Cannot access %s: %s", zoneinfo_file, + strerror(errno)); + if (usedialog) + dialog_mesgbox(title, prompt, 8, 72); + else + fprintf(stderr, "%s\n", prompt); + return (DITEM_FAILURE | DITEM_RECREATE); + } + unlink(path_localtime); + if (symlink(zoneinfo_file, path_localtime) < 0) { + snprintf(title, sizeof(title), "Error"); + snprintf(prompt, sizeof(prompt), + "Cannot create symbolic link %s to %s: %s", + path_localtime, zoneinfo_file, + strerror(errno)); + if (usedialog) + dialog_mesgbox(title, prompt, 8, 72); + else + fprintf(stderr, "%s\n", prompt); + return (DITEM_FAILURE | DITEM_RECREATE); } } } #ifdef VERBOSE + snprintf(title, sizeof(title), "Done"); if (copymode) - asprintf(&msg, "Copied timezone file from %s to " - _PATH_LOCALTIME, filename); + snprintf(prompt, sizeof(prompt), + "Copied timezone file from %s to %s", zoneinfo_file, + path_localtime); else - asprintf(&msg, "Created symbolic link from " _PATH_LOCALTIME - " to %s", filename); - - dialog_mesgbox("Done", msg, 8, 72); - free(msg); + snprintf(prompt, sizeof(prompt), + "Created symbolic link from %s to %s", zoneinfo_file, + path_localtime); + if (usedialog) + dialog_mesgbox(title, prompt, 8, 72); + else + fprintf(stderr, "%s\n", prompt); #endif - return DITEM_LEAVE_MENU; + + return (DITEM_LEAVE_MENU); +} + +static int +install_zoneinfo(const char *zoneinfo) +{ + int rv; + FILE *f; + char path_zoneinfo_file[MAXPATHLEN]; + + sprintf(path_zoneinfo_file, "%s/%s", path_zoneinfo, zoneinfo); + rv = install_zoneinfo_file(path_zoneinfo_file); + + /* Save knowledge for later */ + if ((f = fopen(path_db, "w")) != NULL) { + fprintf(f, "%s\n", zoneinfo); + fclose(f); + } + + return (rv); } static int confirm_zone(const char *filename) { - char *msg; - struct tm *tm; - time_t t = time(0); - int rv; + char title[64], prompt[64]; + time_t t = time(0); + struct tm *tm; + int rv; - setenv("TZ", filename, 1); + setenv("TZ", filename == NULL ? "" : filename, 1); tzset(); tm = localtime(&t); - asprintf(&msg, "Does the abbreviation `%s' look reasonable?", - tm->tm_zone); - rv = !dialog_yesno("Confirmation", msg, 5, 72); - free(msg); - return rv; + snprintf(title, sizeof(title), "Confirmation"); + snprintf(prompt, sizeof(prompt), + "Does the abbreviation `%s' look reasonable?", tm->tm_zone); + rv = !dialog_yesno(title, prompt, 5, 72); + return (rv); } static int set_zone_multi(dialogMenuItem *dmi) { - char *fn; - struct zone *zp = dmi->data; - int rv; + struct zone *zp = dmi->data; + int rv; if (!confirm_zone(zp->filename)) - return DITEM_FAILURE | DITEM_RECREATE; + return (DITEM_FAILURE | DITEM_RECREATE); - asprintf(&fn, "%s/%s", _PATH_ZONEINFO, zp->filename); - rv = install_zone_file(fn); - free(fn); - return rv; + rv = install_zoneinfo(zp->filename); + return (rv); } static int set_zone_whole_country(dialogMenuItem *dmi) { - char *fn; - struct country *cp = dmi->data; - int rv; + struct country *cp = dmi->data; + int rv; if (!confirm_zone(cp->filename)) - return DITEM_FAILURE | DITEM_RECREATE; + return (DITEM_FAILURE | DITEM_RECREATE); *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***