1
0
Fork 0
mirror of https://gitlab.com/niansa/simpsh-httpd.git synced 2025-03-06 20:53:36 +01:00
simpsh-httpd/cport/databuffer.h
2020-08-04 18:07:11 +02:00

167 lines
4.2 KiB
C

#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/mman.h>
struct databuffer {
size_t len;
char *data;
};
void db_init(struct databuffer *db) { // Initialises the db
db->len = 0;
db->data = malloc(1);
db->data[0] = 0x00;
}
void db_deinit(struct databuffer *db) { // Deinitialises the db (TODO)
//free(db->data);
}
const char *db_raw(struct databuffer *db) { // Append temporary null-terminator and returns data
db->data = realloc(db->data, db->len + 1);
db->data[db->len] = 0x00;
return db->data;
}
void db_clear(struct databuffer *db) { // Reinitialises ("clears") the db
db_deinit(db);
db_init(db);
}
void db_append(struct databuffer *db, const struct databuffer *db_src) { // Appends db_src to db
if (db_src->len == 0) {
return;
}
db->len += db_src->len;
db->data = realloc(db->data, db->len);
memcpy(db->data + db->len - db_src->len, db_src->data, db_src->len);
}
void db_set(struct databuffer *db, const struct databuffer *db_src) { // Resets db to db_src
db_clear(db);
db_append(db, db_src);
}
const struct databuffer sized_db(const char *buffer, size_t len) { // Generates sized-size uninitialised (!!!) db
struct databuffer thisdb;
thisdb.data = buffer;
thisdb.len = len;
return thisdb;
}
const struct databuffer auto_db(const char *buffer) { // Same as above but autodetects size
return sized_db(buffer, strlen(buffer));
}
bool db_compare(const struct databuffer *db1, const struct databuffer *db2) { // Compares two dbs
if (db1->len != db2->len) {
return true;
} else {
for (size_t it = 0; it != db1->len; it++) {
if (db1->data[it] != db2->data[it]) {
return false;
}
}
return true;
}
}
ssize_t db_find(const struct databuffer *db, const struct databuffer *db_src) { // Finds db_src in db, returns position or -1
if (db->len < db_src->len) {
return -1;
}
struct databuffer thisdb;
thisdb.len = db_src->len;
for (char *byte = db->data; byte != db->data + db->len - db_src->len + 1; byte++) {
thisdb.data = byte;
if (db_compare(&thisdb, db_src)) {
return byte - db->data;
}
}
return -1;
}
bool db_contains(const struct databuffer *db, const struct databuffer *db_src) { // Checks if db contains db_src
return db_find(db, db_src) != -1;
}
bool db_startswith(const struct databuffer *db, const struct databuffer *db_src) { // Checks if db starts with db_src
return db_find(db, db_src) == 0;
}
bool db_endswith(const struct databuffer *db, const struct databuffer *db_src) { // Checks if db ends with db_src
if (db->len < db_src->len) {
return false;
}
struct databuffer db_aligned;
db_aligned = sized_db(db->data + db->len - db_src->len, db_src->len);
return db_compare(&db_aligned, db_src);
}
bool db_fcheck(FILE *stream) {
if (stream == NULL) {
perror("Couldn't handle file");
return false;
} else {
return true;
}
}
void db_fwrite(const struct databuffer *db, FILE *output) { // writes data from db to output
db_fcheck(output);
fwrite(db->data, db->len, 1, output);
}
void db_fread(struct databuffer *db, FILE *input) { // Reads data from input to db
size_t readbytes;
struct databuffer readdb;
char outb[16];
db_fcheck(input);
while (feof(input) == 0) {
readbytes = fread(outb, 1, sizeof(outb), input);
readdb = sized_db(outb, readbytes);
db_append(db, &readdb);
}
}
void db_readline(struct databuffer *db, FILE *input) { // Appends one line from input to db
struct databuffer thisdb;
char *buffer = NULL;
ssize_t size = 0;
db_fcheck(input);
size = getline(&buffer, &size, input);
assert(size != -1);
thisdb = sized_db(buffer, size);
db_append(db, &thisdb);
}
int runcmd(const char **command, bool wait_exit) { // Dumbly runs command
fflush(stdout);
if (fork() == 0) {
execvp(command[0], command);
perror(command[0]);
}
if (wait_exit) {
int status;
wait(&status);
return status;
} else {
return 0;
}
}
void db_cmdread(struct databuffer *db, const char **command) { // Appends output (stdout) of command to db
struct databuffer thisdb;
int stdout_backup = dup(1);
dup2(memfd_create("pipe", 0), 1);
runcmd(command, true);
FILE *proc_out = fdopen(1, "r");
fseek(proc_out, 0, SEEK_SET);
db_fread(db, proc_out);
close(1);
dup2(stdout_backup, 1);
thisdb = auto_db("\n");
if (db_endswith(db, &thisdb)) {
db->data[db->len - 1] = 0x00;
}
}