/* * 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: main.c,v 1.6 1996/03/31 09:55:00 joerg Exp $"; #include #include #include #include #include #include #include #include #include #include #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("Daemons will only notice\n" "a timezone change.\n" "after rebooting.\n"); end_dialog(); 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 Universal time (UTC)", "2", "CMOS clock is set to local time", "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) { int fd; switch(cmos_state) { case CMOS_LEAVE: break; case CMOS_UTC: if (unlink(PATH_WALL_CMOS_CLOCK) == -1 && errno != ENOENT) dialog_notify("Error removing " PATH_WALL_CMOS_CLOCK); break; case CMOS_LOCAL: if ((fd = open(PATH_WALL_CMOS_CLOCK, O_RDONLY|O_CREAT, 0644)) == -1) dialog_notify("Error creating " PATH_WALL_CMOS_CLOCK); else close(fd); break; } } int setzone(const char *zone) { time_t systime; struct tm *tm; char msg[_POSIX2_LINE_MAX]; int rv; struct stat sb; /* * Make sure the definition file does exist before clobbering * an existing PATH_LOCALTIME. We do this before evaluating * locatlime below, since a missing zoneinfo file would result * in nothing but garbage in the displayed time information. */ snprintf(msg, sizeof msg, PATH_ZONEINFO "/%s", zone); if (stat(msg, &sb) == -1) { snprintf(msg, sizeof msg, "Could not find definition file\n" PATH_ZONEINFO "/%s", zone); dialog_notify(msg); return 1; } 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 + 1, tm->tm_year + 1900, tm->tm_zone); rv = dialog_yesno("Verifying timezone selection", msg, -1, -1); if (rv) return 1; if (lstat(PATH_LOCALTIME, &sb) == 0 && S_ISLNK(sb.st_mode)) { /* The destination is already a symlink, symlink it. */ (void)unlink(PATH_LOCALTIME); snprintf(msg, sizeof msg, PATH_ZONEINFO "/%s", zone); if (symlink(msg, PATH_LOCALTIME) == -1) { dialog_notify("Could not create a symbolic link for " PATH_LOCALTIME); return 1; } } else { /* Copy it. */ snprintf(msg, sizeof msg, "install -C -o bin -g bin -m 0444 " PATH_ZONEINFO "/%s " PATH_LOCALTIME, zone); if (system(msg) != 0) { dialog_notify("Could not copy zone information into " PATH_LOCALTIME); return 1; } } snprintf(msg, sizeof msg, "Installed timezone file %s", zone); dialog_notify(msg); return 0; }