not quite first cut "safety" checkin
authorTom Yu <tlyu@mit.edu>
Thu, 29 Sep 1994 04:39:35 +0000 (04:39 +0000)
committerTom Yu <tlyu@mit.edu>
Thu, 29 Sep 1994 04:39:35 +0000 (04:39 +0000)
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@4374 dc483132-0cff-0310-8789-dd5450dbe970

src/kadmin.new/client/getdate.y [new file with mode: 0644]
src/kadmin.new/client/kadmin.c [new file with mode: 0644]

diff --git a/src/kadmin.new/client/getdate.y b/src/kadmin.new/client/getdate.y
new file mode 100644 (file)
index 0000000..d010cb6
--- /dev/null
@@ -0,0 +1,889 @@
+%{
+/* 1.8
+** @(#)getdate.y 1.8 92/03/03
+**
+**  Originally written by Steven M. Bellovin <smb@research.att.com> while
+**  at the University of North Carolina at Chapel Hill.  Later tweaked by
+**  a couple of people on Usenet.  Completely overhauled by Rich $alz
+**  <rsalz@bbn.com> and Jim Berets <jberets@bbn.com> in August, 1990;
+**  send any email to Rich.
+**
+**  This grammar has eight shift/reduce conflicts.
+**
+**  This code is in the public domain and has no copyright.
+*/
+/* SUPPRESS 287 on yaccpar_sccsid *//* Unused static variable */
+/* SUPPRESS 288 on yyerrlab *//* Label unused */
+
+#include "system.h"
+#include <ctype.h>
+
+#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__)
+#ifdef __GNUC__
+#undef alloca                  /* might get redefined below */
+#endif
+#endif
+
+extern struct tm *localtime();
+
+#define yyparse getdate_yyparse
+#define yylex getdate_yylex
+#define yyerror getdate_yyerror
+
+#if    !defined(lint) && !defined(SABER)
+static char RCS[] = "@(#)getdate.y 1.8 92/03/03";
+#endif /* !defined(lint) && !defined(SABER) */
+
+
+#define EPOCH          1970
+#define HOUR(x)                ((time_t)(x) * 60)
+#define SECSPERDAY     (24L * 60L * 60L)
+
+
+/*
+**  An entry in the lexical lookup table.
+*/
+typedef struct _TABLE {
+    char       *name;
+    int                type;
+    time_t     value;
+} TABLE;
+
+
+/*
+**  Daylight-savings mode:  on, off, or not yet known.
+*/
+typedef enum _DSTMODE {
+    DSTon, DSToff, DSTmaybe
+} DSTMODE;
+
+/*
+**  Meridian:  am, pm, or 24-hour style.
+*/
+typedef enum _MERIDIAN {
+    MERam, MERpm, MER24
+} MERIDIAN;
+
+
+/*
+**  Global variables.  We could get rid of most of these by using a good
+**  union as the yacc stack.  (This routine was originally written before
+**  yacc had the %union construct.)  Maybe someday; right now we only use
+**  the %union very rarely.
+*/
+static char    *yyInput;
+static DSTMODE yyDSTmode;
+static time_t  yyDayOrdinal;
+static time_t  yyDayNumber;
+static int     yyHaveDate;
+static int     yyHaveDay;
+static int     yyHaveRel;
+static int     yyHaveTime;
+static int     yyHaveZone;
+static time_t  yyTimezone;
+static time_t  yyDay;
+static time_t  yyHour;
+static time_t  yyMinutes;
+static time_t  yyMonth;
+static time_t  yySeconds;
+static time_t  yyYear;
+static MERIDIAN        yyMeridian;
+static time_t  yyRelMonth;
+static time_t  yyRelSeconds;
+
+%}
+
+%union {
+    time_t             Number;
+    enum _MERIDIAN     Meridian;
+}
+
+%token tAGO tDAY tDAYZONE tID tMERIDIAN tMINUTE_UNIT tMONTH tMONTH_UNIT
+%token tSEC_UNIT tSNUMBER tUNUMBER tZONE tDST
+
+%type  <Number>        tDAY tDAYZONE tMINUTE_UNIT tMONTH tMONTH_UNIT
+%type  <Number>        tSEC_UNIT tSNUMBER tUNUMBER tZONE
+%type  <Meridian>      tMERIDIAN o_merid
+
+%%
+
+spec   : /* NULL */
+       | spec item
+       ;
+
+item   : time {
+           yyHaveTime++;
+       }
+       | zone {
+           yyHaveZone++;
+       }
+       | date {
+           yyHaveDate++;
+       }
+       | day {
+           yyHaveDay++;
+       }
+       | rel {
+           yyHaveRel++;
+       }
+       | number
+       ;
+
+time   : tUNUMBER tMERIDIAN {
+           yyHour = $1;
+           yyMinutes = 0;
+           yySeconds = 0;
+           yyMeridian = $2;
+       }
+       | tUNUMBER ':' tUNUMBER o_merid {
+           yyHour = $1;
+           yyMinutes = $3;
+           yySeconds = 0;
+           yyMeridian = $4;
+       }
+       | tUNUMBER ':' tUNUMBER tSNUMBER {
+           yyHour = $1;
+           yyMinutes = $3;
+           yyMeridian = MER24;
+           yyDSTmode = DSToff;
+           yyTimezone = - ($4 % 100 + ($4 / 100) * 60);
+       }
+       | tUNUMBER ':' tUNUMBER ':' tUNUMBER o_merid {
+           yyHour = $1;
+           yyMinutes = $3;
+           yySeconds = $5;
+           yyMeridian = $6;
+       }
+       | tUNUMBER ':' tUNUMBER ':' tUNUMBER tSNUMBER {
+           yyHour = $1;
+           yyMinutes = $3;
+           yySeconds = $5;
+           yyMeridian = MER24;
+           yyDSTmode = DSToff;
+           yyTimezone = - ($6 % 100 + ($6 / 100) * 60);
+       }
+       ;
+
+zone   : tZONE {
+           yyTimezone = $1;
+           yyDSTmode = DSToff;
+       }
+       | tDAYZONE {
+           yyTimezone = $1;
+           yyDSTmode = DSTon;
+       }
+       |
+         tZONE tDST {
+           yyTimezone = $1;
+           yyDSTmode = DSTon;
+       }
+       ;
+
+day    : tDAY {
+           yyDayOrdinal = 1;
+           yyDayNumber = $1;
+       }
+       | tDAY ',' {
+           yyDayOrdinal = 1;
+           yyDayNumber = $1;
+       }
+       | tUNUMBER tDAY {
+           yyDayOrdinal = $1;
+           yyDayNumber = $2;
+       }
+       ;
+
+date   : tUNUMBER '/' tUNUMBER {
+           yyMonth = $1;
+           yyDay = $3;
+       }
+       | tUNUMBER '/' tUNUMBER '/' tUNUMBER {
+           yyMonth = $1;
+           yyDay = $3;
+           yyYear = $5;
+       }
+       | tMONTH tUNUMBER {
+           yyMonth = $1;
+           yyDay = $2;
+       }
+       | tMONTH tUNUMBER ',' tUNUMBER {
+           yyMonth = $1;
+           yyDay = $2;
+           yyYear = $4;
+       }
+       | tUNUMBER tMONTH {
+           yyMonth = $2;
+           yyDay = $1;
+       }
+       | tUNUMBER tMONTH tUNUMBER {
+           yyMonth = $2;
+           yyDay = $1;
+           yyYear = $3;
+       }
+       ;
+
+rel    : relunit tAGO {
+           yyRelSeconds = -yyRelSeconds;
+           yyRelMonth = -yyRelMonth;
+       }
+       | relunit
+       ;
+
+relunit        : tUNUMBER tMINUTE_UNIT {
+           yyRelSeconds += $1 * $2 * 60L;
+       }
+       | tSNUMBER tMINUTE_UNIT {
+           yyRelSeconds += $1 * $2 * 60L;
+       }
+       | tMINUTE_UNIT {
+           yyRelSeconds += $1 * 60L;
+       }
+       | tSNUMBER tSEC_UNIT {
+           yyRelSeconds += $1;
+       }
+       | tUNUMBER tSEC_UNIT {
+           yyRelSeconds += $1;
+       }
+       | tSEC_UNIT {
+           yyRelSeconds++;
+       }
+       | tSNUMBER tMONTH_UNIT {
+           yyRelMonth += $1 * $2;
+       }
+       | tUNUMBER tMONTH_UNIT {
+           yyRelMonth += $1 * $2;
+       }
+       | tMONTH_UNIT {
+           yyRelMonth += $1;
+       }
+       ;
+
+number : tUNUMBER {
+           if (yyHaveTime && yyHaveDate && !yyHaveRel)
+               yyYear = $1;
+           else {
+               if($1>10000) {
+                   time_t date_part;
+
+                   date_part= $1/10000;
+                   yyHaveDate++;
+                   yyDay= (date_part)%100;
+                   yyMonth= (date_part/100)%100;
+                   yyYear = date_part/10000;
+               } 
+               yyHaveTime++;
+               if ($1 < 100) {
+                   yyHour = $1;
+                   yyMinutes = 0;
+               }
+               else {
+                   yyHour = $1 / 100;
+                   yyMinutes = $1 % 100;
+               }
+               yySeconds = 0;
+               yyMeridian = MER24;
+           }
+       }
+       ;
+
+o_merid        : /* NULL */ {
+           $$ = MER24;
+       }
+       | tMERIDIAN {
+           $$ = $1;
+       }
+       ;
+
+%%
+
+/* Month and day table. */
+static TABLE   MonthDayTable[] = {
+    { "january",       tMONTH,  1 },
+    { "february",      tMONTH,  2 },
+    { "march",         tMONTH,  3 },
+    { "april",         tMONTH,  4 },
+    { "may",           tMONTH,  5 },
+    { "june",          tMONTH,  6 },
+    { "july",          tMONTH,  7 },
+    { "august",                tMONTH,  8 },
+    { "september",     tMONTH,  9 },
+    { "sept",          tMONTH,  9 },
+    { "october",       tMONTH, 10 },
+    { "november",      tMONTH, 11 },
+    { "december",      tMONTH, 12 },
+    { "sunday",                tDAY, 0 },
+    { "monday",                tDAY, 1 },
+    { "tuesday",       tDAY, 2 },
+    { "tues",          tDAY, 2 },
+    { "wednesday",     tDAY, 3 },
+    { "wednes",                tDAY, 3 },
+    { "thursday",      tDAY, 4 },
+    { "thur",          tDAY, 4 },
+    { "thurs",         tDAY, 4 },
+    { "friday",                tDAY, 5 },
+    { "saturday",      tDAY, 6 },
+    { NULL }
+};
+
+/* Time units table. */
+static TABLE   UnitsTable[] = {
+    { "year",          tMONTH_UNIT,    12 },
+    { "month",         tMONTH_UNIT,    1 },
+    { "fortnight",     tMINUTE_UNIT,   14 * 24 * 60 },
+    { "week",          tMINUTE_UNIT,   7 * 24 * 60 },
+    { "day",           tMINUTE_UNIT,   1 * 24 * 60 },
+    { "hour",          tMINUTE_UNIT,   60 },
+    { "minute",                tMINUTE_UNIT,   1 },
+    { "min",           tMINUTE_UNIT,   1 },
+    { "second",                tSEC_UNIT,      1 },
+    { "sec",           tSEC_UNIT,      1 },
+    { NULL }
+};
+
+/* Assorted relative-time words. */
+static TABLE   OtherTable[] = {
+    { "tomorrow",      tMINUTE_UNIT,   1 * 24 * 60 },
+    { "yesterday",     tMINUTE_UNIT,   -1 * 24 * 60 },
+    { "today",         tMINUTE_UNIT,   0 },
+    { "now",           tMINUTE_UNIT,   0 },
+    { "last",          tUNUMBER,       -1 },
+    { "this",          tMINUTE_UNIT,   0 },
+    { "next",          tUNUMBER,       2 },
+    { "first",         tUNUMBER,       1 },
+/*  { "second",                tUNUMBER,       2 }, */
+    { "third",         tUNUMBER,       3 },
+    { "fourth",                tUNUMBER,       4 },
+    { "fifth",         tUNUMBER,       5 },
+    { "sixth",         tUNUMBER,       6 },
+    { "seventh",       tUNUMBER,       7 },
+    { "eighth",                tUNUMBER,       8 },
+    { "ninth",         tUNUMBER,       9 },
+    { "tenth",         tUNUMBER,       10 },
+    { "eleventh",      tUNUMBER,       11 },
+    { "twelfth",       tUNUMBER,       12 },
+    { "ago",           tAGO,   1 },
+    { NULL }
+};
+
+/* The timezone table. */
+/* Some of these are commented out because a time_t can't store a float. */
+static TABLE   TimezoneTable[] = {
+    { "gmt",   tZONE,     HOUR( 0) },  /* Greenwich Mean */
+    { "ut",    tZONE,     HOUR( 0) },  /* Universal (Coordinated) */
+    { "utc",   tZONE,     HOUR( 0) },
+    { "wet",   tZONE,     HOUR( 0) },  /* Western European */
+    { "bst",   tDAYZONE,  HOUR( 0) },  /* British Summer */
+    { "wat",   tZONE,     HOUR( 1) },  /* West Africa */
+    { "at",    tZONE,     HOUR( 2) },  /* Azores */
+#if    0
+    /* For completeness.  BST is also British Summer, and GST is
+     * also Guam Standard. */
+    { "bst",   tZONE,     HOUR( 3) },  /* Brazil Standard */
+    { "gst",   tZONE,     HOUR( 3) },  /* Greenland Standard */
+#endif
+#if 0
+    { "nft",   tZONE,     HOUR(3.5) }, /* Newfoundland */
+    { "nst",   tZONE,     HOUR(3.5) }, /* Newfoundland Standard */
+    { "ndt",   tDAYZONE,  HOUR(3.5) }, /* Newfoundland Daylight */
+#endif
+    { "ast",   tZONE,     HOUR( 4) },  /* Atlantic Standard */
+    { "adt",   tDAYZONE,  HOUR( 4) },  /* Atlantic Daylight */
+    { "est",   tZONE,     HOUR( 5) },  /* Eastern Standard */
+    { "edt",   tDAYZONE,  HOUR( 5) },  /* Eastern Daylight */
+    { "cst",   tZONE,     HOUR( 6) },  /* Central Standard */
+    { "cdt",   tDAYZONE,  HOUR( 6) },  /* Central Daylight */
+    { "mst",   tZONE,     HOUR( 7) },  /* Mountain Standard */
+    { "mdt",   tDAYZONE,  HOUR( 7) },  /* Mountain Daylight */
+    { "pst",   tZONE,     HOUR( 8) },  /* Pacific Standard */
+    { "pdt",   tDAYZONE,  HOUR( 8) },  /* Pacific Daylight */
+    { "yst",   tZONE,     HOUR( 9) },  /* Yukon Standard */
+    { "ydt",   tDAYZONE,  HOUR( 9) },  /* Yukon Daylight */
+    { "hst",   tZONE,     HOUR(10) },  /* Hawaii Standard */
+    { "hdt",   tDAYZONE,  HOUR(10) },  /* Hawaii Daylight */
+    { "cat",   tZONE,     HOUR(10) },  /* Central Alaska */
+    { "ahst",  tZONE,     HOUR(10) },  /* Alaska-Hawaii Standard */
+    { "nt",    tZONE,     HOUR(11) },  /* Nome */
+    { "idlw",  tZONE,     HOUR(12) },  /* International Date Line West */
+    { "cet",   tZONE,     -HOUR(1) },  /* Central European */
+    { "met",   tZONE,     -HOUR(1) },  /* Middle European */
+    { "mewt",  tZONE,     -HOUR(1) },  /* Middle European Winter */
+    { "mest",  tDAYZONE,  -HOUR(1) },  /* Middle European Summer */
+    { "swt",   tZONE,     -HOUR(1) },  /* Swedish Winter */
+    { "sst",   tDAYZONE,  -HOUR(1) },  /* Swedish Summer */
+    { "fwt",   tZONE,     -HOUR(1) },  /* French Winter */
+    { "fst",   tDAYZONE,  -HOUR(1) },  /* French Summer */
+    { "eet",   tZONE,     -HOUR(2) },  /* Eastern Europe, USSR Zone 1 */
+    { "bt",    tZONE,     -HOUR(3) },  /* Baghdad, USSR Zone 2 */
+#if 0
+    { "it",    tZONE,     -HOUR(3.5) },/* Iran */
+#endif
+    { "zp4",   tZONE,     -HOUR(4) },  /* USSR Zone 3 */
+    { "zp5",   tZONE,     -HOUR(5) },  /* USSR Zone 4 */
+#if 0
+    { "ist",   tZONE,     -HOUR(5.5) },/* Indian Standard */
+#endif
+    { "zp6",   tZONE,     -HOUR(6) },  /* USSR Zone 5 */
+#if    0
+    /* For completeness.  NST is also Newfoundland Stanard, and SST is
+     * also Swedish Summer. */
+    { "nst",   tZONE,     -HOUR(6.5) },/* North Sumatra */
+    { "sst",   tZONE,     -HOUR(7) },  /* South Sumatra, USSR Zone 6 */
+#endif /* 0 */
+    { "wast",  tZONE,     -HOUR(7) },  /* West Australian Standard */
+    { "wadt",  tDAYZONE,  -HOUR(7) },  /* West Australian Daylight */
+#if 0
+    { "jt",    tZONE,     -HOUR(7.5) },/* Java (3pm in Cronusland!) */
+#endif
+    { "cct",   tZONE,     -HOUR(8) },  /* China Coast, USSR Zone 7 */
+    { "jst",   tZONE,     -HOUR(9) },  /* Japan Standard, USSR Zone 8 */
+#if 0
+    { "cast",  tZONE,     -HOUR(9.5) },/* Central Australian Standard */
+    { "cadt",  tDAYZONE,  -HOUR(9.5) },/* Central Australian Daylight */
+#endif
+    { "east",  tZONE,     -HOUR(10) }, /* Eastern Australian Standard */
+    { "eadt",  tDAYZONE,  -HOUR(10) }, /* Eastern Australian Daylight */
+    { "gst",   tZONE,     -HOUR(10) }, /* Guam Standard, USSR Zone 9 */
+    { "nzt",   tZONE,     -HOUR(12) }, /* New Zealand */
+    { "nzst",  tZONE,     -HOUR(12) }, /* New Zealand Standard */
+    { "nzdt",  tDAYZONE,  -HOUR(12) }, /* New Zealand Daylight */
+    { "idle",  tZONE,     -HOUR(12) }, /* International Date Line East */
+    {  NULL  }
+};
+
+/* Military timezone table. */
+static TABLE   MilitaryTable[] = {
+    { "a",     tZONE,  HOUR(  1) },
+    { "b",     tZONE,  HOUR(  2) },
+    { "c",     tZONE,  HOUR(  3) },
+    { "d",     tZONE,  HOUR(  4) },
+    { "e",     tZONE,  HOUR(  5) },
+    { "f",     tZONE,  HOUR(  6) },
+    { "g",     tZONE,  HOUR(  7) },
+    { "h",     tZONE,  HOUR(  8) },
+    { "i",     tZONE,  HOUR(  9) },
+    { "k",     tZONE,  HOUR( 10) },
+    { "l",     tZONE,  HOUR( 11) },
+    { "m",     tZONE,  HOUR( 12) },
+    { "n",     tZONE,  HOUR(- 1) },
+    { "o",     tZONE,  HOUR(- 2) },
+    { "p",     tZONE,  HOUR(- 3) },
+    { "q",     tZONE,  HOUR(- 4) },
+    { "r",     tZONE,  HOUR(- 5) },
+    { "s",     tZONE,  HOUR(- 6) },
+    { "t",     tZONE,  HOUR(- 7) },
+    { "u",     tZONE,  HOUR(- 8) },
+    { "v",     tZONE,  HOUR(- 9) },
+    { "w",     tZONE,  HOUR(-10) },
+    { "x",     tZONE,  HOUR(-11) },
+    { "y",     tZONE,  HOUR(-12) },
+    { "z",     tZONE,  HOUR(  0) },
+    { NULL }
+};
+
+\f
+
+
+/* ARGSUSED */
+int
+yyerror(s)
+    char       *s;
+{
+  return 0;
+}
+
+
+static time_t
+ToSeconds(Hours, Minutes, Seconds, Meridian)
+    time_t     Hours;
+    time_t     Minutes;
+    time_t     Seconds;
+    MERIDIAN   Meridian;
+{
+    if (Minutes < 0 || Minutes > 59 || Seconds < 0 || Seconds > 59)
+       return -1;
+    switch (Meridian) {
+    case MER24:
+       if (Hours < 0 || Hours > 23)
+           return -1;
+       return (Hours * 60L + Minutes) * 60L + Seconds;
+    case MERam:
+       if (Hours < 1 || Hours > 12)
+           return -1;
+       return (Hours * 60L + Minutes) * 60L + Seconds;
+    case MERpm:
+       if (Hours < 1 || Hours > 12)
+           return -1;
+       return ((Hours + 12) * 60L + Minutes) * 60L + Seconds;
+    }
+    /* NOTREACHED */
+}
+
+
+static time_t
+Convert(Month, Day, Year, Hours, Minutes, Seconds, Meridian, DSTmode)
+    time_t     Month;
+    time_t     Day;
+    time_t     Year;
+    time_t     Hours;
+    time_t     Minutes;
+    time_t     Seconds;
+    MERIDIAN   Meridian;
+    DSTMODE    DSTmode;
+{
+    static int DaysInMonth[12] = {
+       31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+    };
+    time_t     tod;
+    time_t     Julian;
+    int                i;
+
+    if (Year < 0)
+       Year = -Year;
+    if (Year < 100)
+       Year += 1900;
+    DaysInMonth[1] = Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0)
+                   ? 29 : 28;
+    if (Year < EPOCH || Year > 1999
+     || Month < 1 || Month > 12
+     /* Lint fluff:  "conversion from long may lose accuracy" */
+     || Day < 1 || Day > DaysInMonth[(int)--Month])
+       return -1;
+
+    for (Julian = Day - 1, i = 0; i < Month; i++)
+       Julian += DaysInMonth[i];
+    for (i = EPOCH; i < Year; i++)
+       Julian += 365 + (i % 4 == 0);
+    Julian *= SECSPERDAY;
+    Julian += yyTimezone * 60L;
+    if ((tod = ToSeconds(Hours, Minutes, Seconds, Meridian)) < 0)
+       return -1;
+    Julian += tod;
+    if (DSTmode == DSTon
+     || (DSTmode == DSTmaybe && localtime(&Julian)->tm_isdst))
+       Julian -= 60 * 60;
+    return Julian;
+}
+
+
+static time_t
+DSTcorrect(Start, Future)
+    time_t     Start;
+    time_t     Future;
+{
+    time_t     StartDay;
+    time_t     FutureDay;
+
+    StartDay = (localtime(&Start)->tm_hour + 1) % 24;
+    FutureDay = (localtime(&Future)->tm_hour + 1) % 24;
+    return (Future - Start) + (StartDay - FutureDay) * 60L * 60L;
+}
+
+
+static time_t
+RelativeDate(Start, DayOrdinal, DayNumber)
+    time_t     Start;
+    time_t     DayOrdinal;
+    time_t     DayNumber;
+{
+    struct tm  *tm;
+    time_t     now;
+
+    now = Start;
+    tm = localtime(&now);
+    now += SECSPERDAY * ((DayNumber - tm->tm_wday + 7) % 7);
+    now += 7 * SECSPERDAY * (DayOrdinal <= 0 ? DayOrdinal : DayOrdinal - 1);
+    return DSTcorrect(Start, now);
+}
+
+
+static time_t
+RelativeMonth(Start, RelMonth)
+    time_t     Start;
+    time_t     RelMonth;
+{
+    struct tm  *tm;
+    time_t     Month;
+    time_t     Year;
+
+    if (RelMonth == 0)
+       return 0;
+    tm = localtime(&Start);
+    Month = 12 * tm->tm_year + tm->tm_mon + RelMonth;
+    Year = Month / 12;
+    Month = Month % 12 + 1;
+    return DSTcorrect(Start,
+           Convert(Month, (time_t)tm->tm_mday, Year,
+               (time_t)tm->tm_hour, (time_t)tm->tm_min, (time_t)tm->tm_sec,
+               MER24, DSTmaybe));
+}
+
+
+static int
+LookupWord(buff)
+    char               *buff;
+{
+    register char      *p;
+    register char      *q;
+    register TABLE     *tp;
+    int                        i;
+    int                        abbrev;
+
+    /* Make it lowercase. */
+    for (p = buff; *p; p++)
+       if (isupper(*p))
+           *p = tolower(*p);
+
+    if (strcmp(buff, "am") == 0 || strcmp(buff, "a.m.") == 0) {
+       yylval.Meridian = MERam;
+       return tMERIDIAN;
+    }
+    if (strcmp(buff, "pm") == 0 || strcmp(buff, "p.m.") == 0) {
+       yylval.Meridian = MERpm;
+       return tMERIDIAN;
+    }
+
+    /* See if we have an abbreviation for a month. */
+    if (strlen(buff) == 3)
+       abbrev = 1;
+    else if (strlen(buff) == 4 && buff[3] == '.') {
+       abbrev = 1;
+       buff[3] = '\0';
+    }
+    else
+       abbrev = 0;
+
+    for (tp = MonthDayTable; tp->name; tp++) {
+       if (abbrev) {
+           if (strncmp(buff, tp->name, 3) == 0) {
+               yylval.Number = tp->value;
+               return tp->type;
+           }
+       }
+       else if (strcmp(buff, tp->name) == 0) {
+           yylval.Number = tp->value;
+           return tp->type;
+       }
+    }
+
+    for (tp = TimezoneTable; tp->name; tp++)
+       if (strcmp(buff, tp->name) == 0) {
+           yylval.Number = tp->value;
+           return tp->type;
+       }
+
+    if (strcmp(buff, "dst") == 0) 
+       return tDST;
+
+    for (tp = UnitsTable; tp->name; tp++)
+       if (strcmp(buff, tp->name) == 0) {
+           yylval.Number = tp->value;
+           return tp->type;
+       }
+
+    /* Strip off any plural and try the units table again. */
+    i = strlen(buff) - 1;
+    if (buff[i] == 's') {
+       buff[i] = '\0';
+       for (tp = UnitsTable; tp->name; tp++)
+           if (strcmp(buff, tp->name) == 0) {
+               yylval.Number = tp->value;
+               return tp->type;
+           }
+       buff[i] = 's';          /* Put back for "this" in OtherTable. */
+    }
+
+    for (tp = OtherTable; tp->name; tp++)
+       if (strcmp(buff, tp->name) == 0) {
+           yylval.Number = tp->value;
+           return tp->type;
+       }
+
+    /* Military timezones. */
+    if (buff[1] == '\0' && isalpha(*buff)) {
+       for (tp = MilitaryTable; tp->name; tp++)
+           if (strcmp(buff, tp->name) == 0) {
+               yylval.Number = tp->value;
+               return tp->type;
+           }
+    }
+
+    /* Drop out any periods and try the timezone table again. */
+    for (i = 0, p = q = buff; *q; q++)
+       if (*q != '.')
+           *p++ = *q;
+       else
+           i++;
+    *p = '\0';
+    if (i)
+       for (tp = TimezoneTable; tp->name; tp++)
+           if (strcmp(buff, tp->name) == 0) {
+               yylval.Number = tp->value;
+               return tp->type;
+           }
+
+    return tID;
+}
+
+
+int
+yylex()
+{
+    register char      c;
+    register char      *p;
+    char               buff[20];
+    int                        Count;
+    int                        sign;
+
+    for ( ; ; ) {
+       while (isspace(*yyInput))
+           yyInput++;
+
+       if (isdigit(c = *yyInput) || c == '-' || c == '+') {
+           if (c == '-' || c == '+') {
+               sign = c == '-' ? -1 : 1;
+               if (!isdigit(*++yyInput))
+                   /* skip the '-' sign */
+                   continue;
+           }
+           else
+               sign = 0;
+           for (yylval.Number = 0; isdigit(c = *yyInput++); )
+               yylval.Number = 10 * yylval.Number + c - '0';
+           yyInput--;
+           if (sign < 0)
+               yylval.Number = -yylval.Number;
+           return sign ? tSNUMBER : tUNUMBER;
+       }
+       if (isalpha(c)) {
+           for (p = buff; isalpha(c = *yyInput++) || c == '.'; )
+               if (p < &buff[sizeof buff - 1])
+                   *p++ = c;
+           *p = '\0';
+           yyInput--;
+           return LookupWord(buff);
+       }
+       if (c != '(')
+           return *yyInput++;
+       Count = 0;
+       do {
+           c = *yyInput++;
+           if (c == '\0')
+               return c;
+           if (c == '(')
+               Count++;
+           else if (c == ')')
+               Count--;
+       } while (Count > 0);
+    }
+}
+
+
+time_t
+get_date(p, now)
+    char               *p;
+    struct timeb       *now;
+{
+    struct tm          *tm;
+    struct timeb       ftz;
+    time_t             Start;
+    time_t             tod;
+
+    yyInput = p;
+    if (now == NULL) {
+       now = &ftz;
+#if    defined(FTIME_MISSING)
+       (void)time(&ftz.time);
+       /* Set the timezone global. */
+       tzset();
+#if    defined(HAVE_TIMEZONE)
+       tm = localtime(&ftz.time);
+       ftz.timezone = tm->tm_gmtoff / 60;
+#else
+#if    defined(timezone)
+       ftz.tzone = (int) timezone / 60;
+#else
+       ftz.timezone = (int) timezone / 60;
+#endif /* defined(timezone) */
+#endif /* defined(HAVE_TIMEZONE) */
+#else
+       (void)ftime(&ftz);
+#endif /* defined(FTIME_MISSING) */
+    }
+
+    tm = localtime(&now->time);
+    yyYear = tm->tm_year;
+    yyMonth = tm->tm_mon + 1;
+    yyDay = tm->tm_mday;
+#if    defined(timezone)
+    yyTimezone = now->tzone;
+#else
+    yyTimezone = now->timezone;
+#endif /* defined(timezone) */
+    yyDSTmode = DSTmaybe;
+    yyHour = 0;
+    yyMinutes = 0;
+    yySeconds = 0;
+    yyMeridian = MER24;
+    yyRelSeconds = 0;
+    yyRelMonth = 0;
+    yyHaveDate = 0;
+    yyHaveDay = 0;
+    yyHaveRel = 0;
+    yyHaveTime = 0;
+    yyHaveZone = 0;
+
+    if (yyparse()
+     || yyHaveTime > 1 || yyHaveZone > 1 || yyHaveDate > 1 || yyHaveDay > 1)
+       return -1;
+
+    if (yyHaveDate || yyHaveTime || yyHaveDay) {
+       Start = Convert(yyMonth, yyDay, yyYear, yyHour, yyMinutes, yySeconds,
+                   yyMeridian, yyDSTmode);
+       if (Start < 0)
+           return -1;
+    }
+    else {
+       Start = now->time;
+       if (!yyHaveRel)
+           Start -= ((tm->tm_hour * 60L + tm->tm_min) * 60L) + tm->tm_sec;
+    }
+
+    Start += yyRelSeconds;
+    Start += RelativeMonth(Start, yyRelMonth);
+
+    if (yyHaveDay && !yyHaveDate) {
+       tod = RelativeDate(Start, yyDayOrdinal, yyDayNumber);
+       Start += tod;
+    }
+
+    /* Have to do *something* with a legitimate -1 so it's distinguishable
+     * from the error return value.  (Alternately could set errno on error.) */
+    return Start == -1 ? 0 : Start;
+}
+
+
+#if    defined(TEST)
+
+/* ARGSUSED */
+main(ac, av)
+    int                ac;
+    char       *av[];
+{
+    char       buff[128];
+    time_t     d;
+
+    (void)printf("Enter date, or blank line to exit.\n\t> ");
+    (void)fflush(stdout);
+    while (gets(buff) && buff[0]) {
+       d = get_date(buff, (struct timeb *)NULL);
+       if (d == -1)
+           (void)printf("Bad format - couldn't convert.\n");
+       else
+           (void)printf("%s", ctime(&d));
+       (void)printf("\t> ");
+       (void)fflush(stdout);
+    }
+    exit(0);
+    /* NOTREACHED */
+}
+#endif /* defined(TEST) */
diff --git a/src/kadmin.new/client/kadmin.c b/src/kadmin.new/client/kadmin.c
new file mode 100644 (file)
index 0000000..f073b7b
--- /dev/null
@@ -0,0 +1,383 @@
+/*
+ * Copyright 1994 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in 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.
+ * 
+ * kadmin.c: base functions for a kadmin command line interface using
+ * the OVSecure library
+ */
+
+#include <krb5/krb5.h>
+#include <krb5/los-proto.h>
+#include <krb5/ext-proto.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <math.h>
+#include <unistd.h>
+#include <pwd.h>
+
+/* special struct to convert flag names for principals
+   to actual krb5_flags for a principal */
+struct princ_flag {
+    char *flagname;            /* name of flag as typed to CLI */
+    int flaglen;               /* length of string (not counting -,+) */
+    krb5_flags theflag;                /* actual principal flag to set/clear */
+    int set;                   /* 0 means clear, 1 means set (on '-') */
+};
+
+static struct princ_flag the_flags = {
+{ "allow_tgs_req", 13, KRB5_KDB_DISALLOW_TGT_BASED, 1 },
+{ "allow_tix", 9, KRB5_KDB_DISALLOW_ALL_TIX, 1 },
+{ "needchange", 10, KRB5_KDB_REQUIRES_PWCHANGE, 0 },
+{ "password_changing_service", 25, KRB5_KDB_PWCHANGE_SERVICE, 0 }
+};
+
+char *getenv();
+struct passwd *getpwuid();
+
+void usage()
+{
+    fprintf(stderr,
+           "usage: kadmin [-r realm] [-p principal] [-k keytab] [-q query]\n");
+    exit(1);
+}
+
+char *kadmin_startup(argc, argv)
+    int argc;
+    char *argv[];
+{
+    extern char *optarg;
+    char *realmname = NULL, princstr = NULL, *keytab = NULL, *query = NULL;
+    char *luser;
+    int optchar, freeprinc = 0;
+    struct passwd *pw;
+    ovsec_kadm_ret_t retval;
+    krb5_ccache cc;
+    krb5_principal princ;
+
+    while ((optchar = getopt(argc, argv, "r:p:k:q:")) != EOF) {
+       switch (optchar) {
+       case 'r':
+           realmname = optarg;
+           break;
+       case 'p':
+           princstr = optarg;
+           break;
+       case 'k':
+           fprintf(stderr, "kadmin: -k not supported yet\n");
+           exit(1);
+           break;
+       case 'q':
+           query = optarg;
+           break;
+       default:
+           usage();
+       }
+    }
+    if (princstr == NULL) {
+       if (!krb5_cc_default(&cc) && !krb5_cc_get_principal(cc, &princ)) {
+           princstr =
+               (char *)malloc(krb5_princ_component(princ, 0)->length +
+                              7 /* "/admin@" */ +
+                              krb5_princ_realm(princ)->length + 1);
+           if (princstr == NULL) {
+               fprintf(stderr, "kadmin: out of memory\n");
+               exit(1);
+           }
+           /* XXX assuming no nulls in principal */
+           strncpy(princstr, krb5_princ_component(princ, 0)->data,
+                   krb5_princ_component(princ, 0)->length);
+           princstr[krb5_princ_component(princ, 0)->length] = '\0';
+           strcat(princstr, "/admin@");
+           strncat(princstr, krb5_princ_realm(princ)->data,
+                   krb5_princ_realm(princ)->length);
+           krb5_free_principal(princ);
+           freeprinc++;
+       } else if (luser = getenv("USER")) {
+           princstr = malloc(strlen(luser) + 6 /* "/admin" */ + 1);
+           if (princstr == NULL) {
+               fprintf(stderr, "kadmin: out of memory\n");
+               exit(1);
+           }
+           strcpy(princstr, luser);
+           strcat(princstr, "/admin");
+           freeprinc++;
+       } else if (pw = getpwuid(getuid())) {
+           princstr = malloc(strlen(pw->pw_name) + 6 /* "/admin" */ + 1);
+           if (princstr == NULL) {
+               fprintf(stderr, "kadmin: out of memory\n");
+               exit(1);
+           }
+           strcpy(princstr, pw->pw_name);
+           strcat(princstr, "/admin");
+           freeprinc++;
+       } else {
+           fprintf(stderr, "kadmin: unable to figure out a principal name\n");
+           exit(1);
+       }
+    }
+    
+    retval = ovsec_kadm_init(princstr, NULL, OVSEC_KADM_ADMIN_SERVICE,
+                            realmname);
+    if (freeprinc)
+       free(princstr);
+    if (retval) {              /* assume kadm_init does init_ets() */
+       com_err("kadmin", retval, "while initializing kadmin interface");
+       exit(1);
+    }
+    return query;
+}
+
+int quit()
+{
+    ovsec_kadm_destroy();
+    /* insert more random cleanup here */
+}
+
+void kadmin_delprinc(argc, argv)
+    int argc;
+    char *argv[];
+{
+    ovsec_kadm_ret_t retval;
+    krb5_principal princ;
+    int i;
+    char reply[5];
+
+    if (argc > 3) {
+       fprintf(stderr, "delete_principal: too many arguments\n");
+       return;
+    }
+    if (argc == 1) {
+       printf("Are you sure you want to delete the principal \"%s\"? (yes/no): ", argv[1]);
+       fgets(reply, sizeof (reply), stdin);
+       if (strcmp("yes\n", reply)) {
+           fprintf(stderr, "Principal \"%s\" not deleted\n", argv[1]);
+           return;
+       }
+    }
+    if ((argc == 2) && ((i = strlen(argv[1])) == 6) &&
+       strcmp("-force", argv[1]) || (i != 6) {
+       fprintf(stderr, "delete_principal: bad arguments\n");
+       return;
+    }
+    retval = krb5_parse_name(argv[argc - 1], &princ);
+    if (retval) {
+       com_err("delete_principal", retval, "while parsing principal name");
+       return;
+    }
+    reval = ovsec_kadm_delete_principal(princ);
+    krb5_free_principal(princ);
+    if (retval) {
+       com_err("delete_principal", retval,
+               "while deleteing principal \"%s\"", argv[argc - 1]);
+       return;
+    }
+    printf("Principal \"%s\" deleted.\nMake sure that you have removed this principal from all ACLs before reusing.\n", argv[argc - 1]);
+    return;
+}
+
+void kadmin_renprinc(argc, argv)
+    int argc;
+    char *argv[];
+{
+    krb5_principal oldprinc, newprinc;
+    int i;
+    char reply[5];
+    ovsec_kadm_ret_t retval;
+
+    if (argc > 4 || argc < 3) {
+       fprintf(stderr, "rename_principal: too many arguments\n");
+       return;
+    }
+    if (argc == 3) {
+       printf("Are you sure you want to rename the principal \"%s\" to \"%s\"? (yes/no): ",
+              argv[1], argv[2]);
+       fgets(reply, sizeof (reply), stdin);
+       if (strcmp("yes\n", reply)) {
+           fprintf(stderr, "rename_principal: \"%s\" NOT renamed to \"%s\".\n",
+                   argv[1], argv[2]);
+           return;
+       }
+    }
+    if ((argc == 4) && ((i = strlen(argv[1])) == 6) &&
+       !strcmp("-force", argv[1]) || (i != 6)) {
+       fprintf(stderr, "rename_principal: wrong arguments\n");
+       return;
+    }
+    retval = krb5_parse_name(argv[argc - 2], &oldprinc);
+    if (retval) {
+       com_err("rename_principal", retval, "while parsing old principal");
+       return;
+    }
+    retval = krb5_parse_name(argv[argc - 1], &newprinc);
+    if (retval) {
+       krb5_free_principal(oldprinc);
+       com_err("rename_principal", retval, "while parsing new principal");
+       return;
+    }
+    retval = ovsed_kadm_rename_principal(oldprinc, newprinc);
+    krb5_free_principal(oldprinc);
+    krb5_free_principal(newprinc);
+    if (retval) {
+       com_err("rename_principal", retval,
+               "while renaming \"%s\" to \"%s\".", argv[argc - 2],
+               argv[argc - 1]);
+       return;
+    }
+    fprintf("Principal \"%s\" renamed to \"%s\".\nMake sure that you have removed \"%s\" from all ACLs before reusing.\n",
+           argv[argc - 2], argv[argc - 1], argv[argc - 2]);
+    return;
+}
+
+void kadmin_cpw(argc, argv)
+    int argc;
+    char *argv[];
+{
+    ovsec_kadm_ret_t retval;
+    static char newpw[1024];
+    static char prompt1[1024], prompt2[1024];
+    krb5_principal princ;
+
+    if (argc > 4) {
+       fprintf(stderr, "change_password: too many arguments\n");
+       return;
+    }
+    retval = krb5_parse_name(argv[argc - 1], &princ);
+    if (retval) {
+       com_err("change_password", retval, "while parsing principal name");
+       return;
+    }
+    if ((argc == 4) && (strlen(argv[1]) == 3) && !strcmp("-pw", argv[1])) {
+       retval = ovsec_kadm_chpass_principal(princ, argv[2]);
+       krb5_free_principal(princ);
+       if (retval) {
+           com_err("change_password", retval,
+                   "while changing password for \"%s\".", argv[3]);
+           return;
+       }
+       printf("Password for \"%s\" changed.\n", argv[3]);
+       return;
+    } else if ((argc == 3) && (strlen(argv[1]) == 8) &&
+              !strcmp("-randkey", argv[1])) {
+       krb5_keyblock *newkey = NULL;
+       retval = ovsec_kadm_randkey_principal(princ, &newkey);
+       krb5_free_principal(princ);
+       if (retval) {
+           com_err("change_password", retval,
+                   "while randomizing key for \"%s\".", argv[2]);
+           return;
+       }
+       memset(newkey->contents, 0, newkey->length);
+       printf("Key for \"%s\" randomized.\n", argv[2]);
+       return;
+    } else if (argc == 2) {
+       int i = sizeof (newpw) - 1;
+
+       sprintf(prompt1, "Enter password for principal \"%.900s\": ",
+               argv[1]);
+       sprintf(prompt2,
+               "Re-enter password for principal \"%.900s\": ",
+               argv[1]);
+       retval = krb5_read_password(prompt1, prompt2,
+                                   newpw, &i);
+       if (retval) {
+           com_err("change_password", retval,
+                   "while reading password for \"%s\".", argv[1]);
+           krb5_free_principal(princ);
+           return;
+       }
+       retval = ovsec_kadm_chpass_principal(princ, newpw);
+       krb5_free_principal(princ);
+       memset(newpw, 0, sizeof (newpw));
+       if (retval) {
+           com_err("change_password", retval,
+                   "while changing password for \"%s\".", argv[1]);
+           return;
+       }
+       printf("Password for \"%s\" changed.", argv[1]);
+       return;
+    }
+    fprintf(stderr, "change_password: bad args\n");
+    krb5_free_principal(princ);
+    return;
+}
+
+int kadmin_parse_princ_args(argc, argv, oprinc, mask, pass)
+    int argc;
+    char *argv[];
+    ovsec_kadm_principal_ent_t *oprinc;
+    u_int32 *mask;
+    char *pw;
+{
+    int i;
+    struct timeb now;
+
+    ftime(&now);
+    for (i = 1; i < argc - 1; i++) {
+       if (strlen(argv[i]) == 7 &&
+           !strcmp("-expire", argv[i])) {
+           if (++i >= argc - 1)
+               return -1;
+           else {
+               oprinc->princ_expire_time = get_date(argv[i], now);
+               *mask |= OVSEC_KADM_PRINC_EXPIRE_TIME;
+               continue;
+           }
+       }
+       if (strlen(argv[i]) == 9 &&
+           !strcmp("-pwexpire", argv[i])) {
+           if (++i >= argc - 1)
+               return -1;
+           else {
+               oprinc->pw_expiration = get_date(argv[i], now);
+               *mask |= OVSEC_KADM_PW_EXPIRATION;
+               continue;
+           }
+       }
+       if (strlen(argv[i]) == 5 &&
+           !strcmp("-kvno", argv[i])) {
+           if (++i >= argc - 1)
+               return -1;
+           else {
+               oprinc->kvno = atoi(argv[i]);
+               *mask |= OVSEC_KADM_KVNO;
+               continue;
+           }
+       }
+       if (strlen(argv[i]) == 8 &&
+           !strcmp("-policy", argv[i])) {
+           if (++i >= argc - 1)
+               return -1;
+           else {
+               oprinc->policy = argv[i];
+               *mask |= OVSEC_KADM_POLICY;
+               continue;
+           }
+       }
+       if (strlen(argv[i]) == 12 &&
+           !strcmp("-clearpolicy", argv[i])) {
+           if (++i >= argc - 1)
+               return -1;
+           else {
+               oprinc->policy = NULL;
+               *mask |= OVSEC_KADM_POLICY_CLR;
+               continue;
+           }
+       }
+    }
+}