2022-09-07 20:45:37 +00:00
|
|
|
#include <iso646.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
|
|
|
|
|
2022-10-01 23:05:39 +00:00
|
|
|
/* Error constants */
|
|
|
|
enum
|
|
|
|
{
|
2022-09-07 20:45:37 +00:00
|
|
|
UNKNOWN_FAIL = 1,
|
|
|
|
MALLOC_FAIL,
|
|
|
|
NEEDARG_FAIL,
|
|
|
|
FOPEN_FAIL,
|
2022-10-01 18:38:29 +00:00
|
|
|
WRITE_FAIL,
|
|
|
|
TIME_FAIL,
|
|
|
|
MISC_FAIL
|
2022-09-07 20:45:37 +00:00
|
|
|
};
|
|
|
|
|
2022-10-01 23:05:39 +00:00
|
|
|
/* Standard data identifiers for nodes */
|
|
|
|
enum
|
2022-09-07 20:45:37 +00:00
|
|
|
{
|
2022-10-01 23:05:39 +00:00
|
|
|
CHAR = 1,
|
|
|
|
INT,
|
|
|
|
LONG,
|
|
|
|
DOUBLE,
|
|
|
|
CHARP,
|
|
|
|
INTP,
|
|
|
|
LONGP,
|
|
|
|
DOUBLEP,
|
|
|
|
NODEP
|
|
|
|
};
|
2022-09-07 20:45:37 +00:00
|
|
|
|
2022-10-01 23:05:39 +00:00
|
|
|
/* node - node type suitable for being a member in a linked list. */
|
|
|
|
/* name - the name of the data in this node */
|
|
|
|
/* data - pointer to arbitrary data */
|
|
|
|
/* type - implementation-defined identifier for what kind of data this node holds */
|
|
|
|
typedef struct LNODE
|
|
|
|
{
|
|
|
|
struct LNODE *previous;
|
|
|
|
char *name;
|
|
|
|
void *data;
|
|
|
|
int type;
|
|
|
|
struct LNODE *next;
|
|
|
|
} node;
|
2022-09-07 20:45:37 +00:00
|
|
|
|
|
|
|
|
|
|
|
/* Condition should be one of the above enum'd strings. Info is optional; it can just be NULL when irrelevant. */
|
|
|
|
void throw(long unsigned int condition, void *info)
|
|
|
|
{
|
|
|
|
switch(condition)
|
|
|
|
{
|
|
|
|
case UNKNOWN_FAIL: printf("unknown failure\n");
|
|
|
|
exit(UNKNOWN_FAIL);
|
|
|
|
case MALLOC_FAIL: printf("malloc failure\n");
|
|
|
|
exit(MALLOC_FAIL);
|
|
|
|
case NEEDARG_FAIL: printf("usage: %s\n", (char *) info);
|
|
|
|
exit(NEEDARG_FAIL);
|
|
|
|
case FOPEN_FAIL: printf("failed to open: %s\n", (char *) info);
|
|
|
|
exit(FOPEN_FAIL);
|
|
|
|
case WRITE_FAIL: printf("failed to write: %s\n", (char *) info);
|
|
|
|
exit(WRITE_FAIL);
|
2022-10-01 18:38:29 +00:00
|
|
|
case TIME_FAIL: printf("time error: %s\n", (char *) info);
|
|
|
|
exit(TIME_FAIL);
|
|
|
|
case MISC_FAIL: printf("%s\n", (char *) info);
|
|
|
|
exit(MISC_FAIL);
|
2022-09-07 20:45:37 +00:00
|
|
|
default: printf("You shouldn't be seeing this.\nSomething is very wrong.\n");
|
|
|
|
exit(-256);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-01 23:05:39 +00:00
|
|
|
|
|
|
|
/* arrccat -- function to copy arr2len bytes from arr2 to the arr1len'th position of arr1. returns *newarr, and stores the length */
|
|
|
|
/* of newarr[] in arr1len (that's why it needs to be a pointer to arr1len and not just a long unsigned integer). */
|
|
|
|
char *arrccat(char *arr1, char *arr2, size_t *arr1len, size_t arr2len)
|
|
|
|
{
|
|
|
|
char *newarr;
|
|
|
|
unsigned int i, i2;
|
|
|
|
newarr = malloc(*arr1len+arr2len);
|
|
|
|
i = i2 = 0;
|
|
|
|
|
|
|
|
for(i = 0; i < *arr1len; i++)
|
|
|
|
{
|
|
|
|
newarr[i] = arr1[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
for(i2 = 0; i2 < arr2len; i2++, i++)
|
|
|
|
{
|
|
|
|
newarr[i] = arr2[i2];
|
|
|
|
}
|
|
|
|
|
|
|
|
*arr1len = *arr1len+arr2len;
|
|
|
|
|
|
|
|
return newarr;
|
|
|
|
}
|
|
|
|
|
2022-09-07 20:45:37 +00:00
|
|
|
/* mastrcat -- improved string concat function. returns a pointer to the first element in a buffer containing the strings str1 */
|
|
|
|
/* and str2 joined end-to-end. */
|
|
|
|
char *mastrcat(char *str1, char *str2)
|
|
|
|
{
|
|
|
|
unsigned long int nbi, stri, nbsize;
|
|
|
|
char *nbuf;
|
|
|
|
nbi = stri = 0;
|
|
|
|
nbsize = (strlen(str1) + strlen(str2));
|
|
|
|
nbuf = malloc(nbsize);
|
|
|
|
|
|
|
|
for(stri = 0; str1[stri] != '\0'; nbi++, stri++)
|
|
|
|
{
|
|
|
|
nbuf[nbi] = str1[stri];
|
|
|
|
}
|
|
|
|
|
|
|
|
for(stri = 0; str2[stri] != '\0'; nbi++, stri++)
|
|
|
|
{
|
|
|
|
nbuf[nbi] = str2[stri];
|
|
|
|
}
|
|
|
|
|
|
|
|
return nbuf;
|
2022-10-01 23:05:39 +00:00
|
|
|
}
|
2022-09-07 20:45:37 +00:00
|
|
|
|
2022-10-01 22:46:19 +00:00
|
|
|
/* open stdin if path is null */
|
|
|
|
FILE *file_open(char *path, char *mode)
|
|
|
|
{
|
|
|
|
FILE *fd;
|
|
|
|
|
|
|
|
fd = 0;
|
|
|
|
|
|
|
|
|
|
|
|
if(!mode)
|
|
|
|
{
|
2022-10-01 23:05:39 +00:00
|
|
|
return(NULL);
|
2022-10-01 22:46:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if(path == NULL || !strcmp(path, "-"))
|
|
|
|
{
|
|
|
|
fd = fopen("/dev/stdin", mode);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fd = fopen(path, mode);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!fd)
|
|
|
|
{
|
2022-10-01 23:05:39 +00:00
|
|
|
return(NULL);
|
2022-10-01 22:46:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return(fd);
|
|
|
|
}
|
|
|
|
|
2022-10-01 23:05:39 +00:00
|
|
|
|
|
|
|
/* return a buffer containing the contents of fd, or NULL if failure. Store the size of the new buffer in newsize; -1 on fail. */
|
|
|
|
char *file_read(FILE *fd, int *newsize)
|
|
|
|
{
|
|
|
|
int bufsize, c, i;
|
|
|
|
|
|
|
|
char *buf, *tmpbuf;
|
|
|
|
|
|
|
|
/* bufsize is arbitrary */
|
|
|
|
bufsize = 4096;
|
|
|
|
c = i = 0;
|
|
|
|
|
|
|
|
buf = tmpbuf = 0;
|
|
|
|
|
|
|
|
|
|
|
|
if( !(buf = malloc(bufsize)))
|
|
|
|
{
|
|
|
|
*newsize = -1;
|
|
|
|
return(NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
for(i = 0; (c = fgetc(fd)) != EOF; i++)
|
|
|
|
{
|
|
|
|
if(i >= bufsize)
|
|
|
|
{
|
|
|
|
if( !(tmpbuf = malloc(bufsize *= 2)))
|
|
|
|
{
|
|
|
|
*newsize = -1;
|
|
|
|
return(NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
memcpy(tmpbuf, buf, i-1);
|
|
|
|
free(buf);
|
|
|
|
buf = tmpbuf;
|
|
|
|
}
|
|
|
|
|
|
|
|
buf[i] = c;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
*newsize = i;
|
|
|
|
return(buf);
|
|
|
|
}
|
2022-10-18 16:47:34 +00:00
|
|
|
|
|
|
|
|
|
|
|
node *node_create()
|
|
|
|
{
|
|
|
|
node *newnode;
|
|
|
|
|
|
|
|
newnode = 0;
|
|
|
|
|
|
|
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
|
|
return(newnode);
|
|
|
|
}
|
|
|
|
|
|
|
|
int node_free(node *todel)
|
|
|
|
{
|
|
|
|
node *nodep;
|
|
|
|
|
|
|
|
|
|
|
|
nodep = todel->previous;
|
|
|
|
nodep->next = todel->next;
|
|
|
|
|
|
|
|
|
|
|
|
free(todel->name);
|
|
|
|
free(todel->data);
|
|
|
|
free(todel);
|
|
|
|
|
|
|
|
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* concat - return a buffer of size new_size containing s1 and s2 concatenated. */
|
|
|
|
char *concat(char *a1, char *a2, int a1_size, int a2_size)
|
|
|
|
{
|
|
|
|
char *newbuf;
|
|
|
|
|
|
|
|
newbuf = 0;
|
|
|
|
|
|
|
|
|
|
|
|
if( !(newbuf = malloc(a1_size+a2_size)))
|
|
|
|
{
|
|
|
|
throw(MALLOC_FAIL, "concat: couldn't create buffer");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if(a1_size)
|
|
|
|
{
|
|
|
|
memcpy(newbuf, a1, a1_size);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(a2_size)
|
|
|
|
{
|
|
|
|
memcpy((newbuf + a1_size), a2, a2_size);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return(newbuf);
|
|
|
|
}
|