This is Unofficial EPICS BASE Doxygen Site
asLibRoutines.c
Go to the documentation of this file.
1 /*************************************************************************\
2 * Copyright (c) 2002 The University of Chicago, as Operator of Argonne
3 * National Laboratory.
4 * Copyright (c) 2002 The Regents of the University of California, as
5 * Operator of Los Alamos National Laboratory.
6 * EPICS BASE is distributed subject to a Software License Agreement found
7 * in file LICENSE that is included with this distribution.
8 \*************************************************************************/
9 /* Author: Marty Kraimer Date: 10-15-93 */
10 
11 #include <stdlib.h>
12 #include <stddef.h>
13 #include <stdio.h>
14 #include <string.h>
15 #include <ctype.h>
16 
17 #include "osiSock.h"
18 #include "epicsTypes.h"
19 #include "epicsStdio.h"
20 #include "dbDefs.h"
21 #include "epicsThread.h"
22 #include "cantProceed.h"
23 #include "epicsMutex.h"
24 #include "errlog.h"
25 #include "gpHash.h"
26 #include "freeList.h"
27 #include "macLib.h"
28 #include "postfix.h"
29 #include "asLib.h"
30 
32 
33 static epicsMutexId asLock;
34 #define LOCK epicsMutexMustLock(asLock)
35 #define UNLOCK epicsMutexUnlock(asLock)
36 
37 /*following must be global because asCa nneeds it*/
38 ASBASE volatile *pasbase=NULL;
39 static ASBASE *pasbasenew=NULL;
41 
42 static void *freeListPvt = NULL;
43 
44 
45 #define DEFAULT "DEFAULT"
46 
47 /* Defined in asLib.y */
48 static int myParse(ASINPUTFUNCPTR inputfunction);
49 
50 /*private routines */
51 static long asAddMemberPvt(ASMEMBERPVT *pasMemberPvt,const char *asgName);
52 static long asComputeAllAsgPvt(void);
53 static long asComputeAsgPvt(ASG *pasg);
54 static long asComputePvt(ASCLIENTPVT asClientPvt);
55 static UAG *asUagAdd(const char *uagName);
56 static long asUagAddUser(UAG *puag,const char *user);
57 static HAG *asHagAdd(const char *hagName);
58 static long asHagAddHost(HAG *phag,const char *host);
59 static ASG *asAsgAdd(const char *asgName);
60 static long asAsgAddInp(ASG *pasg,const char *inp,int inpIndex);
61 static ASGRULE *asAsgAddRule(ASG *pasg,asAccessRights access,int level);
62 static long asAsgAddRuleOptions(ASGRULE *pasgrule,int trapMask);
63 static long asAsgRuleUagAdd(ASGRULE *pasgrule,const char *name);
64 static long asAsgRuleHagAdd(ASGRULE *pasgrule,const char *name);
65 static long asAsgRuleCalc(ASGRULE *pasgrule,const char *calc);
66 
67 /*
68  asInitialize can be called while access security is already active.
69  This is accomplished by doing the following:
70 
71  The version pointed to by pasbase is kept as is but locked against changes
72  A new version is created and pointed to by pasbasenew
73  If anything goes wrong. The original version is kept. This results is some
74  wasted space but at least things still work.
75  If the new access security configuration is successfully read then:
76  the old memberList is moved from old to new.
77  the old structures are freed.
78 */
79 static void asInitializeOnce(void *arg)
80 {
81  osiSockAttach();
82  asLock = epicsMutexMustCreate();
83 }
84 long epicsStdCall asInitialize(ASINPUTFUNCPTR inputfunction)
85 {
86  ASG *pasg;
87  long status;
88  ASBASE *pasbaseold;
89  GPHENTRY *pgphentry;
90  UAG *puag;
91  UAGNAME *puagname;
92  HAG *phag;
93  HAGNAME *phagname;
94  static epicsThreadOnceId asInitializeOnceFlag = EPICS_THREAD_ONCE_INIT;
95 
96  epicsThreadOnce(&asInitializeOnceFlag,asInitializeOnce,(void *)0);
97  LOCK;
98  pasbasenew = asCalloc(1,sizeof(ASBASE));
99  if(!freeListPvt) freeListInitPvt(&freeListPvt,sizeof(ASGCLIENT),20);
100  ellInit(&pasbasenew->uagList);
101  ellInit(&pasbasenew->hagList);
102  ellInit(&pasbasenew->asgList);
103  asAsgAdd(DEFAULT);
104  status = myParse(inputfunction);
105  if(status) {
106  status = S_asLib_badConfig;
107  /*Not safe to call asFreeAll */
108  UNLOCK;
109  return(status);
110  }
111  pasg = (ASG *)ellFirst(&pasbasenew->asgList);
112  while(pasg) {
113  pasg->pavalue = asCalloc(CALCPERFORM_NARGS, sizeof(double));
114  pasg = (ASG *)ellNext(&pasg->node);
115  }
116  gphInitPvt(&pasbasenew->phash, 256);
117  /*Hash each uagname and each hagname*/
118  puag = (UAG *)ellFirst(&pasbasenew->uagList);
119  while(puag) {
120  puagname = (UAGNAME *)ellFirst(&puag->list);
121  while(puagname) {
122  pgphentry = gphAdd(pasbasenew->phash,puagname->user,puag);
123  if(!pgphentry) {
124  errlogPrintf("Duplicated user '%s' in UAG '%s'\n",
125  puagname->user, puag->name);
126  }
127  puagname = (UAGNAME *)ellNext(&puagname->node);
128  }
129  puag = (UAG *)ellNext(&puag->node);
130  }
131  phag = (HAG *)ellFirst(&pasbasenew->hagList);
132  while(phag) {
133  phagname = (HAGNAME *)ellFirst(&phag->list);
134  while(phagname) {
135  pgphentry = gphAdd(pasbasenew->phash,phagname->host,phag);
136  if(!pgphentry) {
137  errlogPrintf("Duplicated host '%s' in HAG '%s'\n",
138  phagname->host, phag->name);
139  }
140  phagname = (HAGNAME *)ellNext(&phagname->node);
141  }
142  phag = (HAG *)ellNext(&phag->node);
143  }
144  pasbaseold = (ASBASE *)pasbase;
145  pasbase = (ASBASE volatile *)pasbasenew;
146  if(pasbaseold) {
147  ASG *poldasg;
148  ASGMEMBER *poldmem;
149  ASGMEMBER *pnextoldmem;
150 
151  poldasg = (ASG *)ellFirst(&pasbaseold->asgList);
152  while(poldasg) {
153  poldmem = (ASGMEMBER *)ellFirst(&poldasg->memberList);
154  while(poldmem) {
155  pnextoldmem = (ASGMEMBER *)ellNext(&poldmem->node);
156  ellDelete(&poldasg->memberList,&poldmem->node);
157  status = asAddMemberPvt(&poldmem,poldmem->asgName);
158  poldmem = pnextoldmem;
159  }
160  poldasg = (ASG *)ellNext(&poldasg->node);
161  }
162  asFreeAll(pasbaseold);
163  }
164  asActive = TRUE;
165  UNLOCK;
166  return(0);
167 }
168 
169 long epicsStdCall asInitFile(const char *filename,const char *substitutions)
170 {
171  FILE *fp;
172  long status;
173 
174  fp = fopen(filename,"r");
175  if(!fp) {
176  errlogPrintf("asInitFile: Can't open file '%s'\n", filename);
177  return(S_asLib_badConfig);
178  }
179  status = asInitFP(fp,substitutions);
180  if(fclose(fp)==EOF) {
181  errMessage(0,"asInitFile: fclose failed!");
182  if(!status) status = S_asLib_badConfig;
183  }
184  return(status);
185 }
186 
187 #define BUF_SIZE 200
188 static char *my_buffer;
189 static char *my_buffer_ptr;
190 static FILE *stream;
191 static char *mac_input_buffer=NULL;
192 static MAC_HANDLE *macHandle = NULL;
193 
194 static int myInputFunction(char *buf, int max_size)
195 {
196  int l,n;
197  char *fgetsRtn;
198 
199  if(*my_buffer_ptr==0) {
200  if(macHandle) {
201  fgetsRtn = fgets(mac_input_buffer,BUF_SIZE,stream);
202  if(fgetsRtn) {
203  n = macExpandString(macHandle,mac_input_buffer,
204  my_buffer,BUF_SIZE);
205  if(n<0) {
206  errlogPrintf("access security: macExpandString failed\n"
207  "input line: %s\n",mac_input_buffer);
208  return(0);
209  }
210  }
211  } else {
212  fgetsRtn = fgets(my_buffer,BUF_SIZE,stream);
213  }
214  if(fgetsRtn==NULL) return(0);
215  my_buffer_ptr = my_buffer;
216  }
217  l = strlen(my_buffer_ptr);
218  n = (l<=max_size ? l : max_size);
219  memcpy(buf,my_buffer_ptr,n);
220  my_buffer_ptr += n;
221  return(n);
222 }
223 
224 long epicsStdCall asInitFP(FILE *fp,const char *substitutions)
225 {
226  char buffer[BUF_SIZE];
227  char mac_buffer[BUF_SIZE];
228  long status;
229  char **macPairs;
230 
231  buffer[0] = 0;
232  my_buffer = buffer;
233  my_buffer_ptr = my_buffer;
234  stream = fp;
235  if(substitutions) {
236  if((status = macCreateHandle(&macHandle,NULL))) {
237  errMessage(status,"asInitFP: macCreateHandle error");
238  return(status);
239  }
240  macParseDefns(macHandle,substitutions,&macPairs);
241  if(macPairs ==NULL) {
242  macDeleteHandle(macHandle);
243  macHandle = NULL;
244  } else {
245  macInstallMacros(macHandle,macPairs);
246  free(macPairs);
247  mac_input_buffer = mac_buffer;
248  }
249  }
250  status = asInitialize(myInputFunction);
251  if(macHandle) {
252  macDeleteHandle(macHandle);
253  macHandle = NULL;
254  }
255  return(status);
256 }
257 
258 static const char* membuf;
259 
260 static int memInputFunction(char *buf, int max_size)
261 {
262  int ret = 0;
263  if(!membuf) return ret;
264 
265  while(max_size && *membuf) {
266  *buf++ = *membuf++;
267  max_size--;
268  ret++;
269  }
270 
271  return ret;
272 }
273 
274 long epicsStdCall asInitMem(const char *acf, const char *substitutions)
275 {
276  long ret = S_asLib_InitFailed;
277  if(!acf) return ret;
278 
279  membuf = acf;
280  ret = asInitialize(&memInputFunction);
281  membuf = NULL;
282 
283  return ret;
284 }
285 
286 long epicsStdCall asAddMember(ASMEMBERPVT *pasMemberPvt,const char *asgName)
287 {
288  long status;
289 
290  if(!asActive) return(S_asLib_asNotActive);
291  LOCK;
292  status = asAddMemberPvt(pasMemberPvt,asgName);
293  UNLOCK;
294  return(status);
295 }
296 
297 long epicsStdCall asRemoveMember(ASMEMBERPVT *asMemberPvt)
298 {
299  ASGMEMBER *pasgmember;
300 
301  if(!asActive) return(S_asLib_asNotActive);
302  pasgmember = *asMemberPvt;
303  if(!pasgmember) return(S_asLib_badMember);
304  LOCK;
305  if (ellCount(&pasgmember->clientList) > 0) {
306  UNLOCK;
307  return(S_asLib_clientsExist);
308  }
309  if(pasgmember->pasg) {
310  ellDelete(&pasgmember->pasg->memberList,&pasgmember->node);
311  } else {
312  errMessage(-1,"Logic error in asRemoveMember");
313  UNLOCK;
314  return(-1);
315  }
316  free(pasgmember);
317  *asMemberPvt = NULL;
318  UNLOCK;
319  return(0);
320 }
321 
322 long epicsStdCall asChangeGroup(ASMEMBERPVT *asMemberPvt,const char *newAsgName)
323 {
324  ASGMEMBER *pasgmember;
325  long status;
326 
327  if(!asActive) return(S_asLib_asNotActive);
328  pasgmember = *asMemberPvt;
329  if(!pasgmember) return(S_asLib_badMember);
330  LOCK;
331  if(pasgmember->pasg) {
332  ellDelete(&pasgmember->pasg->memberList,&pasgmember->node);
333  } else {
334  errMessage(-1,"Logic error in asChangeGroup");
335  UNLOCK;
336  return(-1);
337  }
338  status = asAddMemberPvt(asMemberPvt,newAsgName);
339  UNLOCK;
340  return(status);
341 }
342 
343 void * epicsStdCall asGetMemberPvt(ASMEMBERPVT asMemberPvt)
344 {
345  ASGMEMBER *pasgmember = asMemberPvt;
346 
347  if(!asActive) return(NULL);
348  if(!pasgmember) return(NULL);
349  return(pasgmember->userPvt);
350 }
351 
352 void epicsStdCall asPutMemberPvt(ASMEMBERPVT asMemberPvt,void *userPvt)
353 {
354  ASGMEMBER *pasgmember = asMemberPvt;
355 
356  if(!asActive) return;
357  if(!pasgmember) return;
358  pasgmember->userPvt = userPvt;
359  return;
360 }
361 
362 long epicsStdCall asAddClient(ASCLIENTPVT *pasClientPvt,ASMEMBERPVT asMemberPvt,
363  int asl,const char *user,char *host)
364 {
365  ASGMEMBER *pasgmember = asMemberPvt;
366  ASGCLIENT *pasgclient;
367  int len, i;
368 
369  long status;
370  if(!asActive) return(S_asLib_asNotActive);
371  if(!pasgmember) return(S_asLib_badMember);
372  pasgclient = freeListCalloc(freeListPvt);
373  if(!pasgclient) return(S_asLib_noMemory);
374  len = strlen(host);
375  for (i = 0; i < len; i++) {
376  host[i] = (char)tolower((int)host[i]);
377  }
378  *pasClientPvt = pasgclient;
379  pasgclient->pasgMember = asMemberPvt;
380  pasgclient->level = asl;
381  pasgclient->user = user;
382  pasgclient->host = host;
383  LOCK;
384  ellAdd(&pasgmember->clientList,&pasgclient->node);
385  status = asComputePvt(pasgclient);
386  UNLOCK;
387  return(status);
388 }
389 
390 long epicsStdCall asChangeClient(
391  ASCLIENTPVT asClientPvt,int asl,const char *user,char *host)
392 {
393  ASGCLIENT *pasgclient = asClientPvt;
394  long status;
395  int len, i;
396 
397  if(!asActive) return(S_asLib_asNotActive);
398  if(!pasgclient) return(S_asLib_badClient);
399  len = strlen(host);
400  for (i = 0; i < len; i++) {
401  host[i] = (char)tolower((int)host[i]);
402  }
403  LOCK;
404  pasgclient->level = asl;
405  pasgclient->user = user;
406  pasgclient->host = host;
407  status = asComputePvt(pasgclient);
408  UNLOCK;
409  return(status);
410 }
411 
412 long epicsStdCall asRemoveClient(ASCLIENTPVT *asClientPvt)
413 {
414  ASGCLIENT *pasgclient = *asClientPvt;
415  ASGMEMBER *pasgMember;
416 
417  if(!asActive) return(S_asLib_asNotActive);
418  if(!pasgclient) return(S_asLib_badClient);
419  LOCK;
420  pasgMember = pasgclient->pasgMember;
421  if(!pasgMember) {
422  errMessage(-1,"asRemoveClient: No ASGMEMBER");
423  UNLOCK;
424  return(-1);
425  }
426  ellDelete(&pasgMember->clientList,&pasgclient->node);
427  UNLOCK;
428  freeListFree(freeListPvt,pasgclient);
429  *asClientPvt = NULL;
430  return(0);
431 }
432 
433 long epicsStdCall asRegisterClientCallback(ASCLIENTPVT asClientPvt,
434  ASCLIENTCALLBACK pcallback)
435 {
436  ASGCLIENT *pasgclient = asClientPvt;
437 
438  if(!asActive) return(S_asLib_asNotActive);
439  if(!pasgclient) return(S_asLib_badClient);
440  LOCK;
441  pasgclient->pcallback = pcallback;
442  (*pasgclient->pcallback)(pasgclient,asClientCOAR);
443  UNLOCK;
444  return(0);
445 }
446 
447 void * epicsStdCall asGetClientPvt(ASCLIENTPVT asClientPvt)
448 {
449  ASGCLIENT *pasgclient = asClientPvt;
450 
451  if(!asActive) return(NULL);
452  if(!pasgclient) return(NULL);
453  return(pasgclient->userPvt);
454 }
455 
456 void epicsStdCall asPutClientPvt(ASCLIENTPVT asClientPvt,void *userPvt)
457 {
458  ASGCLIENT *pasgclient = asClientPvt;
459  if(!asActive) return;
460  if(!pasgclient) return;
461  LOCK;
462  pasgclient->userPvt = userPvt;
463  UNLOCK;
464 }
465 
466 long epicsStdCall asComputeAllAsg(void)
467 {
468  long status;
469 
470  if(!asActive) return(S_asLib_asNotActive);
471  LOCK;
472  status = asComputeAllAsgPvt();
473  UNLOCK;
474  return(status);
475 }
476 
477 long epicsStdCall asComputeAsg(ASG *pasg)
478 {
479  long status;
480 
481  if(!asActive) return(S_asLib_asNotActive);
482  LOCK;
483  status = asComputeAsgPvt(pasg);
484  UNLOCK;
485  return(status);
486 }
487 
488 long epicsStdCall asCompute(ASCLIENTPVT asClientPvt)
489 {
490  long status;
491 
492  if(!asActive) return(S_asLib_asNotActive);
493  LOCK;
494  status = asComputePvt(asClientPvt);
495  UNLOCK;
496  return(status);
497 }
498 
499 /*The dump routines do not lock. Thus they may get inconsistant data.*/
500 /*HOWEVER if they did lock and a user interrupts one of then then BAD BAD*/
501 static const char *asAccessName[] = {"NONE","READ","WRITE"};
502 static const char *asTrapOption[] = {"NOTRAPWRITE","TRAPWRITE"};
503 static const char *asLevelName[] = {"ASL0","ASL1"};
504 int epicsStdCall asDump(
505  void (*memcallback)(struct asgMember *,FILE *),
506  void (*clientcallback)(struct asgClient *,FILE *),
507  int verbose)
508 {
509  return asDumpFP(stdout,memcallback,clientcallback,verbose);
510 }
511 
512 int epicsStdCall asDumpFP(
513  FILE *fp,
514  void (*memcallback)(struct asgMember *,FILE *),
515  void (*clientcallback)(struct asgClient *,FILE *),
516  int verbose)
517 {
518  UAG *puag;
519  UAGNAME *puagname;
520  HAG *phag;
521  HAGNAME *phagname;
522  ASG *pasg;
523  ASGINP *pasginp;
524  ASGRULE *pasgrule;
525  ASGHAG *pasghag;
526  ASGUAG *pasguag;
527  ASGMEMBER *pasgmember;
528  ASGCLIENT *pasgclient;
529 
530  if(!asActive) return(0);
531  puag = (UAG *)ellFirst(&pasbase->uagList);
532  if(!puag) fprintf(fp,"No UAGs\n");
533  while(puag) {
534  fprintf(fp,"UAG(%s)",puag->name);
535  puagname = (UAGNAME *)ellFirst(&puag->list);
536  if(puagname) fprintf(fp," {"); else fprintf(fp,"\n");
537  while(puagname) {
538  fprintf(fp,"%s",puagname->user);
539  puagname = (UAGNAME *)ellNext(&puagname->node);
540  if(puagname) fprintf(fp,","); else fprintf(fp,"}\n");
541  }
542  puag = (UAG *)ellNext(&puag->node);
543  }
544  phag = (HAG *)ellFirst(&pasbase->hagList);
545  if(!phag) fprintf(fp,"No HAGs\n");
546  while(phag) {
547  fprintf(fp,"HAG(%s)",phag->name);
548  phagname = (HAGNAME *)ellFirst(&phag->list);
549  if(phagname) fprintf(fp," {"); else fprintf(fp,"\n");
550  while(phagname) {
551  fprintf(fp,"%s",phagname->host);
552  phagname = (HAGNAME *)ellNext(&phagname->node);
553  if(phagname) fprintf(fp,","); else fprintf(fp,"}\n");
554  }
555  phag = (HAG *)ellNext(&phag->node);
556  }
557  pasg = (ASG *)ellFirst(&pasbase->asgList);
558  if(!pasg) fprintf(fp,"No ASGs\n");
559  while(pasg) {
560  int print_end_brace;
561 
562  fprintf(fp,"ASG(%s)",pasg->name);
563  pasginp = (ASGINP *)ellFirst(&pasg->inpList);
564  pasgrule = (ASGRULE *)ellFirst(&pasg->ruleList);
565  if(pasginp || pasgrule) {
566  fprintf(fp," {\n");
567  print_end_brace = TRUE;
568  } else {
569  fprintf(fp,"\n");
570  print_end_brace = FALSE;
571  }
572  while(pasginp) {
573 
574  fprintf(fp,"\tINP%c(%s)",(pasginp->inpIndex + 'A'),pasginp->inp);
575  if(verbose) {
576  if((pasg->inpBad & (1ul << pasginp->inpIndex)))
577  fprintf(fp," INVALID");
578  else
579  fprintf(fp," VALID");
580  fprintf(fp," value=%f",pasg->pavalue[pasginp->inpIndex]);
581  }
582  fprintf(fp,"\n");
583  pasginp = (ASGINP *)ellNext(&pasginp->node);
584  }
585  while(pasgrule) {
586  int print_end_brace;
587 
588  fprintf(fp,"\tRULE(%d,%s,%s)",
589  pasgrule->level,asAccessName[pasgrule->access],
590  asTrapOption[pasgrule->trapMask]);
591  pasguag = (ASGUAG *)ellFirst(&pasgrule->uagList);
592  pasghag = (ASGHAG *)ellFirst(&pasgrule->hagList);
593  if(pasguag || pasghag || pasgrule->calc) {
594  fprintf(fp," {\n");
595  print_end_brace = TRUE;
596  } else {
597  fprintf(fp,"\n");
598  print_end_brace = FALSE;
599  }
600  if(pasguag) fprintf(fp,"\t\tUAG(");
601  while(pasguag) {
602  fprintf(fp,"%s",pasguag->puag->name);
603  pasguag = (ASGUAG *)ellNext(&pasguag->node);
604  if(pasguag) fprintf(fp,","); else fprintf(fp,")\n");
605  }
606  pasghag = (ASGHAG *)ellFirst(&pasgrule->hagList);
607  if(pasghag) fprintf(fp,"\t\tHAG(");
608  while(pasghag) {
609  fprintf(fp,"%s",pasghag->phag->name);
610  pasghag = (ASGHAG *)ellNext(&pasghag->node);
611  if(pasghag) fprintf(fp,","); else fprintf(fp,")\n");
612  }
613  if(pasgrule->calc) {
614  fprintf(fp,"\t\tCALC(\"%s\")",pasgrule->calc);
615  if(verbose)
616  fprintf(fp," result=%s",(pasgrule->result==1 ? "TRUE" : "FALSE"));
617  fprintf(fp,"\n");
618  }
619  if(print_end_brace) fprintf(fp,"\t}\n");
620  pasgrule = (ASGRULE *)ellNext(&pasgrule->node);
621  }
622  pasgmember = (ASGMEMBER *)ellFirst(&pasg->memberList);
623  if(!verbose) pasgmember = NULL;
624  if(pasgmember) fprintf(fp,"\tMEMBERLIST\n");
625  while(pasgmember) {
626  if(strlen(pasgmember->asgName)==0)
627  fprintf(fp,"\t\t<null>");
628  else
629  fprintf(fp,"\t\t%s",pasgmember->asgName);
630  if(memcallback) memcallback(pasgmember,fp);
631  fprintf(fp,"\n");
632  pasgclient = (ASGCLIENT *)ellFirst(&pasgmember->clientList);
633  while(pasgclient) {
634  fprintf(fp,"\t\t\t %s %s",pasgclient->user,pasgclient->host);
635  if(pasgclient->level>=0 && pasgclient->level<=1)
636  fprintf(fp," %s",asLevelName[pasgclient->level]);
637  else
638  fprintf(fp," Illegal Level %d",pasgclient->level);
639  if(pasgclient->access<=2)
640  fprintf(fp," %s %s",
641  asAccessName[pasgclient->access],
642  asTrapOption[pasgclient->trapMask]);
643  else
644  fprintf(fp," Illegal Access %d",pasgclient->access);
645  if(clientcallback) clientcallback(pasgclient,fp);
646  fprintf(fp,"\n");
647  pasgclient = (ASGCLIENT *)ellNext(&pasgclient->node);
648  }
649  pasgmember = (ASGMEMBER *)ellNext(&pasgmember->node);
650  }
651  if(print_end_brace) fprintf(fp,"}\n");
652  pasg = (ASG *)ellNext(&pasg->node);
653  }
654  return(0);
655 }
656 
657 int epicsStdCall asDumpUag(const char *uagname)
658 {
659  return asDumpUagFP(stdout,uagname);
660 }
661 
662 int epicsStdCall asDumpUagFP(FILE *fp,const char *uagname)
663 {
664  UAG *puag;
665  UAGNAME *puagname;
666 
667  if(!asActive) return(0);
668  puag = (UAG *)ellFirst(&pasbase->uagList);
669  if(!puag) fprintf(fp,"No UAGs\n");
670  while(puag) {
671  if(uagname && strcmp(uagname,puag->name)!=0) {
672  puag = (UAG *)ellNext(&puag->node);
673  continue;
674  }
675  fprintf(fp,"UAG(%s)",puag->name);
676  puagname = (UAGNAME *)ellFirst(&puag->list);
677  if(puagname) fprintf(fp," {"); else fprintf(fp,"\n");
678  while(puagname) {
679  fprintf(fp,"%s",puagname->user);
680  puagname = (UAGNAME *)ellNext(&puagname->node);
681  if(puagname) fprintf(fp,","); else fprintf(fp,"}\n");
682  }
683  puag = (UAG *)ellNext(&puag->node);
684  }
685  return(0);
686 }
687 
688 int epicsStdCall asDumpHag(const char *hagname)
689 {
690  return asDumpHagFP(stdout,hagname);
691 }
692 
693 int epicsStdCall asDumpHagFP(FILE *fp,const char *hagname)
694 {
695  HAG *phag;
696  HAGNAME *phagname;
697 
698  if(!asActive) return(0);
699  phag = (HAG *)ellFirst(&pasbase->hagList);
700  if(!phag) fprintf(fp,"No HAGs\n");
701  while(phag) {
702  if(hagname && strcmp(hagname,phag->name)!=0) {
703  phag = (HAG *)ellNext(&phag->node);
704  continue;
705  }
706  fprintf(fp,"HAG(%s)",phag->name);
707  phagname = (HAGNAME *)ellFirst(&phag->list);
708  if(phagname) fprintf(fp," {"); else fprintf(fp,"\n");
709  while(phagname) {
710  fprintf(fp,"%s",phagname->host);
711  phagname = (HAGNAME *)ellNext(&phagname->node);
712  if(phagname) fprintf(fp,","); else fprintf(fp,"}\n");
713  }
714  phag = (HAG *)ellNext(&phag->node);
715  }
716  return(0);
717 }
718 
719 int epicsStdCall asDumpRules(const char *asgname)
720 {
721  return asDumpRulesFP(stdout,asgname);
722 }
723 
724 int epicsStdCall asDumpRulesFP(FILE *fp,const char *asgname)
725 {
726  ASG *pasg;
727  ASGINP *pasginp;
728  ASGRULE *pasgrule;
729  ASGHAG *pasghag;
730  ASGUAG *pasguag;
731 
732  if(!asActive) return(0);
733  pasg = (ASG *)ellFirst(&pasbase->asgList);
734  if(!pasg) fprintf(fp,"No ASGs\n");
735  while(pasg) {
736  int print_end_brace;
737 
738  if(asgname && strcmp(asgname,pasg->name)!=0) {
739  pasg = (ASG *)ellNext(&pasg->node);
740  continue;
741  }
742  fprintf(fp,"ASG(%s)",pasg->name);
743  pasginp = (ASGINP *)ellFirst(&pasg->inpList);
744  pasgrule = (ASGRULE *)ellFirst(&pasg->ruleList);
745  if(pasginp || pasgrule) {
746  fprintf(fp," {\n");
747  print_end_brace = TRUE;
748  } else {
749  fprintf(fp,"\n");
750  print_end_brace = FALSE;
751  }
752  while(pasginp) {
753 
754  fprintf(fp,"\tINP%c(%s)",(pasginp->inpIndex + 'A'),pasginp->inp);
755  if ((pasg->inpBad & (1ul << pasginp->inpIndex)))
756  fprintf(fp," INVALID");
757  fprintf(fp," value=%f",pasg->pavalue[pasginp->inpIndex]);
758  fprintf(fp,"\n");
759  pasginp = (ASGINP *)ellNext(&pasginp->node);
760  }
761  while(pasgrule) {
762  int print_end_brace;
763 
764  fprintf(fp,"\tRULE(%d,%s,%s)",
765  pasgrule->level,asAccessName[pasgrule->access],
766  asTrapOption[pasgrule->trapMask]);
767  pasguag = (ASGUAG *)ellFirst(&pasgrule->uagList);
768  pasghag = (ASGHAG *)ellFirst(&pasgrule->hagList);
769  if(pasguag || pasghag || pasgrule->calc) {
770  fprintf(fp," {\n");
771  print_end_brace = TRUE;
772  } else {
773  fprintf(fp,"\n");
774  print_end_brace = FALSE;
775  }
776  if(pasguag) fprintf(fp,"\t\tUAG(");
777  while(pasguag) {
778  fprintf(fp,"%s",pasguag->puag->name);
779  pasguag = (ASGUAG *)ellNext(&pasguag->node);
780  if(pasguag) fprintf(fp,","); else fprintf(fp,")\n");
781  }
782  pasghag = (ASGHAG *)ellFirst(&pasgrule->hagList);
783  if(pasghag) fprintf(fp,"\t\tHAG(");
784  while(pasghag) {
785  fprintf(fp,"%s",pasghag->phag->name);
786  pasghag = (ASGHAG *)ellNext(&pasghag->node);
787  if(pasghag) fprintf(fp,","); else fprintf(fp,")\n");
788  }
789  if(pasgrule->calc) {
790  fprintf(fp,"\t\tCALC(\"%s\")",pasgrule->calc);
791  fprintf(fp," result=%s",(pasgrule->result==1 ? "TRUE" : "FALSE"));
792  fprintf(fp,"\n");
793  }
794  if(print_end_brace) fprintf(fp,"\t}\n");
795  pasgrule = (ASGRULE *)ellNext(&pasgrule->node);
796  }
797  if(print_end_brace) fprintf(fp,"}\n");
798  pasg = (ASG *)ellNext(&pasg->node);
799  }
800  return(0);
801 }
802 
803 int epicsStdCall asDumpMem(const char *asgname,void (*memcallback)(ASMEMBERPVT,FILE *),
804  int clients)
805 {
806  return asDumpMemFP(stdout,asgname,memcallback,clients);
807 }
808 
809 int epicsStdCall asDumpMemFP(FILE *fp,const char *asgname,
810  void (*memcallback)(ASMEMBERPVT,FILE *),int clients)
811 {
812  ASG *pasg;
813  ASGMEMBER *pasgmember;
814  ASGCLIENT *pasgclient;
815 
816  if(!asActive) return(0);
817  pasg = (ASG *)ellFirst(&pasbase->asgList);
818  if(!pasg) fprintf(fp,"No ASGs\n");
819  while(pasg) {
820 
821  if(asgname && strcmp(asgname,pasg->name)!=0) {
822  pasg = (ASG *)ellNext(&pasg->node);
823  continue;
824  }
825  fprintf(fp,"ASG(%s)\n",pasg->name);
826  pasgmember = (ASGMEMBER *)ellFirst(&pasg->memberList);
827  if(pasgmember) fprintf(fp,"\tMEMBERLIST\n");
828  while(pasgmember) {
829  if(strlen(pasgmember->asgName)==0)
830  fprintf(fp,"\t\t<null>");
831  else
832  fprintf(fp,"\t\t%s",pasgmember->asgName);
833  if(memcallback) memcallback(pasgmember,fp);
834  fprintf(fp,"\n");
835  pasgclient = (ASGCLIENT *)ellFirst(&pasgmember->clientList);
836  if(!clients) pasgclient = NULL;
837  while(pasgclient) {
838  fprintf(fp,"\t\t\t %s %s",
839  pasgclient->user,pasgclient->host);
840  if(pasgclient->level>=0 && pasgclient->level<=1)
841  fprintf(fp," %s",asLevelName[pasgclient->level]);
842  else
843  fprintf(fp," Illegal Level %d",pasgclient->level);
844  if(pasgclient->access<=2)
845  fprintf(fp," %s %s",
846  asAccessName[pasgclient->access],
847  asTrapOption[pasgclient->trapMask]);
848  else
849  fprintf(fp," Illegal Access %d",pasgclient->access);
850  fprintf(fp,"\n");
851  pasgclient = (ASGCLIENT *)ellNext(&pasgclient->node);
852  }
853  pasgmember = (ASGMEMBER *)ellNext(&pasgmember->node);
854  }
855  pasg = (ASG *)ellNext(&pasg->node);
856  }
857  return(0);
858 }
859 
860 LIBCOM_API int epicsStdCall asDumpHash(void)
861 {
862  return asDumpHashFP(stdout);
863 }
864 
865 LIBCOM_API int epicsStdCall asDumpHashFP(FILE *fp)
866 {
867  if(!asActive) return(0);
868  gphDumpFP(fp,pasbase->phash);
869  return(0);
870 }
871 
872 /*Start of private routines*/
873 /* asCalloc is "friend" function */
874 LIBCOM_API void * epicsStdCall asCalloc(size_t nobj,size_t size)
875 {
876  void *p;
877 
878  p=callocMustSucceed(nobj,size,"asCalloc");
879  return(p);
880 }
881 LIBCOM_API char * epicsStdCall asStrdup(unsigned char *str)
882 {
883  size_t len = strlen((char *) str);
884  char *buf = asCalloc(1, len + 1);
885  strcpy(buf, (char *) str);
886  return buf;
887 }
888 
889 static long asAddMemberPvt(ASMEMBERPVT *pasMemberPvt,const char *asgName)
890 {
891  ASGMEMBER *pasgmember;
892  ASG *pgroup;
893  ASGCLIENT *pasgclient;
894 
895  if(*pasMemberPvt) {
896  pasgmember = *pasMemberPvt;
897  } else {
898  pasgmember = asCalloc(1,sizeof(ASGMEMBER));
899  ellInit(&pasgmember->clientList);
900  *pasMemberPvt = pasgmember;
901  }
902  pasgmember->asgName = asgName;
903  pgroup = (ASG *)ellFirst(&pasbase->asgList);
904  while(pgroup) {
905  if(strcmp(pgroup->name,pasgmember->asgName)==0) goto got_it;
906  pgroup = (ASG *)ellNext(&pgroup->node);
907  }
908  /* Put it in DEFAULT*/
909  pgroup = (ASG *)ellFirst(&pasbase->asgList);
910  while(pgroup) {
911  if(strcmp(pgroup->name,DEFAULT)==0) goto got_it;
912  pgroup = (ASG *)ellNext(&pgroup->node);
913  }
914  errMessage(-1,"Logic Error in asAddMember");
915  return(-1);
916 got_it:
917  pasgmember->pasg = pgroup;
918  ellAdd(&pgroup->memberList,&pasgmember->node);
919  pasgclient = (ASGCLIENT *)ellFirst(&pasgmember->clientList);
920  while(pasgclient) {
921  asComputePvt((ASCLIENTPVT)pasgclient);
922  pasgclient = (ASGCLIENT *)ellNext(&pasgclient->node);
923  }
924  return(0);
925 }
926 
927 static long asComputeAllAsgPvt(void)
928 {
929  ASG *pasg;
930 
931  if(!asActive) return(S_asLib_asNotActive);
932  pasg = (ASG *)ellFirst(&pasbase->asgList);
933  while(pasg) {
934  asComputeAsgPvt(pasg);
935  pasg = (ASG *)ellNext(&pasg->node);
936  }
937  return(0);
938 }
939 
940 static long asComputeAsgPvt(ASG *pasg)
941 {
942  ASGRULE *pasgrule;
943  ASGMEMBER *pasgmember;
944  ASGCLIENT *pasgclient;
945 
946  if(!asActive) return(S_asLib_asNotActive);
947  pasgrule = (ASGRULE *)ellFirst(&pasg->ruleList);
948  while(pasgrule) {
949  double result = pasgrule->result; /* set for VAL */
950  long status;
951 
952  if(pasgrule->calc && (pasg->inpChanged & pasgrule->inpUsed)) {
953  status = calcPerform(pasg->pavalue,&result,pasgrule->rpcl);
954  if(status) {
955  pasgrule->result = 0;
956  errMessage(status,"asComputeAsg");
957  } else {
958  pasgrule->result = ((result>.99) && (result<1.01)) ? 1 : 0;
959  }
960  }
961  pasgrule = (ASGRULE *)ellNext(&pasgrule->node);
962  }
963  pasg->inpChanged = FALSE;
964  pasgmember = (ASGMEMBER *)ellFirst(&pasg->memberList);
965  while(pasgmember) {
966  pasgclient = (ASGCLIENT *)ellFirst(&pasgmember->clientList);
967  while(pasgclient) {
968  asComputePvt((ASCLIENTPVT)pasgclient);
969  pasgclient = (ASGCLIENT *)ellNext(&pasgclient->node);
970  }
971  pasgmember = (ASGMEMBER *)ellNext(&pasgmember->node);
972  }
973  return(0);
974 }
975 
976 static long asComputePvt(ASCLIENTPVT asClientPvt)
977 {
978  asAccessRights access=asNOACCESS;
979  int trapMask=0;
980  ASGCLIENT *pasgclient = asClientPvt;
981  ASGMEMBER *pasgMember;
982  ASG *pasg;
983  ASGRULE *pasgrule;
984  asAccessRights oldaccess;
985  GPHENTRY *pgphentry;
986 
987  if(!asActive) return(S_asLib_asNotActive);
988  if(!pasgclient) return(S_asLib_badClient);
989  pasgMember = pasgclient->pasgMember;
990  if(!pasgMember) return(S_asLib_badMember);
991  pasg = pasgMember->pasg;
992  if(!pasg) return(S_asLib_badAsg);
993  oldaccess=pasgclient->access;
994  pasgrule = (ASGRULE *)ellFirst(&pasg->ruleList);
995  while(pasgrule) {
996  if(access == asWRITE) break;
997  if(access>=pasgrule->access) goto next_rule;
998  if(pasgclient->level > pasgrule->level) goto next_rule;
999  /*if uagList is empty then no need to check uag*/
1000  if(ellCount(&pasgrule->uagList)>0){
1001  ASGUAG *pasguag;
1002  UAG *puag;
1003 
1004  pasguag = (ASGUAG *)ellFirst(&pasgrule->uagList);
1005  while(pasguag) {
1006  if((puag = pasguag->puag)) {
1007  pgphentry = gphFind(pasbase->phash,pasgclient->user,puag);
1008  if(pgphentry) goto check_hag;
1009  }
1010  pasguag = (ASGUAG *)ellNext(&pasguag->node);
1011  }
1012  goto next_rule;
1013  }
1014 check_hag:
1015  /*if hagList is empty then no need to check hag*/
1016  if(ellCount(&pasgrule->hagList)>0) {
1017  ASGHAG *pasghag;
1018  HAG *phag;
1019 
1020  pasghag = (ASGHAG *)ellFirst(&pasgrule->hagList);
1021  while(pasghag) {
1022  if((phag = pasghag->phag)) {
1023  pgphentry=gphFind(pasbase->phash,pasgclient->host,phag);
1024  if(pgphentry) goto check_calc;
1025  }
1026  pasghag = (ASGHAG *)ellNext(&pasghag->node);
1027  }
1028  goto next_rule;
1029  }
1030 check_calc:
1031  if(!pasgrule->calc
1032  || (!(pasg->inpBad & pasgrule->inpUsed) && (pasgrule->result==1))) {
1033  access = pasgrule->access;
1034  trapMask = pasgrule->trapMask;
1035  }
1036 next_rule:
1037  pasgrule = (ASGRULE *)ellNext(&pasgrule->node);
1038  }
1039  pasgclient->access = access;
1040  pasgclient->trapMask = trapMask;
1041  if(pasgclient->pcallback && oldaccess!=access) {
1042  (*pasgclient->pcallback)(pasgclient,asClientCOAR);
1043  }
1044  return(0);
1045 }
1046 
1047 void asFreeAll(ASBASE *pasbase)
1048 {
1049  UAG *puag;
1050  UAGNAME *puagname;
1051  HAG *phag;
1052  HAGNAME *phagname;
1053  ASG *pasg;
1054  ASGINP *pasginp;
1055  ASGRULE *pasgrule;
1056  ASGHAG *pasghag;
1057  ASGUAG *pasguag;
1058  void *pnext;
1059 
1060  puag = (UAG *)ellFirst(&pasbase->uagList);
1061  while(puag) {
1062  puagname = (UAGNAME *)ellFirst(&puag->list);
1063  while(puagname) {
1064  pnext = ellNext(&puagname->node);
1065  ellDelete(&puag->list,&puagname->node);
1066  free(puagname);
1067  puagname = pnext;
1068  }
1069  pnext = ellNext(&puag->node);
1070  ellDelete(&pasbase->uagList,&puag->node);
1071  free(puag);
1072  puag = pnext;
1073  }
1074  phag = (HAG *)ellFirst(&pasbase->hagList);
1075  while(phag) {
1076  phagname = (HAGNAME *)ellFirst(&phag->list);
1077  while(phagname) {
1078  pnext = ellNext(&phagname->node);
1079  ellDelete(&phag->list,&phagname->node);
1080  free(phagname);
1081  phagname = pnext;
1082  }
1083  pnext = ellNext(&phag->node);
1084  ellDelete(&pasbase->hagList,&phag->node);
1085  free(phag);
1086  phag = pnext;
1087  }
1088  pasg = (ASG *)ellFirst(&pasbase->asgList);
1089  while(pasg) {
1090  free(pasg->pavalue);
1091  pasginp = (ASGINP *)ellFirst(&pasg->inpList);
1092  while(pasginp) {
1093  pnext = ellNext(&pasginp->node);
1094  ellDelete(&pasg->inpList,&pasginp->node);
1095  free(pasginp);
1096  pasginp = pnext;
1097  }
1098  pasgrule = (ASGRULE *)ellFirst(&pasg->ruleList);
1099  while(pasgrule) {
1100  free(pasgrule->calc);
1101  free(pasgrule->rpcl);
1102  pasguag = (ASGUAG *)ellFirst(&pasgrule->uagList);
1103  while(pasguag) {
1104  pnext = ellNext(&pasguag->node);
1105  ellDelete(&pasgrule->uagList,&pasguag->node);
1106  free(pasguag);
1107  pasguag = pnext;
1108  }
1109  pasghag = (ASGHAG *)ellFirst(&pasgrule->hagList);
1110  while(pasghag) {
1111  pnext = ellNext(&pasghag->node);
1112  ellDelete(&pasgrule->hagList,&pasghag->node);
1113  free(pasghag);
1114  pasghag = pnext;
1115  }
1116  pnext = ellNext(&pasgrule->node);
1117  ellDelete(&pasg->ruleList,&pasgrule->node);
1118  free(pasgrule);
1119  pasgrule = pnext;
1120  }
1121  pnext = ellNext(&pasg->node);
1122  ellDelete(&pasbase->asgList,&pasg->node);
1123  free(pasg);
1124  pasg = pnext;
1125  }
1126  gphFreeMem(pasbase->phash);
1127  free(pasbase);
1128 }
1129 
1130 /*Beginning of routines called by lex code*/
1131 static UAG *asUagAdd(const char *uagName)
1132 {
1133  UAG *pprev;
1134  UAG *pnext;
1135  UAG *puag;
1136  int cmpvalue;
1137  ASBASE *pasbase = (ASBASE *)pasbasenew;
1138 
1139  /*Insert in alphabetic order*/
1140  pnext = (UAG *)ellFirst(&pasbase->uagList);
1141  while(pnext) {
1142  cmpvalue = strcmp(uagName,pnext->name);
1143  if(cmpvalue < 0) break;
1144  if(cmpvalue==0) {
1145  errlogPrintf("Duplicate User Access Group named '%s'\n", uagName);
1146  return(NULL);
1147  }
1148  pnext = (UAG *)ellNext(&pnext->node);
1149  }
1150  puag = asCalloc(1,sizeof(UAG)+strlen(uagName)+1);
1151  ellInit(&puag->list);
1152  puag->name = (char *)(puag+1);
1153  strcpy(puag->name,uagName);
1154  if(pnext==NULL) { /*Add to end of list*/
1155  ellAdd(&pasbase->uagList,&puag->node);
1156  } else {
1157  pprev = (UAG *)ellPrevious(&pnext->node);
1158  ellInsert(&pasbase->uagList,&pprev->node,&puag->node);
1159  }
1160  return(puag);
1161 }
1162 
1163 static long asUagAddUser(UAG *puag,const char *user)
1164 {
1165  UAGNAME *puagname;
1166 
1167  if(!puag) return(0);
1168  puagname = asCalloc(1,sizeof(UAGNAME)+strlen(user)+1);
1169  puagname->user = (char *)(puagname+1);
1170  strcpy(puagname->user,user);
1171  ellAdd(&puag->list,&puagname->node);
1172  return(0);
1173 }
1174 
1175 static HAG *asHagAdd(const char *hagName)
1176 {
1177  HAG *pprev;
1178  HAG *pnext;
1179  HAG *phag;
1180  int cmpvalue;
1181  ASBASE *pasbase = (ASBASE *)pasbasenew;
1182 
1183  /*Insert in alphabetic order*/
1184  pnext = (HAG *)ellFirst(&pasbase->hagList);
1185  while(pnext) {
1186  cmpvalue = strcmp(hagName,pnext->name);
1187  if(cmpvalue < 0) break;
1188  if(cmpvalue==0) {
1189  errlogPrintf("Duplicate Host Access Group named '%s'\n", hagName);
1190  return(NULL);
1191  }
1192  pnext = (HAG *)ellNext(&pnext->node);
1193  }
1194  phag = asCalloc(1,sizeof(HAG)+strlen(hagName)+1);
1195  ellInit(&phag->list);
1196  phag->name = (char *)(phag+1);
1197  strcpy(phag->name,hagName);
1198  if(pnext==NULL) { /*Add to end of list*/
1199  ellAdd(&pasbase->hagList,&phag->node);
1200  } else {
1201  pprev = (HAG *)ellPrevious(&pnext->node);
1202  ellInsert(&pasbase->hagList,&pprev->node,&phag->node);
1203  }
1204  return(phag);
1205 }
1206 
1207 static long asHagAddHost(HAG *phag,const char *host)
1208 {
1209  HAGNAME *phagname;
1210 
1211  if (!phag) return 0;
1212  if(!asCheckClientIP) {
1213  size_t i, len = strlen(host);
1214  phagname = asCalloc(1, sizeof(*phagname) + len);
1215  for (i = 0; i < len; i++) {
1216  phagname->host[i] = (char)tolower((int)host[i]);
1217  }
1218 
1219  } else {
1220  struct sockaddr_in addr;
1221  epicsUInt32 ip;
1222 
1223  if(aToIPAddr(host, 0, &addr)) {
1224  static const char unresolved[] = "unresolved:";
1225 
1226  errlogPrintf("ACF: Unable to resolve host '%s'\n", host);
1227 
1228  phagname = asCalloc(1, sizeof(*phagname) + sizeof(unresolved)-1+strlen(host));
1229  strcpy(phagname->host, unresolved);
1230  strcat(phagname->host, host);
1231 
1232  } else {
1233  ip = ntohl(addr.sin_addr.s_addr);
1234  phagname = asCalloc(1, sizeof(*phagname) + 24);
1235  epicsSnprintf(phagname->host, 24,
1236  "%u.%u.%u.%u",
1237  (ip>>24)&0xff,
1238  (ip>>16)&0xff,
1239  (ip>>8)&0xff,
1240  (ip>>0)&0xff);
1241  }
1242  }
1243  ellAdd(&phag->list, &phagname->node);
1244  return 0;
1245 }
1246 
1247 static ASG *asAsgAdd(const char *asgName)
1248 {
1249  ASG *pprev;
1250  ASG *pnext;
1251  ASG *pasg;
1252  int cmpvalue;
1253  ASBASE *pasbase = (ASBASE *)pasbasenew;
1254 
1255  /*Insert in alphabetic order*/
1256  pnext = (ASG *)ellFirst(&pasbase->asgList);
1257  while(pnext) {
1258  cmpvalue = strcmp(asgName,pnext->name);
1259  if(cmpvalue < 0) break;
1260  if(cmpvalue==0) {
1261  if(strcmp(DEFAULT,pnext->name)==0) {
1262  if(ellCount(&pnext->inpList)==0
1263  && ellCount(&pnext->ruleList)==0)
1264  return(pnext);
1265  }
1266  errlogPrintf("Duplicate Access Security Group named '%s'\n", asgName);
1267  return(NULL);
1268  }
1269  pnext = (ASG *)ellNext(&pnext->node);
1270  }
1271  pasg = asCalloc(1,sizeof(ASG)+strlen(asgName)+1);
1272  ellInit(&pasg->inpList);
1273  ellInit(&pasg->ruleList);
1274  ellInit(&pasg->memberList);
1275  pasg->name = (char *)(pasg+1);
1276  strcpy(pasg->name,asgName);
1277  if(pnext==NULL) { /*Add to end of list*/
1278  ellAdd(&pasbase->asgList,&pasg->node);
1279  } else {
1280  pprev = (ASG *)ellPrevious(&pnext->node);
1281  ellInsert(&pasbase->asgList,&pprev->node,&pasg->node);
1282  }
1283  return(pasg);
1284 }
1285 
1286 static long asAsgAddInp(ASG *pasg,const char *inp,int inpIndex)
1287 {
1288  ASGINP *pasginp;
1289 
1290  if(!pasg) return(0);
1291  pasginp = asCalloc(1,sizeof(ASGINP)+strlen(inp)+1);
1292  pasginp->inp = (char *)(pasginp+1);
1293  strcpy(pasginp->inp,inp);
1294  pasginp->pasg = pasg;
1295  pasginp->inpIndex = inpIndex;
1296  ellAdd(&pasg->inpList,&pasginp->node);
1297  return(0);
1298 }
1299 
1300 static ASGRULE *asAsgAddRule(ASG *pasg,asAccessRights access,int level)
1301 {
1302  ASGRULE *pasgrule;
1303 
1304  if(!pasg) return(0);
1305  pasgrule = asCalloc(1,sizeof(ASGRULE));
1306  pasgrule->access = access;
1307  pasgrule->trapMask = 0;
1308  pasgrule->level = level;
1309  ellInit(&pasgrule->uagList);
1310  ellInit(&pasgrule->hagList);
1311  ellAdd(&pasg->ruleList,&pasgrule->node);
1312  return(pasgrule);
1313 }
1314 
1315 static long asAsgAddRuleOptions(ASGRULE *pasgrule,int trapMask)
1316 {
1317  if(!pasgrule) return(0);
1318  pasgrule->trapMask = trapMask;
1319  return(0);
1320 }
1321 
1322 static long asAsgRuleUagAdd(ASGRULE *pasgrule, const char *name)
1323 {
1324  ASGUAG *pasguag;
1325  UAG *puag;
1326  ASBASE *pasbase = (ASBASE *)pasbasenew;
1327 
1328  if (!pasgrule)
1329  return 0;
1330 
1331  puag = (UAG *)ellFirst(&pasbase->uagList);
1332  while (puag) {
1333  if (strcmp(puag->name, name)==0)
1334  break;
1335  puag = (UAG *)ellNext(&puag->node);
1336  }
1337  if (!puag){
1338  errlogPrintf("No User Access Group named '%s' defined\n", name);
1339  return S_asLib_noUag;
1340  }
1341 
1342  pasguag = asCalloc(1, sizeof(ASGUAG));
1343  pasguag->puag = puag;
1344  ellAdd(&pasgrule->uagList, &pasguag->node);
1345  return 0;
1346 }
1347 
1348 static long asAsgRuleHagAdd(ASGRULE *pasgrule, const char *name)
1349 {
1350  ASGHAG *pasghag;
1351  HAG *phag;
1352  ASBASE *pasbase = (ASBASE *)pasbasenew;
1353 
1354  if (!pasgrule)
1355  return 0;
1356 
1357  phag = (HAG *)ellFirst(&pasbase->hagList);
1358  while (phag) {
1359  if (strcmp(phag->name, name)==0)
1360  break;
1361  phag = (HAG *)ellNext(&phag->node);
1362  }
1363  if (!phag){
1364  errlogPrintf("No Host Access Group named '%s' defined\n", name);
1365  return S_asLib_noHag;
1366  }
1367 
1368  pasghag = asCalloc(1, sizeof(ASGHAG));
1369  pasghag->phag = phag;
1370  ellAdd(&pasgrule->hagList, &pasghag->node);
1371  return 0;
1372 }
1373 
1374 static long asAsgRuleCalc(ASGRULE *pasgrule,const char *calc)
1375 {
1376  short err;
1377  long status;
1378  size_t insize;
1379  unsigned long stores;
1380 
1381  if (!pasgrule) return 0;
1382  insize = strlen(calc) + 1;
1383  pasgrule->calc = asCalloc(1, insize);
1384  strcpy(pasgrule->calc, calc);
1385  pasgrule->rpcl = asCalloc(1, INFIX_TO_POSTFIX_SIZE(insize));
1386  status = postfix(pasgrule->calc, pasgrule->rpcl, &err);
1387  if(status) {
1388  free(pasgrule->calc);
1389  free(pasgrule->rpcl);
1390  pasgrule->calc = NULL;
1391  pasgrule->rpcl = NULL;
1392  status = S_asLib_badCalc;
1393  errlogPrintf("%s in CALC expression '%s'\n", calcErrorStr(err), calc);
1394  return status;
1395  }
1396  calcArgUsage(pasgrule->rpcl, &pasgrule->inpUsed, &stores);
1397  /* Until someone proves stores are not dangerous, don't allow them */
1398  if (stores) {
1399  free(pasgrule->calc);
1400  free(pasgrule->rpcl);
1401  pasgrule->calc = NULL;
1402  pasgrule->rpcl = NULL;
1403  status = S_asLib_badCalc;
1404  errlogPrintf("Assignment operator used in CALC expression '%s'\n",
1405  calc);
1406  }
1407  return(status);
1408 }
void *epicsStdCall asGetMemberPvt(ASMEMBERPVT asMemberPvt)
int epicsStdCall asDumpRules(const char *asgname)
LIBCOM_API void *epicsStdCall freeListCalloc(void *pvt)
Definition: freeListLib.c:60
Definition: asLib.h:147
char * inp
Definition: asLib.h:205
Definition: asLib.h:162
ELLNODE node
Definition: asLib.h:163
pvac::PutEvent result
Definition: clientSync.cpp:117
LIBCOM_API const char * calcErrorStr(short error)
Convert an error code to a string.
Definition: postfix.c:493
ASGMEMBER * pasgMember
Definition: asLib.h:231
LIBCOM_API int epicsStdCall aToIPAddr(const char *pAddrString, unsigned short defaultPort, struct sockaddr_in *pIP)
Definition: aToIPAddr.c:78
int asCheckClientIP
Definition: asLibRoutines.c:31
LIBCOM_API long epicsStdCall macParseDefns(MAC_HANDLE *handle, const char *defns, char **pairs[])
Parse macro definitions into an array of {name, value} pairs.
Definition: macUtil.c:32
void *epicsStdCall asGetClientPvt(ASCLIENTPVT asClientPvt)
#define S_asLib_badMember
Definition: asLib.h:138
#define FALSE
Definition: dbDefs.h:32
int asActive
Definition: asLibRoutines.c:40
#define ellCount(PLIST)
Report the number of nodes in a list.
Definition: ellLib.h:84
ELLLIST memberList
Definition: asLib.h:216
ELLNODE node
Definition: asLib.h:212
int epicsStdCall asDumpUag(const char *uagname)
pvd::Status status
int trapMask
Definition: asLib.h:238
long epicsStdCall asInitialize(ASINPUTFUNCPTR inputfunction)
Definition: asLibRoutines.c:84
ELLLIST ruleList
Definition: asLib.h:215
int i
Definition: scan.c:967
LIBCOM_API long calcArgUsage(const char *pinst, unsigned long *pinputs, unsigned long *pstores)
Find the inputs and outputs of an expression.
Definition: calcPerform.c:405
char host[1]
Definition: asLib.h:174
int trapMask
Definition: asLib.h:201
#define LOCK
Definition: asLibRoutines.c:34
char * calc
Definition: asLib.h:197
int epicsStdCall asDumpMemFP(FILE *fp, const char *asgname, void(*memcallback)(ASMEMBERPVT, FILE *), int clients)
The API for the EPICS Calculation Engine.
Definition: asLib.h:166
#define UNLOCK
Definition: asLibRoutines.c:35
long epicsStdCall asRegisterClientCallback(ASCLIENTPVT asClientPvt, ASCLIENTCALLBACK pcallback)
double * pavalue
Definition: asLib.h:217
long epicsStdCall asChangeGroup(ASMEMBERPVT *asMemberPvt, const char *newAsgName)
char * name
Definition: asLib.h:178
#define S_asLib_noMemory
Definition: asLib.h:141
#define S_asLib_badAsg
Definition: asLib.h:140
#define DEFAULT
Definition: asLibRoutines.c:45
Definition: asLib.h:176
char * user
Definition: asLib.h:164
#define S_asLib_noUag
Definition: asLib.h:129
int epicsStdCall asDumpHagFP(FILE *fp, const char *hagname)
#define S_asLib_badCalc
Definition: asLib.h:134
ELLNODE node
Definition: asLib.h:230
#define epicsMutexMustCreate()
Create an epicsMutex semaphore for use from C code.
Definition: epicsMutex.h:179
int epicsStdCall asDump(void(*memcallback)(struct asgMember *, FILE *), void(*clientcallback)(struct asgClient *, FILE *), int verbose)
#define NULL
Definition: catime.c:38
#define errMessage(S, PM)
Definition: errlog.h:48
#define S_asLib_noHag
Definition: asLib.h:130
Definition: asLib.h:152
LIBCOM_API void epicsStdCall freeListInitPvt(void **ppvt, int size, int nmalloc)
Definition: freeListLib.c:44
const char * user
Definition: asLib.h:232
void * userPvt
Definition: asLib.h:234
#define str(v)
unsigned int epicsUInt32
Definition: epicsTypes.h:43
long epicsStdCall asComputeAllAsg(void)
void * userPvt
Definition: asLib.h:226
unsigned long inpBad
Definition: asLib.h:218
ELLNODE node
Definition: asLib.h:192
long epicsStdCall asCompute(ASCLIENTPVT asClientPvt)
const char * asgName
Definition: asLib.h:225
ELLLIST asgList
Definition: asLib.h:155
#define CALCPERFORM_NARGS
Number of input arguments to a calc expression (A-L)
Definition: postfix.h:25
UAG * puag
Definition: asLib.h:184
Miscellaneous macro definitions.
struct gphPvt * phash
Definition: asLib.h:156
#define ellPrevious(PNODE)
Find the previous node in list.
Definition: ellLib.h:104
long epicsStdCall macExpandString(MAC_HANDLE *handle, const char *src, char *dest, long capacity)
Expand a string which may contain macro references.
Definition: macCore.c:174
ELLNODE node
Definition: asLib.h:204
int result
Definition: asLib.h:196
ASCLIENTCALLBACK pcallback
Definition: asLib.h:235
LIBCOM_API void epicsStdCall gphInitPvt(struct gphPvt **ppvt, int tableSize)
Definition: gpHashLib.c:37
#define S_asLib_InitFailed
Definition: asLib.h:136
int epicsStdCall asDumpHag(const char *hagname)
long epicsStdCall asInitFP(FILE *fp, const char *substitutions)
ELLLIST list
Definition: asLib.h:169
void ellAdd(ELLLIST *pList, ELLNODE *pNode)
Adds a node to the end of a list.
Definition: ellLib.c:24
LIBCOM_API GPHENTRY *epicsStdCall gphFind(struct gphPvt *pvt, const char *name, void *pvtid)
Definition: gpHashLib.c:92
LIBCOM_API long calcPerform(double *parg, double *presult, const char *pinst)
Run the calculation engine.
Definition: calcPerform.c:45
#define ellNext(PNODE)
Find the next node in list.
Definition: ellLib.h:99
char * name
Definition: asLib.h:213
#define EPICS_THREAD_ONCE_INIT
Definition: epicsThread.h:109
#define S_asLib_clientsExist
Definition: asLib.h:128
void epicsStdCall asPutMemberPvt(ASMEMBERPVT asMemberPvt, void *userPvt)
void * rpcl
Definition: asLib.h:198
Macro substitution context, for use by macLib routines only.
Definition: macLib.h:42
APIs for the epicsMutex mutual exclusion semaphore.
LIBCOM_API void epicsStdCall epicsThreadOnce(epicsThreadOnceId *id, EPICSTHREADFUNC, void *arg)
long epicsStdCall asRemoveMember(ASMEMBERPVT *asMemberPvt)
LIBCOM_API void epicsStdCall freeListFree(void *pvt, void *pmem)
Definition: freeListLib.c:131
LIBCOM_API void *epicsStdCall asCalloc(size_t nobj, size_t size)
ELLNODE node
Definition: asLib.h:177
ChannelProviderRegistry::shared_pointer clients
unsigned long inpChanged
Definition: asLib.h:219
asAccessRights access
Definition: asLib.h:237
long epicsStdCall asAddMember(ASMEMBERPVT *pasMemberPvt, const char *asgName)
int epicsStdCall asDumpFP(FILE *fp, void(*memcallback)(struct asgMember *, FILE *), void(*clientcallback)(struct asgClient *, FILE *), int verbose)
LIBCOM_API void epicsStdCall gphDumpFP(FILE *fp, struct gphPvt *pvt)
Definition: gpHashLib.c:211
#define BUF_SIZE
long epicsStdCall asInitFile(const char *filename, const char *substitutions)
ASBASE volatile * pasbase
Definition: asLibRoutines.c:38
void epicsStdCall asPutClientPvt(ASCLIENTPVT asClientPvt, void *userPvt)
ELLLIST list
Definition: asLib.h:179
LIBCOM_API int epicsStdCall asDumpHash(void)
LIBCOM_API void * callocMustSucceed(size_t count, size_t size, const char *msg)
A calloc() that never returns NULL.
Definition: cantProceed.c:22
int epicsStdCall asDumpMem(const char *asgname, void(*memcallback)(ASMEMBERPVT, FILE *), int clients)
ELLNODE node
Definition: asLib.h:167
struct asg * pasg
Definition: asLib.h:207
LIBCOM_API void epicsStdCall gphFreeMem(struct gphPvt *pvt)
Definition: gpHashLib.c:176
int errlogPrintf(const char *pFormat,...)
Definition: errlog.c:105
#define stdout
Definition: epicsStdio.h:30
ELLLIST uagList
Definition: asLib.h:199
int(* ASINPUTFUNCPTR)(char *buf, int max_size)
Definition: asLib.h:31
ELLLIST hagList
Definition: asLib.h:154
ELLLIST uagList
Definition: asLib.h:153
int inpIndex
Definition: asLib.h:208
LIBCOM_API int epicsStdCall asDumpHashFP(FILE *fp)
ELLLIST hagList
Definition: asLib.h:200
long epicsStdCall macDeleteHandle(MAC_HANDLE *handle)
Marks a handle invalid, and frees all storage associated with it.
Definition: macCore.c:360
long epicsStdCall asComputeAsg(ASG *pasg)
void asFreeAll(ASBASE *pasbase)
ELLNODE node
Definition: asLib.h:187
int level
Definition: asLib.h:236
int level
Definition: asLib.h:194
Definition: asLib.h:211
long epicsStdCall macCreateHandle(MAC_HANDLE **pHandle, const char *pairs[])
Creates a new macro substitution context.
Definition: macCore.c:100
HAG * phag
Definition: asLib.h:188
#define TRUE
Definition: dbDefs.h:27
#define S_asLib_badClient
Definition: asLib.h:139
Definition: asLib.h:186
#define ellInit(PLIST)
Initialize a list type.
Definition: ellLib.h:76
void verbose(void)
Definition: verbose.c:27
ELLNODE node
Definition: asLib.h:173
int epicsStdCall asDumpUagFP(FILE *fp, const char *uagname)
void ellInsert(ELLLIST *plist, ELLNODE *pPrev, ELLNODE *pNode)
Inserts a node into a list immediately after a specific node.
Definition: ellLib.c:178
Text macro substitution routines.
int osiSockAttach()
Definition: osdSock.c:54
int epicsStdCall asDumpRulesFP(FILE *fp, const char *asgname)
ASG * pasg
Definition: asLib.h:223
Routines for code that can&#39;t continue or return after an error.
void(* ASCLIENTCALLBACK)(ASCLIENTPVT, asClientStatus)
Definition: asLib.h:37
char * host
Definition: asLib.h:233
ELLLIST inpList
Definition: asLib.h:214
Definition: asLib.h:172
long epicsStdCall asRemoveClient(ASCLIENTPVT *asClientPvt)
LIBCOM_API long postfix(const char *psrc, char *pout, short *perror)
Compile an infix expression into postfix byte-code.
Definition: postfix.c:209
long epicsStdCall asAddClient(ASCLIENTPVT *pasClientPvt, ASMEMBERPVT asMemberPvt, int asl, const char *user, char *host)
long epicsStdCall asInitMem(const char *acf, const char *substitutions)
unsigned long inpUsed
Definition: asLib.h:195
C++ and C descriptions for a thread.
LIBCOM_API long epicsStdCall macInstallMacros(MAC_HANDLE *handle, char *pairs[])
Install set of {name, value} pairs as definitions.
Definition: macUtil.c:253
asAccessRights
Definition: asLib.h:147
ELLNODE node
Definition: asLib.h:183
void ellDelete(ELLLIST *pList, ELLNODE *pNode)
Deletes a node from a list.
Definition: ellLib.c:75
asAccessRights access
Definition: asLib.h:193
ELLNODE node
Definition: asLib.h:222
ELLLIST clientList
Definition: asLib.h:224
#define INFIX_TO_POSTFIX_SIZE(n)
Calculate required size of postfix buffer from infix.
Definition: postfix.h:58
LIBCOM_API char *epicsStdCall asStrdup(unsigned char *str)
Definition: asLib.h:191
#define S_asLib_asNotActive
Definition: asLib.h:137
Definition: asLib.h:182
LIBCOM_API int epicsStdCall epicsSnprintf(char *str, size_t size, const char *format,...) EPICS_PRINTF_STYLE(3
long epicsStdCall asChangeClient(ASCLIENTPVT asClientPvt, int asl, const char *user, char *host)
LIBCOM_API GPHENTRY *epicsStdCall gphAdd(struct gphPvt *pvt, const char *name, void *pvtid)
Definition: gpHashLib.c:97
char * name
Definition: asLib.h:168
Definition: asLib.h:203
#define ellFirst(PLIST)
Find the first node in list.
Definition: ellLib.h:89
#define S_asLib_badConfig
Definition: asLib.h:133