lsdbf.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
#ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.8.5.1 */
/*
* data base routines for the network listener process
*/
/* system include files */
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/tiuser.h>
#include <sys/stropts.h>
/* listener include files */
#include "lsparam.h" /* listener parameters */
#include "listen.h" /* listener includes */
#include "lsfiles.h" /* listener files info */
#include "lserror.h" /* listener error codes */
#include "lsdbf.h" /* data base file stuff */
/* #include "nsaddr.h" nls includes */
#define SUPPRESS 1 /* suppress messages during scan*/
#define NOSUPPRESS 0 /* don't suppress messages */
/* static data */
static char *dbfopenmsg = "Trouble opening data base file";
static char *dbfrderror = "Error reading data base file: line %d";
static char *dbfbadlmsg = "Data base file: Error on line %d";
static char *dbfdupcmsg = "Data base file: Duplicate service code: <%s>";
static char *dbfunknown = "Unknown error reading data base file: line %d";
static char *dbfsvccmsg = "Data base file: Illegal service code: <%s>";
static char *dbfcorrupt = "Data base file has been corrupted";
static int Dbflineno; /* current line number in dbf */
static unsigned Dbfentries; /* number of non-comment lines */
extern char *Server_cmd_lines; /* contains svc_code, cmd_line, mod_list */
extern char *New_cmd_lines; /* svc_code, cmd_line, mod_list (on reread)*/
/* public variables */
/*
* read_dbf:
*
* read the data base file into internal structures
*
* all data base routines under read_dbf log there own errors and return -1
* in case of an error.
*
* if 're_read' is non-zero, this stuff is being called to read a new
* data base file after the listener's initialization.
*/
read_dbf(re_read)
int re_read; /* zero means first time */
{
register unsigned size;
int exit_flag = EXIT | NOCORE;
register dbf_t *dbf_p;
register char *cmd_p;
unsigned scan_dbf();
extern dbf_t *Dbfhead; /* Dbfentries (when allocated) */
extern dbf_t *Newdbf; /* Dbfentries (on re-read) */
extern char *calloc();
DEBUG((9,"in read_dbf"));
if (check_version())
error(E_BADVER, EXIT | NOCORE);
if (re_read) { /* not first time */
exit_flag = CONTINUE;
}
/*
* note: data base routines log their own error messages
*/
Dbfentries = 0;
DEBUG((9,"read_dbf: open file here: %s", DBFNAME));
if ( (size = scan_dbf(DBFNAME)) == (unsigned)(-1) )
error( E_SCAN_DBF, exit_flag | NO_MSG );
DEBUG((5,"read_dbf: scan complete: non-commented lines: %u, size: %u",
Dbfentries, size));
if (!size) {
logmessage("No database? 0 entries?");
return(0);
}
/*
* allocate enough space for Dbfentries of 'size' bytes (total)
* The +1 is to insure a NULL last entry!
*/
if (!(dbf_p = (dbf_t *)calloc(Dbfentries+1,sizeof(dbf_t)))
|| !(cmd_p = calloc(size, 1))) {
DEBUG((1,"cannot calloc %u + %u bytes", size,
(Dbfentries+1)*(unsigned)sizeof(dbf_t)));
error( E_DBF_ALLOC, exit_flag); /* if init, exit */
/* if still here, this is a re-read */
if (dbf_p)
free(dbf_p);
if (cmd_p)
free(cmd_p);
return(-1);
}
if (get_dbf(dbf_p, cmd_p)) {
DEBUG((9, "get_dbf FAILED"));
error(E_DBF_IO, exit_flag | NO_MSG);
/* if still here, this is a re_read */
free(dbf_p);
free(cmd_p);
return(-1);
}
if (re_read) {
Newdbf = dbf_p;
New_cmd_lines = cmd_p;
#ifdef DEBUGMODE
DEBUG((7,"read_dbf: NEW data base dump..."));
if (Newdbf)
for (dbf_p = Newdbf; dbf_p->dbf_svc_code; ++dbf_p)
DEBUG((7, "svc code <%s>; id: %s; private address: %s; modules: %s; cmd line: %s; sflags: %x, prognum: %d version: %d",
dbf_p->dbf_svc_code, dbf_p->dbf_id, dbf_p->dbf_prv_adr, dbf_p->dbf_modules, dbf_p->dbf_cmd_line, dbf_p->dbf_sflags, dbf_p->dbf_prognum, dbf_p->dbf_version));
#endif /* DEBUGMODE */
}
else {
Dbfhead = dbf_p;
Server_cmd_lines = cmd_p;
#ifdef DEBUGMODE
DEBUG((7,"read_dbf: data base dump..."));
if (Dbfhead)
for (dbf_p = Dbfhead; dbf_p->dbf_svc_code; ++dbf_p)
DEBUG((7, "svc code <%s>; id: %s; r1: %s; r2: %s; r3: %s; private address: %s; modules: %s; cmd line: %s; sflags: %x, prognum: %d version: %d",
dbf_p->dbf_svc_code, dbf_p->dbf_id, dbf_p->dbf_res1, dbf_p->dbf_res2, dbf_p->dbf_res3, dbf_p->dbf_prv_adr, dbf_p->dbf_modules, dbf_p->dbf_cmd_line, dbf_p->dbf_sflags, dbf_p->dbf_prognum, dbf_p->dbf_version));
#endif /* DEBUGMODE */
}
return(0);
}
/*
* get_dbf: read the file and fill the structures
* checking for duplicate entries as we go
*/
get_dbf(dbf_p, cmd_p)
register dbf_t *dbf_p;
register char *cmd_p;
{
dbf_t *dbfhead = dbf_p;
register int n, i;
char buf[DBFLINESZ];
register char *p = buf;
char scratch[128];
FILE *dbfilep;
char *cmd_line_p;
int flags;
char *svc_code_p;
char *id_p;
char *res1_p;
char *res2_p;
char *res3_p;
char *private_p;
int sflags;
int prognum;
int vernum;
char *module_p;
register dbf_t *tdbf_p;
extern int atoi();
extern int Dbf_entries;
extern int NLPS_proc;
extern int errno;
Dbflineno = 0;
Dbf_entries = 0; /* number of private addresses in dbf file */
DEBUG((9,"in get_dbf: "));
if (!(dbfilep = fopen(DBFNAME,"r"))) {
logmessage(dbfopenmsg);
error(E_DBF_IO, EXIT | NOCORE | NO_MSG);
}
while (n = rd_dbf_line(dbfilep,p,&svc_code_p,&flags,&id_p,&res1_p,&res2_p,&res3_p,&private_p,&prognum,&vernum,&module_p,&sflags,&cmd_line_p,NOSUPPRESS)) {
if (n == -1) { /* read error */
fclose(dbfilep);
return(-1);
}
/* make sure service code is legal */
i = strlen(svc_code_p);
if ( (i == 0) || (i >= SVC_CODE_SZ) )
goto reject;
/* check for duplicate service code */
tdbf_p = dbfhead;
while (tdbf_p->dbf_svc_code) { /* duplicate svc code? */
if (!strcmp(svc_code_p, tdbf_p->dbf_svc_code)) {
sprintf(scratch, dbfdupcmsg, svc_code_p);
logmessage(scratch);
return(-1);
}
++tdbf_p;
}
/* NLPS_proc is set by the nlps_server, which also uses these
* routines. The actual listener child shouldn't ever need
* to read a database, so it will never be here
*/
if (!NLPS_proc && (strlen(private_p) == 0) && !(sflags & DFLAG))
continue; /* ignore entries with no address */
/*
* child doesn't care about private addresses
*/
if (!NLPS_proc) {
i = strlen(private_p);
if (i >= PRV_ADR_SZ) {
goto p_reject;
}
Dbf_entries++;
}
/*
* legal, non-duplicate entry: copy it into internal data base
*/
dbf_p->dbf_fd = -1; /* set to actual fd in add_prvaddr */
dbf_p->dbf_flags = flags;
dbf_p->dbf_sflags = sflags;
dbf_p->dbf_prognum = prognum;
dbf_p->dbf_version = vernum;
strcpy(cmd_p, svc_code_p);
dbf_p->dbf_svc_code = cmd_p;
cmd_p += strlen(svc_code_p) + 1; /* +1 for null */
strcpy(cmd_p, cmd_line_p);
dbf_p->dbf_cmd_line = cmd_p;
cmd_p += strlen(cmd_line_p) + 1;
strcpy(cmd_p, id_p);
dbf_p->dbf_id = cmd_p;
cmd_p += strlen(id_p) + 1;
strcpy(cmd_p, res1_p);
dbf_p->dbf_res1 = cmd_p;
cmd_p += strlen(res1_p) + 1;
strcpy(cmd_p, res2_p);
dbf_p->dbf_res2 = cmd_p;
cmd_p += strlen(res2_p) + 1;
strcpy(cmd_p, res3_p);
dbf_p->dbf_res3 = cmd_p;
cmd_p += strlen(res3_p) + 1;
if (strlen(private_p) != 0) {
strcpy(cmd_p, private_p);
dbf_p->dbf_prv_adr = cmd_p;
cmd_p += strlen(private_p) + 1;
}
else
dbf_p->dbf_prv_adr = NULL;
strcpy(cmd_p, module_p);
dbf_p->dbf_modules = cmd_p;
cmd_p += strlen(module_p) + 1; /* cmd line + null char */
++dbf_p;
}
fclose(dbfilep);
return(0);
reject:
DEBUG((9, "svc_code <%s> failed validation test", svc_code_p));
sprintf(scratch, dbfsvccmsg, svc_code_p);
logmessage(scratch);
return(-1);
p_reject:
DEBUG((9,"private address <%s> failed validation test", private_p));
sprintf(scratch, "Invalid private address ignored: \\x%x", private_p);
logmessage(scratch);
return(-1);
}
/*
* scan_dbf: Take a quick pass through the data base file to figure out
* approx. how many items in the file we'll need to
* allocate storage for. Essentially, returns the number
* of non-null, non-comment lines in the data base file.
*
* return: -1 == error.
* other == number of non-comment characters.
* Dbfentries set.
*/
unsigned
scan_dbf(path)
register char *path;
{
register unsigned int size = 0;
register int n;
register FILE *dbfilep;
char buf[DBFLINESZ];
register char *p = buf;
char *svc_code_p;
int flags;
char *cmd_line_p;
char *module_p;
char *id_p;
char *res1_p;
char *res2_p;
char *res3_p;
int sflags;
int prognum;
int vernum;
char *private_p;
extern int errno;
DEBUG((9, "In scan_dbf. Scanning data base file %s.", path));
if (!(dbfilep = fopen(path,"r"))) {
DEBUG((9,"errorno = %d", errno));
logmessage(dbfopenmsg);
return(-1);
}
do {
n = rd_dbf_line(dbfilep,p,&svc_code_p,&flags,&id_p,&res1_p,&res2_p,&res3_p,&private_p,&prognum,&vernum,&module_p,&sflags,&cmd_line_p,SUPPRESS);
if (n == -1) {
fclose(dbfilep);
return(-1);
}
size += (unsigned)n;
if (n)
++Dbfentries;
} while (n);
fclose(dbfilep);
return(size);
}
/*
* rd_dbf_line: Returns the next non-comment line into the
* given buffer (up to DBFLINESZ bytes).
* Skips 'ignore' lines.
*
* Returns: 0 = done, -1 = error,
* other = cmd line size incl. terminating null.
* *svc_code_p = service code;
* *id_p = user id string;
* *res1_p = reserved string;
* *res2_p = reserved string;
* *res3_p = reserved string;
* *private_p = contains private address;
* *flags_p = decoded flags;
* prognum = RPC program #;
* vernum = RPC version $;
* cnd_line_p points to null terminated cmd line;
*
* When logging errors, the extern Dbflineno is used.
*/
int
rd_dbf_line(fp, bp, svc_code_p, flags_p, id_p, res1_p, res2_p, res3_p, private_p, prognum, vernum, module_p, sflags, cmd_line_p, mflag)
register FILE *fp;
register char *bp;
char **svc_code_p;
int *flags_p;
char **id_p;
char **res1_p;
char **res2_p;
char **res3_p;
char **private_p;
int *prognum;
int *vernum;
char **module_p;
int *sflags;
char **cmd_line_p;
int mflag;
{
register int length;
register char *p;
do {
++Dbflineno;
length = 0;
if (!fgets(bp, DBFLINESZ, fp)) {
if (feof(fp)) {
return(0); /* EOF */
}
if (ferror(fp)) {
sprintf(bp,dbfrderror,Dbflineno);
logmessage(bp);
return(-1);
}
sprintf(bp,dbfunknown,Dbflineno);
logmessage(bp);
return(-1); /* Unknown error (?) */
}
if (*(bp+strlen(bp)-1) != '\n') { /* terminating newline? */
sprintf(bp, dbfbadlmsg, Dbflineno);
logmessage(bp);
return(-1);
}
*(bp + strlen(bp) -1) = (char)0; /* delete newline */
if (strlen(bp) && (p = strchr(bp, DBFCOMMENT)))
*p = (char)0; /* delete comments */
if (!strlen(bp))
continue;
p = bp + strlen(bp) - 1; /* bp->start; p->end */
while ((p != bp) && (isspace(*p))) {
*p = (char)0; /* delete terminating spaces */
--p;
}
while (*bp) /* del beginning white space*/
if (isspace(*bp))
++bp;
else
break;
if (strlen(bp)) { /* anything left? */
if (!(length=scan_line(bp,svc_code_p,flags_p,id_p,res1_p,res2_p,res3_p,private_p,prognum,vernum,module_p,sflags,cmd_line_p,mflag))) {
DEBUG((1, "rd_dbf_line line %d, error while scanning entry",
Dbflineno));
sprintf(bp, dbfbadlmsg, Dbflineno);
logmessage(bp);
return(-1);
}
}
} while (!length); /* until we have something */
DEBUG((5,"rd_dbf_line: line: %d,cmd line len: %d",Dbflineno, length+1));
return(length+1); /* +1 for the trailing NULL */
}
/*
* scan a non-white space line
* 0 = error;
* other = length of cmd line;
*
* non-null lines have the following format:
*
* service_code: flags: id: res1: res2: res3: private address: rpcdata: sflags: modules: cmd_line # comments
*
* mflag is set to suppress messages (scan_line is called both for parsing
* and counting, messages should only be output once)
*/
int
scan_line(bp, svc_code_p, flags_p, id_p, res1_p, res2_p, res3_p, private_p, prognum, vernum, module_p, sflags, cmd_line_p, mflag)
register char *bp;
char **svc_code_p;
register int *flags_p;
char **id_p;
char **res1_p;
char **res2_p;
char **res3_p;
char **private_p;
int *prognum;
int *vernum;
char **module_p;
int *sflags;
register char **cmd_line_p;
int mflag;
{
register char *p;
register char *nexttok;
register char *ptr;
int sawsep = 0;
char scratch[BUFSIZ];
*flags_p = 0;
if (!(p = strchr(bp, DBFTOKSEP ))) { /* look for service code string */
DEBUG((9,"scan_line failed svc_code strchr"));
return(0);
}
*p = NULL;
*svc_code_p = bp;
nexttok = ++p;
if (!(p = strchr(nexttok, DBFTOKSEP ))) {
DEBUG((9,"scan_line failed flags strchr"));
return(0);
}
*p = NULL;
while (*nexttok) {
switch (*nexttok) {
case 'x': /* service is turned off */
case 'X':
*flags_p |= DBF_OFF;
break;
case 'u': /* create utmp entry */
*flags_p |= DBF_UTMP;
break;
default:
DEBUG((1,"scan_line: unknown flag char: 0x%x",*nexttok));
*flags_p = DBF_UNKNOWN;
break;
}
++nexttok;
}
nexttok = ++p;
if (!(p = strchr(nexttok, DBFTOKSEP ))) {
DEBUG((9,"scan_line failed id strchr"));
return(0);
}
*p = NULL;
*id_p = nexttok;
nexttok = ++p;
if (!(p = strchr(nexttok, DBFTOKSEP ))) {
DEBUG((9,"scan_line failed res1 strchr"));
return(0);
}
*p = NULL;
*res1_p = nexttok;
nexttok = ++p;
if (!(p = strchr(nexttok, DBFTOKSEP ))) {
DEBUG((9,"scan_line failed res2 strchr"));
return(0);
}
*p = NULL;
*res2_p = nexttok;
nexttok = ++p;
if (!(p = strchr(nexttok, DBFTOKSEP ))) {
DEBUG((9,"scan_line failed res3 strchr"));
return(0);
}
*p = NULL;
*res3_p = nexttok;
nexttok = ++p;
if (!(p = strchr(nexttok, DBFTOKSEP ))) {
DEBUG((9,"scan_line failed private strchr"));
return(0);
}
*p = NULL;
*private_p = nexttok;
nexttok = ++p;
if (!(p = strchr(nexttok, DBFTOKSEP ))) {
DEBUG((9,"scan_line failed rpc strchr"));
return(0);
}
*p = NULL;
*prognum = -1;
*vernum = -1;
if (*nexttok) {
/* there is rpc info */
for (ptr = nexttok; *ptr; ++ptr) {
if ((*ptr == ',') && !sawsep) {
/*
* skip separator - note that if
* separator has been seen, it's not
* a digit so it will fail below
*/
sawsep++;
continue;
}
if (!isdigit(*ptr)) {
sprintf(scratch, "service code <%s> specifies non-integer rpc info", *svc_code_p);
logmessage(scratch);
return(0);
}
}
ptr = strchr(nexttok, ',');
if (ptr) {
if ((*prognum = atoi(nexttok)) < 0) {
if (!mflag) {
/* messages aren't suppressed */
sprintf(scratch, "service code <%s> specifies negative program number", *svc_code_p);
logmessage(scratch);
}
return(0);
}
if ((*vernum = atoi(ptr + 1)) < 0) {
if (!mflag) {
sprintf(scratch, "service code <%s> specifies negative version number", *svc_code_p);
logmessage(scratch);
}
return(0);
}
}
else {
if (!mflag) {
sprintf(scratch, "service code <%s> - invalid rpcinfo", *svc_code_p);
logmessage(scratch);
}
return(0);
}
}
nexttok = ++p;
if (!(p = strchr(nexttok, DBFTOKSEP ))) {
DEBUG((9,"scan_line failed sflags strchr"));
return(0);
}
*p = NULL;
*sflags = 0;
while (*nexttok) {
switch (*nexttok) {
case 'c': /* dbf_cmd_line is a command */
*sflags |= CFLAG;
break;
case 'd': /* dynamic address */
if ((int) strlen(*private_p) > 0) {
if (!mflag) {
sprintf(scratch, "service code <%s> specifies static and dynamic address", *svc_code_p);
logmessage(scratch);
logmessage(" address info ignored");
}
/* don't set DFLAG and wipe out private addr */
**private_p = '\0';
}
else {
*sflags |= DFLAG;
}
break;
case 'p': /* dbf_cmd_line is a pipe */
*sflags |= PFLAG;
break;
default:
if (!mflag) {
sprintf(scratch, "service code <%s> unknown flag <%c> ignored", *svc_code_p, *nexttok);
logmessage(scratch);
}
break;
}
++nexttok;
}
nexttok = ++p;
if (!(p = strchr(nexttok, DBFTOKSEP ))) {
DEBUG((9,"scan_line failed module strchr"));
return(0);
}
*p = NULL;
*module_p = nexttok;
nexttok = ++p;
*cmd_line_p = nexttok;
DEBUG((9,"scan_line: modules: %s; line: %s; len: %d", *module_p, *cmd_line_p, strlen(*svc_code_p)+strlen(*id_p)+strlen(*res1_p)+strlen(*res2_p)+strlen(*res3_p)+strlen(*private_p)+strlen(*module_p)+strlen(*cmd_line_p)+9));
/*
* return the length of the buffer. Add 9 for the NULLs after each
* string
*/
return(strlen(*svc_code_p)+strlen(*id_p)+strlen(*res1_p)+strlen(*res2_p)+strlen(*res3_p)+strlen(*private_p)+strlen(*module_p)+strlen(*cmd_line_p)+9);
}
#define VERSIONSTR "# VERSION="
check_version()
{
FILE *fp;
char *line, *p, *tmp;
int version;
if ((fp = fopen(DBFNAME, "r")) == NULL) {
logmessage(dbfopenmsg);
error(E_DBF_IO, EXIT | NOCORE | NO_MSG);
}
if ((line = (char *) malloc(DBFLINESZ)) == NULL)
error(E_DBF_ALLOC, EXIT | NOCORE);
p = line;
while (fgets(p, DBFLINESZ, fp)) {
if (!strncmp(p, VERSIONSTR, strlen(VERSIONSTR))) {
/* pitch the newline */
tmp = strchr(p, '\n');
if (tmp)
*tmp = '\0';
else {
logmessage(dbfcorrupt);
error(E_DBF_CORRUPT, EXIT | NOCORE);
}
p += strlen(VERSIONSTR);
if (*p)
version = atoi(p);
else {
logmessage(dbfcorrupt);
error(E_DBF_CORRUPT, EXIT | NOCORE);
}
free(line);
fclose(fp);
if (version != VERSION)
return(1); /* wrong version */
else
return(0); /* version ok */
}
p = line;
}
logmessage(dbfcorrupt);
error(E_DBF_CORRUPT, EXIT | NOCORE);
return(1);
}
/*
* mkdbfargv: Given a pointer to a dbf_t, construct argv
* for an exec system call.
* Warning: returns a pointer to static data which are
* overritten by each call.
*
* There is a practical limit of 50 arguments (including argv[0])
*
* Warning: calling mkdbfargv destroys the data (by writing null
* characters via strtok) pointed to by dbp->dbf_cmd_line.
*/
static char *dbfargv[50];
static char *delim = " \t'\""; /* delimiters */
char **
mkdbfargv(dbp)
register dbf_t *dbp;
{
register char **argvp = dbfargv;
register char *p = dbp->dbf_cmd_line;
char delch;
register char *savep;
register char *tp;
char scratch[BUFSIZ];
char *strpbrk();
#ifdef DEBUGMODE
register int i = 0;
#endif
*argvp = 0;
savep = p;
while (p && *p) {
if (p = strpbrk(p, delim)) {
switch (*p) {
case ' ':
case '\t':
/* "normal" cases */
*p++ = '\0';
*argvp++ = savep;
DEBUG((9, "argv[%d] = %s", i++, savep));
/* zap trailing white space */
while (isspace(*p))
p++;
savep = p;
break;
case '"':
case '\'':
/* found a string */
delch = *p; /* remember the delimiter */
savep = ++p;
/*
* We work the string in place, embedded instances of the string delimiter,
* i.e. \" must have the '\' removed. Since we'd have to do a compare to
* decide if a copy were needed, it's less work to just do the copy, even
* though it is most likely unnecessary.
*/
tp = p;
for (;;) {
if (*p == '\0') {
sprintf(scratch, "invalid command line, non-terminated string for service code %s", dbp->dbf_svc_code);
logmessage(scratch);
exit(2); /* server, don't log */
}
if (*p == delch) {
if (*(tp - 1) == '\\') { /* \delim */
*(tp - 1) = *p;
p++;
}
else { /* end of string */
*tp = 0;
*argvp++ = savep;
DEBUG((9, "argv[%d] = %s", i++, savep));
p++;
/* zap trailing white space */
while (isspace(*p))
p++;
savep = p;
break;
}
}
else {
*tp++ = *p++;
}
}
break;
default:
logmessage("Internal error in parse routine");
exit(2); /* server, don't log */
}
}
else {
*argvp++ = savep;
DEBUG((9, "argv[%d] = %s", i++, savep));
}
}
*argvp = 0;
return(dbfargv);
}
/*
*
* getentry: Given a fd, this routine will return a
* dbf entry. If the entry doesn't exist it will
* return NULL.
*/
dbf_t *
getentry(fd)
int fd;
{
extern dbf_t *Dbfhead; /* Dbfentries (when allocated) */
register dbf_t *dbp = Dbfhead;
if (!Dbfhead) { /* no private address in database file */
DEBUG((9, "getdbfentry - nothing in Dbfhead = %s ",Dbfhead));
return((dbf_t *)0);
}
else
for (dbp = Dbfhead; dbp->dbf_prv_adr; ++dbp)
if (fd == dbp->dbf_fd) {
return(dbp);
}
return((dbf_t *)0); /* requested private address not in list */
}
/*
* pushmod: push modules if defined in the data base entry.
*
* WARNING: This routine writes into the in-memory copy
* of the database file. Therefore, after it is called,
* the incore copy of the database file will no longer be valid.
*/
int
pushmod(fd, mp)
int fd;
register char *mp;
{
register char *cp;
register char *bufp = mp;
char name[32];
extern int errno;
DEBUG((9,"in pushmod:"));
if (!mp || *mp == NULL) {
DEBUG((9,"NULL list: exiting pushmod"));
return(0);
}
/* pop timod if it is on the stack */
if (ioctl(fd, I_LOOK, name) >= 0) {
if (strcmp(name, "timod") == 0) {
if (ioctl(fd, I_POP, 0) < 0)
DEBUG((9,"pushmod: I_POP failed"));
}
}
while ((cp = strtok(bufp, ",")) != NULL) {
bufp = NULL;
DEBUG((9,"pushmod: about to push %s", cp));
if (ioctl(fd, I_PUSH, cp) < 0) {
DEBUG((9,"pushmod: ioctl failed, errno = %d",errno));
return(1);
}
}
DEBUG((9,"exiting pushmod:"));
return(0);
}