Incremental commit.
[utils.git] / krb5-agent.c
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <unistd.h>
4 #include <krb5.h>
5 #include <time.h>
6 #include <string.h>
7 #include <signal.h>
8 #include <sys/wait.h>
9
10 #define STD_INTERVAL (3600 * 8)
11
12 volatile int died = 0;
13 pid_t child;
14 int execmode = 0, failsafe = 0;
15 int verbose = 0, quiet = 0;
16 krb5_context context = NULL;
17 krb5_ccache ccache = NULL;
18
19 void cleanup_krb5(void)
20 {
21     if(ccache != NULL)
22         krb5_cc_close(context, ccache);
23     if(context != NULL)
24         krb5_free_context(context);
25 }
26
27 void sighandler(int sig)
28 {
29     switch(sig) {
30     case SIGCHLD:
31         died = 1;
32         break;
33     }
34 }
35
36 void renew(void)
37 {
38     int ret;
39     
40     if(ccache == NULL)
41         return;
42 }
43
44 int main(int argc, char **argv)
45 {
46     char *p;
47     int c;
48     time_t interval, last, now;
49     pid_t wpid;
50     int ret, status;
51     
52     interval = STD_INTERVAL;
53     while((c = getopt(argc, argv, "+hi:vqf")) != -1) {
54         switch(c) {
55         case 'v':
56             verbose++;
57             break;
58         case 'q':
59             quiet = 1;
60             break;
61         case 'f':
62             failsafe = 1;
63             break;
64         case 'i':
65             p = optarg + strlen(optarg) - 1;
66             if((*p >= 'a') || (*p <= 'z')) {
67                 if(*p == 'm')
68                     interval = 60;
69                 else if(*p == 'h')
70                     interval = 3600;
71                 else if(*p == 'd')
72                     interval = 86400;
73                 else
74                     interval = 1;
75                 *p = 0;
76             } else {
77                 interval = 1;
78             }
79             interval *= atoi(optarg);
80             break;
81         case 'h':
82         case '?':
83         case ':':
84         default:
85             fprintf(stderr, "usage: krb5-agent [-hvqf] [-i interval] [program args...]\n");
86             exit((c == 'h')?0:1);
87         }
88     }
89     
90     atexit(cleanup_krb5);
91     if((ret = krb5_init_context(&context)) != 0) {
92         if(!quiet)
93             fprintf(stderr, "could not initialize Kerberos context: %s\n", error_message(ret));
94         if(!failsafe)
95             exit(1);
96     }
97     if(context != NULL) {
98         if((ret = krb5_cc_default(context, &ccache)) != 0) {
99             if(!quiet)
100                 fprintf(stderr, "could not initialize Kerberos context: %s\n", error_message(ret));
101             if(!failsafe)
102                 exit(1);
103         }
104     }
105     
106     if(optind < argc) {
107         execmode = 1;
108         signal(SIGCHLD, sighandler);
109         if((child = fork()) < 0) {
110             perror("fork");
111             exit(1);
112         }
113         if(child == 0) {
114             char buf[80];
115             snprintf(buf, 80, "KRB5_AGENT_PID=%i", getpid());
116             putenv(buf);
117             execvp(argv[optind], argv + optind);
118             perror(argv[optind]);
119             exit(255);
120         }
121     }
122     now = last = time(NULL);
123     while(1) {
124         if(died) {
125             wpid = waitpid(-1, &status, WNOHANG);
126             if(wpid < 0) {
127                 perror("waitpid");
128             } else if(execmode && (wpid == child)) {
129                 /* Try to preserve exit status as best as we can... */
130                 if(WIFEXITED(status)) {
131                     exit(WEXITSTATUS(status));
132                 } else {
133                     signal(WTERMSIG(status), SIG_DFL);
134                     kill(getpid(), WTERMSIG(status));
135                     exit(255);
136                 }
137             }
138             died = 0;
139         }
140         sleep((last + interval) - now);
141         now = time(NULL);
142         if(now >= last + interval)
143             renew();
144     }
145 }
146
147 /*
148  * Local Variables:
149  * compile-command: "gcc -Wall -g -o krb5-agent krb5-agent.c -lkrb5"
150  * End:
151  */