source: trunk/athena/bin/aklog/aklog_main.c @ 6385

Revision 6385, 25.8 KB checked in by probe, 32 years ago (diff)
Abstracted the realm-determination, and added that to krb_util.c Renamed the global "cellconfig" to "ak_cellconfig" to help avoid conflicts.
Line 
1/*
2 * $Id: aklog_main.c,v 1.24 1992-12-11 13:47:38 probe Exp $
3 *
4 * Copyright 1990,1991 by the Massachusetts Institute of Technology
5 * For distribution and copying rights, see the file "mit-copyright.h"
6 */
7
8#if !defined(lint) && !defined(SABER)
9static char *rcsid = "$Id: aklog_main.c,v 1.24 1992-12-11 13:47:38 probe Exp $";
10#endif lint || SABER
11
12#include <stdio.h>
13#include <string.h>
14#include <ctype.h>
15#include <sys/types.h>
16#include <sys/param.h>
17#include <sys/errno.h>
18#include <netdb.h>
19#include <sys/socket.h>
20#include <krb.h>
21
22#include <afs/param.h>
23#include <afs/auth.h>
24#include <afs/cellconfig.h>
25#include <afs/vice.h>
26#include <afs/venus.h>
27#include <afs/ptserver.h>
28
29#include "aklog.h"
30#include "linked_list.h"
31
32#define AFSKEY "afs"
33#define AFSINST ""
34
35#define AKLOG_SUCCESS 0
36#define AKLOG_USAGE 1
37#define AKLOG_SOMETHINGSWRONG 2
38#define AKLOG_AFS 3
39#define AKLOG_KERBEROS 4
40#define AKLOG_TOKEN 5
41#define AKLOG_BADPATH 6
42#define AKLOG_MISC 7
43
44#ifndef NULL
45#define NULL 0
46#endif
47
48#ifndef TRUE
49#define TRUE 1
50#endif
51
52#ifndef FALSE
53#define FALSE 0
54#endif
55
56#define DIR '/'                 /* Character that divides directories */
57#define DIRSTRING "/"           /* String form of above */
58#define VOLMARKER ':'           /* Character separating cellname from mntpt */
59#define VOLMARKERSTRING ":"     /* String form of above */
60
61typedef struct {
62    char cell[BUFSIZ];
63    char realm[REALM_SZ];
64} cellinfo_t;
65
66
67struct afsconf_cell ak_cellconfig; /* General information about the cell */
68
69extern int errno;
70extern char *sys_errlist[];
71
72static aklog_params params;     /* Various aklog functions */
73static char msgbuf[BUFSIZ];     /* String for constructing error messages */
74static char *progname = NULL;   /* Name of this program */
75static int dflag = FALSE;       /* Give debugging information */
76static int noauth = FALSE;      /* If true, don't try to get tokens */
77static int zsubs = FALSE;       /* Are we keeping track of zephyr subs? */
78static int hosts = FALSE;       /* Are we keeping track of hosts? */
79static int noprdb = FALSE;      /* Skip resolving name to id? */
80static int force = FALSE;       /* Bash identical tokens? */
81static linked_list zsublist;    /* List of zephyr subscriptions */
82static linked_list hostlist;    /* List of host addresses */
83static linked_list authedcells; /* List of cells already logged to */
84
85
86#ifdef __STDC__
87static char *copy_cellinfo(cellinfo_t *cellinfo)
88#else
89static char *copy_cellinfo(cellinfo)
90  cellinfo_t *cellinfo;
91#endif /* __STDC__ */
92{
93    cellinfo_t *new_cellinfo;
94
95    if (new_cellinfo = (cellinfo_t *)malloc(sizeof(cellinfo_t)))
96        bcopy(cellinfo, new_cellinfo, sizeof(cellinfo_t));
97   
98    return ((char *)new_cellinfo);
99}
100
101
102#ifdef __STDC__
103static char *copy_string(char *string)   
104#else
105static char *copy_string(string)
106  char *string;
107#endif /* __STDC__ */
108{
109    char *new_string;
110
111    if (new_string = (char *)calloc(strlen(string) + 1, sizeof(char)))
112        (void) strcpy(new_string, string);
113
114    return (new_string);
115}
116
117
118#ifdef __STDC__
119static int get_cellconfig(char *cell, struct afsconf_cell *cellconfig, char *local_cell)
120#else
121static int get_cellconfig(cell, cellconfig, local_cell)
122    char *cell;
123    struct afsconf_cell *cellconfig;
124    char *local_cell;
125#endif /* __STDC__ */
126{
127    int status = AKLOG_SUCCESS;
128    struct afsconf_dir *configdir;
129
130    bzero(local_cell, sizeof(local_cell));
131    bzero((char *)cellconfig, sizeof(*cellconfig));
132
133    if (!(configdir = afsconf_Open(AFSCONF_CLIENTNAME))) {
134        sprintf(msgbuf,
135                "%s: can't get afs configuration (afsconf_Open(%s))\n",
136                progname, AFSCONF_CLIENTNAME);
137        params.pstderr(msgbuf);
138        params.exitprog(AKLOG_AFS);
139    }
140
141    if (afsconf_GetLocalCell(configdir, local_cell, MAXCELLCHARS)) {
142        sprintf(msgbuf, "%s: can't determine local cell.\n", progname);
143        params.pstderr(msgbuf);
144        params.exitprog(AKLOG_AFS);
145    }
146
147    if ((cell == NULL) || (cell[0] == 0))
148        cell = local_cell;
149
150    if (afsconf_GetCellInfo(configdir, cell, NULL, cellconfig)) {
151        sprintf(msgbuf, "%s: Can't get information about cell %s.\n",
152                progname, cell);
153        params.pstderr(msgbuf);
154        status = AKLOG_AFS;
155    }
156
157    (void) afsconf_Close(configdir);
158
159    return(status);
160}
161
162
163/*
164 * Log to a cell.  If the cell has already been logged to, return without
165 * doing anything.  Otherwise, log to it and mark that it has been logged
166 * to.
167 */
168#ifdef __STDC__
169static int auth_to_cell(char *cell, char *realm)
170#else
171static int auth_to_cell(cell, realm)
172  char *cell;
173  char *realm;
174#endif /* __STDC__ */
175{
176    int status = AKLOG_SUCCESS;
177    char username[BUFSIZ];      /* To hold client username structure */
178    long viceId;                /* AFS uid of user */
179
180    char name[ANAME_SZ];        /* Name of afs key */
181    char instance[INST_SZ];     /* Instance of afs key */
182    char realm_of_user[REALM_SZ]; /* Kerberos realm of user */
183    char realm_of_cell[REALM_SZ]; /* Kerberos realm of cell */
184    char local_cell[MAXCELLCHARS+1];
185    char cell_to_use[MAXCELLCHARS+1]; /* Cell to authenticate to */
186
187    int i,j;
188
189    CREDENTIALS c;
190    struct ktc_principal aserver;
191    struct ktc_principal aclient;
192    struct ktc_token atoken, btoken;
193   
194    bzero(name, sizeof(name));
195    bzero(instance, sizeof(instance));
196    bzero(realm_of_user, sizeof(realm_of_user));
197    bzero(realm_of_cell, sizeof(realm_of_cell));
198
199    /* NULL or empty cell returns information on local cell */
200    if (status = get_cellconfig(cell, &ak_cellconfig, local_cell))
201        return(status);
202
203    strncpy(cell_to_use, ak_cellconfig.name, MAXCELLCHARS);
204    cell_to_use[MAXCELLCHARS] = 0;
205
206    if (ll_string(&authedcells, ll_s_check, cell_to_use)) {
207        if (dflag) {
208            sprintf(msgbuf, "Already authenticated to %s (or tried to)\n",
209                    cell_to_use);
210            params.pstdout(msgbuf);
211        }
212        return(AKLOG_SUCCESS);
213    }
214
215    /*
216     * Record that we have attempted to log to this cell.  We do this
217     * before we try rather than after so that we will not try
218     * and fail repeatedly for one cell.
219     */
220    (void)ll_string(&authedcells, ll_s_add, cell_to_use);
221
222    /*
223     * Record this cell in the list of zephyr subscriptions.  We may
224     * want zephyr subscriptions even if authentication fails.
225     * If this is done after we attempt to get tokens, aklog -zsubs
226     * can return something different depending on whether or not we
227     * are in -noauth mode.
228     */
229    if (ll_string(&zsublist, ll_s_add, cell_to_use) == LL_FAILURE) {
230        sprintf(msgbuf,
231                "%s: failure adding cell %s to zephyr subscriptions list.\n",
232                progname, cell_to_use);
233        params.pstderr(msgbuf);
234        params.exitprog(AKLOG_MISC);
235    }
236    if (ll_string(&zsublist, ll_s_add, local_cell) == LL_FAILURE) {
237        sprintf(msgbuf,
238                "%s: failure adding cell %s to zephyr subscriptions list.\n",
239                progname, local_cell);
240        params.pstderr(msgbuf);
241        params.exitprog(AKLOG_MISC);
242    }
243
244    if (!noauth) {
245        if (dflag) {
246            sprintf(msgbuf, "Authenticating to cell %s.\n", cell_to_use);
247            params.pstdout(msgbuf);
248        }
249       
250        if (realm && realm[0])
251            strcpy(realm_of_cell, realm);
252        else
253            strcpy(realm_of_cell, afs_realm_of_cell(&ak_cellconfig));
254
255        /* We use the afs.<cellname> convention here... */
256        strcpy(name, AFSKEY);
257        strncpy(instance, cell_to_use, sizeof(instance));
258        instance[sizeof(instance)-1] = '\0';
259       
260        /*
261         * Extract the session key from the ticket file and hand-frob an
262         * afs style authenticator.
263         */
264
265        /*
266         * Try to obtain AFS tickets.  Because there are two valid service
267         * names, we will try both, but trying the more specific first.
268         *
269         *      afs.<cell>@<realm>
270         *      afs@<realm>
271         */
272        if (dflag) {
273            sprintf(msgbuf, "Getting tickets: %s.%s@%s\n", name, instance,
274                    realm_of_cell);
275            params.pstdout(msgbuf);
276        }
277        status = params.get_cred(name, instance, realm_of_cell, &c);
278        if (status == KDC_PR_UNKNOWN) {
279            if (dflag) {
280                sprintf(msgbuf, "Getting tickets: %s@%s\n", name,
281                        realm_of_cell);
282                params.pstdout(msgbuf);
283            }
284            status = params.get_cred(name, "", realm_of_cell, &c);
285        }
286
287        if (status != KSUCCESS) {
288            if (dflag) {
289                sprintf(msgbuf,
290                        "Kerberos error code returned by get_cred: %d\n",
291                        status);
292                params.pstdout(msgbuf);
293            }
294            sprintf(msgbuf, "%s: Couldn't get %s AFS tickets: %s\n",
295                    progname, cell_to_use, krb_err_txt[status]);
296            params.pstderr(msgbuf);
297            return(AKLOG_KERBEROS);
298        }
299       
300        strncpy(aserver.name, AFSKEY, MAXKTCNAMELEN - 1);
301        strncpy(aserver.instance, AFSINST, MAXKTCNAMELEN - 1);
302        strncpy(aserver.cell, cell_to_use, MAXKTCREALMLEN - 1);
303
304        strcpy (username, c.pname);
305        if (c.pinst[0]) {
306            strcat (username, ".");
307            strcat (username, c.pinst);
308        }
309
310        atoken.kvno = c.kvno;
311        atoken.startTime = c.issue_date;
312        /* ticket lifetime is in five-minutes blocks. */
313        atoken.endTime = c.issue_date + ((unsigned char)c.lifetime * 5 * 60);
314        bcopy (c.session, &atoken.sessionKey, 8);
315        atoken.ticketLen = c.ticket_st.length;
316        bcopy (c.ticket_st.dat, atoken.ticket, atoken.ticketLen);
317       
318        if (!force &&
319            !ktc_GetToken(&aserver, &btoken, sizeof(btoken), &aclient) &&
320            atoken.kvno == btoken.kvno &&
321            atoken.ticketLen == btoken.ticketLen &&
322            !bcmp(&atoken.sessionKey, &btoken.sessionKey, sizeof(atoken.sessionKey)) &&
323            !bcmp(atoken.ticket, btoken.ticket, atoken.ticketLen)) {
324
325            if (dflag) {
326                sprintf(msgbuf, "Identical tokens already exist; skipping.\n");
327                params.pstdout(msgbuf);
328            }
329            return 0;
330        }
331
332        if (noprdb) {
333            if (dflag) {
334                sprintf(msgbuf, "Not resolving name %s to id (-noprdb set)\n",
335                        username);
336                params.pstdout(msgbuf);
337            }
338        }
339        else {
340            if ((status = params.get_user_realm(realm_of_user)) != KSUCCESS) {
341                sprintf(msgbuf, "%s: Couldn't determine realm of user: %s)",
342                        progname, krb_err_txt[status]);
343                params.pstderr(msgbuf);
344                return(AKLOG_KERBEROS);
345            }
346            if (strcmp(realm_of_user, realm_of_cell)) {
347                strcat(username, "@");
348                strcat(username, realm_of_user);
349            }
350
351            if (dflag) {
352                sprintf(msgbuf, "About to resolve name %s to id\n",
353                        username);
354                params.pstdout(msgbuf);
355            }
356           
357            if (!pr_Initialize (0, AFSCONF_CLIENTNAME, aserver.cell))
358                    status = pr_SNameToId (username, &viceId);
359           
360            if (dflag) {
361                if (status)
362                    sprintf(msgbuf, "Error %d\n", status);
363                else
364                    sprintf(msgbuf, "Id %d\n", viceId);
365                params.pstdout(msgbuf);
366            }
367           
368                /*
369                 * This is a crock, but it is Transarc's crock, so
370                 * we have to play along in order to get the
371                 * functionality.  The way the afs id is stored is
372                 * as a string in the username field of the token.
373                 * Contrary to what you may think by looking at
374                 * the code for tokens, this hack (AFS ID %d) will
375                 * not work if you change %d to something else.
376                 */
377            if ((status == 0) && (viceId != ANONYMOUSID))
378                sprintf (username, "AFS ID %d", viceId);
379        }
380       
381        if (dflag) {
382            sprintf(msgbuf, "Set username to %s\n", username);
383            params.pstdout(msgbuf);
384        }
385
386        /* Reset the "aclient" structure before we call ktc_SetToken.
387         * This structure was first set by the ktc_GetToken call when
388         * we were comparing whether identical tokens already existed.
389         */
390        strncpy(aclient.name, username, MAXKTCNAMELEN - 1);
391        strcpy(aclient.instance, "");
392        strncpy(aclient.cell, c.realm, MAXKTCREALMLEN - 1);
393
394        if (dflag) {
395            sprintf(msgbuf, "Getting tokens.\n");
396            params.pstdout(msgbuf);
397        }
398        if (status = ktc_SetToken(&aserver, &atoken, &aclient)) {
399            sprintf(msgbuf,
400                    "%s: unable to obtain tokens for cell %s (status: %d).\n",
401                    progname, cell_to_use, status);
402            params.pstderr(msgbuf);
403            status = AKLOG_TOKEN;
404        }
405    }
406    else
407        if (dflag) {
408            sprintf(msgbuf, "Noauth mode; not authenticating.\n");
409            params.pstdout(msgbuf);
410        }
411       
412    return(status);
413}
414
415#ifdef __STDC__
416static int get_afs_mountpoint(char *file, char *mountpoint, int size)
417#else
418static int get_afs_mountpoint(file, mountpoint, size)
419  char *file;
420  char *mountpoint;
421  int size;
422#endif /* __STDC__ */
423{
424    char our_file[MAXPATHLEN + 1];
425    char *parent_dir;
426    char *last_component;
427    struct ViceIoctl vio;
428    char cellname[BUFSIZ];
429
430    bzero(our_file, sizeof(our_file));
431    strcpy(our_file, file);
432
433    if (last_component = strrchr(our_file, DIR)) {
434        *last_component++ = 0;
435        parent_dir = our_file;
436    }
437    else {
438        last_component = our_file;
439        parent_dir = ".";
440    }   
441   
442    bzero(cellname, sizeof(cellname));
443
444    vio.in = last_component;
445    vio.in_size = strlen(last_component)+1;
446    vio.out_size = size;
447    vio.out = mountpoint;
448
449    if (!pioctl(parent_dir, VIOC_AFS_STAT_MT_PT, &vio, 0)) {
450        if (strchr(mountpoint, VOLMARKER) == NULL) {
451            vio.in = file;
452            vio.in_size = strlen(file) + 1;
453            vio.out_size = sizeof(cellname);
454            vio.out = cellname;
455           
456            if (!pioctl(file, VIOC_FILE_CELL_NAME, &vio, 1)) {
457                strcat(cellname, VOLMARKERSTRING);
458                strcat(cellname, mountpoint + 1);
459                bzero(mountpoint + 1, size - 1);
460                strcpy(mountpoint + 1, cellname);
461            }
462        }
463        return(TRUE);
464    }
465    else
466        return(FALSE);
467}
468
469/*
470 * This routine each time it is called returns the next directory
471 * down a pathname.  It resolves all symbolic links.  The first time
472 * it is called, it should be called with the name of the path
473 * to be descended.  After that, it should be called with the arguemnt
474 * NULL.
475 */
476#ifdef __STDC__
477static char *next_path(char *origpath)
478#else
479static char *next_path(origpath)
480  char *origpath;
481#endif /* __STDC__ */
482{
483    static char path[MAXPATHLEN + 1];
484    static char pathtocheck[MAXPATHLEN + 1];
485
486    int link = FALSE;           /* Is this a symbolic link? */
487    char linkbuf[MAXPATHLEN + 1];
488    char tmpbuf[MAXPATHLEN + 1];
489
490    static char *last_comp;     /* last component of directory name */
491    static char *elast_comp;    /* End of last component */
492    char *t;
493    int len;
494   
495    static int symlinkcount = 0; /* We can't exceed MAXSYMLINKS */
496   
497    /* If we are given something for origpath, we are initializing only. */
498    if (origpath) {
499        bzero(path, sizeof(path));
500        bzero(pathtocheck, sizeof(pathtocheck));
501        strcpy(path, origpath);
502        last_comp = path;
503        symlinkcount = 0;
504        return(NULL);
505    }
506
507    /* We were not given origpath; find then next path to check */
508   
509    /* If we've gotten all the way through already, return NULL */
510    if (last_comp == NULL)
511        return(NULL);
512
513    do {
514        while (*last_comp == DIR)
515            strncat(pathtocheck, last_comp++, 1);
516        len = (elast_comp = strchr(last_comp, DIR))
517            ? elast_comp - last_comp : strlen(last_comp);
518        strncat(pathtocheck, last_comp, len);
519        bzero(linkbuf, sizeof(linkbuf));
520        if (link = (params.readlink(pathtocheck, linkbuf,
521                                    sizeof(linkbuf)) > 0)) {
522            if (++symlinkcount > MAXSYMLINKS) {
523                sprintf(msgbuf, "%s: %s\n", progname, sys_errlist[ELOOP]);
524                params.pstderr(msgbuf);
525                params.exitprog(AKLOG_BADPATH);
526            }
527            bzero(tmpbuf, sizeof(tmpbuf));
528            if (elast_comp)
529                strcpy(tmpbuf, elast_comp);
530            if (linkbuf[0] == DIR) {
531                /*
532                 * If this is a symbolic link to an absolute path,
533                 * replace what we have by the absolute path.
534                 */
535                bzero(path, strlen(path));
536                bcopy(linkbuf, path, sizeof(linkbuf));
537                strcat(path, tmpbuf);
538                last_comp = path;
539                elast_comp = NULL;
540                bzero(pathtocheck, sizeof(pathtocheck));
541            }
542            else {
543                /*
544                 * If this is a symbolic link to a relative path,
545                 * replace only the last component with the link name.
546                 */
547                strncpy(last_comp, linkbuf, strlen(linkbuf) + 1);
548                strcat(path, tmpbuf);
549                elast_comp = NULL;
550                if (t = strrchr(pathtocheck, DIR)) {
551                    t++;
552                    bzero(t, strlen(t));
553                }
554                else
555                    bzero(pathtocheck, sizeof(pathtocheck));
556            }
557        }
558        else
559            last_comp = elast_comp;
560    }
561    while(link);
562
563    return(pathtocheck);
564}
565       
566#ifdef __STDC__
567static void add_hosts(char *file)
568#else
569static void add_hosts(file)
570  char *file;
571#endif /* __STDC__ */
572{
573    struct ViceIoctl vio;
574    char outbuf[BUFSIZ];
575    long *phosts;
576    int i;
577    struct hostent *hp;
578    struct in_addr in;
579   
580    bzero(outbuf, sizeof(outbuf));
581
582    vio.out_size = sizeof(outbuf);
583    vio.in_size = 0;
584    vio.out = outbuf;
585
586    if (dflag) {
587        sprintf(msgbuf, "Getting list of hosts for %s\n", file);
588        params.pstdout(msgbuf);
589    }
590    /* Don't worry about errors. */
591    if (!pioctl(file, VIOCWHEREIS, &vio, 1)) {
592        phosts = (long *) outbuf;
593
594        /*
595         * Lists hosts that we care about.  If ALLHOSTS is defined,
596         * then all hosts that you ever may possible go through are
597         * included in this list.  If not, then only hosts that are
598         * the only ones appear.  That is, if a volume you must use
599         * is replaced on only one server, that server is included.
600         * If it is replicated on many servers, then none are included.
601         * This is not perfect, but the result is that people don't
602         * get subscribed to a lot of instances of FILSRV that they
603         * probably won't need which reduces the instances of
604         * people getting messages that don't apply to them.
605         */
606#ifndef ALLHOSTS
607        if (phosts[1] != '\0')
608            return;
609#endif
610        for (i = 0; phosts[i]; i++) {
611            if (hosts) {
612                in.s_addr = phosts[i];
613                if (dflag) {
614                    sprintf(msgbuf, "Got host %s\n", inet_ntoa(in));
615                    params.pstdout(msgbuf);
616                }
617                ll_string(&hostlist, ll_s_add, (char *)inet_ntoa(in));
618            }
619            if (zsubs && (hp=gethostbyaddr(&phosts[i],sizeof(long),AF_INET))) {
620                if (dflag) {
621                    sprintf(msgbuf, "Got host %s\n", hp->h_name);
622                    params.pstdout(msgbuf);
623                }
624                ll_string(&zsublist, ll_s_add, hp->h_name);
625            }
626        }
627    }
628}
629   
630/*
631 * This routine descends through a path to a directory, logging to
632 * every cell it encounters along the way.
633 */
634#ifdef __STDC__
635static int auth_to_path(char *path)
636#else
637static int auth_to_path(path)
638  char *path;                   /* The path to which we try to authenticate */
639#endif /* __STDC__ */
640{
641    int status = AKLOG_SUCCESS;
642    int auth_to_cell_status = AKLOG_SUCCESS;
643
644    char *nextpath;
645    char pathtocheck[MAXPATHLEN + 1];
646    char mountpoint[MAXPATHLEN + 1];
647
648    char *cell;
649    char *endofcell;
650
651    u_char isdir;
652
653    /* Initialize */
654    if (path[0] == DIR)
655        strcpy(pathtocheck, path);
656    else {
657        if (params.getwd(pathtocheck) == NULL) {
658            sprintf(msgbuf, "Unable to find current working directory:\n");
659            params.pstderr(msgbuf);
660            sprintf(msgbuf, "%s\n", pathtocheck);
661            params.pstderr(msgbuf);
662            sprintf(msgbuf, "Try an absolute pathname.\n");
663            params.pstderr(msgbuf);
664            params.exitprog(AKLOG_BADPATH);
665        }
666        else {
667            strcat(pathtocheck, DIRSTRING);
668            strcat(pathtocheck, path);
669        }
670    }
671    next_path(pathtocheck);
672
673    /* Go on to the next level down the path */
674    while (nextpath = next_path(NULL)) {
675        strcpy(pathtocheck, nextpath);
676        if (dflag) {
677            sprintf(msgbuf, "Checking directory %s\n", pathtocheck);
678            params.pstdout(msgbuf);
679        }
680        /*
681         * If this is an afs mountpoint, determine what cell from
682         * the mountpoint name which is of the form
683         * #cellname:volumename or %cellname:volumename.
684         */
685        if (get_afs_mountpoint(pathtocheck, mountpoint, sizeof(mountpoint))) {
686            /* skip over the '#' or '%' */
687            cell = mountpoint + 1;
688            /* Add this (cell:volumename) to the list of zsubs */
689            if (zsubs)
690                ll_string(&zsublist, ll_s_add, cell);
691            if (zsubs || hosts)
692                add_hosts(pathtocheck);
693            if (endofcell = strchr(mountpoint, VOLMARKER)) {
694                *endofcell = '\0';
695                if (auth_to_cell_status = auth_to_cell(cell, NULL)) {
696                    if (status == AKLOG_SUCCESS)
697                        status = auth_to_cell_status;
698                    else if (status != auth_to_cell_status)
699                        status = AKLOG_SOMETHINGSWRONG;
700                }
701            }
702        }
703        else {
704            if (params.isdir(pathtocheck, &isdir) < 0) {
705                /*
706                 * If we've logged and still can't stat, there's
707                 * a problem...
708                 */
709                sprintf(msgbuf, "%s: stat(%s): %s\n", progname,
710                        pathtocheck, sys_errlist[errno]);
711                params.pstderr(msgbuf);
712                return(AKLOG_BADPATH);
713            }
714            else if (! isdir) {
715                /* Allow only directories */
716                sprintf(msgbuf, "%s: %s: %s\n", progname, pathtocheck,
717                        sys_errlist[ENOTDIR]);
718                params.pstderr(msgbuf);
719                return(AKLOG_BADPATH);
720            }
721        }
722    }
723   
724
725    return(status);
726}
727
728/* Print usage message and exit */
729#ifdef __STDC__
730static void usage(void)
731#else
732static void usage()
733#endif /* __STDC__ */
734{
735    sprintf(msgbuf, "\nUsage: %s %s%s%s\n", progname,
736            "[-d] [[-cell | -c] cell [-k krb_realm]] ",
737            "[[-p | -path] pathname]\n",
738            "    [-zsubs] [-hosts] [-noauth] [-noprdb]\n");
739    params.pstderr(msgbuf);
740    sprintf(msgbuf, "    -d gives debugging information.\n");
741    params.pstderr(msgbuf);
742    sprintf(msgbuf, "    krb_realm is the kerberos realm of a cell.\n");
743    params.pstderr(msgbuf);
744    sprintf(msgbuf, "    pathname is the name of a directory to which ");
745    params.pstderr(msgbuf);
746    sprintf(msgbuf, "you wish to authenticate.\n");
747    params.pstderr(msgbuf);
748    sprintf(msgbuf, "    -zsubs gives zephyr subscription information.\n");
749    params.pstderr(msgbuf);
750    sprintf(msgbuf, "    -hosts gives host address information.\n");
751    params.pstderr(msgbuf);
752    sprintf(msgbuf, "    -noauth does not attempt to get tokens.\n");
753    params.pstderr(msgbuf);
754    sprintf(msgbuf, "    -noprdb means don't try to determine AFS ID.\n");
755    params.pstderr(msgbuf);
756    sprintf(msgbuf, "    No commandline arguments means ");
757    params.pstderr(msgbuf);
758    sprintf(msgbuf, "authenticate to the local cell.\n");
759    params.pstderr(msgbuf);
760    sprintf(msgbuf, "\n");
761    params.pstderr(msgbuf);
762    params.exitprog(AKLOG_USAGE);
763}
764
765#ifdef __STDC__
766void aklog(int argc, char *argv[], aklog_params *a_params)
767#else
768void aklog(argc, argv, a_params)
769  int argc;
770  char *argv[];
771  aklog_params *a_params;
772#endif /* __STDC__ */
773{
774    int status = AKLOG_SUCCESS;
775    int i;
776    int somethingswrong = FALSE;
777
778    cellinfo_t cellinfo;
779
780    extern char *progname;      /* Name of this program */
781
782    extern int dflag;           /* Debug mode */
783
784    int cmode = FALSE;          /* Cellname mode */
785    int pmode = FALSE;          /* Path name mode */
786
787    char realm[REALM_SZ];       /* Kerberos realm of afs server */
788    char cell[BUFSIZ];          /* Cell to which we are authenticating */
789    char path[MAXPATHLEN + 1];          /* Path length for path mode */
790
791    linked_list cells;          /* List of cells to log to */
792    linked_list paths;          /* List of paths to log to */
793    ll_node *cur_node;
794
795    bzero(&cellinfo, sizeof(cellinfo));
796
797    bzero(realm, sizeof(realm));
798    bzero(cell, sizeof(cell));
799    bzero(path, sizeof(path));
800
801    ll_init(&cells);
802    ll_init(&paths);
803
804    ll_init(&zsublist);
805    ll_init(&hostlist);
806
807    /* Store the program name here for error messages */
808    if (progname = strrchr(argv[0], DIR))
809        progname++;
810    else
811        progname = argv[0];
812
813    bcopy((char *)a_params, (char *)&params, sizeof(aklog_params));
814
815    /* Initialize list of cells to which we have authenticated */
816    (void)ll_init(&authedcells);
817
818    /* Parse commandline arguments and make list of what to do. */
819    for (i = 1; i < argc; i++) {
820        if (strcmp(argv[i], "-d") == 0)
821            dflag++;
822        else if (strcmp(argv[i], "-noauth") == 0)
823            noauth++;
824        else if (strcmp(argv[i], "-zsubs") == 0)
825            zsubs++;
826        else if (strcmp(argv[i], "-hosts") == 0)
827            hosts++;
828        else if (strcmp(argv[i], "-noprdb") == 0)
829            noprdb++;
830        else if (strcmp(argv[i], "-force") == 0)
831            force++;
832        else if (((strcmp(argv[i], "-cell") == 0) ||
833                  (strcmp(argv[i], "-c") == 0)) && !pmode)
834            if (++i < argc) {
835                cmode++;
836                strcpy(cell, argv[i]);
837            }
838            else
839                usage();
840        else if (((strcmp(argv[i], "-path") == 0) ||
841                  (strcmp(argv[i], "-p") == 0)) && !cmode)
842            if (++i < argc) {
843                pmode++;
844                strcpy(path, argv[i]);
845            }
846            else
847                usage();
848        else if (argv[i][0] == '-')
849            usage();
850        else if (!pmode && !cmode) {
851            if (strchr(argv[i], DIR) || (strcmp(argv[i], ".") == 0) ||
852                (strcmp(argv[i], "..") == 0)) {
853                pmode++;
854                strcpy(path, argv[i]);
855            }
856            else {
857                cmode++;
858                strcpy(cell, argv[i]);
859            }
860        }
861        else
862            usage();
863
864        if (cmode) {
865            if (((i + 1) < argc) && (strcmp(argv[i + 1], "-k") == 0)) {
866                i+=2;
867                if (i < argc)
868                    strcpy(realm, argv[i]);
869                else
870                    usage();
871            }
872            /* Add this cell to list of cells */
873            strcpy(cellinfo.cell, cell);
874            strcpy(cellinfo.realm, realm);
875            if (cur_node = ll_add_node(&cells, ll_tail)) {
876                char *new_cellinfo;
877                if (new_cellinfo = copy_cellinfo(&cellinfo))
878                    ll_add_data(cur_node, new_cellinfo);
879                else {
880                    sprintf(msgbuf,
881                            "%s: failure copying cellinfo.\n", progname);
882                    params.pstderr(msgbuf);
883                    params.exitprog(AKLOG_MISC);
884                }
885            }
886            else {
887                sprintf(msgbuf, "%s: failure adding cell to cells list.\n",
888                        progname);
889                params.pstderr(msgbuf);
890                params.exitprog(AKLOG_MISC);
891            }
892            bzero(&cellinfo, sizeof(cellinfo));
893            cmode = FALSE;
894            bzero(cell, sizeof(cell));
895            bzero(realm, sizeof(realm));
896        }
897        else if (pmode) {
898            /* Add this path to list of paths */
899            if (cur_node = ll_add_node(&paths, ll_tail)) {
900                char *new_path;
901                if (new_path = copy_string(path))
902                    ll_add_data(cur_node, new_path);
903                else {
904                    sprintf(msgbuf, "%s: failure copying path name.\n",
905                            progname);
906                    params.pstderr(msgbuf);
907                    params.exitprog(AKLOG_MISC);
908                }
909            }
910            else {
911                sprintf(msgbuf, "%s: failure adding path to paths list.\n",
912                        progname);
913                params.pstderr(msgbuf);
914                params.exitprog(AKLOG_MISC);
915            }
916            pmode = FALSE;
917            bzero(path, sizeof(path));
918        }
919    }
920
921    /* If nothing was given, log to the local cell. */
922    if ((cells.nelements + paths.nelements) == 0)
923        status = auth_to_cell(NULL, NULL);
924    else {
925        /* Log to all cells in the cells list first */
926        for (cur_node = cells.first; cur_node; cur_node = cur_node->next) {
927            bcopy(cur_node->data, (char *)&cellinfo, sizeof(cellinfo));
928            if (status = auth_to_cell(cellinfo.cell, cellinfo.realm))
929                somethingswrong++;
930        }
931       
932        /* Then, log to all paths in the paths list */
933        for (cur_node = paths.first; cur_node; cur_node = cur_node->next) {
934            if (status = auth_to_path(cur_node->data))
935                somethingswrong++;
936        }
937       
938        /*
939         * If only one thing was logged to, we'll return the status
940         * of the single call.  Otherwise, we'll return a generic
941         * something failed status.
942         */
943        if (somethingswrong && ((cells.nelements + paths.nelements) > 1))
944            status = AKLOG_SOMETHINGSWRONG;
945    }
946
947    /* If we are keeping track of zephyr subscriptions, print them. */
948    if (zsubs)
949        for (cur_node = zsublist.first; cur_node; cur_node = cur_node->next) {
950            sprintf(msgbuf, "zsub: %s\n", cur_node->data);
951            params.pstdout(msgbuf);
952        }
953
954    /* If we are keeping track of host information, print it. */
955    if (hosts)
956        for (cur_node = hostlist.first; cur_node; cur_node = cur_node->next) {
957            sprintf(msgbuf, "host: %s\n", cur_node->data);
958            params.pstdout(msgbuf);
959        }
960
961    params.exitprog(status);
962}
Note: See TracBrowser for help on using the repository browser.