fixes as per OV suggestions
authorTom Yu <tlyu@mit.edu>
Fri, 23 Dec 1994 02:06:37 +0000 (02:06 +0000)
committerTom Yu <tlyu@mit.edu>
Fri, 23 Dec 1994 02:06:37 +0000 (02:06 +0000)
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@4749 dc483132-0cff-0310-8789-dd5450dbe970

src/kadmin.new/client/ChangeLog [new file with mode: 0644]
src/kadmin.new/client/Makefile.in
src/kadmin.new/client/configure.in
src/kadmin.new/client/kadmin.c
src/kadmin.new/client/kadmin_ct.ct
src/kadmin.new/client/ss_wrapper.c
src/kadmin.new/client/strftime.c [new file with mode: 0644]

diff --git a/src/kadmin.new/client/ChangeLog b/src/kadmin.new/client/ChangeLog
new file mode 100644 (file)
index 0000000..0303a76
--- /dev/null
@@ -0,0 +1,5 @@
+Thu Dec 22 20:55:05 1994  Tom Yu  (tlyu@dragons-lair)
+
+       * kadmin.c: lots of bug fixes, fixing addprinc -randkey, cosmetic
+       changes to getprinc, etc.
+
index 160016af98d35ac914f2a167a9b0495ec5d7b3e3..2a4e41c85cfe50d22ef7a894461a2c64ba1a9140 100644 (file)
@@ -1,13 +1,13 @@
 CFLAGS = $(CCOPTS) $(DEFS) $(LOCALINCLUDE) $(OVSECINC)
-OVSECROOT=/home/tlyu/ovsecure
-OVSECSTAGE=/afs/dev.mit.edu/reference/ovsecure/sunos/stage
+OVSECROOT=/home/tlyu/ovsecure/install
+OVSECSTAGE=/home/tlyu/ovsecure/stage
 OVSECINC=-I$(OVSECROOT)/include -I$(OVSECSTAGE)/include
-OVSECLIB=-L$(OVSECSTAGE)/lib -lclient -lcommon -lrpclib -ldyn
+OVSECLIB=-L$(OVSECSTAGE)/lib -ladmclnt -lrpclib -ldyn
 LDFLAGS = -g
 LIBOBJS=@LIBOBJS@
 ISODELIB=$(OVSECROOT)/lib/libisode.a
 COMERRLIB=$(OVSECROOT)/lib/libcom_err.a
-SSLIB=$(OVSECSTAGE)/lib/libss.a
+SSLIB=$(BUILDTOP)/util/ss/libss.a
 DBMLIB=$(OVSECROOT)/lib/libdb.a
 KDBLIB=$(OVSECROOT)/lib/libkdb5.a 
 
index 6528c80e166f9bba57a30428e18e45bd77afbfa7..3ff3f96465561910c040e07729d06bd0f416cf35 100644 (file)
@@ -8,7 +8,7 @@ AC_HAVE_HEADERS(unistd.h sys/timeb.h alloca.h)
 AC_HAVE_FUNCS(ftime timezone)
 AC_CHECK_LIB(ndbm,main)
 AC_CHECK_LIB(dbm,main)
-AC_REPLACE_FUNCS([setenv memmove])
+AC_REPLACE_FUNCS([setenv memmove strftime])
 SS_RULES
 KRB_INCLUDE
 ISODE_INCLUDE
index f2f30b09fb481ab430ec11386d44253844d875ee..33c9fce349412628e71da7627181ce707a4b6c3c 100644 (file)
@@ -52,7 +52,7 @@ static struct pflag flags[] = {
 {"allow_dup_skey",     14,     KRB5_KDB_DISALLOW_DUP_SKEY,     1},
 {"allow_tix",          9,      KRB5_KDB_DISALLOW_ALL_TIX,      1},
 {"requires_preauth",   16,     KRB5_KDB_REQUIRES_PRE_AUTH,     0},
-{"requres_hwauth",     14,     KRB5_KDB_REQUIRES_HW_AUTH,      0},
+{"requires_hwauth",    15,     KRB5_KDB_REQUIRES_HW_AUTH,      0},
 {"needchange",         10,     KRB5_KDB_REQUIRES_PWCHANGE,     0},
 {"allow_svr",          9,      KRB5_KDB_DISALLOW_SVR,          1},
 {"password_changing_service",  25,     KRB5_KDB_PWCHANGE_SERVICE,      0 }
@@ -79,6 +79,9 @@ char *getenv();
 struct passwd *getpwuid();
 int exit_status = 0;
 char *def_realm = NULL;
+time_t get_date();
+
+void *ovsec_hndl = NULL;
 
 void usage()
 {
@@ -87,6 +90,35 @@ void usage()
     exit(1);
 }
 
+char *strdur(duration)
+    time_t duration;
+{
+    static char out[50];
+    int days, hours, minutes, seconds;
+    
+    days = duration / (24 * 3600);
+    duration %= 24 * 3600;
+    hours = duration / 3600;
+    duration %= 3600;
+    minutes = duration / 60;
+    duration %= 60;
+    seconds = duration;
+    sprintf(out, "%d %s %02d:%02d:%02d", days, days == 1 ? "day" : "days",
+           hours, minutes, seconds);
+    return out;
+}
+
+char *strdate(when)
+    time_t when;
+{
+    struct tm *tm;
+    static char out[30];
+    
+    tm = localtime(&when);
+    strftime(out, 30, "%a %b %d %H:%M:%S %Z %Y", tm);
+    return out;
+}
+
 /* this is a wrapper to go around krb5_parse_principal so we can set
    the default realm up properly */
 krb5_error_code kadmin_parse_name(name, principal)
@@ -226,8 +258,12 @@ char *kadmin_startup(argc, argv)
            exit(1);
        }
     }
-    retval = ovsec_kadm_init(princstr, NULL, OVSEC_KADM_ADMIN_SERVICE,
-                            def_realm);
+    retval = ovsec_kadm_init_with_password(princstr, NULL,
+                                          OVSEC_KADM_ADMIN_SERVICE, 
+                                          def_realm,
+                                          OVSEC_KADM_STRUCT_VERSION,
+                                          OVSEC_KADM_API_VERSION_1,
+                                          &ovsec_hndl);
     if (freeprinc)
        free(princstr);
     if (retval) {              /* assume kadm_init does init_ets() */
@@ -239,7 +275,7 @@ char *kadmin_startup(argc, argv)
 
 int quit()
 {
-    ovsec_kadm_destroy();
+    ovsec_kadm_destroy(ovsec_hndl);
     /* insert more random cleanup here */
 }
 
@@ -283,7 +319,7 @@ void kadmin_delprinc(argc, argv)
            return;
        }
     }
-    retval = ovsec_kadm_delete_principal(princ);
+    retval = ovsec_kadm_delete_principal(ovsec_hndl, princ);
     krb5_free_principal(princ);
     if (retval) {
        com_err("delete_principal", retval,
@@ -357,7 +393,7 @@ void kadmin_renprinc(argc, argv)
            return;
        }
     }
-    retval = ovsec_kadm_rename_principal(oldprinc, newprinc);
+    retval = ovsec_kadm_rename_principal(ovsec_hndl, oldprinc, newprinc);
     krb5_free_principal(oldprinc);
     krb5_free_principal(newprinc);
     if (retval) {
@@ -399,7 +435,7 @@ void kadmin_cpw(argc, argv)
        return;
     }
     if ((argc == 4) && (strlen(argv[1]) == 3) && !strcmp("-pw", argv[1])) {
-       retval = ovsec_kadm_chpass_principal(princ, argv[2]);
+       retval = ovsec_kadm_chpass_principal(ovsec_hndl, princ, argv[2]);
        krb5_free_principal(princ);
        if (retval) {
            com_err("change_password", retval,
@@ -413,7 +449,7 @@ void kadmin_cpw(argc, argv)
     } else if ((argc == 3) && (strlen(argv[1]) == 8) &&
               !strcmp("-randkey", argv[1])) {
        krb5_keyblock *newkey = NULL;
-       retval = ovsec_kadm_randkey_principal(princ, &newkey);
+       retval = ovsec_kadm_randkey_principal(ovsec_hndl, princ, &newkey);
        krb5_free_principal(princ);
        if (retval) {
            com_err("change_password", retval,
@@ -422,6 +458,7 @@ void kadmin_cpw(argc, argv)
            return;
        }
        memset(newkey->contents, 0, newkey->length);
+       krb5_free_keyblock(newkey);
        printf("Key for \"%s\" randomized.\n", canon);
        free(canon);
        return;
@@ -442,7 +479,7 @@ void kadmin_cpw(argc, argv)
            krb5_free_principal(princ);
            return;
        }
-       retval = ovsec_kadm_chpass_principal(princ, newpw);
+       retval = ovsec_kadm_chpass_principal(ovsec_hndl, princ, newpw);
        krb5_free_principal(princ);
        memset(newpw, 0, sizeof (newpw));
        if (retval) {
@@ -461,27 +498,33 @@ void kadmin_cpw(argc, argv)
     return;
 }
 
-int kadmin_parse_princ_args(argc, argv, oprinc, mask, pass, caller)
+int kadmin_parse_princ_args(argc, argv, oprinc, mask, pass, randkey, caller)
     int argc;
     char *argv[];
     ovsec_kadm_principal_ent_t oprinc;
     u_int32 *mask;
-    char **pass, *caller;
+    char **pass;
+    int *randkey;
+    char *caller;
 {
-    int i, j;
+    int i, j, attrib_set;
+    time_t date;
     struct timeb now;
     krb5_error_code retval;
     
     *mask = 0;
     *pass = NULL;
     ftime(&now);
+    *randkey = 0;
     for (i = 1; i < argc - 1; i++) {
+       attrib_set = 0;
        if (strlen(argv[i]) == 7 &&
            !strcmp("-expire", argv[i])) {
            if (++i > argc - 2)
                return -1;
            else {
-               oprinc->princ_expire_time = get_date(argv[i], now);
+               date = get_date(argv[i], now);
+               oprinc->princ_expire_time = date == (time_t)-1 ? 0 : date;
                *mask |= OVSEC_KADM_PRINC_EXPIRE_TIME;
                continue;
            }
@@ -491,7 +534,8 @@ int kadmin_parse_princ_args(argc, argv, oprinc, mask, pass, caller)
            if (++i > argc - 2)
                return -1;
            else {
-               oprinc->pw_expiration = get_date(argv[i], now);
+               date = get_date(argv[i], now);
+               oprinc->pw_expiration = date == (time_t)-1 ? 0 : date;
                *mask |= OVSEC_KADM_PW_EXPIRATION;
                continue;
            }
@@ -541,6 +585,11 @@ int kadmin_parse_princ_args(argc, argv, oprinc, mask, pass, caller)
                continue;
            }
        }
+       if (strlen(argv[i]) == 8 &&
+           !strcmp("-randkey", argv[i])) {
+           ++*randkey;
+           continue;
+       }
        for (j = 0; j < sizeof (flags) / sizeof (struct pflag); j++) {
            if (strlen(argv[i]) == flags[j].flaglen + 1 &&
                !strcmp(flags[j].flagname,
@@ -549,18 +598,21 @@ int kadmin_parse_princ_args(argc, argv, oprinc, mask, pass, caller)
                    !flags[j].set && argv[i][0] == '+') {
                    oprinc->attributes |= flags[j].theflag;
                    *mask |= OVSEC_KADM_ATTRIBUTES;
+                   attrib_set++;
                    break;
                } else if (flags[j].set && argv[i][0] == '+' ||
                           !flags[j].set && argv[i][0] == '-') {
                    oprinc->attributes &= ~flags[j].theflag;
                    *mask |= OVSEC_KADM_ATTRIBUTES;
+                   attrib_set++;
                    break;
                } else {
                    return -1;
                }
            }
        }
-       return -1;
+       if (!attrib_set)
+           return -1;          /* nothing was parsed */
     }
     if (i != argc - 1) {
        fprintf(stderr, "%s: parser lost count!\n", caller);
@@ -580,6 +632,7 @@ void kadmin_addprinc(argc, argv)
 {
     ovsec_kadm_principal_ent_rec princ;
     u_int32 mask;
+    int randkey = 0;
     char *pass, *canon;
     krb5_error_code retval;
     static char newpw[1024];
@@ -587,7 +640,8 @@ void kadmin_addprinc(argc, argv)
     
     princ.attributes = 0;
     if (kadmin_parse_princ_args(argc, argv,
-                               &princ, &mask, &pass, "add_principal")) {
+                               &princ, &mask, &pass, &randkey,
+                               "add_principal")) {
        fprintf(stderr, "add_principal: bad arguments\n");
        return;
     }
@@ -598,14 +652,18 @@ void kadmin_addprinc(argc, argv)
        krb5_free_principal(princ.principal);
        return;
     }
-    if (pass == NULL) {
+    if (randkey) {             /* do special stuff if -randkey specified */
+       princ.attributes |= KRB5_KDB_DISALLOW_ALL_TIX; /* set notix */
+       mask |= OVSEC_KADM_ATTRIBUTES;
+       pass = "dummy";
+    } else if (pass == NULL) {
        int i = sizeof (newpw) - 1;
        
        sprintf(prompt1, "Enter password for principal \"%.900s\": ",
-               argv[1]);
+               canon);
        sprintf(prompt2,
                "Re-enter password for principal \"%.900s\": ",
-               argv[1]);
+               canon);
        retval = krb5_read_password(prompt1, prompt2,
                                    newpw, &i);
        if (retval) {
@@ -618,14 +676,39 @@ void kadmin_addprinc(argc, argv)
        pass = newpw;
     }
     mask |= OVSEC_KADM_PRINCIPAL;
-    retval = ovsec_kadm_create_principal(&princ, mask, pass);
-    krb5_free_principal(princ.principal);
+    retval = ovsec_kadm_create_principal(ovsec_hndl, &princ, mask, pass);
     if (retval) {
        com_err("add_principal", retval, "while creating \"%s\".",
                canon);
+       krb5_free_principal(princ.principal);
        free(canon);
        return;
     }
+    if (randkey) {             /* more special stuff for -randkey */
+       krb5_keyblock *newkey = NULL;
+       retval = ovsec_kadm_randkey_principal(ovsec_hndl, princ.principal,
+                                             &newkey);
+       if (retval) {
+           com_err("add_principal", retval,
+                   "while randomizing key for \"%s\".", canon);
+           krb5_free_principal(princ.principal);
+           free(canon);
+           return;
+       }
+       memset(newkey->contents, 0, newkey->length);
+       krb5_free_keyblock(newkey);
+       princ.attributes &= ~KRB5_KDB_DISALLOW_ALL_TIX; /* clear notix */
+       mask = OVSEC_KADM_ATTRIBUTES;
+       retval = ovsec_kadm_modify_principal(ovsec_hndl, &princ, mask);
+       if (retval) {
+           com_err("add_principal", retval,
+                   "while clearing DISALLOW_ALL_TIX for \"%s\".", canon);
+           krb5_free_principal(princ.principal);
+           free(canon);
+           return;
+       }
+    }
+    krb5_free_principal(princ.principal);
     printf("Principal \"%s\" created.\n", canon);
     free(canon);
 }
@@ -635,29 +718,61 @@ void kadmin_modprinc(argc, argv)
     char *argv[];
 {
     ovsec_kadm_principal_ent_rec princ;
+    ovsec_kadm_principal_ent_t oldprinc;
+    krb5_principal kprinc;
     u_int32 mask;
     krb5_error_code retval;
     char *pass, *canon;
-    
-    princ.attributes = 0;
-    if (kadmin_parse_princ_args(argc, argv,
-                               &princ, &mask, &pass, "modify_principal")) {
-       fprintf(stderr, "modify_principal: bad arguments\n");
+    int randkey = 0;
+
+    retval = kadmin_parse_name(argv[argc - 1], &kprinc);
+    if (retval) {
+       com_err("modify_principal", retval, "while parsing principal");
        return;
     }
-    retval = krb5_unparse_name(princ.principal, &canon);
+    retval = krb5_unparse_name(kprinc, &canon);
     if (retval) {
        com_err("modify_principal", retval,
                "while canonicalizing principal");
+       krb5_free_principal(kprinc);
+       return;
+    }
+    retval = ovsec_kadm_get_principal(ovsec_hndl, kprinc, &oldprinc);
+    krb5_free_principal(kprinc);
+    if (retval) {
+       com_err("modify_principal", retval, "while getting \"%s\".",
+               canon);
+       free(canon);
+       return;
+    }
+    princ.attributes = oldprinc->attributes;
+    ovsec_kadm_free_principal_ent(ovsec_hndl, oldprinc);
+    retval = kadmin_parse_princ_args(argc, argv,
+                                    &princ, &mask,
+                                    &pass, &randkey,
+                                    "modify_principal");
+    if (retval) {
+       fprintf(stderr, "modify_principal: bad arguments\n");
        krb5_free_principal(princ.principal);
+       free(canon);
        return;
     }
-    retval = ovsec_kadm_modify_principal(&princ, mask);
+    if (randkey) {
+       fprintf(stderr, "modify_principal: -randkey not allowed\n");
+       krb5_free_principal(princ.principal);
+       free(canon);
+       return;
+    }
+    retval = ovsec_kadm_modify_principal(ovsec_hndl, &princ, mask);
+    krb5_free_principal(princ.principal);
     if (retval) {
-       com_err("modify_principal", retval, "while modifying \"%s\".",
-               argv[argc - 1]);
+       com_err("modify_principal", retval,
+               "while modifying \"%s\".", canon);
+       free(canon);
        return;
     }
+    printf("Principal \"%s\" modified.\n", canon);
+    free(canon);
 }
 
 void kadmin_getprinc(argc, argv)
@@ -690,7 +805,7 @@ void kadmin_getprinc(argc, argv)
        krb5_free_principal(princ);
        return;
     }
-    retval = ovsec_kadm_get_principal(princ, &dprinc);
+    retval = ovsec_kadm_get_principal(ovsec_hndl, princ, &dprinc);
     krb5_free_principal(princ);
     if (retval) {
        com_err("get_principal", retval, "while retrieving \"%s\".", canon);
@@ -700,19 +815,22 @@ void kadmin_getprinc(argc, argv)
     retval = krb5_unparse_name(dprinc->mod_name, &modcanon);
     if (retval) {
        com_err("get_principal", retval, "while unparsing modname");
-       ovsec_kadm_free_principal_ent(dprinc);
+       ovsec_kadm_free_principal_ent(ovsec_hndl, dprinc);
        free(canon);
        return;
     }
     if (argc == 2) {
        printf("Principal: %s\n", canon);
-       printf("Expiration date: %d\n", dprinc->princ_expire_time);
-       printf("Last password change: %d\n", dprinc->last_pwd_change);
-       printf("Password expiration date: %d\n", dprinc->pw_expiration);
-       printf("Maximum life: %d\n", dprinc->max_life);
-       printf("Last modified: by %s\n\ton %d\n",
-              modcanon, dprinc->mod_date);
-       printf("Attributes: ");
+       printf("Expiration date: %s\n", strdate(dprinc->princ_expire_time));
+       printf("Last password change: %s\n",
+              strdate(dprinc->last_pwd_change));
+       printf("Password expiration date: %s\n",
+              dprinc->pw_expiration ?
+              strdate(dprinc->pw_expiration) : "[none]");
+       printf("Maximum life: %s\n", strdur(dprinc->max_life));
+       printf("Last modified: by %s\n\ton %s\n",
+              modcanon, strdate(dprinc->mod_date));
+       printf("Attributes:");
        for (i = 0; i < sizeof (prflags) / sizeof (char *); i++) {
            if (dprinc->attributes & (krb5_flags) 1 << i)
                printf(" %s", prflags[i]);
@@ -720,7 +838,7 @@ void kadmin_getprinc(argc, argv)
        printf("\n");
        printf("Key version: %d\n", dprinc->kvno);
        printf("Master key version: %d\n", dprinc->mkvno);
-       printf("Policy: %s\n", dprinc->policy);
+       printf("Policy: %s\n", dprinc->policy ? dprinc->policy : "[none]");
     } else {
        printf("\"%s\"\t%d\t%d\t%d\t%d\t\"%s\"\t%d\t%d\t%d\t%d\t\"%s\"\n",
               canon, dprinc->princ_expire_time, dprinc->last_pwd_change,
@@ -729,7 +847,7 @@ void kadmin_getprinc(argc, argv)
               dprinc->mkvno, dprinc->policy);
     }
     free(modcanon);
-    ovsec_kadm_free_principal_ent(dprinc);
+    ovsec_kadm_free_principal_ent(ovsec_hndl, dprinc);
     free(canon);
 }
 
@@ -742,6 +860,7 @@ int kadmin_parse_policy_args(argc, argv, policy, mask, caller)
 {
     int i;
     struct timeb now;
+    time_t date;
     krb5_error_code retval;
 
     ftime(&now);
@@ -752,7 +871,9 @@ int kadmin_parse_policy_args(argc, argv, policy, mask, caller)
            if (++i > argc -2)
                return -1;
            else {
-               policy->pw_max_life = get_date(argv[i], now) - now.time;
+               date = get_date(argv[i], now);
+               policy->pw_max_life =
+                   (date == (time_t)-1 ? 0 : date) - now.time;
                *mask |= OVSEC_KADM_PW_MAX_LIFE;
                continue;
            }
@@ -761,7 +882,9 @@ int kadmin_parse_policy_args(argc, argv, policy, mask, caller)
            if (++i > argc - 2)
                return -1;
            else {
-               policy->pw_min_life = get_date(argv[i], now) - now.time;
+               date = get_date(argv[i], now);
+               policy->pw_min_life =
+                   (date == (time_t)-1 ? 0 : date) - now.time;
                *mask |= OVSEC_KADM_PW_MIN_LIFE;
                continue;
            }
@@ -816,7 +939,7 @@ void kadmin_addpol(argc, argv)
     } else {
        policy.policy = argv[argc - 1];
        mask |= OVSEC_KADM_POLICY;
-       retval = ovsec_kadm_create_policy(&policy, mask);
+       retval = ovsec_kadm_create_policy(ovsec_hndl, &policy, mask);
        if (retval) {
            com_err("add_policy", retval, "while creating policy \"%s\".",
                    policy.policy);
@@ -840,7 +963,7 @@ void kadmin_modpol(argc, argv)
        return;
     } else {
        policy.policy = argv[argc - 1];
-       retval = ovsec_kadm_modify_policy(&policy, mask);
+       retval = ovsec_kadm_modify_policy(ovsec_hndl, &policy, mask);
        if (retval) {
            com_err("modify_policy", retval, "while modifying policy \"%s\".",
                    policy.policy);
@@ -874,7 +997,7 @@ void kadmin_delpol(argc, argv)
            return;
        }
     }
-    retval = ovsec_kadm_delete_policy(argv[argc - 1]);
+    retval = ovsec_kadm_delete_policy(ovsec_hndl, argv[argc - 1]);
     if (retval) {
        com_err("delete_policy:", retval, "while deleting policy \"%s\"",
                argv[argc - 1]);
@@ -899,7 +1022,7 @@ void kadmin_getpol(argc, argv)
        fprintf(stderr, "get_policy: bad arguments\n");
        return;
     }
-    retval = ovsec_kadm_get_policy(argv[argc - 1], &policy);
+    retval = ovsec_kadm_get_policy(ovsec_hndl, argv[argc - 1], &policy);
     if (retval) {
        com_err("get_policy", retval, "while retrieving policy \"%s\".",
                argv[argc - 1]);
@@ -920,7 +1043,7 @@ void kadmin_getpol(argc, argv)
               policy->pw_min_length, policy->pw_min_classes,
               policy->pw_history_num, policy->policy_refcnt);
     }
-    ovsec_kadm_free_policy_ent(policy);
+    ovsec_kadm_free_policy_ent(ovsec_hndl, policy);
     return;
 }
 
@@ -937,7 +1060,7 @@ kadmin_getprivs(argc, argv)
        fprintf(stderr, "get_privs: bad arguments\n");
        return;
     }
-    retval = ovsec_kadm_get_privs(&plist);
+    retval = ovsec_kadm_get_privs(ovsec_hndl, &plist);
     if (retval) {
        com_err("get_privs", retval, "while retrieving privileges");
        return;
index d28d3e477c8d5aae4f253db9990ad591af9fef2d..f5a67ed5300b93be82a2831151abe83e4525cccc 100644 (file)
@@ -62,3 +62,6 @@ request       ss_list_requests, "List available requests.",
 
 request        ss_quit, "Exit program.",
        quit, exit, q;
+
+end;
+
index f7bbda5163be2a83e7f1ce3b121d13cd36be3b5b..3fa3aa9f8c68d1b0da40f00d35c6969ab5008047 100644 (file)
@@ -28,6 +28,7 @@
 
 extern ss_request_table kadmin_cmds;
 extern int exit_status;
+extern char *kadmin_startup();
 
 int main(argc, argv)
     int argc;
diff --git a/src/kadmin.new/client/strftime.c b/src/kadmin.new/client/strftime.c
new file mode 100644 (file)
index 0000000..484852a
--- /dev/null
@@ -0,0 +1,469 @@
+/* strftime - custom formatting of date and/or time
+   Copyright (C) 1989, 1991, 1992 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* Note: this version of strftime lacks locale support,
+   but it is standalone.
+
+   Performs `%' substitutions similar to those in printf.  Except
+   where noted, substituted fields have a fixed size; numeric fields are
+   padded if necessary.  Padding is with zeros by default; for fields
+   that display a single number, padding can be changed or inhibited by
+   following the `%' with one of the modifiers described below.  Unknown
+   field specifiers are copied as normal characters.  All other
+   characters are copied to the output without change.
+
+   Supports a superset of the ANSI C field specifiers.
+
+   Literal character fields:
+   %   %
+   n   newline
+   t   tab
+
+   Numeric modifiers (a nonstandard extension):
+   -   do not pad the field
+   _   pad the field with spaces
+
+   Time fields:
+   %H  hour (00..23)
+   %I  hour (01..12)
+   %k  hour ( 0..23)
+   %l  hour ( 1..12)
+   %M  minute (00..59)
+   %p  locale's AM or PM
+   %r  time, 12-hour (hh:mm:ss [AP]M)
+   %R  time, 24-hour (hh:mm)
+   %s  time in seconds since 00:00:00, Jan 1, 1970 (a nonstandard extension)
+   %S  second (00..61)
+   %T  time, 24-hour (hh:mm:ss)
+   %X  locale's time representation (%H:%M:%S)
+   %Z  time zone (EDT), or nothing if no time zone is determinable
+
+   Date fields:
+   %a  locale's abbreviated weekday name (Sun..Sat)
+   %A  locale's full weekday name, variable length (Sunday..Saturday)
+   %b  locale's abbreviated month name (Jan..Dec)
+   %B  locale's full month name, variable length (January..December)
+   %c  locale's date and time (Sat Nov 04 12:02:33 EST 1989)
+   %C  century (00..99)
+   %d  day of month (01..31)
+   %e  day of month ( 1..31)
+   %D  date (mm/dd/yy)
+   %h  same as %b
+   %j  day of year (001..366)
+   %m  month (01..12)
+   %U  week number of year with Sunday as first day of week (00..53)
+   %w  day of week (0..6)
+   %W  week number of year with Monday as first day of week (00..53)
+   %x  locale's date representation (mm/dd/yy)
+   %y  last two digits of year (00..99)
+   %Y  year (1970...)
+
+   David MacKenzie <djm@gnu.ai.mit.edu> */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <sys/types.h>
+#if defined(TM_IN_SYS_TIME) || (!defined(HAVE_TM_ZONE) && !defined(HAVE_TZNAME))
+#include <sys/time.h>
+#else
+#include <time.h>
+#endif
+
+#ifndef STDC_HEADERS
+time_t mktime ();
+#endif
+
+#if defined(HAVE_TZNAME)
+extern char *tzname[2];
+#endif
+
+/* Types of padding for numbers in date and time. */
+enum padding
+{
+  none, blank, zero
+};
+
+static char const* const days[] =
+{
+  "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"
+};
+
+static char const * const months[] =
+{
+  "January", "February", "March", "April", "May", "June",
+  "July", "August", "September", "October", "November", "December"
+};
+
+/* Add character C to STRING and increment LENGTH,
+   unless LENGTH would exceed MAX. */
+
+#define add_char(c)                                                    \
+  do                                                                   \
+    {                                                                  \
+      if (length + 1 <= max)                                           \
+       string[length++] = (c);                                         \
+    }                                                                  \
+  while (0)
+
+/* Add a 2 digit number to STRING, padding if specified.
+   Return the number of characters added, up to MAX. */
+
+static int
+add_num2 (string, num, max, pad)
+     char *string;
+     int num;
+     int max;
+     enum padding pad;
+{
+  int top = num / 10;
+  int length = 0;
+
+  if (top == 0 && pad == blank)
+    add_char (' ');
+  else if (top != 0 || pad == zero)
+    add_char (top + '0');
+  add_char (num % 10 + '0');
+  return length;
+}
+
+/* Add a 3 digit number to STRING, padding if specified.
+   Return the number of characters added, up to MAX. */
+
+static int
+add_num3 (string, num, max, pad)
+     char *string;
+     int num;
+     int max;
+     enum padding pad;
+{
+  int top = num / 100;
+  int mid = (num - top * 100) / 10;
+  int length = 0;
+
+  if (top == 0 && pad == blank)
+    add_char (' ');
+  else if (top != 0 || pad == zero)
+    add_char (top + '0');
+  if (mid == 0 && top == 0 && pad == blank)
+    add_char (' ');
+  else if (mid != 0 || top != 0 || pad == zero)
+    add_char (mid + '0');
+  add_char (num % 10 + '0');
+  return length;
+}
+
+/* Like strncpy except return the number of characters copied. */
+
+static int
+add_str (to, from, max)
+     char *to;
+     const char *from;
+     int max;
+{
+  int i;
+
+  for (i = 0; from[i] && i <= max; ++i)
+    to[i] = from[i];
+  return i;
+}
+
+static int
+add_num_time_t (string, max, num)
+     char *string;
+     int max;
+     time_t num;
+{
+  /* This buffer is large enough to hold the character representation
+     (including the trailing NUL) of any unsigned decimal quantity
+     whose binary representation fits in 128 bits.  */
+  char buf[40];
+  int length;
+
+  if (sizeof (num) > 16)
+    abort ();
+  sprintf (buf, "%lu", (unsigned long) num);
+  length = add_str (string, buf, max);
+  return length;
+}
+
+/* Return the week in the year of the time in TM, with the weeks
+   starting on Sundays. */
+
+static int
+sun_week (tm)
+     struct tm *tm;
+{
+  int dl;
+
+  /* Set `dl' to the day in the year of the last day of the week previous
+     to the one containing the day specified in TM.  If the day specified
+     in TM is in the first week of the year, `dl' will be negative or 0.
+     Otherwise, calculate the number of complete weeks before our week
+     (dl / 7) and add any partial week at the start of the year (dl % 7). */
+  dl = tm->tm_yday - tm->tm_wday;
+  return dl <= 0 ? 0 : dl / 7 + (dl % 7 != 0);
+}
+
+/* Return the week in the year of the time in TM, with the weeks
+   starting on Mondays. */
+
+static int
+mon_week (tm)
+     struct tm *tm;
+{
+  int dl, wday;
+
+  if (tm->tm_wday == 0)
+    wday = 6;
+  else
+    wday = tm->tm_wday - 1;
+  dl = tm->tm_yday - wday;
+  return dl <= 0 ? 0 : dl / 7 + (dl % 7 != 0);
+}
+
+#if !defined(HAVE_TM_ZONE) && !defined(HAVE_TZNAME)
+char *
+zone_name (tp)
+     struct tm *tp;
+{
+  char *timezone ();
+  struct timeval tv;
+  struct timezone tz;
+
+  gettimeofday (&tv, &tz);
+  return timezone (tz.tz_minuteswest, tp->tm_isdst);
+}
+#endif
+
+/* Format the time given in TM according to FORMAT, and put the
+   results in STRING.
+   Return the number of characters (not including terminating null)
+   that were put into STRING, or 0 if the length would have
+   exceeded MAX. */
+
+size_t
+strftime (string, max, format, tm)
+     char *string;
+     size_t max;
+     const char *format;
+     const struct tm *tm;
+{
+  enum padding pad;            /* Type of padding to apply. */
+  size_t length = 0;           /* Characters put in STRING so far. */
+
+  for (; *format && length < max; ++format)
+    {
+      if (*format != '%')
+       add_char (*format);
+      else
+       {
+         ++format;
+         /* Modifiers: */
+         if (*format == '-')
+           {
+             pad = none;
+             ++format;
+           }
+         else if (*format == '_')
+           {
+             pad = blank;
+             ++format;
+           }
+         else
+           pad = zero;
+
+         switch (*format)
+           {
+             /* Literal character fields: */
+           case 0:
+           case '%':
+             add_char ('%');
+             break;
+           case 'n':
+             add_char ('\n');
+             break;
+           case 't':
+             add_char ('\t');
+             break;
+           default:
+             add_char (*format);
+             break;
+
+             /* Time fields: */
+           case 'H':
+           case 'k':
+             length +=
+               add_num2 (&string[length], tm->tm_hour, max - length,
+                         *format == 'H' ? pad : blank);
+             break;
+           case 'I':
+           case 'l':
+             {
+               int hour12;
+
+               if (tm->tm_hour == 0)
+                 hour12 = 12;
+               else if (tm->tm_hour > 12)
+                 hour12 = tm->tm_hour - 12;
+               else
+                 hour12 = tm->tm_hour;
+               length +=
+                 add_num2 (&string[length], hour12, max - length,
+                           *format == 'I' ? pad : blank);
+             }
+             break;
+           case 'M':
+             length +=
+               add_num2 (&string[length], tm->tm_min, max - length, pad);
+             break;
+           case 'p':
+             if (tm->tm_hour < 12)
+               add_char ('A');
+             else
+               add_char ('P');
+             add_char ('M');
+             break;
+           case 'r':
+             length +=
+               strftime (&string[length], max - length, "%I:%M:%S %p", tm);
+             break;
+           case 'R':
+             length +=
+               strftime (&string[length], max - length, "%H:%M", tm);
+             break;
+
+           case 's':
+             {
+               struct tm writable_tm;
+               writable_tm = *tm;
+               length += add_num_time_t (&string[length], max - length,
+                                         mktime (&writable_tm));
+             }
+             break;
+
+           case 'S':
+             length +=
+               add_num2 (&string[length], tm->tm_sec, max - length, pad);
+             break;
+           case 'T':
+             length +=
+               strftime (&string[length], max - length, "%H:%M:%S", tm);
+             break;
+           case 'X':
+             length +=
+               strftime (&string[length], max - length, "%H:%M:%S", tm);
+             break;
+           case 'Z':
+#ifdef HAVE_TM_ZONE
+             length += add_str (&string[length], tm->tm_zone, max - length);
+#else
+#ifdef HAVE_TZNAME
+             if (tm->tm_isdst && tzname[1] && *tzname[1])
+               length += add_str (&string[length], tzname[1], max - length);
+             else
+               length += add_str (&string[length], tzname[0], max - length);
+#else
+             length += add_str (&string[length], zone_name (tm), max - length);
+#endif
+#endif
+             break;
+
+             /* Date fields: */
+           case 'a':
+             add_char (days[tm->tm_wday][0]);
+             add_char (days[tm->tm_wday][1]);
+             add_char (days[tm->tm_wday][2]);
+             break;
+           case 'A':
+             length +=
+               add_str (&string[length], days[tm->tm_wday], max - length);
+             break;
+           case 'b':
+           case 'h':
+             add_char (months[tm->tm_mon][0]);
+             add_char (months[tm->tm_mon][1]);
+             add_char (months[tm->tm_mon][2]);
+             break;
+           case 'B':
+             length +=
+               add_str (&string[length], months[tm->tm_mon], max - length);
+             break;
+           case 'c':
+             length +=
+               strftime (&string[length], max - length,
+                         "%a %b %d %H:%M:%S %Z %Y", tm);
+             break;
+           case 'C':
+             length +=
+               add_num2 (&string[length], (tm->tm_year + 1900) / 100,
+                         max - length, pad);
+             break;
+           case 'd':
+             length +=
+               add_num2 (&string[length], tm->tm_mday, max - length, pad);
+             break;
+           case 'e':
+             length +=
+               add_num2 (&string[length], tm->tm_mday, max - length, blank);
+             break;
+           case 'D':
+             length +=
+               strftime (&string[length], max - length, "%m/%d/%y", tm);
+             break;
+           case 'j':
+             length +=
+               add_num3 (&string[length], tm->tm_yday + 1, max - length, pad);
+             break;
+           case 'm':
+             length +=
+               add_num2 (&string[length], tm->tm_mon + 1, max - length, pad);
+             break;
+           case 'U':
+             length +=
+               add_num2 (&string[length], sun_week (tm), max - length, pad);
+             break;
+           case 'w':
+             add_char (tm->tm_wday + '0');
+             break;
+           case 'W':
+             length +=
+               add_num2 (&string[length], mon_week (tm), max - length, pad);
+             break;
+           case 'x':
+             length +=
+               strftime (&string[length], max - length, "%m/%d/%y", tm);
+             break;
+           case 'y':
+             length +=
+               add_num2 (&string[length], tm->tm_year % 100,
+                         max - length, pad);
+             break;
+           case 'Y':
+             add_char ((tm->tm_year + 1900) / 1000 + '0');
+             length +=
+               add_num3 (&string[length],
+                         (1900 + tm->tm_year) % 1000, max - length, zero);
+             break;
+           }
+       }
+    }
+  add_char (0);
+  return length - 1;
+}