#include <stdio.h>
#include <unistd.h>
#include <krb5.h>
+#include <time.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/wait.h>
+
+#define STD_INTERVAL (3600 * 8)
+
+volatile int died = 0;
+pid_t child;
+int execmode = 0, failsafe = 0;
+int verbose = 0, quiet = 0;
+krb5_context context = NULL;
+krb5_ccache ccache = NULL;
+
+void cleanup_krb5(void)
+{
+ if(ccache != NULL)
+ krb5_cc_close(context, ccache);
+ if(context != NULL)
+ krb5_free_context(context);
+}
+
+void sighandler(int sig)
+{
+ switch(sig) {
+ case SIGCHLD:
+ died = 1;
+ break;
+ }
+}
+
+void renew(void)
+{
+ int ret;
+
+ if(ccache == NULL)
+ return;
+}
int main(int argc, char **argv)
{
- return(0);
+ char *p;
+ int c;
+ time_t interval, last, now;
+ pid_t wpid;
+ int ret, status;
+
+ interval = STD_INTERVAL;
+ while((c = getopt(argc, argv, "+hi:vqf")) != -1) {
+ switch(c) {
+ case 'v':
+ verbose++;
+ break;
+ case 'q':
+ quiet = 1;
+ break;
+ case 'f':
+ failsafe = 1;
+ break;
+ case 'i':
+ p = optarg + strlen(optarg) - 1;
+ if((*p >= 'a') || (*p <= 'z')) {
+ if(*p == 'm')
+ interval = 60;
+ else if(*p == 'h')
+ interval = 3600;
+ else if(*p == 'd')
+ interval = 86400;
+ else
+ interval = 1;
+ *p = 0;
+ } else {
+ interval = 1;
+ }
+ interval *= atoi(optarg);
+ break;
+ case 'h':
+ case '?':
+ case ':':
+ default:
+ fprintf(stderr, "usage: krb5-agent [-hvqf] [-i interval] [program args...]\n");
+ exit((c == 'h')?0:1);
+ }
+ }
+
+ atexit(cleanup_krb5);
+ if((ret = krb5_init_context(&context)) != 0) {
+ if(!quiet)
+ fprintf(stderr, "could not initialize Kerberos context: %s\n", error_message(ret));
+ if(!failsafe)
+ exit(1);
+ }
+ if(context != NULL) {
+ if((ret = krb5_cc_default(context, &ccache)) != 0) {
+ if(!quiet)
+ fprintf(stderr, "could not initialize Kerberos context: %s\n", error_message(ret));
+ if(!failsafe)
+ exit(1);
+ }
+ }
+
+ if(optind < argc) {
+ execmode = 1;
+ signal(SIGCHLD, sighandler);
+ if((child = fork()) < 0) {
+ perror("fork");
+ exit(1);
+ }
+ if(child == 0) {
+ char buf[80];
+ snprintf(buf, 80, "KRB5_AGENT_PID=%i", getpid());
+ putenv(buf);
+ execvp(argv[optind], argv + optind);
+ perror(argv[optind]);
+ exit(255);
+ }
+ }
+ now = last = time(NULL);
+ while(1) {
+ if(died) {
+ wpid = waitpid(-1, &status, WNOHANG);
+ if(wpid < 0) {
+ perror("waitpid");
+ } else if(execmode && (wpid == child)) {
+ /* Try to preserve exit status as best as we can... */
+ if(WIFEXITED(status)) {
+ exit(WEXITSTATUS(status));
+ } else {
+ signal(WTERMSIG(status), SIG_DFL);
+ kill(getpid(), WTERMSIG(status));
+ exit(255);
+ }
+ }
+ died = 0;
+ }
+ sleep((last + interval) - now);
+ now = time(NULL);
+ if(now >= last + interval)
+ renew();
+ }
}
+
+/*
+ * Local Variables:
+ * compile-command: "gcc -Wall -g -o krb5-agent krb5-agent.c -lkrb5"
+ * End:
+ */