#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>
#include "lsparam.h"
#include "listen.h"
#include "lsfiles.h"
#include "lserror.h"
#include "lsdbf.h"
#define SUPPRESS 1
#define NOSUPPRESS 0
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;
static unsigned Dbfentries;
extern char *Server_cmd_lines;
extern char *New_cmd_lines;
int
read_dbf(re_read)
int re_read;
{
register unsigned size;
int exit_flag = EXIT | NOCORE;
register dbf_t *dbf_p;
register char *cmd_p;
unsigned scan_dbf();
extern dbf_t *Dbfhead;
extern dbf_t *Newdbf;
extern char *calloc();
DEBUG((9,"in read_dbf"));
if (check_version())
error(E_BADVER, EXIT | NOCORE);
if (re_read) {
exit_flag = CONTINUE;
}
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);
}
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 (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);
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
}
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
}
return(0);
}
int
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;
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) {
fclose(dbfilep);
return(-1);
}
i = strlen(svc_code_p);
if ( (i == 0) || (i >= SVC_CODE_SZ) )
goto reject;
tdbf_p = dbfhead;
while (tdbf_p->dbf_svc_code) {
if (!strcmp(svc_code_p, tdbf_p->dbf_svc_code)) {
sprintf(scratch, dbfdupcmsg, svc_code_p);
logmessage(scratch);
return(-1);
}
++tdbf_p;
}
if (!NLPS_proc && (strlen(private_p) == 0) && !(sflags & DFLAG))
continue;
if (!NLPS_proc) {
i = strlen(private_p);
if (i >= PRV_ADR_SZ) {
goto p_reject;
}
Dbf_entries++;
}
dbf_p->dbf_fd = -1;
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;
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;
++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);
}
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);
}
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);
}
if (ferror(fp)) {
sprintf(bp,dbfrderror,Dbflineno);
logmessage(bp);
return(-1);
}
sprintf(bp,dbfunknown,Dbflineno);
logmessage(bp);
return(-1);
}
if (*(bp+strlen(bp)-1) != '\n') {
sprintf(bp, dbfbadlmsg, Dbflineno);
logmessage(bp);
return(-1);
}
*(bp + strlen(bp) -1) = (char)0;
if (strlen(bp) && (p = strchr(bp, DBFCOMMENT)))
*p = (char)0;
if (!strlen(bp))
continue;
p = bp + strlen(bp) - 1;
while ((p != bp) && (isspace(*p))) {
*p = (char)0;
--p;
}
while (*bp)
if (isspace(*bp))
++bp;
else
break;
if (strlen(bp)) {
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);
DEBUG((5,"rd_dbf_line: line: %d,cmd line len: %d",Dbflineno, length+1));
return(length+1);
}
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 ))) {
DEBUG((9,"scan_line failed svc_code strchr"));
return(0);
}
*p = '\0';
*svc_code_p = bp;
nexttok = ++p;
if (!(p = strchr(nexttok, DBFTOKSEP ))) {
DEBUG((9,"scan_line failed flags strchr"));
return(0);
}
*p = '\0';
while (*nexttok) {
switch (*nexttok) {
case 'x':
case 'X':
*flags_p |= DBF_OFF;
break;
case 'u':
*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 = '\0';
*id_p = nexttok;
nexttok = ++p;
if (!(p = strchr(nexttok, DBFTOKSEP ))) {
DEBUG((9,"scan_line failed res1 strchr"));
return(0);
}
*p = '\0';
*res1_p = nexttok;
nexttok = ++p;
if (!(p = strchr(nexttok, DBFTOKSEP ))) {
DEBUG((9,"scan_line failed res2 strchr"));
return(0);
}
*p = '\0';
*res2_p = nexttok;
nexttok = ++p;
if (!(p = strchr(nexttok, DBFTOKSEP ))) {
DEBUG((9,"scan_line failed res3 strchr"));
return(0);
}
*p = '\0';
*res3_p = nexttok;
nexttok = ++p;
if (!(p = strchr(nexttok, DBFTOKSEP ))) {
DEBUG((9,"scan_line failed private strchr"));
return(0);
}
*p = '\0';
*private_p = nexttok;
nexttok = ++p;
if (!(p = strchr(nexttok, DBFTOKSEP ))) {
DEBUG((9,"scan_line failed rpc strchr"));
return(0);
}
*p = '\0';
*prognum = -1;
*vernum = -1;
if (*nexttok) {
for (ptr = nexttok; *ptr; ++ptr) {
if ((*ptr == ',') && !sawsep) {
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) {
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 = '\0';
*sflags = 0;
while (*nexttok) {
switch (*nexttok) {
case 'c':
*sflags |= CFLAG;
break;
case 'd':
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");
}
**private_p = '\0';
}
else {
*sflags |= DFLAG;
}
break;
case 'p':
*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 = '\0';
*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(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="
int
check_version(void)
{
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))) {
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);
else
return(0);
}
p = line;
}
logmessage(dbfcorrupt);
error(E_DBF_CORRUPT, EXIT | NOCORE);
return(1);
}
static char *dbfargv[50];
static char *delim = " \t'\"";
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':
*p++ = '\0';
*argvp++ = savep;
DEBUG((9, "argv[%d] = %s", i++, savep));
while (isspace(*p))
p++;
savep = p;
break;
case '"':
case '\'':
delch = *p;
savep = ++p;
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);
}
if (*p == delch) {
if (*(tp - 1) == '\\') {
*(tp - 1) = *p;
p++;
}
else {
*tp = 0;
*argvp++ = savep;
DEBUG((9, "argv[%d] = %s", i++, savep));
p++;
while (isspace(*p))
p++;
savep = p;
break;
}
}
else {
*tp++ = *p++;
}
}
break;
default:
logmessage("Internal error in parse routine");
exit(2);
}
}
else {
*argvp++ = savep;
DEBUG((9, "argv[%d] = %s", i++, savep));
}
}
*argvp = 0;
return(dbfargv);
}
dbf_t *
getentry(fd)
int fd;
{
extern dbf_t *Dbfhead;
register dbf_t *dbp = Dbfhead;
if (!Dbfhead) {
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);
}
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 == '\0') {
DEBUG((9,"NULL list: exiting pushmod"));
return(0);
}
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);
}