Cleanups and pointer vectors.

A repeated pattern in Magicka is to append to dynamically
sized arrays via malloc()/realloc().  Introduce the notion
of a "pointer vector": that is, a growable vector of
pointers, that can be reused to implement that logic more
safely and efficiently (this implementation uses power-of-two
growing).

Many malloc()/realloc() calls were not checked; these
assert() that the return value from realloc() is not NULL.

Add a method to consume the pointer vector: that is, realloc()
it to the current length and return the underlying pointers.

Make the `fmt` argument to dolog() const.
Include <sys/wait.h> in bluewave.c to squash a warning.

Signed-off-by: Dan Cross <patchdev@fat-dragon.org>
This commit is contained in:
Dan Cross 2018-10-09 15:55:15 +00:00 committed by Andrew Pamment
parent 4827dcf8e4
commit 540e359080
7 changed files with 109 additions and 114 deletions

View File

@ -88,7 +88,7 @@ void dolog_www(char *ipaddr, char *fmt, ...) {
fclose(logfptr); fclose(logfptr);
} }
void dolog(char *fmt, ...) { void dolog(const char *fmt, ...) {
char buffer[PATH_MAX]; char buffer[PATH_MAX];
struct tm time_now; struct tm time_now;
time_t timen; time_t timen;

View File

@ -273,6 +273,7 @@ extern int ptr_vector_put(struct ptr_vector *vec, void *p, size_t i);
extern void *ptr_vector_del(struct ptr_vector *vec, size_t i); extern void *ptr_vector_del(struct ptr_vector *vec, size_t i);
extern int ptr_vector_append(struct ptr_vector *vec, void *p); extern int ptr_vector_append(struct ptr_vector *vec, void *p);
extern size_t ptr_vector_len(struct ptr_vector *vec); extern size_t ptr_vector_len(struct ptr_vector *vec);
extern void **consume_ptr_vector(struct ptr_vector *vec);
extern void destroy_ptr_vector(struct ptr_vector *vec); extern void destroy_ptr_vector(struct ptr_vector *vec);
extern char *str_replace(const char *orig, const char *rep, const char *with); extern char *str_replace(const char *orig, const char *rep, const char *with);
@ -281,7 +282,7 @@ extern int recursive_delete(const char *dir);
extern void automessage_write(); extern void automessage_write();
extern void automessage_display(); extern void automessage_display();
extern void automessage(); extern void automessage();
extern void dolog(char *fmt, ...); extern void dolog(const char *fmt, ...);
extern void dolog_www(char *ipaddr, char *fmt, ...); extern void dolog_www(char *ipaddr, char *fmt, ...);
extern void runbbs_ssh(char *ipaddress); extern void runbbs_ssh(char *ipaddress);
extern void runbbs(int sock, char *ipaddress); extern void runbbs(int sock, char *ipaddress);

View File

@ -189,10 +189,11 @@ void bbs_list() {
sqlite3_stmt *res; sqlite3_stmt *res;
int rc; int rc;
char *sql = "SELECT id,bbsname,sysop,telnet FROM bbslist"; char *sql = "SELECT id,bbsname,sysop,telnet FROM bbslist";
struct bbs_list_entry_t **entries; struct ptr_vector entries;
int entrycount; int entrycount;
struct bbs_list_entry_t *newentry; struct bbs_list_entry_t *newentry;
init_ptr_vector(&entries);
while (1) { while (1) {
entrycount = 0; entrycount = 0;
snprintf(buffer, PATH_MAX, "%s/bbslist.sq3", conf.bbs_path); snprintf(buffer, PATH_MAX, "%s/bbslist.sq3", conf.bbs_path);
@ -211,22 +212,17 @@ void bbs_list() {
} else { } else {
while (sqlite3_step(res) == SQLITE_ROW) { while (sqlite3_step(res) == SQLITE_ROW) {
if (entrycount == 0) { struct bbs_list_entry_t *entry = malloz(sizeof(struct bbs_list_entry_t));
entries = (struct bbs_list_entry_t **)malloz(sizeof(struct bbs_list_entry_t *)); entry->id = sqlite3_column_int(res, 0);
} else { entry->bbsname = strdup(sqlite3_column_text(res, 1));
entries = (struct bbs_list_entry_t **)realloc(entries, sizeof(struct bbs_list_entry_t *) * (entrycount + 1)); entry->sysopname = strdup(sqlite3_column_text(res, 2));
} entry->telnet = strdup(sqlite3_column_text(res, 3));
entries[entrycount] = (struct bbs_list_entry_t *)malloz(sizeof(struct bbs_list_entry_t)); ptr_vector_append(&entries, entry);
entries[entrycount]->id = sqlite3_column_int(res, 0);
entries[entrycount]->bbsname = strdup(sqlite3_column_text(res, 1));
entries[entrycount]->sysopname = strdup(sqlite3_column_text(res, 2));
entries[entrycount]->telnet = strdup(sqlite3_column_text(res, 3));
entrycount++;
} }
sqlite3_finalize(res); sqlite3_finalize(res);
sqlite3_close(db); sqlite3_close(db);
} }
entrycount = ptr_vector_len(&entries);
if (entrycount > 0) { if (entrycount > 0) {
while (1) { while (1) {
@ -235,11 +231,9 @@ void bbs_list() {
s_printf(get_string(270)); s_printf(get_string(270));
s_printf(get_string(271)); s_printf(get_string(271));
for (i = start; i < start + 22 && i < entrycount; i++) { for (i = start; i < start + 22 && i < entrycount; i++) {
if (i == selected) { struct bbs_list_entry_t *entry = ptr_vector_get(&entries, i);
s_printf(get_string(269), i - start + 2, i, entries[i]->bbsname, entries[i]->sysopname, entries[i]->telnet); int strn = (i == selected) ? 269 : 268;
} else { s_printf(get_string(strn), i - start + 2, i, entry->bbsname, entry->sysopname, entry->telnet);
s_printf(get_string(268), i - start + 2, i, entries[i]->bbsname, entries[i]->sysopname, entries[i]->telnet);
}
} }
s_printf("\e[%d;5H", selected - start + 2); s_printf("\e[%d;5H", selected - start + 2);
redraw = 0; redraw = 0;
@ -247,42 +241,34 @@ void bbs_list() {
c = s_getchar(); c = s_getchar();
if (tolower(c) == 'q') { if (tolower(c) == 'q') {
for (i = 0; i < entrycount; i++) { for (i = 0; i < entrycount; i++) {
free(entries[i]->bbsname); struct bbs_list_entry_t *entry = ptr_vector_get(&entries, i);
free(entries[i]->sysopname); free(entry->bbsname);
free(entries[i]->telnet); free(entry->sysopname);
free(entries[i]); free(entry->telnet);
free(entry);
} }
free(entries); destroy_ptr_vector(&entries);
return; return;
} else if (tolower(c) == 'a') { } else if (tolower(c) == 'a') {
newentry = (struct bbs_list_entry_t *)malloz(sizeof(struct bbs_list_entry_t)); newentry = (struct bbs_list_entry_t *)malloz(sizeof(struct bbs_list_entry_t));
if (add_bbs(newentry)) { if (add_bbs(newentry)) {
entries = (struct bbs_list_entry_t **)realloc(entries, sizeof(struct bbs_list_entry_t *) * (entrycount + 1)); ptr_vector_append(&entries, newentry);
entries[entrycount] = newentry;
entrycount++; entrycount++;
redraw = 1;
} else { } else {
free(newentry); free(newentry);
redraw = 1;
} }
redraw = 1;
} else if (tolower(c) == 'd') { } else if (tolower(c) == 'd') {
if (delete_bbs(entries[selected]->id)) { struct bbs_list_entry_t *entry = ptr_vector_del(&entries, selected);
free(entries[selected]->bbsname); if (delete_bbs(entry->id)) {
free(entries[selected]->sysopname); free(entry->bbsname);
free(entries[selected]->telnet); free(entry->sysopname);
free(entries[selected]); free(entry->telnet);
free(entry);
for (i = selected; i < entrycount - 1; i++) {
entries[selected] = entries[selected + 1];
}
entrycount--; entrycount--;
if (entrycount == 0) { if (entrycount == 0) {
free(entries);
return; return;
} }
entries = (struct bbs_list_entry_t **)realloc(entries, sizeof(struct bbs_list_entry_t *) * entrycount);
if (selected >= entrycount) { if (selected >= entrycount) {
selected = entrycount - 1; selected = entrycount - 1;
} }
@ -306,8 +292,10 @@ void bbs_list() {
selected = entrycount - 1; selected = entrycount - 1;
} else { } else {
if (!redraw) { if (!redraw) {
s_printf(get_string(268), selected - start + 1, selected - 1, entries[selected - 1]->bbsname, entries[selected - 1]->sysopname, entries[selected - 1]->telnet); struct bbs_list_entry_t *before = ptr_vector_get(&entries, selected - 1);
s_printf(get_string(269), selected - start + 2, selected, entries[selected]->bbsname, entries[selected]->sysopname, entries[selected]->telnet); struct bbs_list_entry_t *entry = ptr_vector_get(&entries, selected);
s_printf(get_string(268), selected - start + 1, selected - 1, before->bbsname, before->sysopname, before->telnet);
s_printf(get_string(269), selected - start + 2, selected, entry->bbsname, entry->sysopname, entry->telnet);
s_printf("\e[%d;4H", selected - start + 2); s_printf("\e[%d;4H", selected - start + 2);
} }
} }
@ -325,8 +313,10 @@ void bbs_list() {
selected = 0; selected = 0;
} else { } else {
if (!redraw) { if (!redraw) {
s_printf(get_string(269), selected - start + 2, selected, entries[selected]->bbsname, entries[selected]->sysopname, entries[selected]->telnet); struct bbs_list_entry_t *entry = ptr_vector_get(&entries, selected);
s_printf(get_string(268), selected - start + 3, selected + 1, entries[selected + 1]->bbsname, entries[selected + 1]->sysopname, entries[selected + 1]->telnet); struct bbs_list_entry_t *after = ptr_vector_get(&entries, selected + 1);
s_printf(get_string(269), selected - start + 2, selected, entry->bbsname, entry->sysopname, entry->telnet);
s_printf(get_string(268), selected - start + 3, selected + 1, after->bbsname, after->sysopname, after->telnet);
s_printf("\e[%d;4H", selected - start + 2); s_printf("\e[%d;4H", selected - start + 2);
} }
} }

View File

@ -8,7 +8,7 @@ extern struct user_record *gUser;
int blog_load(struct blog_entry_t ***entries) { int blog_load(struct blog_entry_t ***entries) {
int blog_entry_count = 0; int blog_entry_count = 0;
struct blog_entry_t **blog_entries; struct ptr_vector blog_entries;
char *sql = "SELECT author, title, body, date FROM blog ORDER BY date DESC"; char *sql = "SELECT author, title, body, date FROM blog ORDER BY date DESC";
char buffer[PATH_MAX]; char buffer[PATH_MAX];
@ -34,25 +34,22 @@ int blog_load(struct blog_entry_t ***entries) {
*entries = NULL; *entries = NULL;
return 0; return 0;
} }
init_ptr_vector(&blog_entries);
while (sqlite3_step(res) == SQLITE_ROW) { while (sqlite3_step(res) == SQLITE_ROW) {
if (blog_entry_count == 0) { struct blog_entry_t *entry = (struct blog_entry_t *)malloz(sizeof(struct blog_entry_t));
blog_entries = (struct blog_entry_t **)malloz(sizeof(struct blog_entry_t *)); entry->author = strdup(sqlite3_column_text(res, 0));
} else { entry->subject = strdup(sqlite3_column_text(res, 1));
blog_entries = (struct blog_entry_t **)realloc(blog_entries, sizeof(struct blog_entry_t *) * (blog_entry_count + 1)); entry->body = strdup(sqlite3_column_text(res, 2));
} entry->date = sqlite3_column_int(res, 3);
blog_entries[blog_entry_count] = (struct blog_entry_t *)malloz(sizeof(struct blog_entry_t)); ptr_vector_append(&blog_entries, entry);
blog_entries[blog_entry_count]->author = strdup(sqlite3_column_text(res, 0));
blog_entries[blog_entry_count]->subject = strdup(sqlite3_column_text(res, 1));
blog_entries[blog_entry_count]->body = strdup(sqlite3_column_text(res, 2));
blog_entries[blog_entry_count]->date = sqlite3_column_int(res, 3);
blog_entry_count++;
} }
sqlite3_finalize(res); sqlite3_finalize(res);
sqlite3_close(db); sqlite3_close(db);
*entries = blog_entries; blog_entry_count = ptr_vector_len(&blog_entries);
*entries = consume_ptr_vector(&blog_entries);
return blog_entry_count; return blog_entry_count;
} }

View File

@ -5,6 +5,7 @@
#include <termios.h> #include <termios.h>
#include <fcntl.h> #include <fcntl.h>
#include <sqlite3.h> #include <sqlite3.h>
#include <sys/wait.h>
#include "bluewave.h" #include "bluewave.h"
#include "jamlib/jam.h" #include "jamlib/jam.h"
#include "bbs.h" #include "bbs.h"
@ -291,7 +292,8 @@ void bwave_create_packet() {
char buffer[1024]; char buffer[1024];
char archive[1024]; char archive[1024];
INF_HEADER hdr; INF_HEADER hdr;
INF_AREA_INFO **areas = NULL; struct ptr_vector areas;
INF_AREA_INFO *area = NULL;
int i; int i;
int j; int j;
int area_count; int area_count;
@ -315,11 +317,13 @@ void bwave_create_packet() {
int tot_areas = 0; int tot_areas = 0;
int totmsgs = 0; int totmsgs = 0;
int ret; int ret;
char **args; char **args, *arg;
int arg_count; struct ptr_vector args_vec;
char *cmd; char *cmd;
pid_t pid; pid_t pid;
init_ptr_vector(&areas);
for (i = 0; i < conf.mail_conference_count; i++) { for (i = 0; i < conf.mail_conference_count; i++) {
for (j = 0; j < conf.mail_conferences[i]->mail_area_count; j++) { for (j = 0; j < conf.mail_conferences[i]->mail_area_count; j++) {
if (msgbase_is_subscribed(i, j)) { if (msgbase_is_subscribed(i, j)) {
@ -386,22 +390,22 @@ void bwave_create_packet() {
totmsgs = bwave_scan_email(area_count + 1, totmsgs, fti_file, mix_file, dat_file, &last_ptr); totmsgs = bwave_scan_email(area_count + 1, totmsgs, fti_file, mix_file, dat_file, &last_ptr);
s_printf(get_string(195), "Private Email", "Private Email", totmsgs); s_printf(get_string(195), "Private Email", "Private Email", totmsgs);
areas = (INF_AREA_INFO **)malloz(sizeof(INF_AREA_INFO *));
flags = 0; flags = 0;
areas[area_count] = (INF_AREA_INFO *)malloz(sizeof(INF_AREA_INFO)); area = (INF_AREA_INFO *)malloz(sizeof(INF_AREA_INFO));
snprintf(areas[area_count]->areanum, 6, "%d", area_count + 1); snprintf(area->areanum, 6, "%d", area_count + 1);
memcpy(areas[area_count]->echotag, "PRIVATE_EMAIL", 13); memcpy(area->echotag, "PRIVATE_EMAIL", 13);
strncpy(areas[area_count]->title, "Private Email", 49); strncpy(area->title, "Private Email", 49);
flags |= INF_POST; flags |= INF_POST;
flags |= INF_NO_PUBLIC; flags |= INF_NO_PUBLIC;
flags |= INF_SCANNING; flags |= INF_SCANNING;
areas[area_count]->area_flags = converts(flags); area->area_flags = converts(flags);
areas[area_count]->network_type = INF_NET_FIDONET; area->network_type = INF_NET_FIDONET;
ptr_vector_append(&areas, area);
area_count++; area_count++;
@ -417,16 +421,14 @@ void bwave_create_packet() {
// continue; // continue;
//} //}
areas = (INF_AREA_INFO **)realloc(areas, sizeof(INF_AREA_INFO *) * (area_count + 1));
flags = 0; flags = 0;
areas[area_count] = (INF_AREA_INFO *)malloz(sizeof(INF_AREA_INFO)); area = (INF_AREA_INFO *)malloz(sizeof(INF_AREA_INFO));
snprintf(areas[area_count]->areanum, 6, "%d", area_count + 1); snprintf(area->areanum, 6, "%d", area_count + 1);
memcpy(areas[area_count]->echotag, conf.mail_conferences[i]->mail_areas[j]->qwkname, strlen(conf.mail_conferences[i]->mail_areas[j]->qwkname)); memcpy(area->echotag, conf.mail_conferences[i]->mail_areas[j]->qwkname, strlen(conf.mail_conferences[i]->mail_areas[j]->qwkname));
strncpy(areas[area_count]->title, conf.mail_conferences[i]->mail_areas[j]->name, 49); strncpy(area->title, conf.mail_conferences[i]->mail_areas[j]->name, 49);
if (conf.mail_conferences[i]->mail_areas[j]->write_sec_level <= gUser->sec_level) { if (conf.mail_conferences[i]->mail_areas[j]->write_sec_level <= gUser->sec_level) {
flags |= INF_POST; flags |= INF_POST;
@ -449,9 +451,10 @@ void bwave_create_packet() {
flags |= INF_SCANNING; flags |= INF_SCANNING;
areas[area_count]->area_flags = converts(flags); area->area_flags = converts(flags);
areas[area_count]->network_type = INF_NET_FIDONET; area->network_type = INF_NET_FIDONET;
ptr_vector_append(&areas, area);
area_count++; area_count++;
if (totmsgs == conf.bwave_max_msgs) { if (totmsgs == conf.bwave_max_msgs) {
break; break;
@ -474,16 +477,13 @@ void bwave_create_packet() {
fwrite(&hdr, sizeof(INF_HEADER), 1, inf_file); fwrite(&hdr, sizeof(INF_HEADER), 1, inf_file);
for (i = 0; i < area_count; i++) { for (i = 0; i < area_count; i++) {
fwrite(areas[i], sizeof(INF_AREA_INFO), 1, inf_file); fwrite(ptr_vector_get(&areas, i), sizeof(INF_AREA_INFO), 1, inf_file);
} }
fclose(inf_file); fclose(inf_file);
for (i = 0; i < area_count; i++) { for (i = 0; i < area_count; i++) {
free(areas[i]); free(ptr_vector_get(&areas, i));
}
if (areas != NULL) {
free(areas);
} }
if (totmsgs > 0) { if (totmsgs > 0) {
@ -530,15 +530,15 @@ void bwave_create_packet() {
dup2(bbs_stdin, STDIN_FILENO); dup2(bbs_stdin, STDIN_FILENO);
} }
args = (char **)malloz(sizeof(char *)); init_ptr_vector(&args_vec);
arg_count = 0; arg = strtok(buffer, " ");
args[arg_count] = strtok(buffer, " "); ptr_vector_append(&args_vec, arg);
while (args[arg_count] != NULL) { while (arg != NULL) {
arg_count++; arg = strtok(NULL, " ");
args = (char **)realloc(args, sizeof(char *) * (arg_count + 1)); ptr_vector_append(&args_vec, arg);
args[arg_count] = strtok(NULL, " ");
} }
cmd = strdup(args[0]); args = (char **)consume_ptr_vector(&args_vec);
cmd = args[0];
pid = fork(); pid = fork();
if (pid == 0) { if (pid == 0) {
execvp(cmd, args); execvp(cmd, args);
@ -548,7 +548,6 @@ void bwave_create_packet() {
} else { } else {
ret = -1; ret = -1;
} }
free(cmd);
free(args); free(args);
if (sshBBS) { if (sshBBS) {
@ -813,8 +812,8 @@ void bwave_upload_reply() {
"seen INTEGER);"; "seen INTEGER);";
char *isql = "INSERT INTO email (sender, recipient, subject, body, date, seen) VALUES(?, ?, ?, ?, ?, 0)"; char *isql = "INSERT INTO email (sender, recipient, subject, body, date, seen) VALUES(?, ?, ?, ?, ?, 0)";
char *err_msg = 0; char *err_msg = 0;
char **args; char **args, *arg;
int arg_count; struct ptr_vector args_vec;
char *cmd; char *cmd;
pid_t pid; pid_t pid;
int ret; int ret;
@ -867,15 +866,15 @@ void bwave_upload_reply() {
dup2(bbs_stderr, STDERR_FILENO); dup2(bbs_stderr, STDERR_FILENO);
dup2(bbs_stdin, STDIN_FILENO); dup2(bbs_stdin, STDIN_FILENO);
} }
args = (char **)malloz(sizeof(char *)); init_ptr_vector(&args_vec);
arg_count = 0; arg = strtok(buffer, " ");
args[arg_count] = strtok(buffer, " "); ptr_vector_append(&args_vec, arg);
while (args[arg_count] != NULL) { while (arg != NULL) {
arg_count++; arg = strtok(NULL, " ");
args = (char **)realloc(args, sizeof(char *) * (arg_count + 1)); ptr_vector_append(&args_vec, arg);
args[arg_count] = strtok(NULL, " ");
} }
cmd = strdup(args[0]); args = (char **)consume_ptr_vector(&args_vec);
cmd = args[0];
pid = fork(); pid = fork();
if (pid == 0) { if (pid == 0) {
execvp(cmd, args); execvp(cmd, args);
@ -885,7 +884,6 @@ void bwave_upload_reply() {
} else { } else {
ret = -1; ret = -1;
} }
free(cmd);
free(args); free(args);
if (sshBBS) { if (sshBBS) {

View File

@ -250,8 +250,8 @@ void runexternal(struct user_record *user, char *cmd, int stdio, char *argv[], c
size_t ouc; size_t ouc;
size_t inc; size_t inc;
size_t sz; size_t sz;
char **args; char **args, *arg;
int arg_count; struct ptr_vector args_vec;
pid_t pid; pid_t pid;
int iac; int iac;
char iac_binary_will[] = {IAC, IAC_WILL, IAC_TRANSMIT_BINARY, '\0'}; char iac_binary_will[] = {IAC, IAC_WILL, IAC_TRANSMIT_BINARY, '\0'};
@ -523,15 +523,15 @@ void runexternal(struct user_record *user, char *cmd, int stdio, char *argv[], c
if (cwd != NULL) { if (cwd != NULL) {
chdir(cwd); chdir(cwd);
} }
args = (char **)malloz(sizeof(char *)); init_ptr_vector(&args_vec);
arg_count = 0; arg = strtok(buffer, " ");
args[arg_count] = strtok(buffer, " "); ptr_vector_append(&args_vec, arg);
while (args[arg_count] != NULL) { while (arg != NULL) {
arg_count++; arg = strtok(NULL, " ");
args = (char **)realloc(args, sizeof(char *) * (arg_count + 1)); ptr_vector_append(&args_vec, arg);
args[arg_count] = strtok(NULL, " ");
} }
cmd = strdup(args[0]); args = (char **)consume_ptr_vector(&args_vec);
cmd = args[0];
pid = fork(); pid = fork();
if (pid == 0) { if (pid == 0) {
execvp(cmd, args); execvp(cmd, args);
@ -541,7 +541,6 @@ void runexternal(struct user_record *user, char *cmd, int stdio, char *argv[], c
} else { } else {
ret = -1; ret = -1;
} }
free(cmd);
free(args); free(args);
if (cwd != NULL) { if (cwd != NULL) {
chdir(conf.bbs_path); chdir(conf.bbs_path);

View File

@ -153,6 +153,16 @@ size_t ptr_vector_len(struct ptr_vector *vec) {
return vec->len; return vec->len;
} }
void **consume_ptr_vector(struct ptr_vector *vec) {
assert(vec != NULL);
void **ps = realloc(vec->ptrs, vec->len * sizeof(void *));
assert(ps != NULL);
vec->ptrs = NULL;
vec->len = 0;
vec->capacity = 0;
return ps;
}
void destroy_ptr_vector(struct ptr_vector *vec) { void destroy_ptr_vector(struct ptr_vector *vec) {
assert(vec != NULL); assert(vec != NULL);
free(vec->ptrs); free(vec->ptrs);