156822Seric /*
268839Seric * Copyright (c) 1992, 1995 Eric P. Allman.
362526Sbostic * Copyright (c) 1992, 1993
462526Sbostic * The Regents of the University of California. All rights reserved.
556822Seric *
656822Seric * %sccs.include.redist.c%
756822Seric */
856822Seric
956822Seric #ifndef lint
10*69954Seric static char sccsid[] = "@(#)map.c 8.79 (Berkeley) 06/20/95";
1156822Seric #endif /* not lint */
1256822Seric
1356822Seric #include "sendmail.h"
1456822Seric
1560089Seric #ifdef NDBM
1668509Seric # include <ndbm.h>
1756822Seric #endif
1860089Seric #ifdef NEWDB
1968509Seric # include <db.h>
2056822Seric #endif
2160089Seric #ifdef NIS
2269651Seric struct dom_binding; /* forward reference needed on IRIX */
2368509Seric # include <rpcsvc/ypclnt.h>
2457208Seric #endif
2556822Seric
2656822Seric /*
2760089Seric ** MAP.C -- implementations for various map classes.
2856822Seric **
2960089Seric ** Each map class implements a series of functions:
3060089Seric **
3160089Seric ** bool map_parse(MAP *map, char *args)
3260089Seric ** Parse the arguments from the config file. Return TRUE
3360089Seric ** if they were ok, FALSE otherwise. Fill in map with the
3460089Seric ** values.
3560089Seric **
3660222Seric ** char *map_lookup(MAP *map, char *key, char **args, int *pstat)
3760222Seric ** Look up the key in the given map. If found, do any
3860222Seric ** rewriting the map wants (including "args" if desired)
3960089Seric ** and return the value. Set *pstat to the appropriate status
4060222Seric ** on error and return NULL. Args will be NULL if called
4160222Seric ** from the alias routines, although this should probably
4260222Seric ** not be relied upon. It is suggested you call map_rewrite
4360222Seric ** to return the results -- it takes care of null termination
4460222Seric ** and uses a dynamically expanded buffer as needed.
4560089Seric **
4660089Seric ** void map_store(MAP *map, char *key, char *value)
4760089Seric ** Store the key:value pair in the map.
4860089Seric **
4960089Seric ** bool map_open(MAP *map, int mode)
5060222Seric ** Open the map for the indicated mode. Mode should
5160222Seric ** be either O_RDONLY or O_RDWR. Return TRUE if it
5260222Seric ** was opened successfully, FALSE otherwise. If the open
5360222Seric ** failed an the MF_OPTIONAL flag is not set, it should
5460222Seric ** also print an error. If the MF_ALIAS bit is set
5560222Seric ** and this map class understands the @:@ convention, it
5660222Seric ** should call aliaswait() before returning.
5760089Seric **
5860089Seric ** void map_close(MAP *map)
5960089Seric ** Close the map.
6069401Seric **
6169401Seric ** This file also includes the implementation for getcanonname.
6269401Seric ** It is currently implemented in a pretty ad-hoc manner; it ought
6369401Seric ** to be more properly integrated into the map structure.
6460089Seric */
6560089Seric
6660089Seric #define DBMMODE 0644
6764718Seric
6864718Seric extern bool aliaswait __P((MAP *, char *, int));
6969833Seric extern bool extract_canonname __P((char *, char *, char[]));
7060089Seric /*
7160089Seric ** MAP_PARSEARGS -- parse config line arguments for database lookup
7260089Seric **
7360089Seric ** This is a generic version of the map_parse method.
7460089Seric **
7556822Seric ** Parameters:
7660089Seric ** map -- the map being initialized.
7760089Seric ** ap -- a pointer to the args on the config line.
7856822Seric **
7956822Seric ** Returns:
8060089Seric ** TRUE -- if everything parsed OK.
8156822Seric ** FALSE -- otherwise.
8256822Seric **
8356822Seric ** Side Effects:
8460089Seric ** null terminates the filename; stores it in map
8556822Seric */
8656822Seric
8756822Seric bool
map_parseargs(map,ap)8860089Seric map_parseargs(map, ap)
8956822Seric MAP *map;
9060089Seric char *ap;
9156822Seric {
9260089Seric register char *p = ap;
9356822Seric
9463753Seric map->map_mflags |= MF_TRY0NULL | MF_TRY1NULL;
9560089Seric for (;;)
9660089Seric {
9760089Seric while (isascii(*p) && isspace(*p))
9860089Seric p++;
9960089Seric if (*p != '-')
10060089Seric break;
10160089Seric switch (*++p)
10260089Seric {
10360089Seric case 'N':
10460207Seric map->map_mflags |= MF_INCLNULL;
10563753Seric map->map_mflags &= ~MF_TRY0NULL;
10660089Seric break;
10760089Seric
10863753Seric case 'O':
10963753Seric map->map_mflags &= ~MF_TRY1NULL;
11063753Seric break;
11163753Seric
11260089Seric case 'o':
11360207Seric map->map_mflags |= MF_OPTIONAL;
11460089Seric break;
11560089Seric
11660089Seric case 'f':
11760207Seric map->map_mflags |= MF_NOFOLDCASE;
11860089Seric break;
11960089Seric
12060089Seric case 'm':
12160207Seric map->map_mflags |= MF_MATCHONLY;
12260089Seric break;
12360089Seric
12468497Seric case 'A':
12568497Seric map->map_mflags |= MF_APPEND;
12668497Seric break;
12768497Seric
12869703Seric case 'q':
12969703Seric map->map_mflags |= MF_KEEPQUOTES;
13069703Seric break;
13169703Seric
13260089Seric case 'a':
13360089Seric map->map_app = ++p;
13460089Seric break;
13568350Seric
13668350Seric case 'k':
13768350Seric while (isascii(*++p) && isspace(*p))
13868350Seric continue;
13968350Seric map->map_keycolnm = p;
14068350Seric break;
14168350Seric
14268350Seric case 'v':
14368350Seric while (isascii(*++p) && isspace(*p))
14468350Seric continue;
14568350Seric map->map_valcolnm = p;
14668350Seric break;
14768350Seric
14868350Seric case 'z':
14968350Seric if (*++p != '\\')
15068350Seric map->map_coldelim = *p;
15168350Seric else
15268350Seric {
15368350Seric switch (*++p)
15468350Seric {
15568350Seric case 'n':
15668350Seric map->map_coldelim = '\n';
15768350Seric break;
15868350Seric
15968350Seric case 't':
16068350Seric map->map_coldelim = '\t';
16168350Seric break;
16268350Seric
16368350Seric default:
16468350Seric map->map_coldelim = '\\';
16568350Seric }
16668350Seric }
16768350Seric break;
16868497Seric #ifdef RESERVED_FOR_SUN
16968497Seric case 'd':
17068497Seric map->map_mflags |= MF_DOMAIN_WIDE;
17168497Seric break;
17268497Seric
17368497Seric case 's':
17468497Seric /* info type */
17568497Seric break;
17668497Seric #endif
17760089Seric }
17860089Seric while (*p != '\0' && !(isascii(*p) && isspace(*p)))
17960089Seric p++;
18060089Seric if (*p != '\0')
18160089Seric *p++ = '\0';
18260089Seric }
18360089Seric if (map->map_app != NULL)
18460089Seric map->map_app = newstr(map->map_app);
18568350Seric if (map->map_keycolnm != NULL)
18668350Seric map->map_keycolnm = newstr(map->map_keycolnm);
18768350Seric if (map->map_valcolnm != NULL)
18868350Seric map->map_valcolnm = newstr(map->map_valcolnm);
18960089Seric
19060089Seric if (*p != '\0')
19160089Seric {
19260089Seric map->map_file = p;
19360089Seric while (*p != '\0' && !(isascii(*p) && isspace(*p)))
19460089Seric p++;
19560089Seric if (*p != '\0')
19660089Seric *p++ = '\0';
19760089Seric map->map_file = newstr(map->map_file);
19860089Seric }
19960089Seric
20060089Seric while (*p != '\0' && isascii(*p) && isspace(*p))
20160089Seric p++;
20260089Seric if (*p != '\0')
20360089Seric map->map_rebuild = newstr(p);
20460089Seric
20568350Seric if (map->map_file == NULL &&
20668350Seric !bitset(MCF_OPTFILE, map->map_class->map_cflags))
20757208Seric {
20860089Seric syserr("No file name for %s map %s",
20960089Seric map->map_class->map_cname, map->map_mname);
21056822Seric return FALSE;
21157208Seric }
21260089Seric return TRUE;
21360089Seric }
21460089Seric /*
21560089Seric ** MAP_REWRITE -- rewrite a database key, interpolating %n indications.
21660089Seric **
21760089Seric ** It also adds the map_app string. It can be used as a utility
21860089Seric ** in the map_lookup method.
21960089Seric **
22060089Seric ** Parameters:
22160089Seric ** map -- the map that causes this.
22260089Seric ** s -- the string to rewrite, NOT necessarily null terminated.
22360089Seric ** slen -- the length of s.
22460089Seric ** av -- arguments to interpolate into buf.
22560089Seric **
22660089Seric ** Returns:
22767895Seric ** Pointer to rewritten result. This is static data that
22867895Seric ** should be copied if it is to be saved!
22960089Seric **
23060089Seric ** Side Effects:
23160089Seric ** none.
23260089Seric */
23360089Seric
23460089Seric char *
map_rewrite(map,s,slen,av)23560089Seric map_rewrite(map, s, slen, av)
23660089Seric register MAP *map;
23760089Seric register char *s;
23860089Seric int slen;
23960089Seric char **av;
24060089Seric {
24160089Seric register char *bp;
24260089Seric register char c;
24360089Seric char **avp;
24460089Seric register char *ap;
24560089Seric int i;
24660089Seric int len;
24767895Seric static int buflen = -1;
24867895Seric static char *buf = NULL;
24960089Seric
25060537Seric if (tTd(39, 1))
25160089Seric {
25260256Seric printf("map_rewrite(%.*s), av =", slen, s);
25360256Seric if (av == NULL)
25460256Seric printf(" (nullv)");
25560256Seric else
25660256Seric {
25760256Seric for (avp = av; *avp != NULL; avp++)
25860256Seric printf("\n\t%s", *avp);
25960256Seric }
26060256Seric printf("\n");
26160089Seric }
26260089Seric
26360089Seric /* count expected size of output (can safely overestimate) */
26460089Seric i = len = slen;
26560089Seric if (av != NULL)
26660089Seric {
26760089Seric bp = s;
26860089Seric for (i = slen; --i >= 0 && (c = *bp++) != 0; )
26960089Seric {
27060089Seric if (c != '%')
27160089Seric continue;
27260089Seric if (--i < 0)
27360089Seric break;
27460089Seric c = *bp++;
27560089Seric if (!(isascii(c) && isdigit(c)))
27660089Seric continue;
27763937Seric for (avp = av; --c >= '0' && *avp != NULL; avp++)
27860089Seric continue;
27960089Seric if (*avp == NULL)
28060089Seric continue;
28160089Seric len += strlen(*avp);
28260089Seric }
28360089Seric }
28460089Seric if (map->map_app != NULL)
28560089Seric len += strlen(map->map_app);
28667895Seric if (buflen < ++len)
28760089Seric {
28860089Seric /* need to malloc additional space */
28967895Seric buflen = len;
29067895Seric if (buf != NULL)
29167895Seric free(buf);
29267895Seric buf = xalloc(buflen);
29360089Seric }
29460089Seric
29567895Seric bp = buf;
29660089Seric if (av == NULL)
29760089Seric {
29860089Seric bcopy(s, bp, slen);
29960089Seric bp += slen;
30060089Seric }
30160089Seric else
30260089Seric {
30360089Seric while (--slen >= 0 && (c = *s++) != '\0')
30460089Seric {
30560089Seric if (c != '%')
30660089Seric {
30760089Seric pushc:
30860089Seric *bp++ = c;
30960089Seric continue;
31060089Seric }
31160089Seric if (--slen < 0 || (c = *s++) == '\0')
31260089Seric c = '%';
31360089Seric if (c == '%')
31460089Seric goto pushc;
31560089Seric if (!(isascii(c) && isdigit(c)))
31660089Seric {
31760089Seric *bp++ = '%';
31860089Seric goto pushc;
31960089Seric }
32063937Seric for (avp = av; --c >= '0' && *avp != NULL; avp++)
32160089Seric continue;
32260089Seric if (*avp == NULL)
32360089Seric continue;
32460089Seric
32560089Seric /* transliterate argument into output string */
32660089Seric for (ap = *avp; (c = *ap++) != '\0'; )
32760089Seric *bp++ = c;
32860089Seric }
32960089Seric }
33060089Seric if (map->map_app != NULL)
33160089Seric strcpy(bp, map->map_app);
33260089Seric else
33360089Seric *bp = '\0';
33460537Seric if (tTd(39, 1))
33567895Seric printf("map_rewrite => %s\n", buf);
33667895Seric return buf;
33760089Seric }
33860089Seric /*
33960537Seric ** INITMAPS -- initialize for aliasing
34060537Seric **
34160537Seric ** Parameters:
34260537Seric ** rebuild -- if TRUE, this rebuilds the cached versions.
34360537Seric ** e -- current envelope.
34460537Seric **
34560537Seric ** Returns:
34660537Seric ** none.
34760537Seric **
34860537Seric ** Side Effects:
34960537Seric ** initializes aliases:
35060537Seric ** if NDBM: opens the database.
35160537Seric ** if ~NDBM: reads the aliases into the symbol table.
35260537Seric */
35360537Seric
35469748Seric void
initmaps(rebuild,e)35560537Seric initmaps(rebuild, e)
35660537Seric bool rebuild;
35760537Seric register ENVELOPE *e;
35860537Seric {
35960537Seric extern void map_init();
36060537Seric
36169881Seric #if XDEBUG
36264671Seric checkfd012("entering initmaps");
36364671Seric #endif
36460537Seric CurEnv = e;
36565085Seric if (rebuild)
36665085Seric {
36765085Seric stabapply(map_init, 1);
36865085Seric stabapply(map_init, 2);
36965085Seric }
37065085Seric else
37165085Seric {
37265085Seric stabapply(map_init, 0);
37365085Seric }
37469881Seric #if XDEBUG
37564671Seric checkfd012("exiting initmaps");
37664671Seric #endif
37760537Seric }
37860537Seric
37960537Seric void
map_init(s,rebuild)38060537Seric map_init(s, rebuild)
38160537Seric register STAB *s;
38260537Seric int rebuild;
38360537Seric {
38460537Seric register MAP *map;
38560537Seric
38660537Seric /* has to be a map */
38760537Seric if (s->s_type != ST_MAP)
38860537Seric return;
38960537Seric
39060537Seric map = &s->s_map;
39160537Seric if (!bitset(MF_VALID, map->map_mflags))
39260537Seric return;
39360537Seric
39460537Seric if (tTd(38, 2))
39568350Seric printf("map_init(%s:%s, %s, %d)\n",
39664690Seric map->map_class->map_cname == NULL ? "NULL" :
39764690Seric map->map_class->map_cname,
39868350Seric map->map_mname == NULL ? "NULL" : map->map_mname,
39965085Seric map->map_file == NULL ? "NULL" : map->map_file,
40065085Seric rebuild);
40160537Seric
40265085Seric if (rebuild == (bitset(MF_ALIAS, map->map_mflags) &&
40365085Seric bitset(MCF_REBUILDABLE, map->map_class->map_cflags) ? 1 : 2))
40465085Seric {
40565085Seric if (tTd(38, 3))
40665085Seric printf("\twrong pass\n");
40765085Seric return;
40865085Seric }
40965085Seric
41060537Seric /* if already open, close it (for nested open) */
41160537Seric if (bitset(MF_OPEN, map->map_mflags))
41260537Seric {
41360537Seric map->map_class->map_close(map);
41460537Seric map->map_mflags &= ~(MF_OPEN|MF_WRITABLE);
41560537Seric }
41660537Seric
41765085Seric if (rebuild == 2)
41860537Seric {
41965085Seric rebuildaliases(map, FALSE);
42060537Seric }
42160537Seric else
42260537Seric {
42360537Seric if (map->map_class->map_open(map, O_RDONLY))
42460537Seric {
42560537Seric if (tTd(38, 4))
42668350Seric printf("\t%s:%s %s: valid\n",
42764690Seric map->map_class->map_cname == NULL ? "NULL" :
42864690Seric map->map_class->map_cname,
42968350Seric map->map_mname == NULL ? "NULL" :
43068350Seric map->map_mname,
43164690Seric map->map_file == NULL ? "NULL" :
43264690Seric map->map_file);
43360537Seric map->map_mflags |= MF_OPEN;
43460537Seric }
43568350Seric else
43668350Seric {
43768350Seric if (tTd(38, 4))
43868350Seric printf("\t%s:%s %s: invalid: %s\n",
43968350Seric map->map_class->map_cname == NULL ? "NULL" :
44068350Seric map->map_class->map_cname,
44168350Seric map->map_mname == NULL ? "NULL" :
44268350Seric map->map_mname,
44368350Seric map->map_file == NULL ? "NULL" :
44468350Seric map->map_file,
44568350Seric errstring(errno));
44668350Seric if (!bitset(MF_OPTIONAL, map->map_mflags))
44768350Seric {
44868350Seric extern MAPCLASS BogusMapClass;
44968350Seric
45068350Seric map->map_class = &BogusMapClass;
45168350Seric map->map_mflags |= MF_OPEN;
45268350Seric }
45368350Seric }
45460537Seric }
45560537Seric }
45660537Seric /*
45769802Seric ** GETCANONNAME -- look up name using service switch
45869802Seric **
45969802Seric ** Parameters:
46069802Seric ** host -- the host name to look up.
46169802Seric ** hbsize -- the size of the host buffer.
46269802Seric ** trymx -- if set, try MX records.
46369802Seric **
46469802Seric ** Returns:
46569802Seric ** TRUE -- if the host was found.
46669802Seric ** FALSE -- otherwise.
46769802Seric */
46869802Seric
46969802Seric bool
getcanonname(host,hbsize,trymx)47069802Seric getcanonname(host, hbsize, trymx)
47169802Seric char *host;
47269802Seric int hbsize;
47369802Seric bool trymx;
47469802Seric {
47569802Seric int nmaps;
47669802Seric int mapno;
47769802Seric bool found = FALSE;
47869802Seric auto int stat;
47969802Seric char *maptype[MAXMAPSTACK];
48069802Seric short mapreturn[MAXMAPACTIONS];
48169802Seric
48269802Seric nmaps = switch_map_find("hosts", maptype, mapreturn);
48369802Seric for (mapno = 0; mapno < nmaps; mapno++)
48469802Seric {
48569802Seric int i;
48669802Seric
48769802Seric if (tTd(38, 20))
48869802Seric printf("getcanonname(%s), trying %s\n",
48969802Seric host, maptype[mapno]);
49069802Seric if (strcmp("files", maptype[mapno]) == 0)
49169802Seric {
49269802Seric extern bool text_getcanonname __P((char *, int, int *));
49369802Seric
49469802Seric found = text_getcanonname(host, hbsize, &stat);
49569802Seric }
49669802Seric #ifdef NIS
49769802Seric else if (strcmp("nis", maptype[mapno]) == 0)
49869802Seric {
49969802Seric extern bool nis_getcanonname __P((char *, int, int *));
50069802Seric
50169802Seric found = nis_getcanonname(host, hbsize, &stat);
50269802Seric }
50369802Seric #endif
50469802Seric #ifdef NISPLUS
50569802Seric else if (strcmp("nisplus", maptype[mapno]) == 0)
50669802Seric {
50769802Seric extern bool nisplus_getcanonname __P((char *, int, int *));
50869802Seric
50969802Seric found = nisplus_getcanonname(host, hbsize, &stat);
51069802Seric }
51169802Seric #endif
51269802Seric #if NAMED_BIND
51369802Seric else if (strcmp("dns", maptype[mapno]) == 0)
51469802Seric {
51569802Seric extern bool dns_getcanonname __P((char *, int, bool, int *));
51669802Seric
51769802Seric found = dns_getcanonname(host, hbsize, trymx, &stat);
51869802Seric }
51969802Seric #endif
52069802Seric else
52169802Seric {
52269802Seric found = FALSE;
52369802Seric stat = EX_UNAVAILABLE;
52469802Seric }
52569802Seric if (found)
52669802Seric break;
52769802Seric
52869802Seric /* see if we should continue */
52969802Seric if (stat == EX_TEMPFAIL)
53069802Seric i = MA_TRYAGAIN;
53169802Seric else if (stat == EX_NOHOST)
53269802Seric i = MA_NOTFOUND;
53369802Seric else
53469802Seric i = MA_UNAVAIL;
53569802Seric if (bitset(1 << mapno, mapreturn[i]))
53669802Seric break;
53769802Seric }
53869802Seric
53969802Seric if (found)
54069802Seric {
54169802Seric char *d;
54269802Seric
54369802Seric if (tTd(38, 20))
54469802Seric printf("getcanonname(%s), found\n", host);
54569802Seric
54669802Seric /*
54769802Seric ** If returned name is still single token, compensate
54869802Seric ** by tagging on $m. This is because some sites set
54969802Seric ** up their DNS or NIS databases wrong.
55069802Seric */
55169802Seric
55269802Seric if ((d = strchr(host, '.')) == NULL || d[1] == '\0')
55369802Seric {
55469802Seric d = macvalue('m', CurEnv);
55569802Seric if (d != NULL &&
55669802Seric hbsize > (int) (strlen(host) + strlen(d) + 1))
55769802Seric {
55869802Seric if (host[strlen(host) - 1] != '.')
55969802Seric strcat(host, ".");
56069802Seric strcat(host, d);
56169802Seric }
56269802Seric else
56369802Seric {
56469802Seric return FALSE;
56569802Seric }
56669802Seric }
56769802Seric return TRUE;
56869802Seric }
56969802Seric
57069802Seric if (tTd(38, 20))
57169802Seric printf("getcanonname(%s), failed, stat=%d\n", host, stat);
57269802Seric
57369802Seric #if NAMED_BIND
57469802Seric if (stat == EX_NOHOST)
57569802Seric h_errno = HOST_NOT_FOUND;
57669802Seric else
57769802Seric h_errno = TRY_AGAIN;
57869802Seric #endif
57969802Seric
58069802Seric return FALSE;
58169802Seric }
58269802Seric /*
58369833Seric ** EXTRACT_CANONNAME -- extract canonical name from /etc/hosts entry
58469833Seric **
58569833Seric ** Parameters:
58669833Seric ** name -- the name against which to match.
58769833Seric ** line -- the /etc/hosts line.
58869833Seric ** cbuf -- the location to store the result.
58969833Seric **
59069833Seric ** Returns:
59169833Seric ** TRUE -- if the line matched the desired name.
59269833Seric ** FALSE -- otherwise.
59369833Seric */
59469833Seric
59569833Seric bool
extract_canonname(name,line,cbuf)59669833Seric extract_canonname(name, line, cbuf)
59769833Seric char *name;
59869833Seric char *line;
59969833Seric char cbuf[];
60069833Seric {
60169833Seric int i;
60269833Seric char *p;
60369833Seric bool found = FALSE;
60469833Seric extern char *get_column();
60569833Seric
60669833Seric cbuf[0] = '\0';
60769833Seric if (line[0] == '#')
60869833Seric return FALSE;
60969833Seric
61069876Seric for (i = 1; ; i++)
61169833Seric {
61269833Seric char nbuf[MAXNAME + 1];
61369833Seric
61469833Seric p = get_column(line, i, '\0', nbuf);
61569833Seric if (p == NULL)
61669833Seric break;
61769833Seric if (cbuf[0] == '\0' ||
61869833Seric (strchr(cbuf, '.') == NULL && strchr(p, '.') != NULL))
61969833Seric strcpy(cbuf, p);
62069833Seric if (strcasecmp(name, p) == 0)
62169833Seric found = TRUE;
62269833Seric }
62369833Seric if (found && strchr(cbuf, '.') == NULL)
62469833Seric {
62569833Seric /* try to add a domain on the end of the name */
62669833Seric char *domain = macvalue('m', CurEnv);
62769833Seric
62869833Seric if (domain != NULL &&
62969833Seric strlen(domain) + strlen(cbuf) + 1 < MAXNAME)
63069833Seric {
63169833Seric p = &cbuf[strlen(cbuf)];
63269833Seric *p++ = '.';
63369833Seric strcpy(p, domain);
63469833Seric }
63569833Seric }
63669833Seric return found;
63769833Seric }
63869833Seric /*
63960089Seric ** NDBM modules
64060089Seric */
64160089Seric
64260089Seric #ifdef NDBM
64360089Seric
64460089Seric /*
64560089Seric ** DBM_MAP_OPEN -- DBM-style map open
64660089Seric */
64760089Seric
64860089Seric bool
ndbm_map_open(map,mode)64960089Seric ndbm_map_open(map, mode)
65060089Seric MAP *map;
65160089Seric int mode;
65260089Seric {
65364284Seric register DBM *dbm;
65464284Seric struct stat st;
65560089Seric
65660537Seric if (tTd(38, 2))
65768350Seric printf("ndbm_map_open(%s, %s, %d)\n",
65868350Seric map->map_mname, map->map_file, mode);
65960089Seric
66060207Seric if (mode == O_RDWR)
66160207Seric mode |= O_CREAT|O_TRUNC;
66260207Seric
66360089Seric /* open the database */
66460089Seric dbm = dbm_open(map->map_file, mode, DBMMODE);
66556822Seric if (dbm == NULL)
66656822Seric {
66764718Seric if (aliaswait(map, ".pag", FALSE))
66864718Seric return TRUE;
66960207Seric if (!bitset(MF_OPTIONAL, map->map_mflags))
67056836Seric syserr("Cannot open DBM database %s", map->map_file);
67156822Seric return FALSE;
67256822Seric }
67360089Seric map->map_db1 = (void *) dbm;
67464964Seric if (mode == O_RDONLY)
67564964Seric {
67664964Seric if (bitset(MF_ALIAS, map->map_mflags) &&
67764964Seric !aliaswait(map, ".pag", TRUE))
67864718Seric return FALSE;
67964964Seric }
68064964Seric else
68164964Seric {
68264964Seric int fd;
68364964Seric
68464964Seric /* exclusive lock for duration of rebuild */
68564964Seric fd = dbm_dirfno((DBM *) map->map_db1);
68664964Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags) &&
68764964Seric lockfile(fd, map->map_file, ".dir", LOCK_EX))
68864964Seric map->map_mflags |= MF_LOCKED;
68964964Seric }
69064718Seric if (fstat(dbm_dirfno((DBM *) map->map_db1), &st) >= 0)
69164284Seric map->map_mtime = st.st_mtime;
69256822Seric return TRUE;
69356822Seric }
69460089Seric
69560089Seric
69660089Seric /*
69756822Seric ** DBM_MAP_LOOKUP -- look up a datum in a DBM-type map
69856822Seric */
69956822Seric
70056822Seric char *
ndbm_map_lookup(map,name,av,statp)70160089Seric ndbm_map_lookup(map, name, av, statp)
70256822Seric MAP *map;
70360089Seric char *name;
70456822Seric char **av;
70559084Seric int *statp;
70656822Seric {
70756822Seric datum key, val;
70864373Seric int fd;
70960089Seric char keybuf[MAXNAME + 1];
71056822Seric
71160537Seric if (tTd(38, 20))
71268350Seric printf("ndbm_map_lookup(%s, %s)\n",
71368350Seric map->map_mname, name);
71460089Seric
71560089Seric key.dptr = name;
71660089Seric key.dsize = strlen(name);
71760207Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags))
71857014Seric {
71960089Seric if (key.dsize > sizeof keybuf - 1)
72060089Seric key.dsize = sizeof keybuf - 1;
72160089Seric bcopy(key.dptr, keybuf, key.dsize + 1);
72260089Seric makelower(keybuf);
72360089Seric key.dptr = keybuf;
72457014Seric }
72564373Seric fd = dbm_dirfno((DBM *) map->map_db1);
72664388Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
72764373Seric (void) lockfile(fd, map->map_file, ".dir", LOCK_SH);
72863753Seric val.dptr = NULL;
72963753Seric if (bitset(MF_TRY0NULL, map->map_mflags))
73063753Seric {
73163753Seric val = dbm_fetch((DBM *) map->map_db1, key);
73263753Seric if (val.dptr != NULL)
73363753Seric map->map_mflags &= ~MF_TRY1NULL;
73463753Seric }
73563753Seric if (val.dptr == NULL && bitset(MF_TRY1NULL, map->map_mflags))
73663753Seric {
73756822Seric key.dsize++;
73863753Seric val = dbm_fetch((DBM *) map->map_db1, key);
73963753Seric if (val.dptr != NULL)
74063753Seric map->map_mflags &= ~MF_TRY0NULL;
74163753Seric }
74264388Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
74364373Seric (void) lockfile(fd, map->map_file, ".dir", LOCK_UN);
74456822Seric if (val.dptr == NULL)
74556822Seric return NULL;
74660207Seric if (bitset(MF_MATCHONLY, map->map_mflags))
74763753Seric return map_rewrite(map, name, strlen(name), NULL);
74863753Seric else
74963753Seric return map_rewrite(map, val.dptr, val.dsize, av);
75056822Seric }
75156822Seric
75256822Seric
75356822Seric /*
75460089Seric ** DBM_MAP_STORE -- store a datum in the database
75556822Seric */
75656822Seric
75760089Seric void
ndbm_map_store(map,lhs,rhs)75860089Seric ndbm_map_store(map, lhs, rhs)
75960089Seric register MAP *map;
76060089Seric char *lhs;
76160089Seric char *rhs;
76260089Seric {
76360089Seric datum key;
76460089Seric datum data;
76560089Seric int stat;
76660089Seric
76760537Seric if (tTd(38, 12))
76868350Seric printf("ndbm_map_store(%s, %s, %s)\n",
76968350Seric map->map_mname, lhs, rhs);
77060089Seric
77160089Seric key.dsize = strlen(lhs);
77260089Seric key.dptr = lhs;
77360089Seric
77460089Seric data.dsize = strlen(rhs);
77560089Seric data.dptr = rhs;
77660089Seric
77760207Seric if (bitset(MF_INCLNULL, map->map_mflags))
77860089Seric {
77960089Seric key.dsize++;
78060089Seric data.dsize++;
78160089Seric }
78260089Seric
78360089Seric stat = dbm_store((DBM *) map->map_db1, key, data, DBM_INSERT);
78460089Seric if (stat > 0)
78560089Seric {
78668497Seric if (!bitset(MF_APPEND, map->map_mflags))
78768497Seric usrerr("050 Warning: duplicate alias name %s", lhs);
78868497Seric else
78968497Seric {
79068497Seric static char *buf = NULL;
79168497Seric static int bufsiz = 0;
79268879Seric auto int xstat;
79368497Seric datum old;
79468497Seric
79568879Seric old.dptr = ndbm_map_lookup(map, key.dptr, NULL, &xstat);
79668497Seric if (old.dptr != NULL && *old.dptr != '\0')
79768497Seric {
79868497Seric old.dsize = strlen(old.dptr);
79968497Seric if (data.dsize + old.dsize + 2 > bufsiz)
80068497Seric {
80168497Seric if (buf != NULL)
80268497Seric (void) free(buf);
80368497Seric bufsiz = data.dsize + old.dsize + 2;
80468497Seric buf = xalloc(bufsiz);
80568497Seric }
80668497Seric sprintf(buf, "%s,%s", data.dptr, old.dptr);
80768497Seric data.dsize = data.dsize + old.dsize + 1;
80868497Seric data.dptr = buf;
80968497Seric if (tTd(38, 9))
81068497Seric printf("ndbm_map_store append=%s\n", data.dptr);
81168497Seric }
81268497Seric }
81360089Seric stat = dbm_store((DBM *) map->map_db1, key, data, DBM_REPLACE);
81460089Seric }
81560089Seric if (stat != 0)
81660089Seric syserr("readaliases: dbm put (%s)", lhs);
81760089Seric }
81860089Seric
81960089Seric
82060089Seric /*
82160207Seric ** NDBM_MAP_CLOSE -- close the database
82260089Seric */
82360089Seric
82460089Seric void
ndbm_map_close(map)82560089Seric ndbm_map_close(map)
82660089Seric register MAP *map;
82760089Seric {
82866773Seric if (tTd(38, 9))
82968350Seric printf("ndbm_map_close(%s, %s, %x)\n",
83068350Seric map->map_mname, map->map_file, map->map_mflags);
83166773Seric
83260207Seric if (bitset(MF_WRITABLE, map->map_mflags))
83360089Seric {
83464250Seric #ifdef NIS
83564075Seric bool inclnull;
83660089Seric char buf[200];
83760089Seric
83864075Seric inclnull = bitset(MF_INCLNULL, map->map_mflags);
83964075Seric map->map_mflags &= ~MF_INCLNULL;
84064075Seric
84169651Seric if (strstr(map->map_file, "/yp/") != NULL)
84269651Seric {
84369651Seric (void) sprintf(buf, "%010ld", curtime());
84469651Seric ndbm_map_store(map, "YP_LAST_MODIFIED", buf);
84560089Seric
84669651Seric (void) gethostname(buf, sizeof buf);
84769651Seric ndbm_map_store(map, "YP_MASTER_NAME", buf);
84869651Seric }
84964075Seric
85064075Seric if (inclnull)
85164075Seric map->map_mflags |= MF_INCLNULL;
85260089Seric #endif
85360089Seric
85460089Seric /* write out the distinguished alias */
85560089Seric ndbm_map_store(map, "@", "@");
85660089Seric }
85760089Seric dbm_close((DBM *) map->map_db1);
85860089Seric }
85960089Seric
86060089Seric #endif
86160089Seric /*
86260582Seric ** NEWDB (Hash and BTree) Modules
86360089Seric */
86460089Seric
86560089Seric #ifdef NEWDB
86660089Seric
86760089Seric /*
86860582Seric ** BT_MAP_OPEN, HASH_MAP_OPEN -- database open primitives.
86960582Seric **
87060582Seric ** These do rather bizarre locking. If you can lock on open,
87160582Seric ** do that to avoid the condition of opening a database that
87260582Seric ** is being rebuilt. If you don't, we'll try to fake it, but
87360582Seric ** there will be a race condition. If opening for read-only,
87460582Seric ** we immediately release the lock to avoid freezing things up.
87560582Seric ** We really ought to hold the lock, but guarantee that we won't
87660582Seric ** be pokey about it. That's hard to do.
87760089Seric */
87860089Seric
87956822Seric bool
bt_map_open(map,mode)88060089Seric bt_map_open(map, mode)
88156822Seric MAP *map;
88260089Seric int mode;
88356822Seric {
88456822Seric DB *db;
88560228Seric int i;
88660582Seric int omode;
88764373Seric int fd;
88864284Seric struct stat st;
88968528Seric char buf[MAXNAME + 1];
89056822Seric
89160537Seric if (tTd(38, 2))
89268350Seric printf("bt_map_open(%s, %s, %d)\n",
89368350Seric map->map_mname, map->map_file, mode);
89460089Seric
89560582Seric omode = mode;
89660582Seric if (omode == O_RDWR)
89760582Seric {
89860582Seric omode |= O_CREAT|O_TRUNC;
89965830Seric #if defined(O_EXLOCK) && HASFLOCK
90060582Seric omode |= O_EXLOCK;
90166843Seric # if !OLD_NEWDB
90260582Seric }
90360582Seric else
90460582Seric {
90560582Seric omode |= O_SHLOCK;
90660582Seric # endif
90760582Seric #endif
90860582Seric }
90960207Seric
91060228Seric (void) strcpy(buf, map->map_file);
91160228Seric i = strlen(buf);
91260228Seric if (i < 3 || strcmp(&buf[i - 3], ".db") != 0)
91360228Seric (void) strcat(buf, ".db");
91460582Seric db = dbopen(buf, omode, DBMMODE, DB_BTREE, NULL);
91556822Seric if (db == NULL)
91656822Seric {
91764718Seric #ifdef MAYBENEXTRELEASE
91864718Seric if (aliaswait(map, ".db", FALSE))
91964718Seric return TRUE;
92064718Seric #endif
92160207Seric if (!bitset(MF_OPTIONAL, map->map_mflags))
92256836Seric syserr("Cannot open BTREE database %s", map->map_file);
92356822Seric return FALSE;
92456822Seric }
92568350Seric #if !OLD_NEWDB
92664373Seric fd = db->fd(db);
92768778Seric # if defined(O_EXLOCK) && HASFLOCK
92868778Seric if (fd >= 0)
92968778Seric {
93068778Seric if (mode == O_RDONLY)
93168778Seric (void) lockfile(fd, map->map_file, ".db", LOCK_UN);
93268778Seric else
93368778Seric map->map_mflags |= MF_LOCKED;
93468778Seric }
93568778Seric # else
93664373Seric if (mode == O_RDWR && fd >= 0)
93764388Seric {
93864388Seric if (lockfile(fd, map->map_file, ".db", LOCK_EX))
93964388Seric map->map_mflags |= MF_LOCKED;
94064388Seric }
94160582Seric # endif
94260582Seric #endif
94360585Seric
94460585Seric /* try to make sure that at least the database header is on disk */
94560585Seric if (mode == O_RDWR)
94666843Seric #if OLD_NEWDB
94764373Seric (void) db->sync(db);
94864373Seric #else
94960585Seric (void) db->sync(db, 0);
95060585Seric
95164373Seric if (fd >= 0 && fstat(fd, &st) >= 0)
95264284Seric map->map_mtime = st.st_mtime;
95364284Seric #endif
95464284Seric
95560089Seric map->map_db2 = (void *) db;
95660207Seric if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags))
95764718Seric if (!aliaswait(map, ".db", TRUE))
95864718Seric return FALSE;
95956822Seric return TRUE;
96056822Seric }
96156822Seric
96256822Seric
96356822Seric /*
96456822Seric ** HASH_MAP_INIT -- HASH-style map initialization
96556822Seric */
96656822Seric
96756822Seric bool
hash_map_open(map,mode)96860089Seric hash_map_open(map, mode)
96956822Seric MAP *map;
97060089Seric int mode;
97156822Seric {
97256822Seric DB *db;
97360228Seric int i;
97460582Seric int omode;
97564373Seric int fd;
97664284Seric struct stat st;
97768528Seric char buf[MAXNAME + 1];
97856822Seric
97960537Seric if (tTd(38, 2))
98068350Seric printf("hash_map_open(%s, %s, %d)\n",
98168350Seric map->map_mname, map->map_file, mode);
98260089Seric
98360582Seric omode = mode;
98460582Seric if (omode == O_RDWR)
98560582Seric {
98660582Seric omode |= O_CREAT|O_TRUNC;
98765830Seric #if defined(O_EXLOCK) && HASFLOCK
98860582Seric omode |= O_EXLOCK;
98966843Seric # if !OLD_NEWDB
99060582Seric }
99160582Seric else
99260582Seric {
99360582Seric omode |= O_SHLOCK;
99460582Seric # endif
99560582Seric #endif
99660582Seric }
99760207Seric
99860228Seric (void) strcpy(buf, map->map_file);
99960228Seric i = strlen(buf);
100060228Seric if (i < 3 || strcmp(&buf[i - 3], ".db") != 0)
100160228Seric (void) strcat(buf, ".db");
100260582Seric db = dbopen(buf, omode, DBMMODE, DB_HASH, NULL);
100356822Seric if (db == NULL)
100456822Seric {
100564718Seric #ifdef MAYBENEXTRELEASE
100664718Seric if (aliaswait(map, ".db", FALSE))
100764718Seric return TRUE;
100864718Seric #endif
100960207Seric if (!bitset(MF_OPTIONAL, map->map_mflags))
101056836Seric syserr("Cannot open HASH database %s", map->map_file);
101156822Seric return FALSE;
101256822Seric }
101368350Seric #if !OLD_NEWDB
101464373Seric fd = db->fd(db);
101568778Seric # if defined(O_EXLOCK) && HASFLOCK
101668778Seric if (fd >= 0)
101768778Seric {
101868778Seric if (mode == O_RDONLY)
101968778Seric (void) lockfile(fd, map->map_file, ".db", LOCK_UN);
102068778Seric else
102168778Seric map->map_mflags |= MF_LOCKED;
102268778Seric }
102368778Seric # else
102464373Seric if (mode == O_RDWR && fd >= 0)
102564388Seric {
102664388Seric if (lockfile(fd, map->map_file, ".db", LOCK_EX))
102764388Seric map->map_mflags |= MF_LOCKED;
102864388Seric }
102960582Seric # endif
103060582Seric #endif
103160585Seric
103260585Seric /* try to make sure that at least the database header is on disk */
103360585Seric if (mode == O_RDWR)
103466843Seric #if OLD_NEWDB
103564373Seric (void) db->sync(db);
103664373Seric #else
103760585Seric (void) db->sync(db, 0);
103860585Seric
103964373Seric if (fd >= 0 && fstat(fd, &st) >= 0)
104064284Seric map->map_mtime = st.st_mtime;
104164284Seric #endif
104264284Seric
104360089Seric map->map_db2 = (void *) db;
104460207Seric if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags))
104564718Seric if (!aliaswait(map, ".db", TRUE))
104664718Seric return FALSE;
104756822Seric return TRUE;
104856822Seric }
104956822Seric
105056822Seric
105156822Seric /*
105256822Seric ** DB_MAP_LOOKUP -- look up a datum in a BTREE- or HASH-type map
105356822Seric */
105456822Seric
105556822Seric char *
db_map_lookup(map,name,av,statp)105660089Seric db_map_lookup(map, name, av, statp)
105756822Seric MAP *map;
105860089Seric char *name;
105956822Seric char **av;
106059084Seric int *statp;
106156822Seric {
106256822Seric DBT key, val;
106360422Seric register DB *db = (DB *) map->map_db2;
106460422Seric int st;
106560422Seric int saveerrno;
106664373Seric int fd;
106760089Seric char keybuf[MAXNAME + 1];
106856822Seric
106960537Seric if (tTd(38, 20))
107068350Seric printf("db_map_lookup(%s, %s)\n",
107168350Seric map->map_mname, name);
107260089Seric
107360089Seric key.size = strlen(name);
107460089Seric if (key.size > sizeof keybuf - 1)
107560089Seric key.size = sizeof keybuf - 1;
107660089Seric key.data = keybuf;
107760089Seric bcopy(name, keybuf, key.size + 1);
107860207Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags))
107960089Seric makelower(keybuf);
108066843Seric #if !OLD_NEWDB
108164388Seric fd = db->fd(db);
108264388Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
108364388Seric (void) lockfile(db->fd(db), map->map_file, ".db", LOCK_SH);
108460422Seric #endif
108563753Seric st = 1;
108663753Seric if (bitset(MF_TRY0NULL, map->map_mflags))
108763753Seric {
108863753Seric st = db->get(db, &key, &val, 0);
108963753Seric if (st == 0)
109063753Seric map->map_mflags &= ~MF_TRY1NULL;
109163753Seric }
109263753Seric if (st != 0 && bitset(MF_TRY1NULL, map->map_mflags))
109363753Seric {
109463753Seric key.size++;
109563753Seric st = db->get(db, &key, &val, 0);
109663753Seric if (st == 0)
109763753Seric map->map_mflags &= ~MF_TRY0NULL;
109863753Seric }
109960422Seric saveerrno = errno;
110066843Seric #if !OLD_NEWDB
110164388Seric if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
110264373Seric (void) lockfile(fd, map->map_file, ".db", LOCK_UN);
110360422Seric #endif
110460422Seric if (st != 0)
110560422Seric {
110660422Seric errno = saveerrno;
110760422Seric if (st < 0)
110860422Seric syserr("db_map_lookup: get (%s)", name);
110956822Seric return NULL;
111060422Seric }
111160207Seric if (bitset(MF_MATCHONLY, map->map_mflags))
111263753Seric return map_rewrite(map, name, strlen(name), NULL);
111363753Seric else
111463753Seric return map_rewrite(map, val.data, val.size, av);
111556822Seric }
111656822Seric
111760089Seric
111860089Seric /*
111960089Seric ** DB_MAP_STORE -- store a datum in the NEWDB database
112056822Seric */
112156822Seric
112260089Seric void
db_map_store(map,lhs,rhs)112360089Seric db_map_store(map, lhs, rhs)
112460089Seric register MAP *map;
112560089Seric char *lhs;
112660089Seric char *rhs;
112756822Seric {
112860089Seric int stat;
112960089Seric DBT key;
113060089Seric DBT data;
113160089Seric register DB *db = map->map_db2;
113256822Seric
113360537Seric if (tTd(38, 20))
113468350Seric printf("db_map_store(%s, %s, %s)\n",
113568350Seric map->map_mname, lhs, rhs);
113660089Seric
113760089Seric key.size = strlen(lhs);
113860089Seric key.data = lhs;
113960089Seric
114060089Seric data.size = strlen(rhs);
114160089Seric data.data = rhs;
114260089Seric
114360207Seric if (bitset(MF_INCLNULL, map->map_mflags))
114456822Seric {
114560089Seric key.size++;
114660089Seric data.size++;
114760089Seric }
114856836Seric
114960089Seric stat = db->put(db, &key, &data, R_NOOVERWRITE);
115060089Seric if (stat > 0)
115160089Seric {
115268497Seric if (!bitset(MF_APPEND, map->map_mflags))
115368497Seric usrerr("050 Warning: duplicate alias name %s", lhs);
115468497Seric else
115568497Seric {
115668497Seric static char *buf = NULL;
115768497Seric static int bufsiz = 0;
115868497Seric DBT old;
115968497Seric
116068497Seric old.data = db_map_lookup(map, key.data, NULL, &stat);
116168497Seric if (old.data != NULL)
116268497Seric {
116368497Seric old.size = strlen(old.data);
116468497Seric if (data.size + old.size + 2 > bufsiz)
116568497Seric {
116668497Seric if (buf != NULL)
116768497Seric (void) free(buf);
116868497Seric bufsiz = data.size + old.size + 2;
116968497Seric buf = xalloc(bufsiz);
117068497Seric }
117168497Seric sprintf(buf, "%s,%s", data.data, old.data);
117268497Seric data.size = data.size + old.size + 1;
117368497Seric data.data = buf;
117468497Seric if (tTd(38, 9))
117568497Seric printf("db_map_store append=%s\n", data.data);
117668497Seric }
117768497Seric }
117860089Seric stat = db->put(db, &key, &data, 0);
117960089Seric }
118060089Seric if (stat != 0)
118160089Seric syserr("readaliases: db put (%s)", lhs);
118260089Seric }
118356836Seric
118456847Seric
118560089Seric /*
118660089Seric ** DB_MAP_CLOSE -- add distinguished entries and close the database
118760089Seric */
118860089Seric
118960089Seric void
db_map_close(map)119060089Seric db_map_close(map)
119160089Seric MAP *map;
119260089Seric {
119360089Seric register DB *db = map->map_db2;
119460089Seric
119560537Seric if (tTd(38, 9))
119668350Seric printf("db_map_close(%s, %s, %x)\n",
119768350Seric map->map_mname, map->map_file, map->map_mflags);
119860089Seric
119960207Seric if (bitset(MF_WRITABLE, map->map_mflags))
120058804Seric {
120160089Seric /* write out the distinguished alias */
120260089Seric db_map_store(map, "@", "@");
120358804Seric }
120458963Seric
120560089Seric if (db->close(db) != 0)
120660089Seric syserr("readaliases: db close failure");
120756822Seric }
120857208Seric
120960089Seric #endif
121060089Seric /*
121160089Seric ** NIS Modules
121260089Seric */
121360089Seric
121460089Seric # ifdef NIS
121560089Seric
121664369Seric # ifndef YPERR_BUSY
121764369Seric # define YPERR_BUSY 16
121864369Seric # endif
121964369Seric
122057208Seric /*
122160089Seric ** NIS_MAP_OPEN -- open DBM map
122257208Seric */
122357208Seric
122457208Seric bool
nis_map_open(map,mode)122560089Seric nis_map_open(map, mode)
122657208Seric MAP *map;
122760089Seric int mode;
122857208Seric {
122957216Seric int yperr;
123060215Seric register char *p;
123160215Seric auto char *vp;
123260215Seric auto int vsize;
123357216Seric
123460537Seric if (tTd(38, 2))
123568350Seric printf("nis_map_open(%s, %s)\n",
123668350Seric map->map_mname, map->map_file);
123760089Seric
123860207Seric if (mode != O_RDONLY)
123960207Seric {
124064650Seric /* issue a pseudo-error message */
124164650Seric #ifdef ENOSYS
124264650Seric errno = ENOSYS;
124364650Seric #else
124464650Seric # ifdef EFTYPE
124564650Seric errno = EFTYPE;
124664650Seric # else
124764650Seric errno = ENXIO;
124864650Seric # endif
124964650Seric #endif
125060207Seric return FALSE;
125160207Seric }
125260207Seric
125360089Seric p = strchr(map->map_file, '@');
125460089Seric if (p != NULL)
125560089Seric {
125660089Seric *p++ = '\0';
125760089Seric if (*p != '\0')
125860089Seric map->map_domain = p;
125960089Seric }
126060215Seric
126160089Seric if (*map->map_file == '\0')
126260089Seric map->map_file = "mail.aliases";
126360089Seric
126466157Seric if (map->map_domain == NULL)
126566157Seric {
126666157Seric yperr = yp_get_default_domain(&map->map_domain);
126766157Seric if (yperr != 0)
126866157Seric {
126966744Seric if (!bitset(MF_OPTIONAL, map->map_mflags))
127068350Seric syserr("421 NIS map %s specified, but NIS not running\n",
127166744Seric map->map_file);
127266157Seric return FALSE;
127366157Seric }
127466157Seric }
127566157Seric
127660215Seric /* check to see if this map actually exists */
127760089Seric yperr = yp_match(map->map_domain, map->map_file, "@", 1,
127860089Seric &vp, &vsize);
127960537Seric if (tTd(38, 10))
128060089Seric printf("nis_map_open: yp_match(%s, %s) => %s\n",
128160089Seric map->map_domain, map->map_file, yperr_string(yperr));
128260089Seric if (yperr == 0 || yperr == YPERR_KEY || yperr == YPERR_BUSY)
128368350Seric {
128468350Seric if (!bitset(MF_ALIAS, map->map_mflags) ||
128568350Seric aliaswait(map, NULL, TRUE))
128668350Seric return TRUE;
128768350Seric }
128860215Seric
128960215Seric if (!bitset(MF_OPTIONAL, map->map_mflags))
129068735Seric {
129168735Seric syserr("421 Cannot bind to map %s in domain %s: %s",
129268735Seric map->map_file, map->map_domain, yperr_string(yperr));
129368735Seric }
129460215Seric
129560089Seric return FALSE;
129660089Seric }
129760089Seric
129860089Seric
129960089Seric /*
130057208Seric ** NIS_MAP_LOOKUP -- look up a datum in a NIS map
130157208Seric */
130257208Seric
130357208Seric char *
nis_map_lookup(map,name,av,statp)130460089Seric nis_map_lookup(map, name, av, statp)
130557208Seric MAP *map;
130660089Seric char *name;
130757208Seric char **av;
130859084Seric int *statp;
130957208Seric {
131057208Seric char *vp;
131157642Seric auto int vsize;
131259274Seric int buflen;
131360215Seric int yperr;
131460089Seric char keybuf[MAXNAME + 1];
131557208Seric
131660537Seric if (tTd(38, 20))
131768350Seric printf("nis_map_lookup(%s, %s)\n",
131868350Seric map->map_mname, name);
131960089Seric
132060089Seric buflen = strlen(name);
132160089Seric if (buflen > sizeof keybuf - 1)
132260089Seric buflen = sizeof keybuf - 1;
132360089Seric bcopy(name, keybuf, buflen + 1);
132460207Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags))
132560089Seric makelower(keybuf);
132663753Seric yperr = YPERR_KEY;
132763753Seric if (bitset(MF_TRY0NULL, map->map_mflags))
132863753Seric {
132963753Seric yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen,
133063753Seric &vp, &vsize);
133163753Seric if (yperr == 0)
133263753Seric map->map_mflags &= ~MF_TRY1NULL;
133363753Seric }
133463753Seric if (yperr == YPERR_KEY && bitset(MF_TRY1NULL, map->map_mflags))
133563753Seric {
133659274Seric buflen++;
133763753Seric yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen,
133863753Seric &vp, &vsize);
133963753Seric if (yperr == 0)
134063753Seric map->map_mflags &= ~MF_TRY0NULL;
134163753Seric }
134260089Seric if (yperr != 0)
134360089Seric {
134460089Seric if (yperr != YPERR_KEY && yperr != YPERR_BUSY)
134560215Seric map->map_mflags &= ~(MF_VALID|MF_OPEN);
134657208Seric return NULL;
134760089Seric }
134860207Seric if (bitset(MF_MATCHONLY, map->map_mflags))
134963753Seric return map_rewrite(map, name, strlen(name), NULL);
135063753Seric else
135163753Seric return map_rewrite(map, vp, vsize, av);
135257208Seric }
135357208Seric
135469401Seric
135569401Seric /*
135669401Seric ** NIS_GETCANONNAME -- look up canonical name in NIS
135769401Seric */
135869401Seric
135969401Seric bool
nis_getcanonname(name,hbsize,statp)136069401Seric nis_getcanonname(name, hbsize, statp)
136169401Seric char *name;
136269401Seric int hbsize;
136369401Seric int *statp;
136469401Seric {
136569401Seric char *vp;
136669401Seric auto int vsize;
136769401Seric int keylen;
136869401Seric int yperr;
136969401Seric static bool try0null = TRUE;
137069401Seric static bool try1null = TRUE;
137169401Seric static char *yp_domain = NULL;
137269748Seric char *domain;
137369401Seric char host_record[MAXLINE];
137469833Seric char cbuf[MAXNAME];
137569780Seric char nbuf[MAXNAME + 1];
137669401Seric extern char *get_column();
137769401Seric
137869401Seric if (tTd(38, 20))
137969401Seric printf("nis_getcanonname(%s)\n", name);
138069401Seric
138169780Seric if (strlen(name) >= sizeof nbuf)
138269780Seric {
138369780Seric *statp = EX_UNAVAILABLE;
138469780Seric return FALSE;
138569780Seric }
138669780Seric (void) strcpy(nbuf, name);
138769780Seric shorten_hostname(nbuf);
138869401Seric
138969401Seric /* we only accept single token search key */
139069780Seric if (strchr(nbuf, '.'))
139169401Seric {
139269401Seric *statp = EX_NOHOST;
139369401Seric return FALSE;
139469401Seric }
139569401Seric
139669780Seric keylen = strlen(nbuf);
139769401Seric
139869401Seric if (yp_domain == NULL)
139969401Seric yp_get_default_domain(&yp_domain);
140069780Seric makelower(nbuf);
140169401Seric yperr = YPERR_KEY;
140269401Seric if (try0null)
140369401Seric {
140469780Seric yperr = yp_match(yp_domain, "hosts.byname", nbuf, keylen,
140569401Seric &vp, &vsize);
140669401Seric if (yperr == 0)
140769401Seric try1null = FALSE;
140869401Seric }
140969401Seric if (yperr == YPERR_KEY && try1null)
141069401Seric {
141169401Seric keylen++;
141269780Seric yperr = yp_match(yp_domain, "hosts.byname", nbuf, keylen,
141369401Seric &vp, &vsize);
141469401Seric if (yperr == 0)
141569401Seric try0null = FALSE;
141669401Seric }
141769401Seric if (yperr != 0)
141869401Seric {
141969401Seric if (yperr == YPERR_KEY)
142069401Seric *statp = EX_NOHOST;
142169401Seric else if (yperr == YPERR_BUSY)
142269401Seric *statp = EX_TEMPFAIL;
142369401Seric else
142469401Seric *statp = EX_UNAVAILABLE;
142569401Seric return FALSE;
142669401Seric }
142769401Seric strncpy(host_record, vp, vsize);
142869401Seric host_record[vsize] = '\0';
142969663Seric if (tTd(38, 44))
143069663Seric printf("got record `%s'\n", host_record);
143169833Seric if (!extract_canonname(nbuf, host_record, cbuf))
143269401Seric {
143369401Seric /* this should not happen, but.... */
143469401Seric *statp = EX_NOHOST;
143569401Seric return FALSE;
143669401Seric }
143769833Seric if (hbsize < strlen(cbuf))
143869401Seric {
143969833Seric *statp = EX_UNAVAILABLE;
144069833Seric return FALSE;
144169703Seric }
144269833Seric strcpy(name, cbuf);
144369833Seric *statp = EX_OK;
144469833Seric return TRUE;
144569401Seric }
144669401Seric
144768350Seric #endif
144868350Seric /*
144968350Seric ** NISPLUS Modules
145068350Seric **
145168350Seric ** This code donated by Sun Microsystems.
145268350Seric */
145367848Seric
145468350Seric #ifdef NISPLUS
145568350Seric
145668350Seric #undef NIS /* symbol conflict in nis.h */
145768350Seric #include <rpcsvc/nis.h>
145868350Seric #include <rpcsvc/nislib.h>
145968350Seric
146068350Seric #define EN_col(col) zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val
146168350Seric #define COL_NAME(res,i) ((res->objects.objects_val)->TA_data.ta_cols.ta_cols_val)[i].tc_name
146268350Seric #define COL_MAX(res) ((res->objects.objects_val)->TA_data.ta_cols.ta_cols_len)
146368350Seric #define PARTIAL_NAME(x) ((x)[strlen(x) - 1] != '.')
146468350Seric
146567848Seric /*
146668350Seric ** NISPLUS_MAP_OPEN -- open nisplus table
146767848Seric */
146867848Seric
146968350Seric bool
nisplus_map_open(map,mode)147068350Seric nisplus_map_open(map, mode)
147167848Seric MAP *map;
147268350Seric int mode;
147367848Seric {
147468350Seric register char *p;
147568350Seric char qbuf[MAXLINE + NIS_MAXNAMELEN];
147668350Seric nis_result *res = NULL;
147768350Seric u_int objs_len;
147868350Seric nis_object *obj_ptr;
147968350Seric int retry_cnt, max_col, i;
148068350Seric
148168350Seric if (tTd(38, 2))
148268350Seric printf("nisplus_map_open(%s, %s, %d)\n",
148368350Seric map->map_mname, map->map_file, mode);
148468350Seric
148568350Seric if (mode != O_RDONLY)
148668350Seric {
148768350Seric errno = ENODEV;
148868350Seric return FALSE;
148968350Seric }
149068350Seric
149168350Seric if (*map->map_file == '\0')
149268350Seric map->map_file = "mail_aliases.org_dir";
149368350Seric
149468350Seric if (PARTIAL_NAME(map->map_file) && map->map_domain == NULL)
149568350Seric {
149668350Seric /* set default NISPLUS Domain to $m */
149768350Seric extern char *nisplus_default_domain();
149868350Seric
149968350Seric map->map_domain = newstr(nisplus_default_domain());
150068350Seric if (tTd(38, 2))
150168350Seric printf("nisplus_map_open(%s): using domain %s\n",
150268350Seric map->map_file, map->map_domain);
150368350Seric }
150468350Seric if (!PARTIAL_NAME(map->map_file))
150568350Seric map->map_domain = newstr("");
150668350Seric
150768350Seric /* check to see if this map actually exists */
150868350Seric if (PARTIAL_NAME(map->map_file))
150968350Seric sprintf(qbuf, "%s.%s", map->map_file, map->map_domain);
151068350Seric else
151168350Seric strcpy(qbuf, map->map_file);
151268350Seric
151368350Seric retry_cnt = 0;
151468350Seric while (res == NULL || res->status != NIS_SUCCESS)
151568350Seric {
151668350Seric res = nis_lookup(qbuf, FOLLOW_LINKS);
151768350Seric switch (res->status)
151868350Seric {
151968350Seric case NIS_SUCCESS:
152068350Seric case NIS_TRYAGAIN:
152168350Seric case NIS_RPCERROR:
152268350Seric case NIS_NAMEUNREACHABLE:
152368350Seric break;
152468350Seric
152568350Seric default: /* all other nisplus errors */
152668350Seric #if 0
152768350Seric if (!bitset(MF_OPTIONAL, map->map_mflags))
152868350Seric syserr("421 Cannot find table %s.%s: %s",
152968350Seric map->map_file, map->map_domain,
153068350Seric nis_sperrno(res->status));
153168350Seric #endif
153268350Seric errno = EBADR;
153368350Seric return FALSE;
153468350Seric }
153568350Seric sleep(2); /* try not to overwhelm hosed server */
153668350Seric if (retry_cnt++ > 4)
153768350Seric {
153868350Seric errno = EBADR;
153968350Seric return FALSE;
154068350Seric }
154168350Seric }
154268350Seric
154368350Seric if (NIS_RES_NUMOBJ(res) != 1 ||
154468350Seric (NIS_RES_OBJECT(res)->zo_data.zo_type != TABLE_OBJ))
154568350Seric {
154668350Seric if (tTd(38, 10))
154768350Seric printf("nisplus_map_open: %s is not a table\n", qbuf);
154868350Seric #if 0
154968350Seric if (!bitset(MF_OPTIONAL, map->map_mflags))
155068350Seric syserr("421 %s.%s: %s is not a table",
155168350Seric map->map_file, map->map_domain,
155268350Seric nis_sperrno(res->status));
155368350Seric #endif
155468350Seric errno = EBADR;
155568350Seric return FALSE;
155668350Seric }
155768350Seric /* default key column is column 0 */
155868350Seric if (map->map_keycolnm == NULL)
155968350Seric map->map_keycolnm = newstr(COL_NAME(res,0));
156068350Seric
156168350Seric max_col = COL_MAX(res);
156268350Seric
156368350Seric /* verify the key column exist */
156468350Seric for (i=0; i< max_col; i++)
156568350Seric {
156668350Seric if (!strcmp(map->map_keycolnm, COL_NAME(res,i)))
156768350Seric break;
156868350Seric }
156968350Seric if (i == max_col)
157068350Seric {
157168350Seric if (tTd(38, 2))
157268350Seric printf("nisplus_map_open(%s): can not find key column %s\n",
157368350Seric map->map_file, map->map_keycolnm);
157468350Seric errno = EBADR;
157568350Seric return FALSE;
157668350Seric }
157768350Seric
157868350Seric /* default value column is the last column */
157968350Seric if (map->map_valcolnm == NULL)
158068350Seric {
158168350Seric map->map_valcolno = max_col - 1;
158268350Seric return TRUE;
158368350Seric }
158468350Seric
158568350Seric for (i=0; i< max_col; i++)
158668350Seric {
158768350Seric if (strcmp(map->map_valcolnm, COL_NAME(res,i)) == 0)
158868350Seric {
158968350Seric map->map_valcolno = i;
159068350Seric return TRUE;
159168350Seric }
159268350Seric }
159368350Seric
159468350Seric if (tTd(38, 2))
159568350Seric printf("nisplus_map_open(%s): can not find column %s\n",
159668350Seric map->map_file, map->map_keycolnm);
159768350Seric errno = EBADR;
159868350Seric return FALSE;
159967848Seric }
160067848Seric
160167848Seric
160267848Seric /*
160368350Seric ** NISPLUS_MAP_LOOKUP -- look up a datum in a NISPLUS table
160467848Seric */
160567848Seric
160668350Seric char *
nisplus_map_lookup(map,name,av,statp)160768350Seric nisplus_map_lookup(map, name, av, statp)
160867848Seric MAP *map;
160968350Seric char *name;
161068350Seric char **av;
161168350Seric int *statp;
161267848Seric {
161368350Seric char *vp;
161468350Seric auto int vsize;
161568350Seric int buflen;
161668350Seric char search_key[MAXNAME + 1];
161768350Seric char qbuf[MAXLINE + NIS_MAXNAMELEN];
161868350Seric nis_result *result;
161968350Seric
162068350Seric if (tTd(38, 20))
162168350Seric printf("nisplus_map_lookup(%s, %s)\n",
162268350Seric map->map_mname, name);
162368350Seric
162468350Seric if (!bitset(MF_OPEN, map->map_mflags))
162568350Seric {
162668350Seric if (nisplus_map_open(map, O_RDONLY))
162768350Seric map->map_mflags |= MF_OPEN;
162868350Seric else
162968350Seric {
163068350Seric *statp = EX_UNAVAILABLE;
163168350Seric return NULL;
163268350Seric }
163368350Seric }
163468350Seric
163568350Seric buflen = strlen(name);
163668350Seric if (buflen > sizeof search_key - 1)
163768350Seric buflen = sizeof search_key - 1;
163868350Seric bcopy(name, search_key, buflen + 1);
163968350Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags))
164068350Seric makelower(search_key);
164168350Seric
164268350Seric /* construct the query */
164368350Seric if (PARTIAL_NAME(map->map_file))
164468350Seric sprintf(qbuf, "[%s=%s],%s.%s", map->map_keycolnm,
164568350Seric search_key, map->map_file, map->map_domain);
164668350Seric else
164768350Seric sprintf(qbuf, "[%s=%s],%s", map->map_keycolnm,
164868350Seric search_key, map->map_file);
164968350Seric
165068350Seric if (tTd(38, 20))
165168350Seric printf("qbuf=%s\n", qbuf);
165268350Seric result = nis_list(qbuf, FOLLOW_LINKS | FOLLOW_PATH, NULL, NULL);
165368350Seric if (result->status == NIS_SUCCESS)
165468350Seric {
165568350Seric int count;
165668350Seric char *str;
165768350Seric
165868350Seric if ((count = NIS_RES_NUMOBJ(result)) != 1)
165968350Seric {
166068350Seric if (LogLevel > 10)
166168350Seric syslog(LOG_WARNING,
166268350Seric "%s:Lookup error, expected 1 entry, got (%d)",
166368350Seric map->map_file, count);
166468350Seric
166568350Seric /* ignore second entry */
166668350Seric if (tTd(38, 20))
166768350Seric printf("nisplus_map_lookup(%s), got %d entries, additional entries ignored\n",
166868350Seric name, count);
166968350Seric }
167068350Seric
167168350Seric vp = ((NIS_RES_OBJECT(result))->EN_col(map->map_valcolno));
167268350Seric /* set the length of the result */
167368350Seric if (vp == NULL)
167468350Seric vp = "";
167568350Seric vsize = strlen(vp);
167668350Seric if (tTd(38, 20))
167768350Seric printf("nisplus_map_lookup(%s), found %s\n",
167868350Seric name, vp);
167968350Seric if (bitset(MF_MATCHONLY, map->map_mflags))
168068350Seric str = map_rewrite(map, name, strlen(name), NULL);
168168350Seric else
168268350Seric str = map_rewrite(map, vp, vsize, av);
168368350Seric nis_freeresult(result);
168468350Seric #ifdef MAP_EXIT_STAT
168568350Seric *statp = EX_OK;
168668350Seric #endif
168768350Seric return str;
168868350Seric }
168968350Seric else
169068350Seric {
169168350Seric #ifdef MAP_EXIT_STAT
169268350Seric if (result->status == NIS_NOTFOUND)
169368350Seric *statp = EX_NOTFOUND;
169468350Seric else if (result->status == NIS_TRYAGAIN)
169568350Seric *statp = EX_TEMPFAIL;
169668350Seric else
169768350Seric {
169868350Seric *statp = EX_UNAVAILABLE;
169968350Seric map->map_mflags &= ~(MF_VALID|MF_OPEN);
170068350Seric }
170168350Seric #else
170268350Seric if ((result->status != NIS_NOTFOUND) &&
170368350Seric (result->status != NIS_TRYAGAIN))
170468350Seric map->map_mflags &= ~(MF_VALID|MF_OPEN);
170568350Seric #endif
170668350Seric }
170768350Seric if (tTd(38, 20))
170868350Seric printf("nisplus_map_lookup(%s), failed\n", name);
170968350Seric nis_freeresult(result);
171068350Seric return NULL;
171167848Seric }
171267848Seric
171368350Seric
171469401Seric
171569401Seric /*
171669401Seric ** NISPLUS_GETCANONNAME -- look up canonical name in NIS+
171769401Seric */
171869401Seric
171969401Seric bool
nisplus_getcanonname(name,hbsize,statp)172069401Seric nisplus_getcanonname(name, hbsize, statp)
172169401Seric char *name;
172269401Seric int hbsize;
172369401Seric int *statp;
172469401Seric {
172569401Seric char *vp;
172669401Seric auto int vsize;
172769401Seric int buflen;
172869401Seric nis_result *result;
172969401Seric char *p;
173069401Seric int len;
173169780Seric char nbuf[MAXNAME + 1];
173269780Seric char qbuf[MAXLINE + NIS_MAXNAMELEN];
173369401Seric
173469780Seric if (strlen(name) >= sizeof nbuf)
173569780Seric {
173669780Seric *statp = EX_UNAVAILABLE;
173769780Seric return FALSE;
173869780Seric }
173969780Seric (void) strcpy(nbuf, name);
174069780Seric shorten_hostname(nbuf);
174169401Seric
174269780Seric p = strchr(nbuf, '.');
174369401Seric if (p == NULL)
174469401Seric {
174569401Seric /* single token */
174669780Seric sprintf(qbuf, "[name=%s],hosts.org_dir", nbuf);
174769401Seric }
174869401Seric else if (p[1] != '\0')
174969401Seric {
175069780Seric /* multi token -- take only first token in nbuf */
175169401Seric *p = '\0';
175269780Seric sprintf(qbuf, "[name=%s],hosts.org_dir.%s", nbuf, &p[1]);
175369401Seric }
175469401Seric else
175569401Seric {
175669401Seric *statp = EX_NOHOST;
175769401Seric return FALSE;
175869401Seric }
175969401Seric
176069401Seric if (tTd(38, 20))
176169478Seric printf("\nnisplus_getcanoname(%s), qbuf=%s\n",
176269780Seric name, qbuf);
176369401Seric
176469780Seric result = nis_list(qbuf, EXPAND_NAME|FOLLOW_LINKS|FOLLOW_PATH,
176569401Seric NULL, NULL);
176669401Seric
176769401Seric if (result->status == NIS_SUCCESS)
176869401Seric {
176969401Seric int count;
177069401Seric char *str;
177169401Seric char *domain;
177269401Seric
177369401Seric if ((count = NIS_RES_NUMOBJ(result)) != 1)
177469401Seric {
177569401Seric #ifdef LOG
177669401Seric if (LogLevel > 10)
177769401Seric syslog(LOG_WARNING,
177869401Seric "nisplus_getcanonname: Lookup error, expected 1 entry, got (%d)",
177969401Seric count);
178069401Seric #endif
178169401Seric
178269401Seric /* ignore second entry */
178369401Seric if (tTd(38, 20))
178469401Seric printf("nisplus_getcanoname(%s), got %d entries, addtional entries ignores\n", name);
178569401Seric }
178669401Seric
178769401Seric if (tTd(38, 20))
178869401Seric printf("nisplus_getcanoname(%s), found in directory \"%s\"\n",
178969401Seric name, (NIS_RES_OBJECT(result))->zo_domain);
179069401Seric
179169401Seric
179269401Seric vp = ((NIS_RES_OBJECT(result))->EN_col(0));
179369401Seric vsize = strlen(vp);
179469401Seric if (tTd(38, 20))
179569401Seric printf("nisplus_getcanonname(%s), found %s\n",
179669401Seric name, vp);
179769703Seric if (strchr(vp, '.') != NULL)
179869703Seric {
179969636Seric domain = "";
180069703Seric }
180169703Seric else
180269703Seric {
180369703Seric domain = macvalue('m', CurEnv);
180469703Seric if (domain == NULL)
180569703Seric domain = "";
180669703Seric }
180769636Seric if (hbsize > vsize + (int) strlen(domain) + 1)
180869401Seric {
180969636Seric if (domain[0] == '\0')
181069636Seric strcpy(name, vp);
181169636Seric else
181269636Seric sprintf(name, "%s.%s", vp, domain);
181369401Seric *statp = EX_OK;
181469401Seric }
181569401Seric else
181669401Seric *statp = EX_NOHOST;
181769401Seric nis_freeresult(result);
181869401Seric return TRUE;
181969401Seric }
182069401Seric else
182169401Seric {
182269401Seric if (result->status == NIS_NOTFOUND)
182369401Seric *statp = EX_NOHOST;
182469401Seric else if (result->status == NIS_TRYAGAIN)
182569401Seric *statp = EX_TEMPFAIL;
182669401Seric else
182769401Seric *statp = EX_UNAVAILABLE;
182869401Seric }
182969401Seric if (tTd(38, 20))
183069401Seric printf("nisplus_getcanonname(%s), failed, status=%d, nsw_stat=%d\n",
183169401Seric name, result->status, *statp);
183269401Seric nis_freeresult(result);
183369401Seric return FALSE;
183469401Seric }
183569401Seric
183669401Seric
183768350Seric char *
nisplus_default_domain()183868350Seric nisplus_default_domain()
183968350Seric {
184068528Seric static char default_domain[MAXNAME + 1] = "";
184168350Seric char *p;
184268350Seric
184368350Seric if (default_domain[0] != '\0')
184468350Seric return(default_domain);
184568350Seric
184668458Seric p = nis_local_directory();
184768350Seric strcpy(default_domain, p);
184868458Seric return default_domain;
184968350Seric }
185068350Seric
185168350Seric #endif /* NISPLUS */
185267848Seric /*
185368350Seric ** HESIOD Modules
185468350Seric */
185568350Seric
185668350Seric #ifdef HESIOD
185768350Seric
185868350Seric #include <hesiod.h>
185968350Seric
186068350Seric char *
hes_map_lookup(map,name,av,statp)186168350Seric hes_map_lookup(map, name, av, statp)
186268350Seric MAP *map;
186368350Seric char *name;
186468350Seric char **av;
186568350Seric int *statp;
186668350Seric {
186768350Seric char **hp;
186868350Seric
186968350Seric if (tTd(38, 20))
187068350Seric printf("hes_map_lookup(%s, %s)\n", map->map_file, name);
187168350Seric
187269688Seric if (name[0] == '\\')
187369688Seric {
187469688Seric char *np;
187569688Seric int nl;
187669688Seric char nbuf[MAXNAME];
187769688Seric
187869688Seric nl = strlen(name);
187969688Seric if (nl < sizeof nbuf - 1)
188069688Seric np = nbuf;
188169688Seric else
188269688Seric np = xalloc(strlen(name) + 2);
188369688Seric np[0] = '\\';
188469688Seric strcpy(&np[1], name);
188569688Seric hp = hes_resolve(np, map->map_file);
188669688Seric if (np != nbuf)
188769688Seric free(np);
188869688Seric }
188969688Seric else
189069688Seric {
189169688Seric hp = hes_resolve(name, map->map_file);
189269688Seric }
189369623Seric if (hp == NULL || hp[0] == NULL)
189468350Seric return NULL;
189568350Seric
189669623Seric if (bitset(MF_MATCHONLY, map->map_mflags))
189769623Seric return map_rewrite(map, name, strlen(name), NULL);
189869623Seric else
189969623Seric return map_rewrite(map, hp[0], strlen(hp[0]), av);
190068350Seric }
190168350Seric
190268350Seric #endif
190368350Seric /*
190468350Seric ** NeXT NETINFO Modules
190568350Seric */
190668350Seric
190769881Seric #if NETINFO
190868350Seric
190968350Seric #define NETINFO_DEFAULT_DIR "/aliases"
191068350Seric #define NETINFO_DEFAULT_PROPERTY "members"
191168350Seric
191268350Seric
191368350Seric /*
191468350Seric ** NI_MAP_OPEN -- open NetInfo Aliases
191568350Seric */
191668350Seric
191768350Seric bool
ni_map_open(map,mode)191868350Seric ni_map_open(map, mode)
191968350Seric MAP *map;
192068350Seric int mode;
192168350Seric {
192268350Seric char *p;
192368350Seric
192468350Seric if (tTd(38, 20))
192568350Seric printf("ni_map_open: %s\n", map->map_file);
192668350Seric
192768350Seric if (*map->map_file == '\0')
192868350Seric map->map_file = NETINFO_DEFAULT_DIR;
192968350Seric
193068350Seric if (map->map_valcolnm == NULL)
193168350Seric map->map_valcolnm = NETINFO_DEFAULT_PROPERTY;
193268350Seric
193368350Seric if (map->map_coldelim == '\0' && bitset(MF_ALIAS, map->map_mflags))
193468350Seric map->map_coldelim = ',';
193568350Seric
193668350Seric return TRUE;
193768350Seric }
193868350Seric
193968350Seric
194068350Seric /*
194168350Seric ** NI_MAP_LOOKUP -- look up a datum in NetInfo
194268350Seric */
194368350Seric
194468350Seric char *
ni_map_lookup(map,name,av,statp)194568350Seric ni_map_lookup(map, name, av, statp)
194668350Seric MAP *map;
194768350Seric char *name;
194868350Seric char **av;
194968350Seric int *statp;
195068350Seric {
195168350Seric char *res;
195268350Seric char *propval;
195368350Seric extern char *ni_propval();
195468350Seric
195568350Seric if (tTd(38, 20))
195668350Seric printf("ni_map_lookup(%s, %s)\n",
195768350Seric map->map_mname, name);
195868350Seric
195968350Seric propval = ni_propval(map->map_file, map->map_keycolnm, name,
196068350Seric map->map_valcolnm, map->map_coldelim);
196168350Seric
196268350Seric if (propval == NULL)
196368350Seric return NULL;
196468350Seric
196568350Seric if (bitset(MF_MATCHONLY, map->map_mflags))
196668350Seric res = map_rewrite(map, name, strlen(name), NULL);
196768350Seric else
196868350Seric res = map_rewrite(map, propval, strlen(propval), av);
196968350Seric free(propval);
197068350Seric return res;
197168350Seric }
197268350Seric
197368350Seric #endif
197468350Seric /*
197568350Seric ** TEXT (unindexed text file) Modules
197668350Seric **
197768350Seric ** This code donated by Sun Microsystems.
197868350Seric */
197968350Seric
198068350Seric
198168350Seric /*
198268350Seric ** TEXT_MAP_OPEN -- open text table
198368350Seric */
198468350Seric
198568350Seric bool
text_map_open(map,mode)198668350Seric text_map_open(map, mode)
198768350Seric MAP *map;
198868350Seric int mode;
198968350Seric {
199068350Seric struct stat sbuf;
199168350Seric
199268350Seric if (tTd(38, 2))
199368350Seric printf("text_map_open(%s, %s, %d)\n",
199468350Seric map->map_mname, map->map_file, mode);
199568350Seric
199668350Seric if (mode != O_RDONLY)
199768350Seric {
199868350Seric errno = ENODEV;
199968350Seric return FALSE;
200068350Seric }
200168350Seric
200268350Seric if (*map->map_file == '\0')
200368350Seric {
200468350Seric if (tTd(38, 2))
200568350Seric printf("text_map_open: file name required\n");
200668350Seric return FALSE;
200768350Seric }
200868350Seric
200968350Seric if (map->map_file[0] != '/')
201068350Seric {
201168350Seric if (tTd(38, 2))
201268350Seric printf("text_map_open(%s): file name must be fully qualified\n",
201368350Seric map->map_file);
201468350Seric return FALSE;
201568350Seric }
201668350Seric /* check to see if this map actually accessable */
201768350Seric if (access(map->map_file, R_OK) <0)
201868350Seric return FALSE;
201968350Seric
202068350Seric /* check to see if this map actually exist */
202168350Seric if (stat(map->map_file, &sbuf) <0)
202268350Seric {
202368350Seric if (tTd(38, 2))
202468350Seric printf("text_map_open(%s): can not stat %s\n",
202568350Seric map->map_file, map->map_file);
202668350Seric return FALSE;
202768350Seric }
202868350Seric
202968350Seric if (!S_ISREG(sbuf.st_mode))
203068350Seric {
203168350Seric if (tTd(38, 2))
203268350Seric printf("text_map_open(%s): %s is not a file\n",
203368350Seric map->map_file, map->map_file);
203468350Seric return FALSE;
203568350Seric }
203668350Seric
203768350Seric if (map->map_keycolnm == NULL)
203868350Seric map->map_keycolno = 0;
203968350Seric else
204068350Seric {
204168350Seric if (!isdigit(*map->map_keycolnm))
204268350Seric {
204368350Seric if (tTd(38, 2))
204468350Seric printf("text_map_open(%s): -k should specify a number, not %s\n",
204568350Seric map->map_file, map->map_keycolnm);
204668350Seric return FALSE;
204768350Seric }
204868350Seric map->map_keycolno = atoi(map->map_keycolnm);
204968350Seric }
205068350Seric
205168350Seric if (map->map_valcolnm == NULL)
205268350Seric map->map_valcolno = 0;
205368350Seric else
205468350Seric {
205568350Seric if (!isdigit(*map->map_valcolnm))
205668350Seric {
205768350Seric if (tTd(38, 2))
205868350Seric printf("text_map_open(%s): -v should specify a number, not %s\n",
205968350Seric map->map_file, map->map_valcolnm);
206068350Seric return FALSE;
206168350Seric }
206268350Seric map->map_valcolno = atoi(map->map_valcolnm);
206368350Seric }
206468350Seric
206568350Seric if (tTd(38, 2))
206668350Seric {
206768520Seric printf("text_map_open(%s): delimiter = ",
206868520Seric map->map_file);
206968520Seric if (map->map_coldelim == '\0')
207068520Seric printf("(white space)\n");
207168520Seric else
207268520Seric printf("%c\n", map->map_coldelim);
207368350Seric }
207468350Seric
207568350Seric return TRUE;
207668350Seric }
207768350Seric
207868350Seric
207968350Seric /*
208068350Seric ** TEXT_MAP_LOOKUP -- look up a datum in a TEXT table
208168350Seric */
208268350Seric
208368350Seric char *
text_map_lookup(map,name,av,statp)208468350Seric text_map_lookup(map, name, av, statp)
208568350Seric MAP *map;
208668350Seric char *name;
208768350Seric char **av;
208868350Seric int *statp;
208968350Seric {
209068350Seric char *vp;
209168350Seric auto int vsize;
209268350Seric int buflen;
209368350Seric char search_key[MAXNAME + 1];
209468350Seric char linebuf[MAXLINE];
209568350Seric FILE *f;
209668528Seric char buf[MAXNAME + 1];
209768350Seric char delim;
209868350Seric int key_idx;
209968350Seric bool found_it;
210068350Seric extern char *get_column();
210168350Seric
210268350Seric
210368350Seric found_it = FALSE;
210468350Seric if (tTd(38, 20))
210568350Seric printf("text_map_lookup(%s)\n", name);
210668350Seric
210768350Seric buflen = strlen(name);
210868350Seric if (buflen > sizeof search_key - 1)
210968350Seric buflen = sizeof search_key - 1;
211068350Seric bcopy(name, search_key, buflen + 1);
211168350Seric if (!bitset(MF_NOFOLDCASE, map->map_mflags))
211268350Seric makelower(search_key);
211368350Seric
211468350Seric f = fopen(map->map_file, "r");
211568350Seric if (f == NULL)
211668350Seric {
211768350Seric map->map_mflags &= ~(MF_VALID|MF_OPEN);
211868350Seric *statp = EX_UNAVAILABLE;
211968350Seric return NULL;
212068350Seric }
212168350Seric key_idx = map->map_keycolno;
212268350Seric delim = map->map_coldelim;
212368350Seric while (fgets(linebuf, MAXLINE, f))
212468350Seric {
212568350Seric char *lf;
212668350Seric if (linebuf[0] == '#')
212768350Seric continue; /* skip comment line */
212868350Seric if (lf = strchr(linebuf, '\n'))
212968350Seric *lf = '\0';
213068350Seric if (!strcasecmp(search_key,
213168350Seric get_column(linebuf, key_idx, delim, buf)))
213268350Seric {
213368350Seric found_it = TRUE;
213468350Seric break;
213568350Seric }
213668350Seric }
213768350Seric fclose(f);
213868350Seric if (!found_it)
213968350Seric {
214068350Seric #ifdef MAP_EXIT_STAT
214168350Seric *statp = EX_NOTFOUND;
214268350Seric #endif
214368350Seric return(NULL);
214468350Seric }
214568350Seric vp = get_column(linebuf, map->map_valcolno, delim, buf);
214668350Seric vsize = strlen(vp);
214768350Seric #ifdef MAP_EXIT_STAT
214868350Seric *statp = EX_OK;
214968350Seric #endif
215068350Seric if (bitset(MF_MATCHONLY, map->map_mflags))
215168350Seric return map_rewrite(map, name, strlen(name), NULL);
215268350Seric else
215368350Seric return map_rewrite(map, vp, vsize, av);
215468350Seric }
215569401Seric
215669401Seric
215769401Seric /*
215869401Seric ** TEXT_GETCANONNAME -- look up canonical name in hosts file
215969401Seric */
216069401Seric
216169401Seric bool
text_getcanonname(name,hbsize,statp)216269401Seric text_getcanonname(name, hbsize, statp)
216369401Seric char *name;
216469401Seric int hbsize;
216569401Seric int *statp;
216669401Seric {
216769401Seric int key_idx;
216869401Seric bool found;
216969401Seric FILE *f;
217069401Seric char linebuf[MAXLINE];
217169401Seric char cbuf[MAXNAME + 1];
217269780Seric char fbuf[MAXNAME + 1];
217369780Seric char nbuf[MAXNAME + 1];
217469401Seric extern char *get_column();
217569401Seric
217669780Seric if (strlen(name) >= sizeof nbuf)
217769780Seric {
217869780Seric *statp = EX_UNAVAILABLE;
217969780Seric return FALSE;
218069780Seric }
218169780Seric (void) strcpy(nbuf, name);
218269780Seric shorten_hostname(nbuf);
218369401Seric
218469401Seric /* we only accept single token search key */
218569780Seric if (strchr(nbuf, '.') != NULL)
218669401Seric {
218769401Seric *statp = EX_NOHOST;
218869401Seric return FALSE;
218969401Seric }
219069401Seric
219169401Seric found = FALSE;
219269401Seric
219369401Seric f = fopen(HostsFile, "r");
219469401Seric if (f == NULL)
219569401Seric {
219669401Seric #ifdef MAP_EXIT_STAT
219769401Seric *statp = EX_UNAVAILABLE;
219869401Seric #endif
219969401Seric return FALSE;
220069401Seric }
220169401Seric while (!found && fgets(linebuf, MAXLINE, f) != NULL)
220269401Seric {
220369401Seric char *p;
220469401Seric
220569401Seric if (linebuf[0] == '#')
220669401Seric continue;
220769401Seric if ((p = strchr(linebuf, '\n')) != NULL)
220869401Seric *p = '\0';
220969833Seric found = extract_canonname(nbuf, linebuf, cbuf);
221069401Seric }
221169401Seric fclose(f);
221269401Seric if (!found)
221369401Seric {
221469401Seric *statp = EX_NOHOST;
221569401Seric return FALSE;
221669401Seric }
221769401Seric
221869833Seric if (hbsize >= strlen(cbuf))
221969401Seric {
222069833Seric strcpy(name, cbuf);
222169401Seric *statp = EX_OK;
222269401Seric return TRUE;
222369401Seric }
222469401Seric *statp = EX_UNAVAILABLE;
222569401Seric return FALSE;
222669401Seric }
222768350Seric /*
222860089Seric ** STAB (Symbol Table) Modules
222960089Seric */
223060089Seric
223160089Seric
223260089Seric /*
223360207Seric ** STAB_MAP_LOOKUP -- look up alias in symbol table
223460089Seric */
223560089Seric
223660089Seric char *
stab_map_lookup(map,name,av,pstat)223761707Seric stab_map_lookup(map, name, av, pstat)
223860089Seric register MAP *map;
223960089Seric char *name;
224061707Seric char **av;
224161707Seric int *pstat;
224260089Seric {
224360089Seric register STAB *s;
224460089Seric
224560537Seric if (tTd(38, 20))
224668350Seric printf("stab_lookup(%s, %s)\n",
224768350Seric map->map_mname, name);
224860089Seric
224960089Seric s = stab(name, ST_ALIAS, ST_FIND);
225060089Seric if (s != NULL)
225160089Seric return (s->s_alias);
225260089Seric return (NULL);
225360089Seric }
225460089Seric
225560089Seric
225660089Seric /*
225760207Seric ** STAB_MAP_STORE -- store in symtab (actually using during init, not rebuild)
225860089Seric */
225960089Seric
226060089Seric void
stab_map_store(map,lhs,rhs)226160089Seric stab_map_store(map, lhs, rhs)
226260089Seric register MAP *map;
226360089Seric char *lhs;
226460089Seric char *rhs;
226560089Seric {
226660089Seric register STAB *s;
226760089Seric
226860089Seric s = stab(lhs, ST_ALIAS, ST_ENTER);
226960089Seric s->s_alias = newstr(rhs);
227060089Seric }
227160089Seric
227260089Seric
227360089Seric /*
227460207Seric ** STAB_MAP_OPEN -- initialize (reads data file)
227560207Seric **
227660207Seric ** This is a wierd case -- it is only intended as a fallback for
227760207Seric ** aliases. For this reason, opens for write (only during a
227860207Seric ** "newaliases") always fails, and opens for read open the
227960207Seric ** actual underlying text file instead of the database.
228060089Seric */
228160089Seric
228260089Seric bool
stab_map_open(map,mode)228360089Seric stab_map_open(map, mode)
228460089Seric register MAP *map;
228560089Seric int mode;
228660089Seric {
228763835Seric FILE *af;
228864284Seric struct stat st;
228963835Seric
229060537Seric if (tTd(38, 2))
229168350Seric printf("stab_map_open(%s, %s)\n",
229268350Seric map->map_mname, map->map_file);
229360089Seric
229460089Seric if (mode != O_RDONLY)
229560207Seric {
229660207Seric errno = ENODEV;
229760089Seric return FALSE;
229860207Seric }
229960089Seric
230063835Seric af = fopen(map->map_file, "r");
230163835Seric if (af == NULL)
230263835Seric return FALSE;
230368350Seric readaliases(map, af, FALSE, FALSE);
230464284Seric
230564284Seric if (fstat(fileno(af), &st) >= 0)
230664284Seric map->map_mtime = st.st_mtime;
230763835Seric fclose(af);
230863835Seric
230960089Seric return TRUE;
231060089Seric }
231160089Seric /*
231260089Seric ** Implicit Modules
231356822Seric **
231460089Seric ** Tries several types. For back compatibility of aliases.
231556822Seric */
231656822Seric
231760089Seric
231860089Seric /*
231960207Seric ** IMPL_MAP_LOOKUP -- lookup in best open database
232060089Seric */
232160089Seric
232260089Seric char *
impl_map_lookup(map,name,av,pstat)232360089Seric impl_map_lookup(map, name, av, pstat)
232460089Seric MAP *map;
232560089Seric char *name;
232656822Seric char **av;
232760089Seric int *pstat;
232856822Seric {
232960537Seric if (tTd(38, 20))
233068350Seric printf("impl_map_lookup(%s, %s)\n",
233168350Seric map->map_mname, name);
233256822Seric
233360089Seric #ifdef NEWDB
233460207Seric if (bitset(MF_IMPL_HASH, map->map_mflags))
233560089Seric return db_map_lookup(map, name, av, pstat);
233660089Seric #endif
233760089Seric #ifdef NDBM
233860207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags))
233960089Seric return ndbm_map_lookup(map, name, av, pstat);
234060089Seric #endif
234160089Seric return stab_map_lookup(map, name, av, pstat);
234260089Seric }
234360089Seric
234460089Seric /*
234560207Seric ** IMPL_MAP_STORE -- store in open databases
234660089Seric */
234760089Seric
234860089Seric void
impl_map_store(map,lhs,rhs)234960089Seric impl_map_store(map, lhs, rhs)
235060089Seric MAP *map;
235160089Seric char *lhs;
235260089Seric char *rhs;
235360089Seric {
235460089Seric #ifdef NEWDB
235560207Seric if (bitset(MF_IMPL_HASH, map->map_mflags))
235660089Seric db_map_store(map, lhs, rhs);
235760089Seric #endif
235860089Seric #ifdef NDBM
235960207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags))
236060089Seric ndbm_map_store(map, lhs, rhs);
236160089Seric #endif
236260089Seric stab_map_store(map, lhs, rhs);
236360089Seric }
236460089Seric
236560089Seric /*
236660089Seric ** IMPL_MAP_OPEN -- implicit database open
236760089Seric */
236860089Seric
236960089Seric bool
impl_map_open(map,mode)237060089Seric impl_map_open(map, mode)
237160089Seric MAP *map;
237260089Seric int mode;
237360089Seric {
237460089Seric struct stat stb;
237560089Seric
237660537Seric if (tTd(38, 2))
237768350Seric printf("impl_map_open(%s, %s, %d)\n",
237868350Seric map->map_mname, map->map_file, mode);
237960089Seric
238060089Seric if (stat(map->map_file, &stb) < 0)
238156822Seric {
238260089Seric /* no alias file at all */
238364718Seric if (tTd(38, 3))
238464718Seric printf("no map file\n");
238560089Seric return FALSE;
238656822Seric }
238756822Seric
238860089Seric #ifdef NEWDB
238960207Seric map->map_mflags |= MF_IMPL_HASH;
239060089Seric if (hash_map_open(map, mode))
239156822Seric {
239264250Seric #if defined(NDBM) && defined(NIS)
239369651Seric if (mode == O_RDONLY || strstr(map->map_file, "/yp/") == NULL)
239460207Seric #endif
239560207Seric return TRUE;
239660089Seric }
239760207Seric else
239860207Seric map->map_mflags &= ~MF_IMPL_HASH;
239960089Seric #endif
240060089Seric #ifdef NDBM
240160207Seric map->map_mflags |= MF_IMPL_NDBM;
240260089Seric if (ndbm_map_open(map, mode))
240360089Seric {
240460089Seric return TRUE;
240560089Seric }
240660207Seric else
240760207Seric map->map_mflags &= ~MF_IMPL_NDBM;
240860089Seric #endif
240956822Seric
241064650Seric #if defined(NEWDB) || defined(NDBM)
241160089Seric if (Verbose)
241260089Seric message("WARNING: cannot open alias database %s", map->map_file);
241364964Seric #else
241464964Seric if (mode != O_RDONLY)
241564964Seric usrerr("Cannot rebuild aliases: no database format defined");
241660207Seric #endif
241760089Seric
241860207Seric return stab_map_open(map, mode);
241956822Seric }
242060089Seric
242160207Seric
242260089Seric /*
242360207Seric ** IMPL_MAP_CLOSE -- close any open database(s)
242460089Seric */
242560089Seric
242660089Seric void
impl_map_close(map)242760207Seric impl_map_close(map)
242860089Seric MAP *map;
242960089Seric {
243068350Seric if (tTd(38, 20))
243168350Seric printf("impl_map_close(%s, %s, %x)\n",
243268350Seric map->map_mname, map->map_file, map->map_mflags);
243360089Seric #ifdef NEWDB
243460207Seric if (bitset(MF_IMPL_HASH, map->map_mflags))
243560089Seric {
243660207Seric db_map_close(map);
243760207Seric map->map_mflags &= ~MF_IMPL_HASH;
243860089Seric }
243960089Seric #endif
244060089Seric
244160089Seric #ifdef NDBM
244260207Seric if (bitset(MF_IMPL_NDBM, map->map_mflags))
244360089Seric {
244460207Seric ndbm_map_close(map);
244560207Seric map->map_mflags &= ~MF_IMPL_NDBM;
244660089Seric }
244760089Seric #endif
244860089Seric }
244960207Seric /*
245068350Seric ** User map class.
245168350Seric **
245268350Seric ** Provides access to the system password file.
245368350Seric */
245468350Seric
245568350Seric /*
245668350Seric ** USER_MAP_OPEN -- open user map
245768350Seric **
245868350Seric ** Really just binds field names to field numbers.
245968350Seric */
246068350Seric
246168350Seric bool
user_map_open(map,mode)246268350Seric user_map_open(map, mode)
246368350Seric MAP *map;
246468350Seric int mode;
246568350Seric {
246668350Seric if (tTd(38, 2))
246768350Seric printf("user_map_open(%s)\n", map->map_mname);
246868350Seric
246968350Seric if (mode != O_RDONLY)
247068350Seric {
247168350Seric /* issue a pseudo-error message */
247268350Seric #ifdef ENOSYS
247368350Seric errno = ENOSYS;
247468350Seric #else
247568350Seric # ifdef EFTYPE
247668350Seric errno = EFTYPE;
247768350Seric # else
247868350Seric errno = ENXIO;
247968350Seric # endif
248068350Seric #endif
248168350Seric return FALSE;
248268350Seric }
248368350Seric if (map->map_valcolnm == NULL)
248468350Seric /* nothing */ ;
248568350Seric else if (strcasecmp(map->map_valcolnm, "name") == 0)
248668350Seric map->map_valcolno = 1;
248768350Seric else if (strcasecmp(map->map_valcolnm, "passwd") == 0)
248868350Seric map->map_valcolno = 2;
248968350Seric else if (strcasecmp(map->map_valcolnm, "uid") == 0)
249068350Seric map->map_valcolno = 3;
249168350Seric else if (strcasecmp(map->map_valcolnm, "gid") == 0)
249268350Seric map->map_valcolno = 4;
249368350Seric else if (strcasecmp(map->map_valcolnm, "gecos") == 0)
249468350Seric map->map_valcolno = 5;
249568350Seric else if (strcasecmp(map->map_valcolnm, "dir") == 0)
249668350Seric map->map_valcolno = 6;
249768350Seric else if (strcasecmp(map->map_valcolnm, "shell") == 0)
249868350Seric map->map_valcolno = 7;
249968350Seric else
250068350Seric {
250168350Seric syserr("User map %s: unknown column name %s",
250268350Seric map->map_mname, map->map_valcolnm);
250368350Seric return FALSE;
250468350Seric }
250568350Seric return TRUE;
250668350Seric }
250768350Seric
250868350Seric
250968350Seric /*
251068350Seric ** USER_MAP_LOOKUP -- look up a user in the passwd file.
251168350Seric */
251268350Seric
251368350Seric char *
user_map_lookup(map,key,av,statp)251468350Seric user_map_lookup(map, key, av, statp)
251568350Seric MAP *map;
251668350Seric char *key;
251768350Seric char **av;
251868350Seric int *statp;
251968350Seric {
252068350Seric struct passwd *pw;
252168350Seric
252268350Seric if (tTd(38, 20))
252368350Seric printf("user_map_lookup(%s, %s)\n",
252468350Seric map->map_mname, key);
252568350Seric
252668693Seric pw = sm_getpwnam(key);
252768350Seric if (pw == NULL)
252868350Seric return NULL;
252968350Seric if (bitset(MF_MATCHONLY, map->map_mflags))
253068350Seric return map_rewrite(map, key, strlen(key), NULL);
253168350Seric else
253268350Seric {
253368433Seric char *rwval = NULL;
253468350Seric char buf[30];
253568350Seric
253668350Seric switch (map->map_valcolno)
253768350Seric {
253868350Seric case 0:
253968350Seric case 1:
254068350Seric rwval = pw->pw_name;
254168350Seric break;
254268350Seric
254368350Seric case 2:
254468350Seric rwval = pw->pw_passwd;
254568350Seric break;
254668350Seric
254768350Seric case 3:
254868350Seric sprintf(buf, "%d", pw->pw_uid);
254968350Seric rwval = buf;
255068350Seric break;
255168350Seric
255268350Seric case 4:
255368350Seric sprintf(buf, "%d", pw->pw_gid);
255468350Seric rwval = buf;
255568350Seric break;
255668350Seric
255768350Seric case 5:
255868350Seric rwval = pw->pw_gecos;
255968350Seric break;
256068350Seric
256168350Seric case 6:
256268350Seric rwval = pw->pw_dir;
256368350Seric break;
256468350Seric
256568350Seric case 7:
256668350Seric rwval = pw->pw_shell;
256768350Seric break;
256868350Seric }
256968350Seric return map_rewrite(map, rwval, strlen(rwval), av);
257068350Seric }
257168350Seric }
257268350Seric /*
257369453Seric ** Program map type.
257469453Seric **
257569453Seric ** This provides access to arbitrary programs. It should be used
257669453Seric ** only very sparingly, since there is no way to bound the cost
257769453Seric ** of invoking an arbitrary program.
257869453Seric */
257969453Seric
258069453Seric char *
prog_map_lookup(map,name,av,statp)258169453Seric prog_map_lookup(map, name, av, statp)
258269453Seric MAP *map;
258369453Seric char *name;
258469453Seric char **av;
258569453Seric int *statp;
258669453Seric {
258769453Seric int i;
258869453Seric register char *p;
258969453Seric int fd;
259069453Seric auto pid_t pid;
259169827Seric char *rval;
259269827Seric int stat;
259369453Seric char *argv[MAXPV + 1];
259469453Seric char buf[MAXLINE];
259569453Seric
259669453Seric if (tTd(38, 20))
259769453Seric printf("prog_map_lookup(%s, %s) %s\n",
259869453Seric map->map_mname, name, map->map_file);
259969453Seric
260069453Seric i = 0;
260169453Seric argv[i++] = map->map_file;
260269453Seric strcpy(buf, map->map_rebuild);
260369453Seric for (p = strtok(buf, " \t"); p != NULL; p = strtok(NULL, " \t"))
260469453Seric {
260569453Seric if (i >= MAXPV - 1)
260669453Seric break;
260769453Seric argv[i++] = p;
260869453Seric }
260969453Seric argv[i++] = name;
261069453Seric argv[i] = NULL;
261169453Seric pid = prog_open(argv, &fd, CurEnv);
261269453Seric if (pid < 0)
261369453Seric {
261469827Seric if (!bitset(MF_OPTIONAL, map->map_mflags))
261569827Seric syserr("prog_map_lookup(%s) failed (%s) -- closing",
261669827Seric map->map_mname, errstring(errno));
261769827Seric else if (tTd(38, 9))
261869453Seric printf("prog_map_lookup(%s) failed (%s) -- closing",
261969453Seric map->map_mname, errstring(errno));
262069453Seric map->map_mflags &= ~(MF_VALID|MF_OPEN);
262169827Seric *statp = EX_OSFILE;
262269453Seric return NULL;
262369453Seric }
262469453Seric i = read(fd, buf, sizeof buf - 1);
262569827Seric if (i < 0)
262669827Seric {
262769827Seric syserr("prog_map_lookup(%s): read error %s\n",
262869562Seric map->map_mname, errstring(errno));
262969827Seric rval = NULL;
263069827Seric }
263169827Seric else if (i == 0 && tTd(38, 2))
263269827Seric {
263369827Seric printf("prog_map_lookup(%s): empty answer\n",
263469827Seric map->map_mname);
263569827Seric rval = NULL;
263669827Seric }
263769453Seric if (i > 0)
263869453Seric {
263969453Seric buf[i] = '\0';
264069453Seric p = strchr(buf, '\n');
264169453Seric if (p != NULL)
264269453Seric *p = '\0';
264369453Seric
264469453Seric /* collect the return value */
264569453Seric if (bitset(MF_MATCHONLY, map->map_mflags))
264669453Seric rval = map_rewrite(map, name, strlen(name), NULL);
264769453Seric else
264869453Seric rval = map_rewrite(map, buf, strlen(buf), NULL);
264969453Seric
265069453Seric /* now flush any additional output */
265169453Seric while ((i = read(fd, buf, sizeof buf)) > 0)
265269453Seric continue;
265369827Seric }
265469453Seric
265569827Seric /* wait for the process to terminate */
265669827Seric close(fd);
265769827Seric stat = waitfor(pid);
265869453Seric
265969827Seric if (stat == -1)
266069827Seric {
266169827Seric syserr("prog_map_lookup(%s): wait error %s\n",
266269827Seric map->map_mname, errstring(errno));
266369827Seric *statp = EX_SOFTWARE;
266469827Seric rval = NULL;
266569453Seric }
266669872Seric else if (WIFEXITED(stat))
266769827Seric {
266869872Seric *statp = WEXITSTATUS(stat);
266969827Seric }
267069827Seric else
267169827Seric {
267269827Seric syserr("prog_map_lookup(%s): child died on signal %d",
267369872Seric map->map_mname, stat);
267469827Seric *statp = EX_UNAVAILABLE;
267569827Seric rval = NULL;
267669827Seric }
267769827Seric return rval;
267869453Seric }
267969453Seric /*
268068350Seric ** Sequenced map type.
268168350Seric **
268268350Seric ** Tries each map in order until something matches, much like
268368350Seric ** implicit. Stores go to the first map in the list that can
268468350Seric ** support storing.
268568350Seric **
268668350Seric ** This is slightly unusual in that there are two interfaces.
268768350Seric ** The "sequence" interface lets you stack maps arbitrarily.
268868350Seric ** The "switch" interface builds a sequence map by looking
268968350Seric ** at a system-dependent configuration file such as
269068350Seric ** /etc/nsswitch.conf on Solaris or /etc/svc.conf on Ultrix.
269168350Seric **
269268350Seric ** We don't need an explicit open, since all maps are
269368350Seric ** opened during startup, including underlying maps.
269468350Seric */
269568350Seric
269668350Seric /*
269768350Seric ** SEQ_MAP_PARSE -- Sequenced map parsing
269868350Seric */
269968350Seric
270068350Seric bool
seq_map_parse(map,ap)270168350Seric seq_map_parse(map, ap)
270268350Seric MAP *map;
270368350Seric char *ap;
270468350Seric {
270568350Seric int maxmap;
270668350Seric
270768350Seric if (tTd(38, 2))
270868350Seric printf("seq_map_parse(%s, %s)\n", map->map_mname, ap);
270968350Seric maxmap = 0;
271068350Seric while (*ap != '\0')
271168350Seric {
271268350Seric register char *p;
271368350Seric STAB *s;
271468350Seric
271568350Seric /* find beginning of map name */
271668350Seric while (isascii(*ap) && isspace(*ap))
271768350Seric ap++;
271868350Seric for (p = ap; isascii(*p) && isalnum(*p); p++)
271968350Seric continue;
272068350Seric if (*p != '\0')
272168350Seric *p++ = '\0';
272268350Seric while (*p != '\0' && (!isascii(*p) || !isalnum(*p)))
272368350Seric p++;
272468350Seric if (*ap == '\0')
272568350Seric {
272668350Seric ap = p;
272768350Seric continue;
272868350Seric }
272968350Seric s = stab(ap, ST_MAP, ST_FIND);
273068350Seric if (s == NULL)
273168350Seric {
273268350Seric syserr("Sequence map %s: unknown member map %s",
273368350Seric map->map_mname, ap);
273468350Seric }
273568350Seric else if (maxmap == MAXMAPSTACK)
273668350Seric {
273768350Seric syserr("Sequence map %s: too many member maps (%d max)",
273868350Seric map->map_mname, MAXMAPSTACK);
273968350Seric maxmap++;
274068350Seric }
274168350Seric else if (maxmap < MAXMAPSTACK)
274268350Seric {
274368350Seric map->map_stack[maxmap++] = &s->s_map;
274468350Seric }
274568350Seric ap = p;
274668350Seric }
274768350Seric return TRUE;
274868350Seric }
274968350Seric
275068350Seric
275168350Seric /*
275268350Seric ** SWITCH_MAP_OPEN -- open a switched map
275368350Seric **
275468350Seric ** This looks at the system-dependent configuration and builds
275568350Seric ** a sequence map that does the same thing.
275668350Seric **
275768350Seric ** Every system must define a switch_map_find routine in conf.c
275868350Seric ** that will return the list of service types associated with a
275968350Seric ** given service class.
276068350Seric */
276168350Seric
276268350Seric bool
switch_map_open(map,mode)276368350Seric switch_map_open(map, mode)
276468350Seric MAP *map;
276568350Seric int mode;
276668350Seric {
276768350Seric int mapno;
276868350Seric int nmaps;
276968350Seric char *maptype[MAXMAPSTACK];
277068350Seric
277168350Seric if (tTd(38, 2))
277268350Seric printf("switch_map_open(%s, %s, %d)\n",
277368350Seric map->map_mname, map->map_file, mode);
277468350Seric
277568350Seric nmaps = switch_map_find(map->map_file, maptype, map->map_return);
277668350Seric if (tTd(38, 19))
277768350Seric {
277868350Seric printf("\tswitch_map_find => %d\n", nmaps);
277968350Seric for (mapno = 0; mapno < nmaps; mapno++)
278068350Seric printf("\t\t%s\n", maptype[mapno]);
278168350Seric }
278268350Seric if (nmaps <= 0 || nmaps > MAXMAPSTACK)
278368350Seric return FALSE;
278468350Seric
278568350Seric for (mapno = 0; mapno < nmaps; mapno++)
278668350Seric {
278768350Seric register STAB *s;
278868350Seric char nbuf[MAXNAME + 1];
278968350Seric
279068350Seric if (maptype[mapno] == NULL)
279168350Seric continue;
279268350Seric (void) sprintf(nbuf, "%s.%s", map->map_file, maptype[mapno]);
279368350Seric s = stab(nbuf, ST_MAP, ST_FIND);
279468350Seric if (s == NULL)
279568350Seric {
279668350Seric syserr("Switch map %s: unknown member map %s",
279768350Seric map->map_mname, nbuf);
279868350Seric }
279968350Seric else
280068350Seric {
280168350Seric map->map_stack[mapno] = &s->s_map;
280268350Seric if (tTd(38, 4))
280368350Seric printf("\tmap_stack[%d] = %s:%s\n",
280468350Seric mapno, s->s_map.map_class->map_cname,
280568350Seric nbuf);
280668350Seric }
280768350Seric }
280868350Seric return TRUE;
280968350Seric }
281068350Seric
281168350Seric
281268350Seric /*
281368350Seric ** SEQ_MAP_CLOSE -- close all underlying maps
281468350Seric */
281568350Seric
281669748Seric void
seq_map_close(map)281768350Seric seq_map_close(map)
281868350Seric MAP *map;
281968350Seric {
282068350Seric int mapno;
282168350Seric
282268350Seric if (tTd(38, 20))
282368350Seric printf("seq_map_close(%s)\n", map->map_mname);
282468350Seric for (mapno = 0; mapno < MAXMAPSTACK; mapno++)
282568350Seric {
282668350Seric MAP *mm = map->map_stack[mapno];
282768350Seric
282868350Seric if (mm == NULL || !bitset(MF_OPEN, mm->map_mflags))
282968350Seric continue;
283068350Seric mm->map_class->map_close(mm);
283168798Seric mm->map_mflags &= ~(MF_OPEN|MF_WRITABLE);
283268350Seric }
283368350Seric }
283468350Seric
283568350Seric
283668350Seric /*
283768350Seric ** SEQ_MAP_LOOKUP -- sequenced map lookup
283868350Seric */
283968350Seric
284068350Seric char *
seq_map_lookup(map,key,args,pstat)284168350Seric seq_map_lookup(map, key, args, pstat)
284268350Seric MAP *map;
284368350Seric char *key;
284468350Seric char **args;
284568350Seric int *pstat;
284668350Seric {
284768350Seric int mapno;
284868350Seric int mapbit = 0x01;
284968350Seric
285068350Seric if (tTd(38, 20))
285168350Seric printf("seq_map_lookup(%s, %s)\n", map->map_mname, key);
285268350Seric
285368350Seric for (mapno = 0; mapno < MAXMAPSTACK; mapbit <<= 1, mapno++)
285468350Seric {
285568350Seric MAP *mm = map->map_stack[mapno];
285668350Seric int stat = 0;
285768350Seric char *rv;
285868350Seric
285968350Seric if (mm == NULL)
286068350Seric continue;
286168350Seric if (!bitset(MF_OPEN, mm->map_mflags))
286268350Seric {
286368350Seric if (bitset(mapbit, map->map_return[MA_UNAVAIL]))
286468350Seric {
286568350Seric *pstat = EX_UNAVAILABLE;
286668350Seric return NULL;
286768350Seric }
286868350Seric continue;
286968350Seric }
287068350Seric rv = mm->map_class->map_lookup(mm, key, args, &stat);
287168350Seric if (rv != NULL)
287268350Seric return rv;
287368350Seric if (stat == 0 && bitset(mapbit, map->map_return[MA_NOTFOUND]))
287468350Seric return NULL;
287568350Seric if (stat != 0 && bitset(mapbit, map->map_return[MA_TRYAGAIN]))
287668350Seric {
287768350Seric *pstat = stat;
287868350Seric return NULL;
287968350Seric }
288068350Seric }
288168350Seric return NULL;
288268350Seric }
288368350Seric
288468350Seric
288568350Seric /*
288668350Seric ** SEQ_MAP_STORE -- sequenced map store
288768350Seric */
288868350Seric
288968350Seric void
seq_map_store(map,key,val)289068350Seric seq_map_store(map, key, val)
289168350Seric MAP *map;
289268350Seric char *key;
289368350Seric char *val;
289468350Seric {
289568350Seric int mapno;
289668350Seric
289768350Seric if (tTd(38, 12))
289868350Seric printf("seq_map_store(%s, %s, %s)\n",
289968350Seric map->map_mname, key, val);
290068350Seric
290168350Seric for (mapno = 0; mapno < MAXMAPSTACK; mapno++)
290268350Seric {
290368350Seric MAP *mm = map->map_stack[mapno];
290468350Seric
290568350Seric if (mm == NULL || !bitset(MF_WRITABLE, mm->map_mflags))
290668350Seric continue;
290768350Seric
290868350Seric mm->map_class->map_store(mm, key, val);
290968350Seric return;
291068350Seric }
291168350Seric syserr("seq_map_store(%s, %s, %s): no writable map",
291268350Seric map->map_mname, key, val);
291368350Seric }
291468350Seric /*
291560207Seric ** NULL stubs
291660089Seric */
291760089Seric
291860207Seric bool
null_map_open(map,mode)291960207Seric null_map_open(map, mode)
292060089Seric MAP *map;
292160207Seric int mode;
292260089Seric {
292360207Seric return TRUE;
292460089Seric }
292560089Seric
292660207Seric void
null_map_close(map)292760207Seric null_map_close(map)
292860207Seric MAP *map;
292960089Seric {
293060207Seric return;
293160207Seric }
293260089Seric
293360207Seric void
null_map_store(map,key,val)293460207Seric null_map_store(map, key, val)
293560207Seric MAP *map;
293660207Seric char *key;
293760207Seric char *val;
293860089Seric {
293960207Seric return;
294060089Seric }
294168350Seric
294268350Seric
294368350Seric /*
294468350Seric ** BOGUS stubs
294568350Seric */
294668350Seric
294768350Seric char *
bogus_map_lookup(map,key,args,pstat)294868350Seric bogus_map_lookup(map, key, args, pstat)
294968350Seric MAP *map;
295068350Seric char *key;
295168350Seric char **args;
295268350Seric int *pstat;
295368350Seric {
295468350Seric *pstat = EX_TEMPFAIL;
295568350Seric return NULL;
295668350Seric }
295768350Seric
295868350Seric MAPCLASS BogusMapClass =
295968350Seric {
296068350Seric "bogus-map", NULL, 0,
296168350Seric NULL, bogus_map_lookup, null_map_store,
296268350Seric null_map_open, null_map_close,
296368350Seric };
2964