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

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