Util.c
From Organic Design wiki
// [[[[http://www.organicdesign.co.nz/peerd|peerd]]]] - nodal p2p wiki daemon
// This article and all its includes are licenced under LGPL
// GPL: [[[[http://www.gnu.org/copyleft/lesser.html]]]]
// SRC: [[[[http://www.organicdesign.co.nz/util.c]]]]
// included in [[[[http://www.organicdesign.co.nz/category:peerd/files/C|peerd]]]][[[[http://www.organicdesign.co.nz/peerd.c|/peerd.c]]]]
void logAdd(char*, ... );
char **split(char,char*);
char *itob(int,char*);
int insertPointer(void*);
void *removePointer(int);
void **pointer(int);
void args(int,char**);
// ----------------------------------------------------------------------------------------- //
// util.c
// Output a log entry
// - Output format is "Ddd Mmm dd HH:mm:ss : [grandpa.parent.this] : message"
// - Message can contain format like printf but only %s and %d
// - todo: Should use [[[[io.c]]]] to send multiplexly
char *laMsg = NULL;
void logAdd(char *format, ... ) {
if (laMsg == NULL) laMsg = malloc(1000);
char *msg = laMsg;
va_list args;
va_start(args,format);
time_t now = time(NULL);
char *nowtext = ctime(&now);
if (nowtext) while (*msg++ = *nowtext++);
sprintf(msg-2," : [%d.%d.%d] ",grandpa,parent,this);
msg += 17;
*(msg-2) = ':';
*(msg-1) = ' ';
while (*format) {
if (strncmp(format,"%d",2)==0) {
msg += sprintf(msg,"%d",va_arg(args,int));
format += 2;
}
else if (strncmp(format,"%s",2)==0) {
char *arg = va_arg(args,char*);
while (*arg) *msg++ = *arg++;
format += 2;
}
else *msg++ = *format++;
}
va_end(args);
*msg++ = '\n';
*msg++ = '\0';
printf(laMsg);
}
// Return an array of strings resulting from splitting passed text at passed character
// - the array is terminated by a NULL pointer
char **split(char c,char *text) {
int len = strlen(text), items = 0, size = 10;
char **list = malloc(size);
char *i = malloc(len+1), *j = i, *k = i, *item = i;
while(*j++ = *text++);
while(i <= k+len) {
if (*i == c) *i = '\0';
if ((*i++ == '\0')&&strlen(item)) {
if (items>size-2) realloc(list,size+=10);
list[items++] = item;
list[items] = NULL;
item = i;
}
}
return list;
}
// Replaces missing itoa() and is specialised for binary return a string of \1 and \2 characters
char *itob(int value, char *buf) {
int i;
char *j = buf;
for (i=1; i<=value>>1; i<<=1) *j++ = value&i ? '\1' : '\2';
*j = '\0';
return buf;
}
// ----------------------------------------------------------------------------------------- //
// Global Pointer List
// - use insertPointer() and removePointer() to access the dynamically allocating pointer-array
// - internally uses freePush() and freePop() to maintain a linked-list of free array slots
int psize = 100, pitem = 1;
void **plist = NULL;
typedef struct fi {
int index;
struct fi *next;
} fitem;
fitem *flist = NULL;
// add a new pointer to the list, try using slots from the free-list before extending array
int insertPointer(void *ptr) {
int index;
if (plist == NULL) plist = malloc(psize*sizeof(void*));
if (flist) {
fitem *kill = flist;
flist = (fitem*)kill->next;
index = kill->index;
free(kill);
}
else if ((index = ++pitem) > psize) realloc(plist,psize += 100);
plist[index] = ptr;
return index;
}
// push the index onto the free-list, returning the pointer at that index
void *removePointer(int index) {
fitem *newfree = (fitem*)malloc(sizeof(fitem));
newfree->next = flist ? flist : NULL;
flist = newfree;
return plist[newfree->index = index];
}
void **pointer(int index) {
return plist+index;
}
// Process command-line args
void args(int argc, char **argv) {
// Scan args for known parameters
if (argc>1) {
int l = strlen(argv[1]);
peer = strncpy(malloc(l+1),argv[1],l);
peer[l] = '\0';
while(argc-->2) {
char **arg = split('=',argv[argc]);
if (strcmp("port",*arg)==0) port = atoi(strncpy(malloc(l=strlen(arg[1])+1),arg[1],l));
if (strcmp("file",*arg)==0) file = strncpy(malloc(l=strlen(arg[1])+1),arg[1],l);
free(*arg);
free(arg);
}
}
#if __unix__
// Set name as seen in ps list if ux
int l;
char *tmp = *argv;
for (l=40;l--;) *tmp++ = '\0';
sprintf(*argv,"peerd: %s (http%d)",peer,port);
#endif
}