+#define ATOI2(p) (p[0] - '0') * 10 + (p[1] - '0'); p += 2;
+static int dmsize[] =
+ { -1, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+
+getoffset(timearg)
+ register char *timearg;
+{
+ register struct tm *lt;
+ register char *p;
+ time_t now, time();
+ int year, month, day, hour, min;
+
+ if (!strcasecmp(timearg, "now")) { /* now */
+ offset = 0;
+ return;
+ }
+
+ (void)time(&now);
+ if (*timearg == '+') { /* +minutes */
+ if (!isdigit(*++timearg))
+ goto badtime;
+ min = atoi(timearg);
+ offset = min * 60;
+ shuttime = now + offset;
+ return;
+ }
+
+ /* handle hh:mm by getting rid of the colon */
+ for (p = timearg; *p; ++p)
+ if (!isascii(*p) || !isdigit(*p))
+ if (*p == ':' && strlen(p) == 3) {
+ p[0] = p[1];
+ p[1] = p[2];
+ p[2] = '\0';
+ }
+ else
+ goto badtime;
+
+ unsetenv("TZ"); /* OUR timezone */
+ lt = localtime(&now); /* [yymmdd]hhmm */
+ year = lt->tm_year;
+ month = lt->tm_mon + 1;
+ day = lt->tm_mday;
+
+ switch(strlen(timearg)) {
+ case 10:
+ year = ATOI2(timearg);
+ /* FALLTHROUGH */
+ case 8:
+ month = ATOI2(timearg);
+ /* FALLTHROUGH */
+ case 6:
+ day = ATOI2(timearg);
+ /* FALLTHROUGH */
+ case 4:
+ hour = ATOI2(timearg);
+ min = ATOI2(timearg);
+ if (month < 1 || month > 12 || day < 1 || day > 31 ||
+ hour < 0 || hour > 23 || min < 0 || min > 59)
+ goto badtime;
+ shuttime = 0;
+ year += TM_YEAR_BASE;
+ if (isleap(year) && month > 2)
+ ++shuttime;
+ for (--year; year >= EPOCH_YEAR; --year)
+ shuttime += isleap(year) ?
+ DAYSPERLYEAR : DAYSPERNYEAR;
+ while (--month)
+ shuttime += dmsize[month];
+ shuttime += day - 1;
+ shuttime = HOURSPERDAY * shuttime + hour;
+ shuttime = MINSPERHOUR * shuttime + min;
+ shuttime *= SECSPERMIN;
+ shuttime -= lt->tm_gmtoff;
+ if ((offset = shuttime - now) >= 0)
+ break;
+ /* FALLTHROUGH */
+ default:
+badtime: fprintf(stderr,
+ "shutdown: bad time format, or already past.\n");
+ exit(1);
+ }
+}
+
+#define FSMSG "fastboot file for fsck\n"
+doitfast()