#include "xklife.h"
#include "xklife.icon"

#if defined(ultrix) || defined(SOLARIS)
extern double rint();
#endif
static void     PollingTktStatus();
char *getenv();

Widget toplevel, base;
Widget tacho, label, title;

char *whoami;
char *tkt_file = (char *)NULL;  
int  update_time, update, quiet;
long issue_time, expire_time;
char kname[MAX_K_NAME_SZ];
char my_realm[REALM_SZ];


static XrmOptionDescRec options[] = {
{"-rv",		"*reverseVideo",	XrmoptionNoArg,		"TRUE"},
{"-file",	"*tktFile", 		XrmoptionSepArg,	NULL},
{"-update",	"*updateTime", 		XrmoptionSepArg,	NULL},
};

/*
 * Definition of the Application resources structure.
 */

typedef struct _XKlifeResources {
  char *file;
  int updatetime;  
} XKlifeResources;

/*
 * The structure containing the resource information for the
 * XKlife application resources.
 */

#define Offset(field) (XtOffset(XKlifeResources *, field))

static XtResource my_resources[] = {
  {"tktFile", "TktFile", XtRString, sizeof(char *),
     Offset(file), XtRImmediate, (caddr_t) NULL},
  {"updateTime", "UpdateTime", XtRInt, sizeof(int),
     Offset(updatetime), XtRImmediate, (caddr_t) DEFAULT_UPDATE_TIME},
};

#undef Offset

main(argc, argv)
int             argc;
char          **argv;
{
    Arg             args[10];
    Cardinal        i;
    char *cp;
    int ret;
    XKlifeResources resources;

#ifdef XAPPLRESDIR
    setenv("XAPPLRESDIR", XAPPLRESDIR, 1);
#endif

    whoami = (cp = strrchr(*argv, '/')) ? cp + 1 : *argv;
    quiet = 1;


    toplevel = XtInitialize("kerberometer", "Kerberometer", options, XtNumber(options),
			    &argc, argv);

    XtGetApplicationResources( toplevel, (caddr_t) &resources, 
			      my_resources, XtNumber(my_resources),
			      NULL, (Cardinal) 0);

    XtGetApplicationResources( toplevel, (caddr_t) &resources, 
			      my_resources, XtNumber(my_resources),
			      NULL, (Cardinal) 0);

    /* Read in other arguments */
    while (*(++argv)) {
	if (!strcmp(*argv, "-v")) {
	    quiet = 0;
	}
	else Usage();
    }

    tkt_file = resources.file;
    update_time = resources.updatetime * 1000;

    /* Get my kerberos realm */
    krb_get_lrealm(my_realm, 1);
    
    /* Read tkt_file */
    ret = read_tkt_file(tkt_file, kname, 0);
    if (ret < 0)
	exit(-1);

   /**** Shell Widget ****/
    i = 0;
    XtSetArg(args[0], XtNiconPixmap,
	     XCreateBitmapFromData(XtDisplay(toplevel),
				   XtScreen(toplevel)->root, xklife_bits,
				   xklife_width, xklife_height)); i++;
    XtSetValues(toplevel, args, i);
    
    /**** Form widget ****/
    base = XtCreateManagedWidget("pane", panedWidgetClass, toplevel, NULL, 0);

    /**** Label widget (Title) ****/
    i = 0;
    XtSetArg(args[i], XtNlabel, "Kerberos Ticket Life"); i++;
    label = XtCreateManagedWidget("title", labelWidgetClass,
				  base, args, i);

    /**** Label widget ****/
    i = 0;
    XtSetArg(args[i], XtNlabel, kname); i++;
    label = XtCreateManagedWidget("name", labelWidgetClass,
				  base, args, i);
    
    /**** Tachometer widget ****/
    tacho = XtCreateManagedWidget("meter",
				  tachometerWidgetClass,
				  base, NULL, 0);
    
    /* Interval timer start */
    /* Initially start with a poll time of zero so the 
     * guage is updated immediately after the window is
     * displayed. */
    XtAddTimeOut(0, PollingTktStatus, NULL);
    
    XtRealizeWidget(toplevel);
    XtMainLoop();
}



Usage()
{
    fprintf(stderr, 
	    "kerberometer <Toolkit Options> [-rv] [-file filename] [-v] [-update second]\n");
    exit(-1);
}


read_tkt_file(file, name, no_mess)
char *file;
char *name;
int no_mess;
{
    CREDENTIALS c;
    char    pname[ANAME_SZ];
    char    pinst[INST_SZ];
    char    prealm[REALM_SZ];
    int     k_errno;

    /* Initialize name in case of error */
    name[0] = '\0';

    /* Set the  appropriate ticket file name */
    if ((file == NULL) && ((file = getenv("KRBTKFILE")) == NULL))
        file = TKT_FILE;

    /* Open & close the ticket file so see if it exists */
    if (k_errno = tf_init(file, R_TKT_FIL)) {
	if (!no_mess) fprintf(stderr, "%s: %s\n", whoami, krb_err_txt[k_errno]);
        return(-1);
    }
    (void) tf_close();

    /* Find out realm */
    if ((k_errno = krb_get_tf_realm(file, prealm)) != KSUCCESS) {
	if (!no_mess) 
	    fprintf(stderr, "%s: can't find realm of ticket file: %s\n",
		    whoami, krb_err_txt[k_errno]);
        return(-1);
    }
    
    /* Open ticket file */
    if (k_errno = tf_init(file, R_TKT_FIL)) {
	if (!no_mess) fprintf(stderr, "%s: %s\n", whoami, krb_err_txt[k_errno]);
	return(-1);
    }
    /* Get principal name and instance */
    if ((k_errno = tf_get_pname(pname)) ||
        (k_errno = tf_get_pinst(pinst))) {
	if (!no_mess) fprintf(stderr, "%s: %s\n", whoami, krb_err_txt[k_errno]);
	(void) tf_close();
	return(-1);
    }

    make_kname(pname, pinst, prealm, name);
    if (prealm[0] == '\0') strncpy(prealm, my_realm, REALM_SZ);

    /* Look through credentials looking for the ticket-granting ticket */
    while ((k_errno = tf_get_cred(&c)) == KSUCCESS) {
	if (!strcmp(c.service, TICKET_GRANTING_TICKET) &&
	    (!strcmp(c.instance, prealm))) {
	    issue_time = c.issue_date;
	    expire_time = c.issue_date + ((unsigned char) c.lifetime) * 5 * 60;
	    break;
	}
    }
    (void) tf_close();
    if (k_errno == KSUCCESS)
	return(0);
    else
	return(-1);
}

#ifdef i386
#define rint (int)
#endif	


/*ARGSUSED*/
static void PollingTktStatus(client_data, id)
caddr_t         client_data;
XtIntervalId    id;
{
    int ret, new;
    long current_time;
    char name[MAX_K_NAME_SZ];
    Arg args[5];
    Cardinal i;

    ret = read_tkt_file(tkt_file, name, quiet);
    current_time = time(0);

    if (!ret) {
	if (strncmp(name, kname, MAX_K_NAME_SZ)) {
	    strncpy(kname, name, MAX_K_NAME_SZ);
	    i = 0;
	    XtSetArg(args[i], XtNlabel, kname); i++;
	    XtSetValues(label, args, i);
	}
	
	if (current_time > expire_time)
	    new = 0;
	else if (current_time < issue_time)
	    new = 100;
	else new = rint((((double)expire_time - (double)current_time) * 100.0) / 
			((double)expire_time - (double)issue_time));
    } else {
	i = 0;
	strcpy(kname, "- None - ");
	XtSetArg(args[i], XtNlabel, kname); i++;
	XtSetValues(label, args, i);	
	new = 0;
    }
    
    TachometerSetValue(tacho, new);
     
    XtAddTimeOut(update_time, PollingTktStatus, NULL);
}


make_kname(principal, instance, realm, out_name)
char *principal, *instance, *realm, *out_name;
{
    
    if (!strncmp(realm, my_realm, REALM_SZ))
	realm[0] = '\0';

    if ((instance[0] == '\0') && (realm[0] == '\0'))
        strcpy(out_name, principal);
    else {
        if (realm[0] == '\0')
            sprintf(out_name, "%s.%s", principal, instance);
        else {
            if (instance[0] == '\0')
                sprintf(out_name, "%s@%s", principal, realm);
            else
                sprintf(out_name, "%s.%s@%s", principal,
                        instance, realm);
        }
    }
}


