/* data/xattrib.c librock_CHISEL _summary Example of filling in structures from an attributes file. Table of Contents. [License and Disclaimer of Warranty] [License Attributes] [How to Reuse this software] [Definitions and header file inclusions] [Function Implementation and inline documentation] [EXAMPLE FILE] [Revision summary and Changelog] */ /*************************************************************/ /***[License and Disclaimer of Warranty]**********************/ /* By copyright law, you must agree to these terms before you modify or copy this software or any part of it. Copyright (c) 2004, Forrest J. Cavalier III Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************/ /***[License Attributes]**************************************/ /* The librock LIDESC tool reports some license attributes. It reports the following for the MIT license used for this software: A notice must be included in documentation or other materials when a binary is distributed. (librock_DOCNOTE_1C_WITHBIN) Notices must remain in source code. (librock_SRCNOTE_1) The Free Software Foundation says this license is a Free software license. (librock_LIDESC_COMBINE_FSF_OK) The Free Software Foundation says this license is GPL compatible. (librock_LIDESC_COMBINE_GPL_OK) The Open Source Initiative approved this license as OSD compliant. (librock_LIDESC_COMBINE_OSD_OK) Note: You may be able to use LIDESC tools to check compatibility with other licenses. */ /*************************************************************/ /***[How to Reuse this software]******************************/ /* 1. Agree to the license and disclaimer of warranty. 2. Read through the comments in this file for pointers on how to adapt it for your use. Verify the implementation is suitable for you. 3. An example.conf file appears in comments at the end of this file..... This file is originally from libROCK: the Reusable Opensource Code and Knowledge library. For an automated update and build system, license certificates, and more, see http://www.mibsoftware.com/librock/ This file is written for ANSI C: librock_CHISEL _portreport_permit_ansi */ /*************************************************************/ /*************************************************************/ /***[Function Implementation and inline documentation]********/ #ifdef librock_IMPL_LIDESC #include /* librock_LIDESC_HC=cc598307414a9997b32b60a2e7a8e7c6a13d6438 */ void *librock_LIDESC_xattrib[] = { "\n" __FILE__ librock_LIDESC_mit "\n", 0 }; #endif /*************************************************************/ #include #include #include #include #include #include #include /**************************************************************/ struct peer_s { /* Every element you will create and fill will need a pszPrefix */ char *pszPrefix; /* The name (entire prefix) in the config file */ /* You do not have to have a linked list, but this example does */ struct peer_s *next; /* Structure members here */ unsigned long max_connections; int streaming; /* 0 or 1 */ const char *name; const char *ip_name; } *peers; struct peer_s *peer_alloc(struct librock_attributes_s *pa,const char *pPrefix,int cbPrefix) { /**{* Create it and add it to the linked list */ struct peer_s *peer = malloc(sizeof(*peer)); if (!peer) { return 0; } /**{* Store the prefix we see in the file */ peer->pszPrefix = malloc(cbPrefix+1); if (!peer->pszPrefix) { free(peer); return 0; } librock_strn0cpy(peer->pszPrefix,pPrefix,cbPrefix); /**}*/ peer->next = peers; peers = peer; /**}*/ /* Caller must fill out other elements */ return peer; } /**************************************************************/ int ssboolean(const char *ptr,int *pRet) { /* Helper function for scanning booleans */ if (!librock_strcasecmp(ptr,"false")) { *pRet = 0; return strlen(ptr); } if (!librock_strcasecmp(ptr,"true")) { *pRet = 1; return strlen(ptr); } return 0; } /**************************************************************/ /**************************************************************/ void peer_attrib_set(struct librock_attributes_s *pa,struct peer_s *peer,const char *pszEnv,int cbPREFIX,const char *pval) { /* Store an attribute into a peer structure, or check the syntax of a default attribute. This is a subroutine called by peerlist_config(). This and that function are good examples for how to fill in structures and lists from a libROCK attribute file. */ /* Copyright 2004 Forrest J. Cavalier III, http://www.mibsoftware.com Open-source under MIT license. NO WARRANTY. Copies must retain this block. License, originals, details: http://www.mibsoftware.com/librock/ */ int c; if (!peer && (cbPREFIX >= 2)&& (pszEnv[cbPREFIX-2] == ']')) { /**{* locate or create a new peer structure */ peer = peers; while(peer) { if (!librock_strncasecmp(pszEnv,peer->pszPrefix,cbPREFIX)&& !peer->pszPrefix[cbPREFIX]) { break; /* Match */ } peer = peer->next; } if (!peer) { /* Not found.*/ /**{* Add to list */ const char *val; peer = peer_alloc(pa,pszEnv,cbPREFIX); if (!peer) { printf("Could not get memory for (%s)...\n",pszEnv); return; } /**}*/ /**{* Set defaults which do not come from parent contexts */ /* Some of these may not come from the attribute file at all.*/ peer->ip_name = 0; /* no getparent default for this one*/ peer->name = 0; /* no getparent default for this one */ /**}*/ /**{* Recurse to set default values found by using _getparent....*/ /* ->max-connections */ val = librock_attributes_getparent(pa,peer->pszPrefix,"max-connections",-1); if (!val) { printf("Error: Attribute file does not specify default max-connections for %s\n",peer->pszPrefix); val = "7"; } peer_attrib_set(pa,peer,"max-connections=",0,val); /* ->streaming */ val = librock_attributes_getparent(pa,peer->pszPrefix,"streaming",-1); if (!val) { printf("Error: Attribute file does not specify default streaming for %s\n",peer->pszPrefix); val = "false"; } peer_attrib_set(pa,peer,"streaming=",0,val); /**}*/ } /**}*/ } else { /* Leaving peer==0 for syntax check only */ } /**{* Recognize the expected attribute names and translate values */ c = librock_counttoch(pszEnv+cbPREFIX,'='); /* There is one clause here for each element in the structure that can be set from the attributes file. */ if (!librock_strncasecmp(pszEnv+cbPREFIX,"max-connections=",c)) { /* This code is a good example for an unsigned long. */ if (peer) { peer->max_connections = strtoul(pval,(char **)&pval,10); } else { strtoul(pval,(char **)&pval,10); } } else if (!librock_strncasecmp(pszEnv+cbPREFIX,"ip-name=",c)) { /* This code is a good example for copying a string */ if (peer) { char *asz =0; librock_astrcpy(&asz,pval); peer->ip_name = librock_astrstatic(&asz); } pval += strlen(pval); } else if (!librock_strncasecmp(pszEnv+cbPREFIX,"name=",c)) { /* This code is a good example for copying a string */ if (peer) { char *asz =0; librock_astrcpy(&asz,pval); peer->name = librock_astrstatic(&asz); } pval += strlen(pval); } else if (!librock_strncasecmp(pszEnv+cbPREFIX,"streaming=",c)) { /* Good example for a boolean, or enumerated value. */ int testi; /* Dummy value for syntax checking when !peer */ pval += ssboolean(pval,peer ? &peer->streaming : &testi); } else { printf("Error. peer_attrib_set does not handle the attribute %s\n",pszEnv); return; } /* If the parser above did not grab all of the string, report an error */ if (*pval) { printf("Error. %d unprocessed characters when setting %s.\n",strlen(pval),pszEnv); } /**}*/ } /**************************************************************/ /**************************************************************/ void peerlist_config(struct librock_attributes_s *pa) { /* Iterate a list of attributes and create a linked list of peers. This is a good example for filling in structures and lists from an attribute file. You would probably copy all of this function, and change: the function name the prefix parameter given to librock_attributes_iter() and call your function instead of peer_attrib_set() Call this function after calling librock_attributes_readfile(). */ /* Copyright 2004 Forrest J. Cavalier III, http://www.mibsoftware.com Open-source under MIT license. NO WARRANTY. Copies must retain this block. License, originals, details: http://www.mibsoftware.com/librock/ */ const char *penv = 0; while(1) { const char *ptr; char *pval; int cbPREFIX; penv = librock_attributes_iter(pa,"peerlist.",penv); if (!penv) { break; } pval = strchr(penv,'='); /**{* Determine the entire prefix for this attribute. */ ptr = pval; while((ptr > penv)&&(*ptr != '.')) { ptr--; } if (*ptr == '.') { ptr++; } cbPREFIX = ptr - penv; /**}*/ /**{* Store or syntax check. If the prefix ends with "]." then this is a list item we are interested in storing.... peer_attrib_set() will locate the named structure and translate the attribute. otherwise it is a default attribute.... peer_attrib_set() does syntax checking. */ peer_attrib_set(pa,0,penv,cbPREFIX,pval+1); /**}*/ } } /**************************************************************/ /**************************************************************/ const char *doenv_lookup(struct librock_attributes_s *pa,const char *name,int cbName) { const char *ret; char *asz = 0; if (cbName == -1) { librock_astrn0cpy(&asz,name,librock_countCid(name)); } else { librock_astrn0cpy(&asz,name,cbName); } ret = getenv(asz); librock_astrfree(&asz); return ret; } /**************************************************************/ /**************************************************************/ int main(int argc,char **argv) { /* Copyright 2004 Forrest J. Cavalier III, http://www.mibsoftware.com Open-source under MIT license. NO WARRANTY. Copies must retain this block. License, originals, details: http://www.mibsoftware.com/librock/ */ FILE *f; struct librock_attributes_s *paENV; struct librock_attributes_s *pa; char *aszErr = 0; const char *pszSRC = argv[1]; paENV = librock_attributes_alloc(); pa = librock_attributes_alloc(); librock_attributes_setfnget(paENV,doenv_lookup); /* Use getenv() as outermost context for name-value pairs */ librock_attributes_setcontext(pa,paENV,&aszErr); /**{* Open and read the file */ f = fopen(pszSRC,librock_FOPEN_MODE_RB); if (f) { const char *penv = 0; librock_attributes_readfile(f,pa,0,pszSRC,0,&aszErr); fclose(f); /**{* Set and retrieve some values */ librock_attributes_set(pa,"prefix.","name",-1,"value",-1); penv = librock_attributes_get(pa,"prefix.name",-1); if (penv) { printf("Defined as:%s\n",penv); } /**}*/ /**{* Show results. Iterate everything */ printf("---------Iterating everything-------------\n"); penv = 0; while(1) { penv = librock_attributes_iter(pa,0,penv); if (!penv) { break; } printf("%s\n",penv); } /**}*/ /**{* Show errors */ if (aszErr) { printf("%s",aszErr); } /**}*/ } else { /* Could not read the file */ fprintf(stderr,"Could not open the file for reading\n"); } /**}*/ { struct peer_s *peer; peerlist_config(pa); /* Process attributes into a linked list of peers */ printf("\n--------- Showing peers as loaded-------------\n"); peer=peers; while(peer) { printf("\n{\n.prefix %s\n",peer->pszPrefix); printf(" name=%s\n",peer->name); printf(" ip-name=%s\n",peer->ip_name); printf(" max-connections=%ld\n",peer->max_connections); printf(" streaming=%d\n",peer->streaming); printf("}\n"); peer = peer->next; } } librock_astrfree(&aszErr); librock_attributes_free(pa); librock_attributes_free(paENV); return 0; } /***[EXAMPLE FILE]**************************/ /* ########################################################################### ## This is a libROCK attributes file. See ## http://www.mibsoftware.com/librock/data/attributes_file.htm ## for an explanation of syntax. ## # We want to allow '-' in names..... .idchars "_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-" max-connections= 5 streaming= true ## ## Peers that get standard defaults. ## { .prefix peerlist. .list [000]. { name=decwrl ip-name= generic.example.com } { ip-name= uunet.uu.net max-connections= 10 } } {if 1 #Conditionally disable this whole section.... # ## Faster peers get different defaults. .prefix peerlist.fast. .list [000]. max-connections= 7 { name=data.ramona.vix.com # ip-name defaults to data.ramona.vix.com streaming= false } { name=bb.home.vix.com ip-name= 192.5.5.33 } } ##******************************************************************/ /***[Revision summary and Changelog]**************************/ /* $Log: xattrib.c,v $ Revision 1.1 2004/07/24 13:05:09 fcavalier@mibsoftware.com rights=#1 Initial commit rights#1 Copyright (c) Forrest J Cavalier III d-b-a Mib Software rights#1 License text in librock_LIDESC_HC=cc598307414a9997b32b60a2e7a8e7c6a13d6438 */