source: trunk/athena/bin/discuss/libds/dsname.c @ 22404

Revision 22404, 12.5 KB checked in by ghudson, 18 years ago (diff)
Eliminate declarations of system functions which cause warnings or errors. Fix some broken ss library calls.
Line 
1/*
2 *
3 *      Copyright (C) 1988, 1989 by the Massachusetts Institute of Technology
4 *      Developed by the MIT Student Information Processing Board (SIPB).
5 *      For copying information, see the file mit-copyright.h in this release.
6 *
7 */
8/*
9 *      $Id: dsname.c,v 1.29 2006-03-10 07:11:38 ghudson Exp $
10 *
11 */
12
13/*
14 * db: Implements user's meetings database.
15 *
16 */
17
18#include <stdio.h>
19#include <stdlib.h>
20#include <string.h>
21#if HAVE_UNISTD_H
22#include <unistd.h>
23#endif
24#include <pwd.h>
25#include <sys/file.h>
26#include <sys/param.h>
27#include <errno.h>
28#include <assert.h>
29#include <discuss/dsname.h>
30#include <discuss/dsc_et.h>
31#include "ansi.h"
32
33#ifndef lint
34static const char rcsid_dsname_c[] =
35    "$Id: dsname.c,v 1.29 2006-03-10 07:11:38 ghudson Exp $";
36#endif
37
38extern char *local_realm ();
39
40/*
41 * Format of data file:
42 *    status:last_time:last_seen:uid:name1,name2name3,....,nameN:
43 */
44
45static FILE *db = (FILE *)NULL;
46static char *db_file = (char *)NULL;
47static char *db_user_id = (char *)NULL;
48
49static server_name_blk current = {
50    (char *)NULL, (char *)NULL, (char *)NULL, 0, 0, 0
51};
52
53static char disrcbuf[MAXPATHLEN]; /* user's MEETINGS file */
54static char *disrcfile = NULL;  /* pointer to above */
55
56static char mtgs[] = "/.meetings";
57
58
59#ifdef __GNUC__
60#define INLINE inline
61#else
62#define INLINE
63#endif
64
65/*
66 * ds() -- duplicate a string.  a useful utility routine...
67 */
68
69INLINE static char * ds(s)
70    const char *s;
71{
72    register int len = strlen (s) + 1;
73    register char *ns = malloc (len);
74    memcpy (ns, s, len);
75    return (ns);
76}
77
78/*
79 * Attempt to locate user's .meetings file.  This is intended to be
80 * used as a test routine from an application.
81 *
82 * search path is:
83 *      $MEETINGS environment variable
84 *      $HOME/.meetings
85 *      <pw->pw_dir>/.meetings
86 * This function is "sticky"; it only evaluates the filename once.
87 */
88
89int find_rc_filename()
90{
91    struct passwd *pw = NULL;
92    register char *cp;
93
94    if (disrcfile)
95        return 0;
96
97    pw = getpwuid(getuid());
98    if (!pw)
99        return NO_SUCH_USER;
100
101    cp = getenv("MEETINGS");
102    if (cp)
103        strcpy(disrcbuf, cp);
104    if (!cp) {
105        cp = getenv("HOME");
106        if (cp) {
107            strcpy(disrcbuf, cp);
108            strcat(disrcbuf, mtgs);
109        }
110    }
111    if (!cp) {
112        strcpy(disrcbuf, pw->pw_dir);
113        strcat(disrcbuf, mtgs);
114    }
115    if (!access(disrcbuf, R_OK|W_OK)) {
116        disrcfile = disrcbuf;
117        return 0;
118    }
119    return errno;
120}
121
122static void clear_current () {
123    if (current.hostname) {
124        free (current.hostname);
125        current.hostname = (char *) NULL;
126    }
127    if (current.pathname) {
128        free (current.pathname);
129        current.pathname = (char *) NULL;
130    }
131    if (current.alias_list) {
132        free (current.alias_list);
133        current.alias_list = (char *) NULL;
134    }
135    if (current.spare) {
136        free (current.spare);
137        current.spare = (char *) NULL;
138    }
139}
140
141static void enddbent()
142{
143    if (db) {
144        fclose(db);
145        db = (FILE *)NULL;
146        free(db_file);
147        db_file = (char *)NULL;
148        free(db_user_id);
149        db_user_id = (char *)NULL;
150    }
151    clear_current ();
152}
153
154/*
155 * getdbent() -- get the next entry out of the file.  returns
156 * zero on end of file or uncorrectable error, one on success, minus
157 * one on correctable error.
158 */
159
160static int getdbent()
161{
162    char buffer[BUFSIZ];
163    char *bufp, *cp;
164
165    if (!db) {
166        errno = NO_MTGS_FILE;
167        return(0);
168    }
169    if (!fgets(buffer, BUFSIZ, db)) {
170        return 0;
171    }
172
173    bufp = strchr(buffer, '\n');
174    if (bufp)
175        *bufp = '\0';
176    bufp = buffer;
177
178    /* meeting status flags (per-user) */
179    current.status = atoi(bufp);
180    bufp = strchr(bufp, ':');
181    if (!bufp) {
182    bad_fmt:
183        errno = BAD_MTGS_FILE;
184        return(-1);
185    }
186    else
187        bufp++;
188
189    /* date user last attended meeting */
190    current.date_attended = atoi(bufp);
191    bufp = strchr(bufp, ':');
192    if (!bufp)
193        goto bad_fmt;
194    else
195        bufp++;
196
197    /* last transaction seen */
198    current.last = atoi(bufp);
199    bufp = strchr(bufp, ':');
200    if (!bufp)
201        goto bad_fmt;
202    else
203        bufp++;
204
205    /* hostname of meeting */
206    if (current.hostname)
207        free(current.hostname);
208    cp = strchr(bufp, ':');
209    if (cp == NULL) goto bad_fmt;
210    else {
211        *cp = '\0';
212        current.hostname = ds(bufp);
213        bufp = cp+1;
214    }
215
216    /* pathname of meeting on remote host */
217    if (current.pathname)
218        free(current.pathname);
219    cp = strchr(bufp, ':');
220    if (cp == NULL) goto bad_fmt;
221    else {
222        *cp = '\0';
223        current.pathname = ds(bufp);
224        bufp = cp+1;
225    }
226
227    /* list of aliases for meeting */
228    if (current.alias_list)
229        free(current.alias_list);
230    cp = strchr(bufp, ':');
231    if (cp == NULL) goto bad_fmt;
232    else {
233        *cp = '\0';
234        current.alias_list = ds(bufp);
235        bufp = cp+1;
236    }
237
238    if (current.spare)
239        free(current.spare);
240    current.spare = ds(bufp);
241
242    return(1);
243}
244
245static int setdbent(user_id)
246    const char *user_id;
247{
248    char *auid;
249    register int code;
250
251    enddbent();
252
253    if (!user_id)
254        user_id = "";
255    if (!disrcfile) {
256        code = find_rc_filename();
257        if (code)
258            return code;
259    }
260    db_file = ds(disrcfile);
261
262    db = fopen(db_file, "r");
263    if (!db)
264        return(errno);
265    if (db_user_id)
266        free(db_user_id);
267    db_user_id = ds(user_id);
268    if (current.user_id)
269        free(current.user_id);
270    current.user_id = ds(user_id);
271    return(0);
272}
273
274static int is_a_name(name)
275    register char *name;
276{
277    register int len;
278    register char *ns = current.alias_list;
279
280    if (*name == '*')
281        return(1);
282    len = strlen(name);
283
284    while (1) {
285        if (!strncmp(name, ns, len) && (!ns[len] || ns[len] == ',')) {
286            return(1);
287        }
288        ns = strchr(ns+1, ',');
289        if (!ns || !ns[1]) {
290            return(0);
291        }
292        ns++;
293    }
294}
295
296static char ** expand(list)
297    char *list;
298{
299    register int num = 2;
300    register char *cp;
301    register char **rv, **rv1;
302    for (cp = list; cp;) {
303        num++;
304        cp = strchr(cp, ',');
305        if (cp)
306            cp++;
307    }
308    rv = (char **) calloc (num, sizeof(char *));
309    rv1 = rv;
310    while (list && *list) {
311        while (*list == ',')
312            list++;
313        cp = strchr(list, ',');
314        if (cp)
315            *cp = '\0';
316        *rv1 = ds(list);
317        rv1++;
318        if (cp) {
319            *cp = ',';
320            cp++;
321            list = cp;
322        }
323        else list = (char *) NULL;
324    }
325    *rv1 = (char *) NULL;
326    return(rv);
327}
328
329static char * compress(list)
330    char **list;
331{
332    int len;
333    char **cp;
334    char *rv;
335    len = 1;
336    for (cp = list; *cp; cp++)
337        len += 1 + strlen(*cp);
338    rv = malloc (len);
339    strcpy(rv, *list);
340    for (cp = list+1; *cp; cp++) {
341        strcat(rv, ",");
342        strcat(rv, *cp);
343    }
344    return (rv);
345}
346
347dsc_expand_mtg_set(user_id, name, set, num, result)
348    char *user_id;              /* userid to do lookup for */
349    char *name;                 /* user's name for meeting */
350    name_blk **set;             /* returned values */
351    int *num;                   /* number of returned meetings */
352    int *result;                /* return code */
353{
354    int count;
355    register int r;
356
357    *set = 0;
358    *num = 0;
359    *result = 0;
360
361    if (!user_id)
362        user_id = "";
363    if (!name) {
364        *result = EINVAL;
365        *num = 0;
366        return;
367    }
368    r = setdbent(user_id);
369    if (r) {
370        *result = r;
371        return;
372    }
373    count = 0;
374    while ((r=getdbent()) > 0) {
375        if (is_a_name(name))
376            count++;
377    }
378    if (r) {                    /* getdbent returns -1 */
379        *result = errno;
380        return;
381    }
382    r = setdbent(user_id);
383    if (r) {
384        *result = r;
385        return;
386    }
387    *set = (name_blk *) malloc(count * sizeof(name_blk));
388    if (*set == (name_blk *)NULL) {
389        *result = errno;
390        return;
391    }
392    while ((r=getdbent()) > 0)
393        if (is_a_name(name)) {
394            register name_blk *nb = *set + (*num)++;
395            memset((char *)nb, 0, sizeof(*nb));
396            nb->date_attended = current.date_attended;
397            nb->last = current.last;
398            nb->status = current.status;
399            nb->hostname = ds(current.hostname);
400            nb->pathname = ds(current.pathname);
401            nb->aliases = expand(current.alias_list);
402            nb->spare = ds(current.spare);
403            nb->user_id = ds(user_id);
404        }
405    if (r)
406        *result = r;
407}
408
409void dsc_copy_name_blk (src, dest)
410    register name_blk *src, *dest;
411{
412    char **cpp;
413    char **dpp;
414    int count;
415
416    *dest = *src;
417    dest->hostname = ds(dest->hostname);
418    dest->pathname = ds(dest->pathname);
419    dest->user_id = ds(dest->user_id);
420    dest->spare = ds(dest->spare);
421
422    for (count=1, cpp = src->aliases; *cpp; cpp++) {
423        count++;
424    }
425    dpp = dest->aliases = (char **)malloc ((count+1) * sizeof (char *));
426    for (cpp = src->aliases; *cpp; cpp++, dpp++)
427        *dpp = ds (*cpp);
428    *dpp = NULL;
429}
430/*
431 * Free all allocated storage associated with *nbp;
432 * Note: this does not free the nbp itself.
433 */
434void dsc_destroy_name_blk(nbp)
435    name_blk *nbp;
436{
437    if (nbp->aliases) {
438        register char **alp = nbp->aliases;
439        while (*alp) {
440            free (*alp);
441            alp++;
442        }
443        free (nbp->aliases);
444        nbp->aliases = 0;
445    }
446    if (nbp->hostname) {
447        free(nbp->hostname);
448        nbp->hostname = 0;
449    }
450    if (nbp->pathname) {
451        free(nbp->pathname);
452        nbp->pathname = 0;
453    }
454    if (nbp->spare) {
455        free(nbp->spare);
456        nbp->spare = 0;
457    }
458    if (nbp->user_id) {
459        free (nbp->user_id);
460        nbp->user_id = 0;
461    }
462}
463
464void dsc_destroy_mtg_set(nbp, count)
465    register name_blk *nbp;
466    register int count;
467{
468    register int i;
469
470    if (nbp == NULL) return;
471    for (i=0; i<count; i++)
472        dsc_destroy_name_blk(&nbp[i]);
473
474    free((char *)nbp);
475}
476
477dsc_get_mtg (user_id, name, nbp, result)
478    char *user_id;
479    char *name;
480    name_blk *nbp;
481    int *result;
482{
483    name_blk *set = NULL;
484    int num;
485
486    if (!name) {
487        *result = EINVAL;
488    }
489    dsc_expand_mtg_set(user_id, name, &set, &num, result);
490    if (num == 0) {
491        if (!*result)
492            *result = NO_SUCH_MTG;
493        goto bad;
494    } else if (num > 1) {
495        register int i;
496        for (i = 1; i < num; i++) {
497            dsc_destroy_name_blk(&set[i]);
498        }
499    }
500    memcpy(nbp, &set[0], sizeof(name_blk));
501
502bad:
503    if (set)
504        free((char *)set);
505}
506
507static const char format[] = "%d:%d:%d:%s:%s:%s:%s\n";
508
509void dsc_update_mtg_set(user_id, set, num, result)
510    char const *user_id;        /* input */
511    name_blk *set;              /* array of name_blk's */
512    int num;                    /* number in set */
513    int *result;                /* error code */
514{
515    name_blk *nbp;
516    int i;
517    register int r;
518    char *touched;              /* array of booleans */
519    char *new_name;
520    FILE *new_file = NULL;
521    char *old_name;
522
523    if (!num) {
524        *result = 0;
525        return;
526    }
527    else if (!set) {
528        *result = EINVAL;
529        return;
530    }
531    if (*result = setdbent(user_id)) {
532        if (*result != NO_MTGS_FILE && *result != ENOENT)
533            return;
534        else
535            *result = 0;
536    }
537
538    new_name = malloc(strlen(db_file) + 2);
539    strcpy (new_name, db_file);
540    strcat (new_name, "~");             /* emacsish, but who cares? */
541    old_name = malloc(strlen(db_file) + 1);
542    strcpy (old_name, db_file);
543
544    new_file = fopen (new_name, "w+");
545    if (new_file == NULL) {
546        *result = errno;
547        free(old_name);
548        free (new_name);
549        return;
550    }
551
552    touched = malloc (num);
553    for (i = 0; i < num; i++)
554        touched[i] = 0;
555
556    while ((r=getdbent()) != 0) {
557        if (r == -1) {  /* if bad format, we complain loudly */
558             *result = BAD_MTGS_FILE;
559             goto punt;
560        }
561        /* walk through user structures, look for matching entries */
562        for (i = 0, nbp = set;  i < num; i++, nbp++) {
563            if (!strcmp (current.hostname, nbp -> hostname) &&
564                !strcmp(current.pathname, nbp->pathname)) {
565                /* match, update */
566                current.last = nbp -> last;
567                current.date_attended =
568                    nbp -> date_attended;
569                current.status = nbp -> status;
570                if (current.alias_list != NULL)
571                    free (current.alias_list);
572                current.alias_list = compress(nbp -> aliases);
573                if (current.spare)
574                    free (current.spare);
575                current.spare = ds(nbp->spare);
576                touched[i] = 1;
577            }
578        }
579        if (current.status & DSC_ST_DELETED) continue;
580
581        if (fprintf(new_file, format,
582                    current.status, current.date_attended, current.last,
583                    current.hostname, current.pathname,
584                    current.alias_list, current.spare) == EOF)
585            goto punt;
586    }
587
588    clear_current ();
589
590    /* clean up ones we haven't touched in memory yet */
591    for (i = 0, nbp = set; i < num; i++, nbp++) {
592        if (!touched[i]) {
593            char *temp = compress (nbp->aliases);
594
595            assert (nbp->hostname != 0 && nbp->pathname != 0);
596            assert (nbp->spare != 0);
597            if (fprintf (new_file, format,
598                         nbp->status, nbp->date_attended, nbp->last,
599                         nbp->hostname, nbp->pathname,
600                         temp, nbp->spare) == EOF) {
601                free (temp);
602                goto punt;
603            }
604            free (temp);
605        }
606    }
607    enddbent();
608    /* Fsync the file, just to be sure */
609    fflush(new_file);
610    if (fsync (fileno (new_file)) == -1)
611         goto punt;
612    if (ferror (new_file)) {
613         *result = CANT_WRITE_TEMP;
614         goto punt;
615    }
616    if (fclose (new_file)) {
617         *result = CANT_WRITE_TEMP;
618         goto punt;
619    }
620    new_file = NULL;
621    *result = (rename(new_name, old_name) < 0) ? errno : 0;
622    if (*result)
623        (void) unlink (new_name);
624    new_file = NULL;
625    free(new_name);
626    free(old_name);
627    free(touched);
628    return;
629
630punt:
631    if (new_file)
632        fclose(new_file);
633    enddbent();
634    unlink(new_name);
635    free(new_name);
636    free(old_name);
637    free(touched);
638    return;
639}
Note: See TracBrowser for help on using the repository browser.