#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include <limits.h>
#include "mslp_sd.h"
#include "slp.h"
#include "mslp.h"
#include "mslpd_store.h"
static int init_pstore(FILE *fp, char *pcLine, SAStore *pstore);
static SLPInternalError parse_url_props(const char *pcLine, SAStore *pstore, int item);
static int count_attrs(FILE *fp, char *pcLine, int *piGotScopes);
static char * get_srvtype(const char *pcURL);
static SLPInternalError fill_values(Values *pv, const char *pc, int offset);
static SLPInternalError fill_attrs(FILE *fp, char *pcLine, SAStore *pstore,
int item, const char *pcSL);
static void serialize_attrs(SAStore *pstore, int item);
#if defined(EXTRA_MSGS)
static void set_sa_srvtype_attr(const SAStore *pstore);
#endif
#define MAXLINE 4096
void delete_regfile(const char *pcFile)
{
char* command = (char*)malloc(strlen(pcFile) + 4);
sprintf( command, "rm %s", pcFile );
system( command );
free(command);
}
SLPInternalError process_regfile(SAStore *pstore, const char *pcFile)
{
FILE *fp;
char pcLine[MAXLINE];
int count = 0;
int item = 0;
const char *pcSL = GetEncodedScopeToRegisterIn();
assert(pcSL);
if (pstore == NULL || pcFile == NULL)
{
return SLP_PARAMETER_BAD;
}
if ((fp = fopen(pcFile,"rb")) == NULL)
{
sprintf(pcLine,"process_regfile: could not open file [%s]\n",pcFile);
LOG_SLP_ERROR_AND_RETURN(SLP_LOG_ERR,pcLine,SLP_PARAMETER_BAD);
}
if ((count = init_pstore(fp,pcLine,pstore)) == 0)
{
fclose(fp);
return SLP_OK;
}
else if (count < 0)
{
fclose(fp);
return (SLPInternalError) count;
}
rewind(fp);
while (fgets(pcLine,MAXLINE,fp))
{
SLPInternalError err;
if (pcLine[0] == ';' || pcLine[0] == '#' ||
pcLine[0] == '\n' || pcLine[0] == '\r' || pcLine[0] == '\0')
{
continue;
}
if ((err = parse_url_props(pcLine, pstore, item)) != SLP_OK)
{
SLP_LOG( SLP_LOG_ERR, "process_regfile encountered an error" );
fclose(fp);
return err;
}
if ((err = fill_attrs(fp, pcLine, pstore, item, pcSL)) != SLP_OK)
{
fclose(fp);
SLP_LOG(SLP_LOG_DEBUG,"mslpd_reader.c, process_regfile(), fill_attrs: (%d)", err);
return err;
}
item++;
}
fclose(fp);
#if defined(EXTRA_MSGS)
set_sa_srvtype_attr(pstore);
#endif
if (pstore && SLPGetProperty("net.slp.traceReg") &&
!SDstrcasecmp("true",SLPGetProperty("net.slp.traceReg")))
{
int i, j, k;
printf("regfile dump: %d items\n",pstore->size);
for (i = 0; i < pstore->size; i++)
{
printf("%d. URL [%s] scope [%s] type [%s] lang [%s] life [%i]\n",
i, pstore->url[i], pstore->scope[i],
pstore->srvtype[i], pstore->lang[i], pstore->life[i]);
if (pstore->tag[i])
{
for (j = 0; pstore->tag[i][j]; j++)
{
printf("\t%d. %s",j,pstore->tag[i][j]);
if (pstore->values[i] && pstore->values[i][j].numvals > 0)
{
for (k = 0; k < pstore->values[i][j].numvals; k++)
{
switch(pstore->values[i][j].type)
{
case TYPE_BOOL:
printf("<boolean:%s>",
(pstore->values[i][j].pval[k].v_i)?"true":"false");
break;
case TYPE_INT:
printf("<int:%d>",pstore->values[i][j].pval[k].v_i);
break;
case TYPE_STR:
printf("<string:%s>",pstore->values[i][j].pval[k].v_pc);
break;
case TYPE_OPAQUE:
printf("<opaque:%s>",pstore->values[i][j].pval[k].v_pc);
break;
default:
printf("<unknown>");
break;
}
if (k < (pstore->values[i][j].numvals - 1))
printf(",");
}
}
printf("\n");
}
}
}
}
{
char logStr[256];
sprintf( logStr, "process_regfile finished, %d items are currently registered", pstore->size );
LOG( SLP_LOG_REG, logStr );
}
return SLP_OK;
}
static int init_pstore(FILE *fp, char *pcLine, SAStore *pstore) {
char *pc = pcLine;
int count = 0;
if (fp == NULL || pcLine == NULL) {
return SLP_PARAMETER_BAD;
}
while (pc != NULL) {
do {
pc = fgets(pcLine,MAXLINE,fp);
} while ( pc != NULL &&
(pcLine[0] == ';' || pcLine[0] == '#' ||
pcLine[0] == 0x0a || pcLine[0] == 0x0d ||
pcLine[0] == 0x00));
if (pc != NULL) {
count++;
}
while ( pc != NULL
&& (pcLine[0] != 0x0a && pcLine[0] != 0x0d && pcLine[0] != 0x00)) {
pc = fgets(pcLine,MAXLINE,fp);
}
}
pstore->size = count;
pstore->srvtype = (char**) safe_malloc((count+1) * sizeof(char*),0,0);
pstore->scope = (char**) safe_malloc((count+1) * sizeof(char**),0,0);
pstore->lang = (char**) safe_malloc((count+1) * sizeof(char*),0,0);
pstore->life = (int*) safe_malloc((count+1) * sizeof(int), 0, 0);
pstore->url = (char**) safe_malloc((count+1) * sizeof(char*),0,0);
pstore->tag = (char***) safe_malloc((count+1) * sizeof(char**),0,0);
pstore->values = (Values**) safe_malloc((count+1) * sizeof(Values*),0,0);
pstore->attrlist= (char**) safe_malloc((count+1) * sizeof(char*),0,0);
return count;
}
static SLPInternalError parse_url_props(const char *pcLine,
SAStore *pstore, int item) {
int index = 0;
char c, *pcTemp = NULL;
const char *pcLoc = SLPGetProperty("net.slp.locale");
if (pcLine == NULL || pstore == NULL || item < 0 || item >= pstore->size) {
return SLP_PARAMETER_BAD;
}
if (!(pstore->url[item] = get_next_string(",",pcLine,&index,&c))) {
LOG_SLP_ERROR_AND_RETURN(SLP_LOG_ERR,"process_regfile bad url",SLP_INVALID_REGISTRATION);
}
if (c == '\0' || c == '\n' || c == EOF ||
!(pstore->lang[item] = get_next_string(",",pcLine,&index,&c))) {
LOG(SLP_LOG_DEBUG,"process_regfile no language: set to default language.");
pstore->lang[item] = safe_malloc(strlen(pcLoc)+1,pcLoc,strlen(pcLoc));
}
if (c == '\0' || c == '\n' || c == EOF ||
!(pcTemp = get_next_string(",",pcLine,&index,&c))) {
LOG(SLP_LOG_DEBUG,"process_regfile bad lifetime - ignored.");
}
if (pcTemp == NULL) {
pstore->life[item] = 0xffff;
} else {
char* endPtr = NULL;
pstore->life[item] = strtol(pcTemp,&endPtr,10);
if (pstore->life[item] < 1 || pstore->life[item] > 0xffff) {
pstore->life[item] = 0xffff;
LOG(SLP_LOG_DEBUG,"process_regfile: lifetime <min or >max, use default");
}
}
SLPFree((void*)pcTemp);
if (c == '\0' || c == '\n' || c == EOF ||
(pcTemp = get_next_string("\000",pcLine,&index,&c)) == NULL) {
pstore->srvtype[item] = get_srvtype(pstore->url[item]);
} else {
pstore->srvtype[item] = pcTemp;
}
return SLP_OK;
}
static SLPInternalError fill_values(Values *pv, const char *pc, int offset) {
SLPInternalError err = SLP_OK;
int loop, iValCount = 0;
char *pcPacked = list_pack(&pc[offset]);
char *pcScan = pcPacked;
int iValueOffset = 0;
if (pv == NULL || pc == NULL || offset < 0) {
return SLP_PARAMETER_BAD;
}
if (pcPacked == NULL || pcPacked[0] == '\0') {
SLPFree(pcPacked);
pv->numvals = 0;
return SLP_OK;
}
for( ; pcScan; pcScan++) {
if (*pcScan == ',') iValCount++;
if (*pcScan == '\n' || *pcScan == '\0' || *pcScan == EOF) {
iValCount++;
break;
}
}
pv->pval = (Val*) safe_malloc((iValCount+1)*sizeof(Val), NULL, 0);
pv->type = TYPE_UNKNOWN;
for (loop = 0; loop < iValCount; loop++) {
if ((err = fill_value(pv, loop, pcPacked, &iValueOffset)) != SLP_OK) {
SLPFree(pcPacked);
return err;
}
}
pv->numvals = iValCount;
SLPFree(pcPacked);
return SLP_OK;
}
SLPInternalError fill_value(Values *pv, int i, const char *pc, int *piOffset) {
int result;
char c;
char *pcVal;
if (pv==NULL || pc == NULL || piOffset == NULL || i < 0 || *piOffset < 0) {
return SLP_PARAMETER_BAD;
}
pcVal= get_next_string(",",pc,piOffset,&c);
if (pcVal == NULL || *pcVal == '\0') {
return SLP_INVALID_REGISTRATION;
}
if (!SDstrcasecmp(pcVal,"true")) {
pv->type = TYPE_BOOL;
pv->pval[i].v_i = 1;
SLPFree((void*)pcVal);
} else if (!SDstrcasecmp(pcVal,"false")) {
pv->type = TYPE_BOOL;
pv->pval[i].v_i = 0;
SLPFree((void*)pcVal);
} else if (!SDstrncasecmp(pcVal,"\\FF",3)) {
pv->type = TYPE_OPAQUE;
pv->pval[i].v_pc = pcVal;
} else {
char *ptr;
long lVal;
errno = 0;
lVal = strtol(pcVal,&ptr,10);
if (*ptr == '\0' && errno == 0) {
pv->type = TYPE_INT;
pv->pval[i].v_i = (int) lVal;
SLPFree(pcVal);
} else {
if (errno == ERANGE) {
mslplog(SLP_LOG_DEBUG,"fill_value: Value over or under allowed integer: ",
pcVal);
}
result = isAttrvalEscapedOK(pcVal);
if (result < 0) return (SLPInternalError) result;
pv->type = TYPE_STR;
pv->pval[i].v_pc = pcVal;
}
}
return SLP_OK;
}
static SLPInternalError fill_attrs(FILE *fp, char *pcLine, SAStore *pstore, int item, const char *pcSL)
{
int loop;
int gotScope = 0;
int iNumAttrs;
char *pc;
char *pcTrim;
char *pcTag = NULL;
int offset = 0;
char c;
if ( fp==NULL || pcLine == NULL ||
pstore == NULL || item < 0 || pcSL == NULL )
{
return SLP_PARAMETER_BAD;
}
iNumAttrs = count_attrs(fp,pcLine,&gotScope);
if (iNumAttrs < 0)
{
LOG_SLP_ERROR_AND_RETURN(SLP_LOG_ERR,"mslpd_reader.c, process_regfile(), count_attrs", SLP_INVALID_REGISTRATION);
}
if (gotScope)
{
char *pcTemp;
pc = fgets(pcLine,MAXLINE,fp);
pcTemp = get_next_string("=", pcLine, &offset, &c);
SLPFree(pcTemp);
pcTemp = get_next_string("\000", pcLine, &offset, &c);
pcTrim = list_pack(pcTemp);
SLPFree(pcTemp);
#if 1
if (!list_subset(pcTrim, SLPGetProperty("net.slp.useScopes")))
{
char newScopeList[1024];
sprintf( newScopeList, "%s,%s", SLPGetProperty("net.slp.useScopes"), pcTrim );
SLPSetProperty("net.slp.useScopes", newScopeList ); }
pstore->scope[item] = pcTrim;
#else
if (!list_subset(pcTrim,pcSL))
{
mslplog(SLP_LOG_ERR, "fill_attrs: unconfigured scope in service registration", pcLine);
SLPFree(pcTrim);
pstore->scope[item] = safe_malloc(strlen(pcSL)+1,pcSL,strlen(pcSL));
}
else
{
pstore->scope[item] = pcTrim;
}
#endif
}
else
{
pstore->scope[item] = safe_malloc(strlen(pcSL)+1,pcSL,strlen(pcSL));
}
iNumAttrs -= gotScope;
if (iNumAttrs == 0)
{
pstore->tag[item] = NULL;
pstore->values[item] = NULL;
}
else
{
pstore->tag[item] = (char **) safe_malloc((iNumAttrs+1)*sizeof(char*),0,0);
pstore->values[item] =
(Values *) safe_malloc((iNumAttrs+1)*sizeof(Values),0,0);
for (loop = 0; loop < iNumAttrs; loop++)
{
fgets(pcLine,MAXLINE,fp);
offset = 0;
pcTag = get_next_string("=", pcLine, &offset, &c);
pcTrim = list_pack(pcTag);
if (pcTrim == NULL || pcTrim[0] == '\0')
{
SLPFree(pcTrim);
SLPFree(pcTag);
pcTag = safe_malloc(1,0,0);
}
else
{
SLPFree(pcTag);
pcTag = pcTrim;
}
pstore->tag[item][loop] = pcTag;
if (c == '=')
{
SLPInternalError err = fill_values(&(pstore->values[item][loop]),pcLine,offset);
if (err != SLP_OK)
return err;
if (!pstore->tag[item][loop])
LOG_SLP_ERROR_AND_RETURN(SLP_LOG_ERR,"fill_attr: prob getting vals",err);
}
else
{
pstore->values[item][loop].type = TYPE_KEYWORD;
pstore->values[item][loop].numvals = 0;
pstore->values[item][loop].pval = NULL;
}
}
}
serialize_attrs(pstore,item);
return SLP_OK;
}
static int count_attrs(FILE *fp, char *pcLine, int *piScope)
{
int count = 0;
long start;
char *pcPacked = NULL;
*piScope = 0;
if (fp == NULL)
{
return SLP_PARAMETER_BAD;
}
start = ftell(fp);
do {
if (fgets(pcLine,MAXLINE,fp) == NULL)
break;
pcPacked = list_pack(pcLine);
if (pcPacked[0] == '\0')
{
break;
}
else
{
if (count == 0 && !SDstrncasecmp("scopes=",pcPacked,7))
{
*piScope = 1;
}
count++;
}
SLPFree(pcPacked);
pcPacked = NULL;
} while (1);
if (fseek(fp,start,SEEK_SET) < 0)
{
LOG_SLP_ERROR_AND_RETURN(SLP_LOG_ERR,"mslpd_reader.c, count_attrs(), fseek failed", SLP_INTERNAL_SYSTEM_ERROR);
}
SLPFree(pcPacked);
return count;
}
static void init_or_merge(const char *pcNewString, char **pcList, int *len) {
if (pcNewString == NULL) return;
if (*pcList == NULL || *pcList[0] == '\0') {
*len = strlen(pcNewString);
*pcList = safe_malloc(*len+1,pcNewString,*len);
} else {
list_merge(pcNewString,pcList,len,CHECK);
}
}
char * serialize_values(SAStore *pstore, int item, int attr) {
int vcount;
char *pcVals = safe_malloc(1,0,0);
int vListLen = 0;
for (vcount=0; vcount < pstore->values[item][attr].numvals; vcount++){
char buf[32];
if (pstore->values[item][attr].type == TYPE_INT) {
sprintf(buf,"%d",pstore->values[item][attr].pval[vcount].v_i);
init_or_merge(buf,&pcVals,&vListLen);
} else if (pstore->values[item][attr].type == TYPE_BOOL) {
if (pstore->values[item][attr].pval[vcount].v_i == 0) {
sprintf(buf,"FALSE");
} else {
sprintf(buf,"TRUE");
}
init_or_merge(buf,&pcVals,&vListLen);
} else {
init_or_merge(pstore->values[item][attr].pval[vcount].v_pc,
&pcVals,&vListLen);
}
}
return pcVals;
}
static void serialize_attrs(SAStore *pstore, int item) {
int icount = 0;
int iListLen = 0;
char *pcAttrs = NULL;
char pcItem[MAXLINE+4];
memset(pcItem,0,MAXLINE+4);
if (pstore->tag[item] == NULL) return;
for (icount = 0; pstore->tag[item][icount]; icount++) {
if (pstore->values[item][icount].numvals == 0) {
init_or_merge(pstore->tag[item][icount],&pcAttrs,&iListLen);
} else {
char *pcVals = serialize_values(pstore,item,icount);
sprintf(pcItem,"(%s=%s)",pstore->tag[item][icount],pcVals);
SLPFree(pcVals);
}
init_or_merge(pcItem,&pcAttrs,&iListLen);
}
pstore->attrlist[item] = pcAttrs;
}
static char * get_srvtype(const char *pcURL) {
int i=0;
char *pcSrvtype;
assert(pcURL);
while (pcURL[i] != '\0' && pcURL[i] != '/') i++;
if (pcURL[i] == '\0') return NULL;
pcSrvtype = safe_malloc(i,pcURL,i-1);
return pcSrvtype;
}
#if defined(EXTRA_MSGS)
static void set_sa_srvtype_attr(const SAStore *pstore) {
int i;
char *pcSTList = safe_malloc(1,0,0);
int iSTListLen = 0;
for (i=0; i<pstore->size; i++) {
list_merge(pstore->srvtype[i],&pcSTList,&iSTListLen, CHECK);
}
SLPSetProperty("com.sun.slp.saSrvTypes",pcSTList);
SLPFree(pcSTList);
}
#endif
#ifdef READER_TEST
char *reader_get_srvtype(const char *pcURL) {
return get_srvtype(pcURL);
}
SLPInternalError reader_parse_url_props(const char *pcLine, SAStore *pstore,
int item) {
return parse_url_props(pcLine, pstore, item);
}
int reader_count_attrs(FILE *fp,int *piGotScopes) {
char line[MAXLINE];
return count_attrs(fp,line,piGotScopes);
}
SLPInternalError reader_fill_attrs(FILE *fp, char *pcLine, SAStore *pstore,
int item, const char *pcSL) {
return fill_attrs(fp, pcLine, pstore, item, pcSL);
}
SLPInternalError reader_fill_values(Values *pv, const char *pc, int piOffset) {
return fill_values(pv,pc,piOffset);
}
int reader_init_pstore(FILE *fp, char *pcLine, SAStore *pstore) {
return init_pstore(fp, pcLine,pstore);
}
#endif