From 738547268937f094ef65ed9e0f0bae6f00d01b23 Mon Sep 17 00:00:00 2001 From: Marty Kraimer Date: Mon, 16 Mar 1998 15:51:10 +0000 Subject: [PATCH] Fix problems that could cause crash when asInit called after iocInit Add macro substitution capability --- src/as/asCa.c | 300 ++++++++++----------- src/as/asDbLib.c | 140 +++------- src/as/asDbLib.h | 45 +--- src/as/asLib.h | 93 ++----- src/as/asLib.y | 25 +- src/as/asLibRoutines.c | 579 ++++++++++++++++++++++++++--------------- src/as/ascheck.c | 96 +++---- src/include/asDbLib.h | 45 +--- src/include/asLib.h | 93 ++----- 9 files changed, 660 insertions(+), 756 deletions(-) diff --git a/src/as/asCa.c b/src/as/asCa.c index e2b9ff9ff..a818ce01c 100644 --- a/src/as/asCa.c +++ b/src/as/asCa.c @@ -5,53 +5,19 @@ COPYRIGHT NOTIFICATION ***************************************************************** -THE FOLLOWING IS A NOTICE OF COPYRIGHT, AVAILABILITY OF THE CODE, -AND DISCLAIMER WHICH MUST BE INCLUDED IN THE PROLOGUE OF THE CODE -AND IN ALL SOURCE LISTINGS OF THE CODE. - (C) COPYRIGHT 1993 UNIVERSITY OF CHICAGO - -Argonne National Laboratory (ANL), with facilities in the States of -Illinois and Idaho, is owned by the United States Government, and -operated by the University of Chicago under provision of a contract -with the Department of Energy. -Portions of this material resulted from work developed under a U.S. -Government contract and are subject to the following license: For -a period of five years from March 30, 1993, the Government is -granted for itself and others acting on its behalf a paid-up, -nonexclusive, irrevocable worldwide license in this computer -software to reproduce, prepare derivative works, and perform -publicly and display publicly. With the approval of DOE, this -period may be renewed for two additional five year periods. -Following the expiration of this period or periods, the Government -is granted for itself and others acting on its behalf, a paid-up, -nonexclusive, irrevocable worldwide license in this computer -software to reproduce, prepare derivative works, distribute copies -to the public, perform publicly and display publicly, and to permit -others to do so. - -***************************************************************** - DISCLAIMER -***************************************************************** - -NEITHER THE UNITED STATES GOVERNMENT NOR ANY AGENCY THEREOF, NOR -THE UNIVERSITY OF CHICAGO, NOR ANY OF THEIR EMPLOYEES OR OFFICERS, -MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR ASSUMES ANY LEGAL -LIABILITY OR RESPONSIBILITY FOR THE ACCURACY, COMPLETENESS, OR -USEFULNESS OF ANY INFORMATION, APPARATUS, PRODUCT, OR PROCESS -DISCLOSED, OR REPRESENTS THAT ITS USE WOULD NOT INFRINGE PRIVATELY -OWNED RIGHTS. - -***************************************************************** -LICENSING INQUIRIES MAY BE DIRECTED TO THE INDUSTRIAL TECHNOLOGY -DEVELOPMENT CENTER AT ARGONNE NATIONAL LABORATORY (708-252-2000). +This software was developed under a United States Government license +described on the COPYRIGHT_UniversityOfChicago file included as part +of this distribution. +**********************************************************************/ +/* * * Modification Log: * ----------------- * .01 03-22-94 mrk Initial Implementation */ - + /*This module is separate from asDbLib because CA uses old database access*/ #include #include @@ -59,6 +25,7 @@ DEVELOPMENT CENTER AT ARGONNE NATIONAL LABORATORY (708-252-2000). #include #include #include +#include #include "dbDefs.h" #include "errlog.h" @@ -70,87 +37,80 @@ DEVELOPMENT CENTER AT ARGONNE NATIONAL LABORATORY (708-252-2000). #include "task_params.h" #include "alarm.h" +int asCaDebug = 0; +extern ASBASE volatile *pasbase; +LOCAL int firstTime = TRUE; LOCAL int taskid=0; LOCAL int caInitializing=FALSE; -extern ASBASE *pasbase; +LOCAL SEM_ID asCaTaskLock; /*lock access to task */ +LOCAL SEM_ID asCaTaskWait; /*Wait for task to respond*/ +LOCAL SEM_ID asCaTaskAddChannels; /*Tell asCaTask to add channels*/ +LOCAL SEM_ID asCaTaskClearChannels; /*Tell asCaTask to clear channels*/ typedef struct { struct dbr_sts_double rtndata; chid chid; - evid evid; } CAPVT; -LOCAL void accessRightsCallback(struct access_rights_handler_args arha) +/*connectCallback only handles disconnects*/ +LOCAL void connectCallback(struct connection_handler_args arg) { - chid chid = arha.chid; - ASGINP *pasginp; - ASG *pasg; - CAPVT *pcapvt; - int Ilocked=FALSE; + chid chid = arg.chid; + ASGINP *pasginp = (ASGINP *)ca_puser(chid); + ASG *pasg = pasginp->pasg; - if(!caInitializing) { - FASTLOCK(&asLock); - Ilocked = TRUE; - } - pasginp = (ASGINP *)ca_puser(chid); - pasg = (ASG *)pasginp->pasg; - pcapvt = pasginp->capvt; - if(!ca_read_access(chid)) { - pasg->inpBad |= (1<inpIndex); - if(!caInitializing) asComputeAsg(pasg); - } /*eventCallback will set inpBad false*/ - if(Ilocked) FASTUNLOCK(&asLock); -} - -LOCAL void connectCallback(struct connection_handler_args cha) -{ - chid chid = cha.chid; - ASGINP *pasginp; - ASG *pasg; - CAPVT *pcapvt; - int Ilocked=FALSE; - - if(!caInitializing) { - FASTLOCK(&asLock); - Ilocked = TRUE; - } - pasginp = (ASGINP *)ca_puser(chid); - pasg = (ASG *)pasginp->pasg; - pcapvt = pasginp->capvt; if(ca_state(chid)!=cs_conn) { - pasg->inpBad |= (1<inpIndex); - if(!caInitializing) asComputeAsg(pasg); - } /*eventCallback will set inpBad false*/ - if(Ilocked) FASTUNLOCK(&asLock); -} - -LOCAL void eventCallback(struct event_handler_args eha) -{ - ASGINP *pasginp; - CAPVT *pcapvt; - ASG *pasg; - READONLY struct dbr_sts_double *pdata = eha.dbr; - int Ilocked=FALSE; - - if(!caInitializing) { - FASTLOCK(&asLock); - Ilocked = TRUE; - } - pasginp = (ASGINP *)eha.usr; - pcapvt = (CAPVT *)pasginp->capvt; - if(ca_read_access(pcapvt->chid)) { - pasg = (ASG *)pasginp->pasg; - pcapvt->rtndata = *pdata; /*structure copy*/ - if(pdata->severity==INVALID_ALARM) { + if(!(pasg->inpBad & (1<inpIndex))) { + /*was good so lets make it bad*/ pasg->inpBad |= (1<inpIndex); + if(!caInitializing) asComputeAsg(pasg); + if(asCaDebug) printf("as connectCallback disconnect %s\n", + ca_name(chid)); + } + } +} + +LOCAL void eventCallback(struct event_handler_args arg) +{ + ASGINP *pasginp = (ASGINP *)arg.usr; + ASG *pasg = pasginp->pasg; + CAPVT *pcapvt = (CAPVT *)pasginp->capvt; + chid chid = pcapvt->chid; + int caStatus = arg.status; + READONLY struct dbr_sts_double *pdata = arg.dbr; + + if(ca_state(chid)!=cs_conn || !ca_read_access(chid)) { + if(!(pasg->inpBad & (1<inpIndex))) { + /*was good so lets make it bad*/ + pasg->inpBad |= (1<inpIndex); + if(!caInitializing) asComputeAsg(pasg); + if(asCaDebug) { + printf("as eventCallback %s inpBad ca_state %d" + " ca_read_access %d\n", + ca_name(chid),ca_state(chid),ca_read_access(chid)); + } + } + } else { + if(caStatus!=ECA_NORMAL) { + epicsPrintf("asCa: eventCallback error %s\n",ca_message(caStatus)); } else { - pasg->inpBad &= ~((1<inpIndex)); - pasg->pavalue[pasginp->inpIndex] = pdata->value; + pcapvt->rtndata = *pdata; /*structure copy*/ + if(pdata->severity==INVALID_ALARM) { + pasg->inpBad |= (1<inpIndex); + if(asCaDebug) + printf("as eventCallback %s inpBad because INVALID_ALARM\n", + ca_name(chid)); + } else { + pasg->inpBad &= ~((1<inpIndex)); + pasg->pavalue[pasginp->inpIndex] = pdata->value; + if(asCaDebug) + printf("as eventCallback %s inpGood data %f\n", + ca_name(chid),pdata->value); + } + pasg->inpChanged |= (1<inpIndex); + if(!caInitializing) asComputeAsg(pasg); } - pasg->inpChanged |= (1<inpIndex); - if(!caInitializing) asComputeAsg(pasg); } - if(Ilocked) FASTUNLOCK(&asLock); } LOCAL void asCaTask(void) @@ -161,66 +121,90 @@ LOCAL void asCaTask(void) taskwdInsert(taskIdSelf(),NULL,NULL); SEVCHK(ca_task_initialize(),"ca_task_initialize"); - caInitializing = TRUE; - FASTLOCK(&asLock); - pasg = (ASG *)ellFirst(&pasbase->asgList); - while(pasg) { - pasginp = (ASGINP *)ellFirst(&pasg->inpList); - while(pasginp) { - pasg->inpBad |= (1<inpIndex); - pcapvt = pasginp->capvt = asCalloc(1,sizeof(CAPVT)); - /*Note calls connectCallback immediately called for local Pvs*/ - SEVCHK(ca_search_and_connect(pasginp->inp,&pcapvt->chid, - connectCallback,pasginp),"ca_build_and_connect"); - /*Note calls accessRightsCallback immediately called for local Pvs*/ - SEVCHK(ca_replace_access_rights_event(pcapvt->chid,accessRightsCallback), - "ca_replace_access_rights_event"); - /*Note calls eventCallback immediately called for local Pvs*/ - SEVCHK(ca_add_event(DBR_STS_DOUBLE,pcapvt->chid, - eventCallback,pasginp,&pcapvt->evid), - "ca_add_event"); - pasginp = (ASGINP *)ellNext((ELLNODE *)pasginp); + while(TRUE) { + if(semTake(asCaTaskAddChannels,WAIT_FOREVER)!=OK) { + epicsPrintf("asCa semTake error for asCaTaskClearChannels\n"); + taskSuspend(0); } - pasg = (ASG *)ellNext((ELLNODE *)pasg); + caInitializing = TRUE; + pasg = (ASG *)ellFirst(&pasbase->asgList); + while(pasg) { + pasginp = (ASGINP *)ellFirst(&pasg->inpList); + while(pasginp) { + pasg->inpBad |= (1<inpIndex); + pcapvt = pasginp->capvt = asCalloc(1,sizeof(CAPVT)); + /*Note calls connectCallback immediately called for local Pvs*/ + SEVCHK(ca_search_and_connect(pasginp->inp,&pcapvt->chid, + connectCallback,pasginp),"ca_build_and_connect"); + /*Note calls eventCallback immediately called for local Pvs*/ + SEVCHK(ca_add_event(DBR_STS_DOUBLE,pcapvt->chid, + eventCallback,pasginp,0),"ca_add_event"); + pasginp = (ASGINP *)ellNext((ELLNODE *)pasginp); + } + pasg = (ASG *)ellNext((ELLNODE *)pasg); + } + asComputeAllAsg(); + caInitializing = FALSE; + if(asCaDebug) printf("asCaTask initialized\n"); + semGive(asCaTaskWait); + while(TRUE) { + if(semTake(asCaTaskClearChannels,NO_WAIT)==OK) break; + ca_pend_event(2.0); + } + pasg = (ASG *)ellFirst(&pasbase->asgList); + while(pasg) { + pasginp = (ASGINP *)ellFirst(&pasg->inpList); + while(pasginp) { + pcapvt = (CAPVT *)pasginp->capvt; + SEVCHK(ca_clear_channel(pcapvt->chid),"as ca_clear_channel"); + free(pasginp->capvt); + pasginp->capvt = 0; + pasginp = (ASGINP *)ellNext((ELLNODE *)pasginp); + } + pasg = (ASG *)ellNext((ELLNODE *)pasg); + } + if(asCaDebug) printf("asCaTask has cleared all channels\n"); + semGive(asCaTaskWait); } - asComputeAllAsg(); - caInitializing = FALSE; - FASTUNLOCK(&asLock); - SEVCHK(ca_pend_event(0.0),"ca_pend_event"); - exit(-1); } - + void asCaStart(void) { - taskid = taskSpawn("asCaTask",CA_CLIENT_PRI-1,VX_FP_TASK,CA_CLIENT_STACK, - (FUNCPTR)asCaTask,0,0,0,0,0,0,0,0,0,0); - if(taskid==ERROR) { - errMessage(0,"asCaStart: taskSpawn Failure\n"); - } else { - taskDelay(1); + if(asCaDebug) printf("asCaStart called\n"); + if(firstTime) { + firstTime = FALSE; + if((asCaTaskLock=semBCreate(SEM_Q_FIFO,SEM_FULL))==NULL) + epicsPrintf("asCa semBCreate failure\n"); + if((asCaTaskWait=semBCreate(SEM_Q_FIFO,SEM_EMPTY))==NULL) + epicsPrintf("asCa semBCreate failure\n"); + if((asCaTaskAddChannels=semBCreate(SEM_Q_FIFO,SEM_EMPTY))==NULL) + epicsPrintf("asCa semBCreate failure\n"); + if((asCaTaskClearChannels=semBCreate(SEM_Q_FIFO,SEM_EMPTY))==NULL) + epicsPrintf("asCa semBCreate failure\n"); + taskid = taskSpawn("asCaTask",CA_CLIENT_PRI-1,VX_FP_TASK, + CA_CLIENT_STACK, (FUNCPTR)asCaTask,0,0,0,0,0,0,0,0,0,0); + if(taskid==ERROR) { + errMessage(0,"asCaStart: taskSpawn Failure\n"); + } } + if(semTake(asCaTaskLock,WAIT_FOREVER)!=OK) + epicsPrintf("asCa semTake error\n"); + semGive(asCaTaskAddChannels); + if(semTake(asCaTaskWait,WAIT_FOREVER)!=OK) + epicsPrintf("asCa semTake error\n"); + if(asCaDebug) printf("asCaStart done\n"); + semGive(asCaTaskLock); } - + void asCaStop(void) { - ASG *pasg; - ASGINP *pasginp; - STATUS status; - if(taskid==0 || taskid==ERROR) return; - taskwdRemove(taskid); - status = taskDelete(taskid); - if(status!=OK) errMessage(0,"asCaStop: taskDelete Failure\n"); - while(taskIdVerify(taskid)==OK) { - taskDelay(5); - } - pasg = (ASG *)ellFirst(&pasbase->asgList); - while(pasg) { - pasginp = (ASGINP *)ellFirst(&pasg->inpList); - while(pasginp) { - free(pasginp->capvt); - pasginp = (ASGINP *)ellNext((ELLNODE *)pasginp); - } - pasg = (ASG *)ellNext((ELLNODE *)pasg); - } + if(asCaDebug) printf("asCaStop called\n"); + if(semTake(asCaTaskLock,WAIT_FOREVER)!=OK) + epicsPrintf("asCa semTake error\n"); + semGive(asCaTaskClearChannels); + if(semTake(asCaTaskWait,WAIT_FOREVER)!=OK) + epicsPrintf("asCa semTake error\n"); + if(asCaDebug) printf("asCaStop done\n"); + semGive(asCaTaskLock); } diff --git a/src/as/asDbLib.c b/src/as/asDbLib.c index 77866df75..099a01c57 100644 --- a/src/as/asDbLib.c +++ b/src/as/asDbLib.c @@ -5,53 +5,19 @@ COPYRIGHT NOTIFICATION ***************************************************************** -THE FOLLOWING IS A NOTICE OF COPYRIGHT, AVAILABILITY OF THE CODE, -AND DISCLAIMER WHICH MUST BE INCLUDED IN THE PROLOGUE OF THE CODE -AND IN ALL SOURCE LISTINGS OF THE CODE. - (C) COPYRIGHT 1993 UNIVERSITY OF CHICAGO - -Argonne National Laboratory (ANL), with facilities in the States of -Illinois and Idaho, is owned by the United States Government, and -operated by the University of Chicago under provision of a contract -with the Department of Energy. -Portions of this material resulted from work developed under a U.S. -Government contract and are subject to the following license: For -a period of five years from March 30, 1993, the Government is -granted for itself and others acting on its behalf a paid-up, -nonexclusive, irrevocable worldwide license in this computer -software to reproduce, prepare derivative works, and perform -publicly and display publicly. With the approval of DOE, this -period may be renewed for two additional five year periods. -Following the expiration of this period or periods, the Government -is granted for itself and others acting on its behalf, a paid-up, -nonexclusive, irrevocable worldwide license in this computer -software to reproduce, prepare derivative works, distribute copies -to the public, perform publicly and display publicly, and to permit -others to do so. +This software was developed under a United States Government license +described on the COPYRIGHT_UniversityOfChicago file included as part +of this distribution. +**********************************************************************/ -***************************************************************** - DISCLAIMER -***************************************************************** - -NEITHER THE UNITED STATES GOVERNMENT NOR ANY AGENCY THEREOF, NOR -THE UNIVERSITY OF CHICAGO, NOR ANY OF THEIR EMPLOYEES OR OFFICERS, -MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR ASSUMES ANY LEGAL -LIABILITY OR RESPONSIBILITY FOR THE ACCURACY, COMPLETENESS, OR -USEFULNESS OF ANY INFORMATION, APPARATUS, PRODUCT, OR PROCESS -DISCLOSED, OR REPRESENTS THAT ITS USE WOULD NOT INFRINGE PRIVATELY -OWNED RIGHTS. - -***************************************************************** -LICENSING INQUIRIES MAY BE DIRECTED TO THE INDUSTRIAL TECHNOLOGY -DEVELOPMENT CENTER AT ARGONNE NATIONAL LABORATORY (708-252-2000). - * +/* * Modification Log: * ----------------- * .01 02-11-94 mrk Initial Implementation */ - + #include #include #include @@ -75,31 +41,11 @@ DEVELOPMENT CENTER AT ARGONNE NATIONAL LABORATORY (708-252-2000). #include "task_params.h" extern struct dbBase *pdbbase; -static FILE *stream; -#define BUF_SIZE 100 -FAST_LOCK asLock; -static char *my_buffer; -static char *my_buffer_ptr=NULL; static char *pacf=NULL; -static int asLockInit=TRUE; +static char *psubstitutions=NULL; static int initTaskId=0; - - -static int my_yyinput(char *buf, int max_size) -{ - int l,n; - - if(*my_buffer_ptr==0) { - if(fgets(my_buffer,BUF_SIZE,stream)==NULL) return(0); - my_buffer_ptr = my_buffer; - } - l = strlen(my_buffer_ptr); - n = (l<=max_size ? l : max_size); - memcpy(buf,my_buffer_ptr,n); - my_buffer_ptr += n; - return(n); -} +static int firstTime = TRUE; static long asDbAddRecords(void) { @@ -129,11 +75,6 @@ static long asDbAddRecords(void) int asSetFilename(char *acf) { - if(asLockInit) { - FASTLOCKINIT(&asLock); - asLockInit = FALSE; - } - FASTLOCK(&asLock); if(pacf) free ((void *)pacf); if(acf) { pacf = calloc(1,strlen(acf)+1); @@ -145,41 +86,46 @@ int asSetFilename(char *acf) } else { pacf = NULL; } - FASTUNLOCK(&asLock); + return(0); +} + +int asSetSubstitutions(char *substitutions) +{ + if(psubstitutions) free ((void *)psubstitutions); + if(substitutions) { + psubstitutions = calloc(1,strlen(substitutions)+1); + if(!psubstitutions) { + errMessage(0,"asSetSubstitutions calloc failure"); + } else { + strcpy(psubstitutions,substitutions); + } + } else { + psubstitutions = NULL; + } return(0); } static long asInitCommon(void) { long status; - char buffer[BUF_SIZE]; + int asWasActive = asActive; - if(asLockInit) { - FASTLOCKINIT(&asLock); - asLockInit = FALSE; + if(firstTime) { + firstTime = FALSE; + if(!pacf) return(0); /*access security will NEVER be turned on*/ + } else { + if(!asActive) return(S_asLib_asNotActive); + if(pacf) { + asCaStop(); + } else { /*Just leave everything as is */ + return(S_asLib_badConfig); + } } - FASTLOCK(&asLock); - if(asActive)asCaStop(); - if(!pacf) { - asActive = FALSE; - return(0); - } - buffer[0] = 0; - my_buffer = buffer; - my_buffer_ptr = my_buffer; - stream = fopen(pacf,"r"); - if(!stream) { - errMessage(0,"asInit failure"); - FASTUNLOCK(&asLock); - return(-1); - } - status = asInitialize(my_yyinput); - if(fclose(stream)==EOF) errMessage(0,"asInit fclose failure"); + status = asInitFile(pacf,psubstitutions); if(asActive) { - asDbAddRecords(); + if(!asWasActive) asDbAddRecords(); asCaStart(); } - FASTUNLOCK(&asLock); return(status); } @@ -300,7 +246,7 @@ ASMEMBERPVT asDbGetMemberPvt(void *paddress) precord = paddr->precord; return((ASMEMBERPVT)precord->asp); } - + static void astacCallback(ASCLIENTPVT clientPvt,asClientStatus status) { char *recordname; @@ -350,41 +296,31 @@ static void myMemberCallback(ASMEMBERPVT memPvt) int asdbdump(void) { - FASTLOCK(&asLock); asDump(myMemberCallback,NULL,1); - FASTUNLOCK(&asLock); return(0); } int aspuag(char *uagname) { - FASTLOCK(&asLock); asDumpUag(uagname); - FASTUNLOCK(&asLock); return(0); } int asphag(char *hagname) { - FASTLOCK(&asLock); asDumpHag(hagname); - FASTUNLOCK(&asLock); return(0); } int asprules(char *asgname) { - FASTLOCK(&asLock); asDumpRules(asgname); - FASTUNLOCK(&asLock); return(0); } int aspmem(char *asgname,int clients) { - FASTLOCK(&asLock); asDumpMem(asgname,myMemberCallback,clients); - FASTUNLOCK(&asLock); return(0); } diff --git a/src/as/asDbLib.h b/src/as/asDbLib.h index cafc13033..5f943b80d 100644 --- a/src/as/asDbLib.h +++ b/src/as/asDbLib.h @@ -5,48 +5,14 @@ COPYRIGHT NOTIFICATION ***************************************************************** -THE FOLLOWING IS A NOTICE OF COPYRIGHT, AVAILABILITY OF THE CODE, -AND DISCLAIMER WHICH MUST BE INCLUDED IN THE PROLOGUE OF THE CODE -AND IN ALL SOURCE LISTINGS OF THE CODE. - (C) COPYRIGHT 1993 UNIVERSITY OF CHICAGO - -Argonne National Laboratory (ANL), with facilities in the States of -Illinois and Idaho, is owned by the United States Government, and -operated by the University of Chicago under provision of a contract -with the Department of Energy. -Portions of this material resulted from work developed under a U.S. -Government contract and are subject to the following license: For -a period of five years from March 30, 1993, the Government is -granted for itself and others acting on its behalf a paid-up, -nonexclusive, irrevocable worldwide license in this computer -software to reproduce, prepare derivative works, and perform -publicly and display publicly. With the approval of DOE, this -period may be renewed for two additional five year periods. -Following the expiration of this period or periods, the Government -is granted for itself and others acting on its behalf, a paid-up, -nonexclusive, irrevocable worldwide license in this computer -software to reproduce, prepare derivative works, distribute copies -to the public, perform publicly and display publicly, and to permit -others to do so. +This software was developed under a United States Government license +described on the COPYRIGHT_UniversityOfChicago file included as part +of this distribution. +**********************************************************************/ -***************************************************************** - DISCLAIMER -***************************************************************** - -NEITHER THE UNITED STATES GOVERNMENT NOR ANY AGENCY THEREOF, NOR -THE UNIVERSITY OF CHICAGO, NOR ANY OF THEIR EMPLOYEES OR OFFICERS, -MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR ASSUMES ANY LEGAL -LIABILITY OR RESPONSIBILITY FOR THE ACCURACY, COMPLETENESS, OR -USEFULNESS OF ANY INFORMATION, APPARATUS, PRODUCT, OR PROCESS -DISCLOSED, OR REPRESENTS THAT ITS USE WOULD NOT INFRINGE PRIVATELY -OWNED RIGHTS. - -***************************************************************** -LICENSING INQUIRIES MAY BE DIRECTED TO THE INDUSTRIAL TECHNOLOGY -DEVELOPMENT CENTER AT ARGONNE NATIONAL LABORATORY (708-252-2000). - * +/* * Modification Log: * ----------------- * .01 02-23-94 mrk Initial Implementation @@ -63,6 +29,7 @@ typedef struct { } ASDBCALLBACK; int asSetFilename(char *acf); +int asSetSubstitutions(char *substitutions); int asInit(void); int asInitAsyn(ASDBCALLBACK *pcallback); int asDbGetAsl( void *paddr); diff --git a/src/as/asLib.h b/src/as/asLib.h index e3e6cf9b9..b04e87f23 100644 --- a/src/as/asLib.h +++ b/src/as/asLib.h @@ -4,48 +4,14 @@ COPYRIGHT NOTIFICATION ***************************************************************** -THE FOLLOWING IS A NOTICE OF COPYRIGHT, AVAILABILITY OF THE CODE, -AND DISCLAIMER WHICH MUST BE INCLUDED IN THE PROLOGUE OF THE CODE -AND IN ALL SOURCE LISTINGS OF THE CODE. - (C) COPYRIGHT 1993 UNIVERSITY OF CHICAGO - -Argonne National Laboratory (ANL), with facilities in the States of -Illinois and Idaho, is owned by the United States Government, and -operated by the University of Chicago under provision of a contract -with the Department of Energy. -Portions of this material resulted from work developed under a U.S. -Government contract and are subject to the following license: For -a period of five years from March 30, 1993, the Government is -granted for itself and others acting on its behalf a paid-up, -nonexclusive, irrevocable worldwide license in this computer -software to reproduce, prepare derivative works, and perform -publicly and display publicly. With the approval of DOE, this -period may be renewed for two additional five year periods. -Following the expiration of this period or periods, the Government -is granted for itself and others acting on its behalf, a paid-up, -nonexclusive, irrevocable worldwide license in this computer -software to reproduce, prepare derivative works, distribute copies -to the public, perform publicly and display publicly, and to permit -others to do so. +This software was developed under a United States Government license +described on the COPYRIGHT_UniversityOfChicago file included as part +of this distribution. +**********************************************************************/ -***************************************************************** - DISCLAIMER -***************************************************************** - -NEITHER THE UNITED STATES GOVERNMENT NOR ANY AGENCY THEREOF, NOR -THE UNIVERSITY OF CHICAGO, NOR ANY OF THEIR EMPLOYEES OR OFFICERS, -MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR ASSUMES ANY LEGAL -LIABILITY OR RESPONSIBILITY FOR THE ACCURACY, COMPLETENESS, OR -USEFULNESS OF ANY INFORMATION, APPARATUS, PRODUCT, OR PROCESS -DISCLOSED, OR REPRESENTS THAT ITS USE WOULD NOT INFRINGE PRIVATELY -OWNED RIGHTS. - -***************************************************************** -LICENSING INQUIRIES MAY BE DIRECTED TO THE INDUSTRIAL TECHNOLOGY -DEVELOPMENT CENTER AT ARGONNE NATIONAL LABORATORY (708-252-2000). - * +/* * Modification Log: * ----------------- * .01 09-27-93 mrk Initial Implementation @@ -55,9 +21,10 @@ DEVELOPMENT CENTER AT ARGONNE NATIONAL LABORATORY (708-252-2000). #include #include +#include #include #include - + typedef struct asgMember *ASMEMBERPVT; typedef struct asgClient *ASCLIENTPVT; typedef int (*ASINPUTFUNCPTR)(char *buf,int max_size); @@ -65,14 +32,25 @@ typedef enum{ asClientCOAR /*Change of access rights*/ /*For now this is all*/ } asClientStatus; + typedef void (*ASCLIENTCALLBACK) (ASCLIENTPVT,asClientStatus); /* The following routines are macros with the following syntax long asCheckGet(ASCLIENTPVT asClientPvt); long asCheckPut(ASCLIENTPVT asClientPvt); -end of macros */ +#define asCheckGet(asClientPvt)\ + (asActive ?\ + ((asClientPvt)->access>=asREAD ? TRUE : FALSE)\ + : TRUE) +#define asCheckPut(asClientPvt)\ + (asActive ?\ + ((asClientPvt)->access>=asWRITE ? TRUE : FALSE)\ + : TRUE) + int asInit(void); long asInitialize(ASINPUTFUNCPTR inputfunction); +long asInitFile(const char *filename,const char *substitutions); +long asInitFP(FILE *fp,const char *substitutions); /*caller must provide permanent storage for asgName*/ long asAddMember(ASMEMBERPVT *asMemberPvt,char *asgName); long asRemoveMember(ASMEMBERPVT *asMemberPvt); @@ -91,9 +69,12 @@ void asPutClientPvt(ASCLIENTPVT asClientPvt,void *userPvt); long asRegisterClientCallback(ASCLIENTPVT asClientPvt, ASCLIENTCALLBACK pcallback); long asComputeAllAsg(void); -/*asComputeAsg is defined after ASG is defined*/ +/* following declared below after ASG is declared +long asComputeAsg(ASG *pasg); +*/ long asCompute(ASCLIENTPVT asClientPvt); -int asDump(void (*memcallback)(ASMEMBERPVT),void (*clientcallback)(ASCLIENTPVT),int verbose); +int asDump(void (*memcallback)(ASMEMBERPVT), + void (*clientcallback)(ASCLIENTPVT),int verbose); int asDumpUag(char *uagname); int asDumpHag(char *hagname); int asDumpRules(char *asgname); @@ -117,17 +98,6 @@ int asDumpHash(void); /*Private declarations */ #define ASMAXINP 12 -#ifdef vxWorks -#include -#else -/*This only works in a single threaded environment */ -#define FAST_LOCK int -#define FASTLOCKINIT(PFAST_LOCK) -#define FASTLOCK(PFAST_LOCK) -#define FASTUNLOCK(PFAST_LOCK) -#endif -extern int asLockInit; -extern FAST_LOCK asLock; extern int asActive; /* definition of access rights*/ typedef enum{asNOACCESS,asREAD,asWRITE} asAccessRights; @@ -186,6 +156,7 @@ typedef struct{ struct asg *pasg; int inpIndex; }ASGINP; + typedef struct asg{ ELLNODE node; char *name; @@ -213,17 +184,9 @@ typedef struct asgClient { int level; asAccessRights access; } ASGCLIENT; -/* function prototypes*/ -void *asCalloc(size_t nobj,size_t size); + long asComputeAsg(ASG *pasg); -/*macros*/ -#define asCheckGet(asClientPvt)\ - (asActive ?\ - ((asClientPvt)->access>=asREAD ? TRUE : FALSE)\ - : TRUE) -#define asCheckPut(asClientPvt)\ - (asActive ?\ - ((asClientPvt)->access>=asWRITE ? TRUE : FALSE)\ - : TRUE) +/*following is "friend" function*/ +void * asCalloc(size_t nobj,size_t size); #endif /*INCasLibh*/ diff --git a/src/as/asLib.y b/src/as/asLib.y index b41dcb3a8..aad348e2b 100644 --- a/src/as/asLib.y +++ b/src/as/asLib.y @@ -42,7 +42,7 @@ asconfig_item: tokenUAG uag_head uag_body uag_head: '(' tokenNAME ')' { yyUag = asUagAdd($2); - if(!yyUag) yyerror($2); + if(!yyUag) yyerror(""); free((void *)$2); } ; @@ -63,7 +63,6 @@ uag_user_list_name: tokenNAME status = asUagAddUser(yyUag,$1); if(status) { - errMessage(status,"Error while adding UAG"); yyerror($1); } free((void *)$1); @@ -73,7 +72,7 @@ uag_user_list_name: tokenNAME hag_head: '(' tokenNAME ')' { yyHag = asHagAdd($2); - if(!yyHag) yyerror($2); + if(!yyHag) yyerror(""); free((void *)$2); } ; @@ -91,8 +90,7 @@ hag_user_list_name: tokenNAME status = asHagAddHost(yyHag,$1); if(status) { - errMessage(status,"Error while adding HAG"); - yyerror($1); + yyerror(""); } free((void *)$1); } @@ -101,7 +99,7 @@ hag_user_list_name: tokenNAME asg_head: '(' tokenNAME ')' { yyAsg = asAsgAdd($2); - if(!yyAsg) yyerror($2); + if(!yyAsg) yyerror(""); free((void *)$2); } ; @@ -122,8 +120,7 @@ inp_config: tokenINP '(' inp_body ')' status = asAsgAddInp(yyAsg,$3,$1); if(status) { - errMessage(status,"Error while adding INP"); - yyerror($1); + yyerror(""); } free((void *)$3); } @@ -170,8 +167,7 @@ rule_list_item: tokenUAG '(' rule_uag_list ')' status = asAsgRuleCalc(yyAsgRule,$3); if(status){ - errMessage(status,$3); - yyerror("CALC failure"); + yyerror("access security CALC failure"); } free((void *)$3); } @@ -187,8 +183,7 @@ rule_uag_list_name: tokenNAME status = asAsgRuleUagAdd(yyAsgRule,$1); if(status) { - errMessage(status,"Error while adding UAG"); - yyerror($1); + yyerror(""); } free((void *)$1); } @@ -204,8 +199,7 @@ rule_hag_list_name: tokenNAME status = asAsgRuleHagAdd(yyAsgRule,$1); if(status) { - errMessage(status,"Error while adding HAG"); - yyerror($1); + yyerror(""); } free((void *)$1); } @@ -217,7 +211,8 @@ rule_hag_list_name: tokenNAME static int yyerror(str) char *str; { - fprintf(stderr,"Error line %d : %s %s\n",line_num,str,yytext); + epicsPrintf("Access Security Error(%s) line %d token %s\n", + str,line_num,yytext); yyFailed = TRUE; return(0); } diff --git a/src/as/asLibRoutines.c b/src/as/asLibRoutines.c index 527a0ecca..d2c57862d 100644 --- a/src/as/asLibRoutines.c +++ b/src/as/asLibRoutines.c @@ -5,48 +5,14 @@ COPYRIGHT NOTIFICATION ***************************************************************** -THE FOLLOWING IS A NOTICE OF COPYRIGHT, AVAILABILITY OF THE CODE, -AND DISCLAIMER WHICH MUST BE INCLUDED IN THE PROLOGUE OF THE CODE -AND IN ALL SOURCE LISTINGS OF THE CODE. - (C) COPYRIGHT 1993 UNIVERSITY OF CHICAGO - -Argonne National Laboratory (ANL), with facilities in the States of -Illinois and Idaho, is owned by the United States Government, and -operated by the University of Chicago under provision of a contract -with the Department of Energy. -Portions of this material resulted from work developed under a U.S. -Government contract and are subject to the following license: For -a period of five years from March 30, 1993, the Government is -granted for itself and others acting on its behalf a paid-up, -nonexclusive, irrevocable worldwide license in this computer -software to reproduce, prepare derivative works, and perform -publicly and display publicly. With the approval of DOE, this -period may be renewed for two additional five year periods. -Following the expiration of this period or periods, the Government -is granted for itself and others acting on its behalf, a paid-up, -nonexclusive, irrevocable worldwide license in this computer -software to reproduce, prepare derivative works, distribute copies -to the public, perform publicly and display publicly, and to permit -others to do so. +This software was developed under a United States Government license +described on the COPYRIGHT_UniversityOfChicago file included as part +of this distribution. +**********************************************************************/ -***************************************************************** - DISCLAIMER -***************************************************************** - -NEITHER THE UNITED STATES GOVERNMENT NOR ANY AGENCY THEREOF, NOR -THE UNIVERSITY OF CHICAGO, NOR ANY OF THEIR EMPLOYEES OR OFFICERS, -MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR ASSUMES ANY LEGAL -LIABILITY OR RESPONSIBILITY FOR THE ACCURACY, COMPLETENESS, OR -USEFULNESS OF ANY INFORMATION, APPARATUS, PRODUCT, OR PROCESS -DISCLOSED, OR REPRESENTS THAT ITS USE WOULD NOT INFRINGE PRIVATELY -OWNED RIGHTS. - -***************************************************************** -LICENSING INQUIRIES MAY BE DIRECTED TO THE INDUSTRIAL TECHNOLOGY -DEVELOPMENT CENTER AT ARGONNE NATIONAL LABORATORY (708-252-2000). - * +/* * Modification Log: * ----------------- * .01 10-15-93 mrk Initial Implementation @@ -66,20 +32,36 @@ DEVELOPMENT CENTER AT ARGONNE NATIONAL LABORATORY (708-252-2000). #include "asLib.h" #include "gpHash.h" #include "freeList.h" +#include "macLib.h" #include "postfix.h" -/*Declare storage for Global Variables */ -ASBASE *pasbase=NULL; +#ifdef vxWorks +#include +#else +/*This only works in a single threaded environment */ +#define FAST_LOCK int +#define FASTLOCKINIT(PFAST_LOCK) +#define FASTLOCK(PFAST_LOCK) +#define FASTUNLOCK(PFAST_LOCK) +#endif +static FAST_LOCK asLock; +static int asLockInit=TRUE; int asActive = FALSE; - -/*storage for freelist */ static void *freeListPvt = NULL; +/*following must be global because asCa nneeds it*/ +ASBASE volatile *pasbase=NULL; +static ASBASE *pasbasenew=NULL; + #define RPCL_LEN 184 #define DEFAULT "DEFAULT" /*private routines */ +static long asAddMemberPvt(ASMEMBERPVT *pasMemberPvt,char *asgName); +static long asComputeAllAsgPvt(void); +static long asComputeAsgPvt(ASG *pasg); +static long asComputePvt(ASCLIENTPVT asClientPvt); static void asFreeAll(ASBASE *pasbase); static UAG *asUagAdd(char *uagName); static long asUagAddUser(UAG *puag,char *user); @@ -92,43 +74,59 @@ static long asAsgRuleUagAdd(ASGRULE *pasgrule,char *name); static long asAsgRuleHagAdd(ASGRULE *pasgrule,char *name); static long asAsgRuleCalc(ASGRULE *pasgrule,char *calc); +/* + asInitialize can be called while access security is already active. + This is accomplished by doing the following: + + The version pointed to by pasbase is kept as is but locked against changes + A new version is created and pointed to by pasbasenew + If anything goes wrong. The original version is kept. This results is some + wasted space but at least things still work. + If the new access security configuration is successfully read then: + the old memberList is moved from old to new. + the old structures are freed. +*/ long asInitialize(ASINPUTFUNCPTR inputfunction) { ASG *pasg; long status; - ASBASE *pasbaseold; + ASBASE *pasbaseold; GPHENTRY *pgphentry; UAG *puag; UAGNAME *puagname; HAG *phag; HAGNAME *phagname; - pasbaseold = pasbase; - pasbase = asCalloc(1,sizeof(ASBASE)); + if(asLockInit) { + FASTLOCKINIT(&asLock); + asLockInit = FALSE; + } + FASTLOCK(&asLock); + pasbasenew = asCalloc(1,sizeof(ASBASE)); if(!freeListPvt) freeListInitPvt(&freeListPvt,sizeof(ASGCLIENT),20); - ellInit(&pasbase->uagList); - ellInit(&pasbase->hagList); - ellInit(&pasbase->asgList); + ellInit(&pasbasenew->uagList); + ellInit(&pasbasenew->hagList); + ellInit(&pasbasenew->asgList); asAsgAdd(DEFAULT); status = myParse(inputfunction); if(status) { status = S_asLib_badConfig; /*Not safe to call asFreeAll */ - pasbase = pasbaseold; + FASTUNLOCK(&asLock); return(status); } - pasg = (ASG *)ellFirst(&pasbase->asgList); + pasg = (ASG *)ellFirst(&pasbasenew->asgList); while(pasg) { pasg->pavalue = asCalloc(ASMAXINP,sizeof(double)); pasg = (ASG *)ellNext((ELLNODE *)pasg); } - gphInitPvt(&pasbase->phash,256); + gphInitPvt(&((ASBASE *)pasbasenew)->phash,256); /*Hash each uagname and each hagname*/ - puag = (UAG *)ellFirst(&pasbase->uagList); + puag = (UAG *)ellFirst(&pasbasenew->uagList); while(puag) { puagname = (UAGNAME *)ellFirst(&puag->list); while(puagname) { - pgphentry = gphAdd(pasbase->phash,puagname->user,puag); + pgphentry = gphAdd(pasbasenew->phash,puagname->user,puag); if(!pgphentry) { epicsPrintf("UAG %s duplicate user = %s\n", puag->name, puagname->user); @@ -137,11 +135,11 @@ long asInitialize(ASINPUTFUNCPTR inputfunction) } puag = (UAG *)ellNext((ELLNODE *)puag); } - phag = (HAG *)ellFirst(&pasbase->hagList); + phag = (HAG *)ellFirst(&pasbasenew->hagList); while(phag) { phagname = (HAGNAME *)ellFirst(&phag->list); while(phagname) { - pgphentry = gphAdd(pasbase->phash,phagname->host,phag); + pgphentry = gphAdd(pasbasenew->phash,phagname->host,phag); if(!pgphentry) { epicsPrintf("HAG %s duplicate host = %s\n", phag->name,phagname->host); @@ -150,7 +148,8 @@ long asInitialize(ASINPUTFUNCPTR inputfunction) } phag = (HAG *)ellNext((ELLNODE *)phag); } - asActive = TRUE; + pasbaseold = (ASBASE *)pasbase; + pasbase = (ASBASE volatile *)pasbasenew; if(pasbaseold) { ASG *poldasg; ASGMEMBER *poldmem; @@ -162,55 +161,118 @@ long asInitialize(ASINPUTFUNCPTR inputfunction) while(poldmem) { pnextoldmem = (ASGMEMBER *)ellNext((ELLNODE *)poldmem); ellDelete(&poldasg->memberList,(ELLNODE *)poldmem); - status = asAddMember(&poldmem,poldmem->asgName); + status = asAddMemberPvt(&poldmem,poldmem->asgName); poldmem = pnextoldmem; } poldasg = (ASG *)ellNext((ELLNODE *)poldasg); } asFreeAll(pasbaseold); } + asActive = TRUE; + FASTUNLOCK(&asLock); return(0); } + +long asInitFile(const char *filename,const char *substitutions) +{ + FILE *fp; + long status; + + fp = fopen(filename,"r"); + if(!fp) { + errMessage(0,"asInitFile failure on fopen"); + return(S_asLib_badConfig); + } + status = asInitFP(fp,substitutions); + if(fclose(fp)==EOF) { + errMessage(0,"asInitFile fclose failure"); + if(!status) status = S_asLib_badConfig; + } + return(status); +} + +#define BUF_SIZE 200 +static char *my_buffer; +static char *my_buffer_ptr; +static FILE *stream; +static char *mac_input_buffer=NULL; +static MAC_HANDLE *macHandle = NULL; + +static int myInputFunction(char *buf, int max_size) +{ + int l,n; + char *fgetsRtn; + + if(*my_buffer_ptr==0) { + if(macHandle) { + fgetsRtn = fgets(mac_input_buffer,BUF_SIZE,stream); + if(fgetsRtn) { + n = macExpandString(macHandle,mac_input_buffer, + my_buffer,BUF_SIZE-1); + if(n<0) { + epicsPrintf("access security: macExpandString failed\n" + "input line: %s\n",mac_input_buffer); + return(0); + } + } + } else { + fgetsRtn = fgets(my_buffer,BUF_SIZE,stream); + } + if(fgetsRtn==NULL) return(0); + my_buffer_ptr = my_buffer; + } + l = strlen(my_buffer_ptr); + n = (l<=max_size ? l : max_size); + memcpy(buf,my_buffer_ptr,n); + my_buffer_ptr += n; + return(n); +} + +long asInitFP(FILE *fp,const char *substitutions) +{ + char buffer[BUF_SIZE]; + char mac_buffer[BUF_SIZE]; + long status; + char **macPairs; + + buffer[0] = 0; + my_buffer = buffer; + my_buffer_ptr = my_buffer; + stream = fp; + if(substitutions) { + if((status = macCreateHandle(&macHandle,NULL))) { + errMessage(status,"asInitFP: macCreateHandle error"); + return(status); + } + macParseDefns(macHandle,(char *)substitutions,&macPairs); + if(macPairs ==NULL) { + macDeleteHandle(macHandle); + macHandle = NULL; + } else { + macInstallMacros(macHandle,macPairs); + free((void *)macPairs); + mac_input_buffer = mac_buffer; + } + } + status = asInitialize(myInputFunction); + if(macHandle) { + macDeleteHandle(macHandle); + macHandle = NULL; + } + return(status); +} long asAddMember(ASMEMBERPVT *pasMemberPvt,char *asgName) { - ASGMEMBER *pasgmember; - ASG *pgroup; - ASGCLIENT *pasgclient; + long status; if(!asActive) return(S_asLib_asNotActive); - if(*pasMemberPvt) { - pasgmember = *pasMemberPvt; - } else { - pasgmember = asCalloc(1,sizeof(ASGMEMBER)); - ellInit(&pasgmember->clientList); - *pasMemberPvt = pasgmember; - } - pasgmember->asgName = asgName; - pgroup = (ASG *)ellFirst(&pasbase->asgList); - while(pgroup) { - if(strcmp(pgroup->name,pasgmember->asgName)==0) goto got_it; - pgroup = (ASG *)ellNext((ELLNODE *)pgroup); - } - /* Put it in DEFAULT*/ - pgroup = (ASG *)ellFirst(&pasbase->asgList); - while(pgroup) { - if(strcmp(pgroup->name,DEFAULT)==0) goto got_it; - pgroup = (ASG *)ellNext((ELLNODE *)pgroup); - } - errMessage(-1,"Logic Error in asAddMember"); - exit(1); -got_it: - pasgmember->pasg = pgroup; - ellAdd(&pgroup->memberList,(ELLNODE *)pasgmember); - pasgclient = (ASGCLIENT *)ellFirst(&pasgmember->clientList); - while(pasgclient) { - asCompute((ASCLIENTPVT)pasgclient); - pasgclient = (ASGCLIENT *)ellNext((ELLNODE *)pasgclient); - } - return(0); + FASTLOCK(&asLock); + status = asAddMemberPvt(pasMemberPvt,asgName); + FASTUNLOCK(&asLock); + return(status); } - + long asRemoveMember(ASMEMBERPVT *asMemberPvt) { ASGMEMBER *pasgmember; @@ -218,15 +280,18 @@ long asRemoveMember(ASMEMBERPVT *asMemberPvt) if(!asActive) return(S_asLib_asNotActive); pasgmember = *asMemberPvt; if(!pasgmember) return(S_asLib_badMember); + FASTLOCK(&asLock); if(ellCount(&pasgmember->clientList)>0) return(S_asLib_clientsExist); if(pasgmember->pasg) { ellDelete(&pasgmember->pasg->memberList,(ELLNODE *)pasgmember); } else { errMessage(-1,"Logic error in asRemoveMember"); + FASTUNLOCK(&asLock); exit(-1); } free((void *)pasgmember); *asMemberPvt = NULL; + FASTUNLOCK(&asLock); return(0); } @@ -288,7 +353,7 @@ long asAddClient(ASCLIENTPVT *pasClientPvt,ASMEMBERPVT asMemberPvt, pasgclient->host = host; FASTLOCK(&asLock); ellAdd(&pasgmember->clientList,(ELLNODE *)pasgclient); - status = asCompute(pasgclient); + status = asComputePvt(pasgclient); FASTUNLOCK(&asLock); return(status); } @@ -300,15 +365,15 @@ long asChangeClient(ASCLIENTPVT asClientPvt,int asl,char *user,char *host) if(!asActive) return(S_asLib_asNotActive); if(!pasgclient) return(S_asLib_badClient); + FASTLOCK(&asLock); pasgclient->level = asl; pasgclient->user = user; pasgclient->host = host; - FASTLOCK(&asLock); - status = asCompute(pasgclient); + status = asComputePvt(pasgclient); FASTUNLOCK(&asLock); return(status); } - + long asRemoveClient(ASCLIENTPVT *asClientPvt) { ASGCLIENT *pasgclient = *asClientPvt; @@ -329,7 +394,7 @@ long asRemoveClient(ASCLIENTPVT *asClientPvt) *asClientPvt = NULL; return(0); } - + long asRegisterClientCallback(ASCLIENTPVT asClientPvt, ASCLIENTCALLBACK pcallback) { @@ -343,7 +408,7 @@ long asRegisterClientCallback(ASCLIENTPVT asClientPvt, FASTUNLOCK(&asLock); return(0); } - + void *asGetClientPvt(ASCLIENTPVT asClientPvt) { ASGCLIENT *pasgclient = asClientPvt; @@ -358,125 +423,46 @@ void asPutClientPvt(ASCLIENTPVT asClientPvt,void *userPvt) ASGCLIENT *pasgclient = asClientPvt; if(!asActive) return; if(!pasgclient) return; + FASTLOCK(&asLock); pasgclient->userPvt = userPvt; + FASTUNLOCK(&asLock); } long asComputeAllAsg(void) { - ASG *pasg; + long status; if(!asActive) return(S_asLib_asNotActive); - pasg = (ASG *)ellFirst(&pasbase->asgList); - while(pasg) { - asComputeAsg(pasg); - pasg = (ASG *)ellNext((ELLNODE *)pasg); - } - return(0); + FASTLOCK(&asLock); + status = asComputeAllAsgPvt(); + FASTUNLOCK(&asLock); + return(status); } long asComputeAsg(ASG *pasg) { - ASGRULE *pasgrule; - ASGMEMBER *pasgmember; - ASGCLIENT *pasgclient; + long status; if(!asActive) return(S_asLib_asNotActive); - pasgrule = (ASGRULE *)ellFirst(&pasg->ruleList); - while(pasgrule) { - double result; - long status; - - if(pasgrule->calc && (pasg->inpChanged & pasgrule->inpUsed)) { - status = calcPerform(pasg->pavalue,&result,pasgrule->rpcl); - if(status) { - pasgrule->result = 0; - errMessage(status,"asComputeAsg"); - } else { - pasgrule->result = ((result>.99) && (result<1.01)) ? 1 : 0; - } - } - pasgrule = (ASGRULE *)ellNext((ELLNODE *)pasgrule); - } - pasg->inpChanged = FALSE; - pasgmember = (ASGMEMBER *)ellFirst(&pasg->memberList); - while(pasgmember) { - pasgclient = (ASGCLIENT *)ellFirst(&pasgmember->clientList); - while(pasgclient) { - asCompute((ASCLIENTPVT)pasgclient); - pasgclient = (ASGCLIENT *)ellNext((ELLNODE *)pasgclient); - } - pasgmember = (ASGMEMBER *)ellNext((ELLNODE *)pasgmember); - } - return(0); + FASTLOCK(&asLock); + status = asComputeAsgPvt(pasg); + FASTUNLOCK(&asLock); + return(status); } - + long asCompute(ASCLIENTPVT asClientPvt) { - asAccessRights access=asNOACCESS; - ASGCLIENT *pasgclient = asClientPvt; - ASGMEMBER *pasgMember; - ASG *pasg; - ASGRULE *pasgrule; - asAccessRights oldaccess; - GPHENTRY *pgphentry; + long status; if(!asActive) return(S_asLib_asNotActive); - if(!pasgclient) return(S_asLib_badClient); - pasgMember = pasgclient->pasgMember; - if(!pasgMember) return(S_asLib_badMember); - pasg = pasgMember->pasg; - if(!pasg) return(S_asLib_badAsg); - oldaccess=pasgclient->access; - pasgrule = (ASGRULE *)ellFirst(&pasg->ruleList); - while(pasgrule) { - if(access == asWRITE) break; - if(access>=pasgrule->access) goto next_rule; - if(pasgclient->level > pasgrule->level) goto next_rule; - /*if uagList is empty then no need to check uag*/ - if(ellCount(&pasgrule->uagList)>0){ - ASGUAG *pasguag; - UAG *puag; - - pasguag = (ASGUAG *)ellFirst(&pasgrule->uagList); - while(pasguag) { - if((puag = pasguag->puag)) { - pgphentry = gphFind(pasbase->phash,pasgclient->user,puag); - if(pgphentry) goto check_hag; - } - pasguag = (ASGUAG *)ellNext((ELLNODE *)pasguag); - } - goto next_rule; - } -check_hag: - /*if hagList is empty then no need to check hag*/ - if(ellCount(&pasgrule->hagList)>0) { - ASGHAG *pasghag; - HAG *phag; - - pasghag = (ASGHAG *)ellFirst(&pasgrule->hagList); - while(pasghag) { - if((phag = pasghag->phag)) { - pgphentry=gphFind(pasbase->phash,pasgclient->host,phag); - if(pgphentry) goto check_calc; - } - pasghag = (ASGHAG *)ellNext((ELLNODE *)pasghag); - } - goto next_rule; - } -check_calc: - if(!pasgrule->calc - || (!(pasg->inpBad & pasgrule->inpUsed) && (pasgrule->result==1))) - access = pasgrule->access; -next_rule: - pasgrule = (ASGRULE *)ellNext((ELLNODE *)pasgrule); - } - pasgclient->access = access; - if(pasgclient->pcallback && oldaccess!=access) { - (*pasgclient->pcallback)(pasgclient,asClientCOAR); - } - return(0); + FASTLOCK(&asLock); + status = asComputePvt(asClientPvt); + FASTUNLOCK(&asLock); + return(status); } +/*The dump routines do not lock. Thus they may get inconsistant data.*/ +/*HOWEVER if they did lock and a user interrupts one of then then BAD BAD*/ static char *asAccessName[] = {"NONE","READ","WRITE"}; static char *asLevelName[] = {"ASL0","ASL1"}; int asDump( @@ -805,6 +791,7 @@ int asDumpHash(void) } /*Start of private routines*/ +/* asCalloc is "friend" function */ void * asCalloc(size_t nobj,size_t size) { void *p; @@ -818,6 +805,160 @@ void * asCalloc(size_t nobj,size_t size) #endif return(NULL); } + +static long asAddMemberPvt(ASMEMBERPVT *pasMemberPvt,char *asgName) +{ + ASGMEMBER *pasgmember; + ASG *pgroup; + ASGCLIENT *pasgclient; + + if(*pasMemberPvt) { + pasgmember = *pasMemberPvt; + } else { + pasgmember = asCalloc(1,sizeof(ASGMEMBER)); + ellInit(&pasgmember->clientList); + *pasMemberPvt = pasgmember; + } + pasgmember->asgName = asgName; + pgroup = (ASG *)ellFirst(&pasbase->asgList); + while(pgroup) { + if(strcmp(pgroup->name,pasgmember->asgName)==0) goto got_it; + pgroup = (ASG *)ellNext((ELLNODE *)pgroup); + } + /* Put it in DEFAULT*/ + pgroup = (ASG *)ellFirst(&pasbase->asgList); + while(pgroup) { + if(strcmp(pgroup->name,DEFAULT)==0) goto got_it; + pgroup = (ASG *)ellNext((ELLNODE *)pgroup); + } + errMessage(-1,"Logic Error in asAddMember"); + exit(1); +got_it: + pasgmember->pasg = pgroup; + ellAdd(&pgroup->memberList,(ELLNODE *)pasgmember); + pasgclient = (ASGCLIENT *)ellFirst(&pasgmember->clientList); + while(pasgclient) { + asComputePvt((ASCLIENTPVT)pasgclient); + pasgclient = (ASGCLIENT *)ellNext((ELLNODE *)pasgclient); + } + return(0); +} + +static long asComputeAllAsgPvt(void) +{ + ASG *pasg; + + if(!asActive) return(S_asLib_asNotActive); + pasg = (ASG *)ellFirst(&pasbase->asgList); + while(pasg) { + asComputeAsgPvt(pasg); + pasg = (ASG *)ellNext((ELLNODE *)pasg); + } + return(0); +} + +static long asComputeAsgPvt(ASG *pasg) +{ + ASGRULE *pasgrule; + ASGMEMBER *pasgmember; + ASGCLIENT *pasgclient; + + if(!asActive) return(S_asLib_asNotActive); + pasgrule = (ASGRULE *)ellFirst(&pasg->ruleList); + while(pasgrule) { + double result; + long status; + + if(pasgrule->calc && (pasg->inpChanged & pasgrule->inpUsed)) { + status = calcPerform(pasg->pavalue,&result,pasgrule->rpcl); + if(status) { + pasgrule->result = 0; + errMessage(status,"asComputeAsg"); + } else { + pasgrule->result = ((result>.99) && (result<1.01)) ? 1 : 0; + } + } + pasgrule = (ASGRULE *)ellNext((ELLNODE *)pasgrule); + } + pasg->inpChanged = FALSE; + pasgmember = (ASGMEMBER *)ellFirst(&pasg->memberList); + while(pasgmember) { + pasgclient = (ASGCLIENT *)ellFirst(&pasgmember->clientList); + while(pasgclient) { + asComputePvt((ASCLIENTPVT)pasgclient); + pasgclient = (ASGCLIENT *)ellNext((ELLNODE *)pasgclient); + } + pasgmember = (ASGMEMBER *)ellNext((ELLNODE *)pasgmember); + } + return(0); +} + +static long asComputePvt(ASCLIENTPVT asClientPvt) +{ + asAccessRights access=asNOACCESS; + ASGCLIENT *pasgclient = asClientPvt; + ASGMEMBER *pasgMember; + ASG *pasg; + ASGRULE *pasgrule; + asAccessRights oldaccess; + GPHENTRY *pgphentry; + + if(!asActive) return(S_asLib_asNotActive); + if(!pasgclient) return(S_asLib_badClient); + pasgMember = pasgclient->pasgMember; + if(!pasgMember) return(S_asLib_badMember); + pasg = pasgMember->pasg; + if(!pasg) return(S_asLib_badAsg); + oldaccess=pasgclient->access; + pasgrule = (ASGRULE *)ellFirst(&pasg->ruleList); + while(pasgrule) { + if(access == asWRITE) break; + if(access>=pasgrule->access) goto next_rule; + if(pasgclient->level > pasgrule->level) goto next_rule; + /*if uagList is empty then no need to check uag*/ + if(ellCount(&pasgrule->uagList)>0){ + ASGUAG *pasguag; + UAG *puag; + + pasguag = (ASGUAG *)ellFirst(&pasgrule->uagList); + while(pasguag) { + if((puag = pasguag->puag)) { + pgphentry = gphFind(pasbase->phash,pasgclient->user,puag); + if(pgphentry) goto check_hag; + } + pasguag = (ASGUAG *)ellNext((ELLNODE *)pasguag); + } + goto next_rule; + } +check_hag: + /*if hagList is empty then no need to check hag*/ + if(ellCount(&pasgrule->hagList)>0) { + ASGHAG *pasghag; + HAG *phag; + + pasghag = (ASGHAG *)ellFirst(&pasgrule->hagList); + while(pasghag) { + if((phag = pasghag->phag)) { + pgphentry=gphFind(pasbase->phash,pasgclient->host,phag); + if(pgphentry) goto check_calc; + } + pasghag = (ASGHAG *)ellNext((ELLNODE *)pasghag); + } + goto next_rule; + } +check_calc: + if(!pasgrule->calc + || (!(pasg->inpBad & pasgrule->inpUsed) && (pasgrule->result==1))) + access = pasgrule->access; +next_rule: + pasgrule = (ASGRULE *)ellNext((ELLNODE *)pasgrule); + } + pasgclient->access = access; + if(pasgclient->pcallback && oldaccess!=access) { + (*pasgclient->pcallback)(pasgclient,asClientCOAR); + } + return(0); +} static void asFreeAll(ASBASE *pasbase) { @@ -902,13 +1043,14 @@ static void asFreeAll(ASBASE *pasbase) free((void *)pasbase); } +/*Beginning of routines called by lex code*/ static UAG *asUagAdd(char *uagName) { UAG *pprev; UAG *pnext; UAG *puag; int cmpvalue; - ASBASE *pbase = (ASBASE *)pasbase; + ASBASE *pasbase = (ASBASE *)pasbasenew; /*Insert in alphabetic order*/ pnext = (UAG *)ellFirst(&pasbase->uagList); @@ -926,10 +1068,10 @@ static UAG *asUagAdd(char *uagName) puag->name = (char *)(puag+1); strcpy(puag->name,uagName); if(pnext==NULL) { /*Add to end of list*/ - ellAdd(&pbase->uagList,(ELLNODE *)puag); + ellAdd(&pasbase->uagList,(ELLNODE *)puag); } else { pprev = (UAG *)ellPrevious((ELLNODE *)pnext); - ellInsert(&pbase->uagList,(ELLNODE *)pprev,(ELLNODE *)puag); + ellInsert(&pasbase->uagList,(ELLNODE *)pprev,(ELLNODE *)puag); } return(puag); } @@ -939,7 +1081,7 @@ static long asUagAddUser(UAG *puag,char *user) UAGNAME *puagname; if(!puag) return(0); - puagname = asCalloc(1,sizeof(UAG)+strlen(user)+1); + puagname = asCalloc(1,sizeof(UAGNAME)+strlen(user)+1); puagname->user = (char *)(puagname+1); strcpy(puagname->user,user); ellAdd(&puag->list,(ELLNODE *)puagname); @@ -952,7 +1094,7 @@ static HAG *asHagAdd(char *hagName) HAG *pnext; HAG *phag; int cmpvalue; - ASBASE *pbase = (ASBASE *)pasbase; + ASBASE *pasbase = (ASBASE *)pasbasenew; /*Insert in alphabetic order*/ pnext = (HAG *)ellFirst(&pasbase->hagList); @@ -970,10 +1112,10 @@ static HAG *asHagAdd(char *hagName) phag->name = (char *)(phag+1); strcpy(phag->name,hagName); if(pnext==NULL) { /*Add to end of list*/ - ellAdd(&pbase->hagList,(ELLNODE *)phag); + ellAdd(&pasbase->hagList,(ELLNODE *)phag); } else { pprev = (HAG *)ellPrevious((ELLNODE *)pnext); - ellInsert(&pbase->hagList,(ELLNODE *)pprev,(ELLNODE *)phag); + ellInsert(&pasbase->hagList,(ELLNODE *)pprev,(ELLNODE *)phag); } return(phag); } @@ -983,7 +1125,7 @@ static long asHagAddHost(HAG *phag,char *host) HAGNAME *phagname; if(!phag) return(0); - phagname = asCalloc(1,sizeof(HAG)+strlen(host)+1); + phagname = asCalloc(1,sizeof(HAGNAME)+strlen(host)+1); phagname->host = (char *)(phagname+1); strcpy(phagname->host,host); ellAdd(&phag->list,(ELLNODE *)phagname); @@ -996,7 +1138,7 @@ static ASG *asAsgAdd(char *asgName) ASG *pnext; ASG *pasg; int cmpvalue; - ASBASE *pbase = (ASBASE *)pasbase; + ASBASE *pasbase = (ASBASE *)pasbasenew; /*Insert in alphabetic order*/ pnext = (ASG *)ellFirst(&pasbase->asgList); @@ -1021,10 +1163,10 @@ static ASG *asAsgAdd(char *asgName) pasg->name = (char *)(pasg+1); strcpy(pasg->name,asgName); if(pnext==NULL) { /*Add to end of list*/ - ellAdd(&pbase->asgList,(ELLNODE *)pasg); + ellAdd(&pasbase->asgList,(ELLNODE *)pasg); } else { pprev = (ASG *)ellPrevious((ELLNODE *)pnext); - ellInsert(&pbase->asgList,(ELLNODE *)pprev,(ELLNODE *)pasg); + ellInsert(&pasbase->asgList,(ELLNODE *)pprev,(ELLNODE *)pasg); } return(pasg); } @@ -1056,11 +1198,13 @@ static ASGRULE *asAsgAddRule(ASG *pasg,asAccessRights access,int level) ellAdd(&pasg->ruleList,(ELLNODE *)pasgrule); return(pasgrule); } - + static long asAsgRuleUagAdd(ASGRULE *pasgrule,char *name) { ASGUAG *pasguag; UAG *puag; + ASBASE *pasbase = (ASBASE *)pasbasenew; + long status; if(!pasgrule) return(0); puag = (UAG *)ellFirst(&pasbase->uagList); @@ -1068,17 +1212,23 @@ static long asAsgRuleUagAdd(ASGRULE *pasgrule,char *name) if(strcmp(puag->name,name)==0) break; puag = (UAG *)ellNext((ELLNODE *)puag); } - if(!puag) return(S_asLib_noUag); + if(!puag){ + status = S_asLib_noUag; + errMessage(status,": access security Error while adding UAG to RULE"); + return(S_asLib_noUag); + } pasguag = asCalloc(1,sizeof(ASGUAG)); pasguag->puag = puag; ellAdd(&pasgrule->uagList,(ELLNODE *)pasguag); return(0); } - + static long asAsgRuleHagAdd(ASGRULE *pasgrule,char *name) { ASGHAG *pasghag; HAG *phag; + ASBASE *pasbase = (ASBASE *)pasbasenew; + long status; if(!pasgrule) return(0); phag = (HAG *)ellFirst(&pasbase->hagList); @@ -1086,7 +1236,11 @@ static long asAsgRuleHagAdd(ASGRULE *pasgrule,char *name) if(strcmp(phag->name,name)==0) break; phag = (HAG *)ellNext((ELLNODE *)phag); } - if(!phag) return(S_asLib_noHag); + if(!phag){ + status = S_asLib_noHag; + errMessage(status,": access security Error while adding HAG to RULE"); + return(S_asLib_noHag); + } pasghag = asCalloc(1,sizeof(ASGHAG)); pasghag->phag = phag; ellAdd(&pasgrule->hagList,(ELLNODE *)pasghag); @@ -1109,6 +1263,7 @@ static long asAsgRuleCalc(ASGRULE *pasgrule,char *calc) pasgrule->calc = NULL; pasgrule->rpcl = NULL; status = S_asLib_badCalc; + errMessage(status,":Access Security Failure"); } else { int i; diff --git a/src/as/ascheck.c b/src/as/ascheck.c index 543da01bf..fc0cffba6 100644 --- a/src/as/ascheck.c +++ b/src/as/ascheck.c @@ -5,48 +5,13 @@ COPYRIGHT NOTIFICATION ***************************************************************** -THE FOLLOWING IS A NOTICE OF COPYRIGHT, AVAILABILITY OF THE CODE, -AND DISCLAIMER WHICH MUST BE INCLUDED IN THE PROLOGUE OF THE CODE -AND IN ALL SOURCE LISTINGS OF THE CODE. - (C) COPYRIGHT 1993 UNIVERSITY OF CHICAGO - -Argonne National Laboratory (ANL), with facilities in the States of -Illinois and Idaho, is owned by the United States Government, and -operated by the University of Chicago under provision of a contract -with the Department of Energy. -Portions of this material resulted from work developed under a U.S. -Government contract and are subject to the following license: For -a period of five years from March 30, 1993, the Government is -granted for itself and others acting on its behalf a paid-up, -nonexclusive, irrevocable worldwide license in this computer -software to reproduce, prepare derivative works, and perform -publicly and display publicly. With the approval of DOE, this -period may be renewed for two additional five year periods. -Following the expiration of this period or periods, the Government -is granted for itself and others acting on its behalf, a paid-up, -nonexclusive, irrevocable worldwide license in this computer -software to reproduce, prepare derivative works, distribute copies -to the public, perform publicly and display publicly, and to permit -others to do so. +This software was developed under a United States Government license +described on the COPYRIGHT_UniversityOfChicago file included as part +of this distribution. +**********************************************************************/ -***************************************************************** - DISCLAIMER -***************************************************************** - -NEITHER THE UNITED STATES GOVERNMENT NOR ANY AGENCY THEREOF, NOR -THE UNIVERSITY OF CHICAGO, NOR ANY OF THEIR EMPLOYEES OR OFFICERS, -MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR ASSUMES ANY LEGAL -LIABILITY OR RESPONSIBILITY FOR THE ACCURACY, COMPLETENESS, OR -USEFULNESS OF ANY INFORMATION, APPARATUS, PRODUCT, OR PROCESS -DISCLOSED, OR REPRESENTS THAT ITS USE WOULD NOT INFRINGE PRIVATELY -OWNED RIGHTS. - -***************************************************************** -LICENSING INQUIRIES MAY BE DIRECTED TO THE INDUSTRIAL TECHNOLOGY -DEVELOPMENT CENTER AT ARGONNE NATIONAL LABORATORY (708-252-2000). -*/ /* Modification Log: * ----------------- * .01 03-24-94 mrk Initial Implementation @@ -59,29 +24,38 @@ DEVELOPMENT CENTER AT ARGONNE NATIONAL LABORATORY (708-252-2000). #include "dbDefs.h" #include "errlog.h" #include "asLib.h" -static char my_buffer[1000]; -static char *my_buffer_ptr="\0"; - -static int my_yyinput(char *buf, int max_size) +int main(int argc,char **argv) { - int l,n; - - if(*my_buffer_ptr==0) { - if(gets(my_buffer)==NULL) return(0); - my_buffer_ptr = &my_buffer[0]; - strcat(my_buffer_ptr,"\n"); + int i; + int strip; + char *sub = NULL; + int subLength = 0; + char **pstr; + char *psep; + int *len; + long status; + static char *subSep = ","; + + /*Look for options*/ + while(argc>1 && (strncmp(argv[1],"-S",2)==0)) { + pstr = ⊂ + psep = subSep; + len = &subLength; + if(strlen(argv[1])==2) { + dbCatString(pstr,len,argv[2],psep); + strip = 2; + } else { + dbCatString(pstr,len,argv[1]+2,psep); + strip = 1; + } + argc -= strip; + for(i=1; i #include +#include #include #include - + typedef struct asgMember *ASMEMBERPVT; typedef struct asgClient *ASCLIENTPVT; typedef int (*ASINPUTFUNCPTR)(char *buf,int max_size); @@ -65,14 +32,25 @@ typedef enum{ asClientCOAR /*Change of access rights*/ /*For now this is all*/ } asClientStatus; + typedef void (*ASCLIENTCALLBACK) (ASCLIENTPVT,asClientStatus); /* The following routines are macros with the following syntax long asCheckGet(ASCLIENTPVT asClientPvt); long asCheckPut(ASCLIENTPVT asClientPvt); -end of macros */ +#define asCheckGet(asClientPvt)\ + (asActive ?\ + ((asClientPvt)->access>=asREAD ? TRUE : FALSE)\ + : TRUE) +#define asCheckPut(asClientPvt)\ + (asActive ?\ + ((asClientPvt)->access>=asWRITE ? TRUE : FALSE)\ + : TRUE) + int asInit(void); long asInitialize(ASINPUTFUNCPTR inputfunction); +long asInitFile(const char *filename,const char *substitutions); +long asInitFP(FILE *fp,const char *substitutions); /*caller must provide permanent storage for asgName*/ long asAddMember(ASMEMBERPVT *asMemberPvt,char *asgName); long asRemoveMember(ASMEMBERPVT *asMemberPvt); @@ -91,9 +69,12 @@ void asPutClientPvt(ASCLIENTPVT asClientPvt,void *userPvt); long asRegisterClientCallback(ASCLIENTPVT asClientPvt, ASCLIENTCALLBACK pcallback); long asComputeAllAsg(void); -/*asComputeAsg is defined after ASG is defined*/ +/* following declared below after ASG is declared +long asComputeAsg(ASG *pasg); +*/ long asCompute(ASCLIENTPVT asClientPvt); -int asDump(void (*memcallback)(ASMEMBERPVT),void (*clientcallback)(ASCLIENTPVT),int verbose); +int asDump(void (*memcallback)(ASMEMBERPVT), + void (*clientcallback)(ASCLIENTPVT),int verbose); int asDumpUag(char *uagname); int asDumpHag(char *hagname); int asDumpRules(char *asgname); @@ -117,17 +98,6 @@ int asDumpHash(void); /*Private declarations */ #define ASMAXINP 12 -#ifdef vxWorks -#include -#else -/*This only works in a single threaded environment */ -#define FAST_LOCK int -#define FASTLOCKINIT(PFAST_LOCK) -#define FASTLOCK(PFAST_LOCK) -#define FASTUNLOCK(PFAST_LOCK) -#endif -extern int asLockInit; -extern FAST_LOCK asLock; extern int asActive; /* definition of access rights*/ typedef enum{asNOACCESS,asREAD,asWRITE} asAccessRights; @@ -186,6 +156,7 @@ typedef struct{ struct asg *pasg; int inpIndex; }ASGINP; + typedef struct asg{ ELLNODE node; char *name; @@ -213,17 +184,9 @@ typedef struct asgClient { int level; asAccessRights access; } ASGCLIENT; -/* function prototypes*/ -void *asCalloc(size_t nobj,size_t size); + long asComputeAsg(ASG *pasg); -/*macros*/ -#define asCheckGet(asClientPvt)\ - (asActive ?\ - ((asClientPvt)->access>=asREAD ? TRUE : FALSE)\ - : TRUE) -#define asCheckPut(asClientPvt)\ - (asActive ?\ - ((asClientPvt)->access>=asWRITE ? TRUE : FALSE)\ - : TRUE) +/*following is "friend" function*/ +void * asCalloc(size_t nobj,size_t size); #endif /*INCasLibh*/