hirc

IRC client
Log | Files | Refs

commit e40a241de1201c089d999bfc5b38194cb815b073
parent fbfba15809e91570657f263cadc455f6d403f819
Author: hhvn <dev@hhvn.uk>
Date:   Wed, 23 Mar 2022 15:07:08 +0000

Use custom free function + remove talloc

Diffstat:
Msrc/chan.c | 8++++----
Msrc/commands.c | 23++++++++++++++---------
Msrc/config.c | 10+++++-----
Msrc/handle.c | 11++++++-----
Msrc/hirc.h | 2++
Msrc/hist.c | 18+++++++++---------
Msrc/main.c | 22+++++++++++-----------
Asrc/mem.c | 117+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/nick.c | 15+++++++++------
Msrc/serv.c | 42+++++++++++++++++++++---------------------
Msrc/ui.c | 91+++++++++++++++++++++++++++++++++++++++----------------------------------------
11 files changed, 243 insertions(+), 116 deletions(-)

diff --git a/src/chan.c b/src/chan.c @@ -24,12 +24,12 @@ void chan_free(struct Channel *channel) { if (channel) { - free(channel->name); - free(channel->mode); + pfree(&channel->name); + pfree(&channel->mode); nick_free_list(&channel->nicks); - free(channel->nicks); + pfree(&channel->nicks); hist_free_list(channel->history); - free(channel); + pfree(&channel); } } diff --git a/src/commands.c b/src/commands.c @@ -989,9 +989,10 @@ command_format) { } len = strlen(str) + strlen("format.") + 1; - newstr = talloc(len); + newstr = emalloc(len); snprintf(newstr, len, "format.%s", str); command_set(server, channel, newstr); + pfree(&newstr); } COMMAND( @@ -1811,7 +1812,7 @@ modelset(char *cmd, struct Server *server, struct Channel *channel, /* 2 = null byte and +/- */ len = percmd + 2; - modes = talloc(len); + modes = emalloc(len); *modes = remove ? '-' : '+'; for (i = 0; i < percmd; i++) *(modes + i + 1) = mode; @@ -1833,6 +1834,7 @@ modelset(char *cmd, struct Server *server, struct Channel *channel, } expect_set(server, Expect_nosuchnick, channel->name); + pfree(&modes); } COMMAND( @@ -2011,9 +2013,9 @@ alias_remove(char *alias) { if (p->next) p->next->prev = p->prev; - free(p->alias); - free(p->cmd); - free(p); + pfree(&p->alias); + pfree(&p->cmd); + pfree(&p); return 0; } } @@ -2052,9 +2054,9 @@ command_eval(struct Server *server, char *str) { struct Command *cmdp; char msg[512]; char *cmd; - char *s; + char *s, *dup; - s = tstrdup(alias_eval(str)); + s = dup = estrdup(alias_eval(str)); if (*s != '/' || strncmp(s, "/ /", sizeof("/ /")) == 0) { /* Provide a way to escape commands @@ -2070,7 +2072,7 @@ command_eval(struct Server *server, char *str) { } else { ui_error("channel not selected, message ignored", NULL); } - return; + goto end; } else { s++; cmd = s; @@ -2093,10 +2095,13 @@ command_eval(struct Server *server, char *str) { else cmdp->func(server, selected.channel, s); - return; + + goto end; } } ui_error("no such command: '%s'", cmd); } +end: + pfree(&dup); } diff --git a/src/config.c b/src/config.c @@ -1351,7 +1351,7 @@ config_sets(char *name, char *str) { if (!config[i].strhandle(str)) return; if (!config[i].isdef) - free(config[i].str); + pfree(&config[i].str); else config[i].isdef = 0; config[i].str = estrdup(str); @@ -1405,7 +1405,7 @@ config_set(char *name, char *val) { else config_get_print(name); - free(str); + pfree(&str); } void @@ -1427,7 +1427,7 @@ config_read(char *filename) { for (i = 0; i < btoffset; i++) { if (strcmp(path, *(bt + i)) == 0) { ui_error("recursive read of '%s' is not allowed", filename); - free(path); + pfree(&path); return; } } @@ -1458,10 +1458,10 @@ config_read(char *filename) { shrink: /* Remove path from bt and shrink */ - free(path); + pfree(&path); btoffset--; if (btoffset == 0) { - free(bt); + pfree(&bt); bt = NULL; } else { bt = erealloc(bt, (sizeof(char *)) * btoffset); diff --git a/src/handle.c b/src/handle.c @@ -323,7 +323,7 @@ handle_RPL_ISUPPORT) { /* skip the last param ".... :are supported by this server" */ for (; *params && *(params+1); params++) { - key = tstrdup(*params); + key = estrdup(*params); if ((value = strchr(key, '=')) != NULL) { *value = '\0'; if (*(value+1)) @@ -333,6 +333,7 @@ handle_RPL_ISUPPORT) { } support_set(server, key, value); + pfree(&key); } } @@ -359,7 +360,7 @@ handle_RPL_CHANNELMODEIS) { if ((chan = chan_get(&server->channels, *(msg->params+2), -1)) == NULL) chan = chan_add(server, &server->channels, *(msg->params+2), 0); - free(chan->mode); + pfree(&chan->mode); chan->mode = estrdup(*(msg->params+3)); hist_addp(server->history, msg, Activity_status, HIST_LOG); @@ -529,7 +530,7 @@ handle_TOPIC) { if ((chan = chan_get(&server->channels, *(msg->params+1), -1)) != NULL) { hist_addp(chan->history, msg, Activity_status, HIST_DFL); - free(chan->topic); + pfree(&chan->topic); chan->topic = *(msg->params+2) ? estrdup(*(msg->params+2)) : NULL; } } @@ -572,7 +573,7 @@ handle_RPL_TOPIC) { if ((chan = chan_get(&server->channels, target, -1)) == NULL) return; - free(chan->topic); + pfree(&chan->topic); chan->topic = topic ? estrdup(topic) : NULL; if (strcmp_n(target, expect_get(server, Expect_topic)) == 0) { @@ -645,7 +646,7 @@ handle(struct Server *server, char *msg) { timestamp = time(NULL); params = param_create(msg); if (!*params) { - free(params); + pfree(&params); return; } diff --git a/src/hirc.h b/src/hirc.h @@ -56,6 +56,8 @@ char * strntok(char *str, char *sep, int n); char * strrdate(time_t secs); /* mem.c */ +void pfree_(void **ptr); +#define pfree(ptr) pfree_((void **)ptr) void * emalloc(size_t size); void * erealloc(void *ptr, size_t size); char * estrdup(const char *str); diff --git a/src/hist.c b/src/hist.c @@ -33,12 +33,12 @@ void hist_free(struct History *history) { param_free(history->_params); if (history->from) { - free(history->from->prefix); - free(history->from); + pfree(&history->from->prefix); + pfree(&history->from); } - free(history->raw); - free(history->format); - free(history); + pfree(&history->raw); + pfree(&history->format); + pfree(&history); } void @@ -141,7 +141,7 @@ hist_add(struct HistInfo *histinfo, for (i=0, p = histinfo->history; p && p->next; p = p->next, i++); if (i == (HIST_MAX-1)) { - free(p->next); + pfree(&p->next); p->next = NULL; } @@ -191,7 +191,7 @@ hist_purgeopt(struct HistInfo *histinfo, enum HistOpt options) { else if (!p->prev) histinfo->history = NULL; - free(p); + pfree(&p); } } } @@ -316,7 +316,7 @@ hist_loadlog(struct HistInfo *hist, char *server, char *channel) { memset(lines, 0, sizeof(lines)); while (fgets(buf, sizeof(buf), f)) { - free(lines[HIST_MAX - 1]); + pfree(&lines[HIST_MAX - 1]); memmove(lines + 1, lines, HIST_MAX - 1); buf[strlen(buf) - 1] = '\0'; /* strip newline */ lines[0] = estrdup(buf); @@ -363,7 +363,7 @@ hist_loadlog(struct HistInfo *hist, char *server, char *channel) { prev = p; nick_free(from); - free(lines[i]); + pfree(&lines[i]); } fclose(f); diff --git a/src/main.c b/src/main.c @@ -54,8 +54,8 @@ param_free(char **params) { char **p; for (p = params; p && *p; p++) - free(*p); - free(params); + pfree(&*p); + pfree(&params); } int @@ -120,7 +120,7 @@ void ircread(struct Server *sp) { char *line, *end; char *err; - char *reason = "connection closed"; + char *reason = NULL; size_t len; int ret; @@ -133,14 +133,15 @@ ircread(struct Server *sp) { case -1: err = (char *)tls_error(sp->tls_ctx); len = strlen("tls_read(): ") + strlen(err) + 1; - reason = talloc(len); + reason = emalloc(len); snprintf(reason, len, "tls_read(): %s", err); /* fallthrough */ case 0: serv_disconnect(sp, 1, "EOF"); hist_format(sp->history, Activity_error, HIST_SHOW, "SELF_CONNECTLOST %s %s %s :%s", - sp->name, sp->host, sp->port, reason); + sp->name, sp->host, sp->port, reason ? reason : "connection close"); + pfree(&reason); return; case TLS_WANT_POLLIN: case TLS_WANT_POLLOUT: @@ -153,16 +154,18 @@ ircread(struct Server *sp) { #endif /* TLS */ switch (ret = read(sp->rfd, &sp->inputbuf[sp->inputlen], SERVER_INPUT_SIZE - sp->inputlen - 1)) { case -1: - err = tstrdup(strerror(errno)); + err = estrdup(strerror(errno)); len = strlen("read(): ") + strlen(err) + 1; - reason = talloc(len); + reason = emalloc(len); snprintf(reason, len, "read(): %s", err); + pfree(&err); /* fallthrough */ case 0: serv_disconnect(sp, 1, "EOF"); hist_format(sp->history, Activity_error, HIST_SHOW, "SELF_CONNECTLOST %s %s %s :%s", - sp->name, sp->host, sp->port, reason); + sp->name, sp->host, sp->port, reason ? reason : "connection closed"); + pfree(&reason); return; default: sp->inputlen += ret; @@ -491,9 +494,6 @@ main(int argc, char *argv[]) { wrefresh(windows[Win_input].window); ui_read(); - - /* free temporary mem */ - talloc(0); } return 0; diff --git a/src/mem.c b/src/mem.c @@ -0,0 +1,117 @@ +/* + * src/mem.c from hirc + * + * Copyright (c) 2021-2022 hhvn <dev@hhvn.uk> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include <stdio.h> +#include <wchar.h> +#include <string.h> +#include <stdlib.h> +#include <ncurses.h> +#include "hirc.h" + +/* Free memory and make the original pointer point to NULL. + * This makes it hard to double free or access free'd memory. + * Anything that attempts to dereference free'd memory will + * instead dereference NULL resulting in a segfault, rather + * than producing potential heisenbugs. */ +void +pfree_(void **ptr) { + size_t i; + if (!ptr || !*ptr) + return; + + free(*ptr); + *ptr = NULL; +} + +/* Error-checking memory allocation. + * IRC isn't that critical in most cases, better + * to kill ourself than let oomkiller do it */ +void * +emalloc(size_t size) { + void *mem; + + if ((mem = malloc(size)) == NULL) { + endwin(); + perror("malloc()"); + exit(EXIT_FAILURE); + } + + return mem; +} + +void * +erealloc(void *ptr, size_t size) { + void *mem; + + if ((mem = realloc(ptr, size)) == NULL) { + endwin(); + perror("realloc()"); + exit(EXIT_FAILURE); + } + + return mem; +} + +char * +estrdup(const char *str) { + char *ret; + + if ((ret = strdup(str)) == NULL) { + endwin(); + perror("strdup()"); + exit(EXIT_FAILURE); + } + + return ret; +} + +wchar_t * +ewcsdup(const wchar_t *str) { + wchar_t *ret; + if ((ret = wcsdup(str)) == NULL) { + endwin(); + perror("wcsdup()"); + exit(EXIT_FAILURE); + } + return ret; +} + +/* Helper functions for widechar <-> utf-8 conversion */ +wchar_t * +stowc(char *str) { + wchar_t *ret; + size_t len; + + len = mbstowcs(NULL, str, 0) + 1; + ret = emalloc(len * sizeof(wchar_t)); + mbstowcs(ret, str, len); + return ret; +} + +char * +wctos(wchar_t *str) { + char *ret; + size_t len; + + len = wcstombs(NULL, str, 0) + 1; + ret = emalloc(len); + wcstombs(ret, str, len); + return ret; +} + diff --git a/src/nick.c b/src/nick.c @@ -67,7 +67,9 @@ nick_getcolour(struct Nick *nick) { void prefix_tokenize(char *prefix, char **nick, char **ident, char **host) { enum { ISNICK, ISIDENT, ISHOST } segment = ISNICK; - char *p = tstrdup(prefix); + char *p, *dup; + + p = dup = estrdup(prefix); if (*p == ':') p++; @@ -94,16 +96,17 @@ prefix_tokenize(char *prefix, char **nick, char **ident, char **host) { if (nick && *nick) *nick = estrdup(*nick); if (ident && *ident) *ident = estrdup(*ident); if (host && *host) *host = estrdup(*host); + pfree(&dup); } void nick_free(struct Nick *nick) { if (nick) { - free(nick->prefix); - free(nick->nick); - free(nick->ident); - free(nick->host); - free(nick); + pfree(&nick->prefix); + pfree(&nick->nick); + pfree(&nick->ident); + pfree(&nick->host); + pfree(&nick); } } diff --git a/src/serv.c b/src/serv.c @@ -38,27 +38,27 @@ serv_free(struct Server *server) { if (!server) return; - free(server->name); - free(server->username); - free(server->realname); - free(server->host); - free(server->port); - free(server->rpollfd); + pfree(&server->name); + pfree(&server->username); + pfree(&server->realname); + pfree(&server->host); + pfree(&server->port); + pfree(&server->rpollfd); nick_free(server->self); hist_free_list(server->history); chan_free_list(&server->channels); chan_free_list(&server->privs); for (p = server->supports; p; p = p->next) { - free(p->prev); - free(p->key); - free(p->value); + pfree(&p->prev); + pfree(&p->key); + pfree(&p->value); } #ifdef TLS if (server->tls) if (server->tls_ctx) tls_free(server->tls_ctx); #endif /* TLS */ - free(p); + pfree(&p); } struct Server * @@ -208,9 +208,9 @@ serv_connect(struct Server *server) { for (s = server->supports, prev = NULL; s; s = s->next) { if (prev) { - free(prev->key); - free(prev->value); - free(prev); + pfree(&prev->key); + pfree(&prev->value); + pfree(&prev); } prev = s; } @@ -418,7 +418,7 @@ support_set(struct Server *server, char *key, char *value) { for (p = server->supports; p && p->next; p = p->next) { if (strcmp(p->key, key) == 0) { - free(p->value); + pfree(&p->value); p->value = strdup(value); return; } @@ -475,8 +475,8 @@ serv_auto_free(struct Server *server) { return; for (p = server->autocmds; *p; p++) - free(*p); - free(server->autocmds); + pfree(&*p); + pfree(&server->autocmds); server->autocmds = NULL; } @@ -544,7 +544,7 @@ schedule_pull(struct Server *server, char *tmsg) { for (p = server->schedule; p; p = p->next) { if (strcmp(p->tmsg, tmsg) == 0) { - free(p->tmsg); + pfree(&p->tmsg); /* Don't free p->msg, instead save it to * a static pointer that we free the next @@ -552,7 +552,7 @@ schedule_pull(struct Server *server, char *tmsg) { * schedule_pull will probably be used in * while loops until it equals NULL, this * will likely be set free quite quickly */ - free(ret); + pfree(&ret); ret = p->msg; if (p->prev) p->prev->next = p->next; @@ -561,12 +561,12 @@ schedule_pull(struct Server *server, char *tmsg) { if (!p->prev) server->schedule = p->next; - free(p); + pfree(&p); return ret; } } - free(ret); + pfree(&ret); ret = NULL; return NULL; } @@ -576,7 +576,7 @@ expect_set(struct Server *server, enum Expect cmd, char *about) { if (cmd >= Expect_last || cmd < 0 || nouich) return; - free(server->expect[cmd]); + pfree(&server->expect[cmd]); server->expect[cmd] = about ? estrdup(about) : NULL; } diff --git a/src/ui.c b/src/ui.c @@ -416,13 +416,12 @@ ui_read(void) { &input.string[input.counter], (wcslen(&input.string[input.counter]) + 1) * sizeof(wchar_t)); input.counter = savecounter; - free(str); return; } } if (input.histindex) { - free(backup); + pfree(&backup); backup = NULL; input.histindex = -1; } @@ -461,7 +460,7 @@ ui_read(void) { if (input.histindex == -1) { if (backup) wcslcpy(input.string, backup, sizeof(input.string)); - free(backup); + pfree(&backup); backup = NULL; } else { mbstowcs(input.string, input.history[input.histindex], sizeof(input.string)); @@ -486,7 +485,7 @@ ui_read(void) { /* no need to free str as assigned to input.history[0] */ str = wctos(input.string); command_eval(selected.server, str); - free(input.history[INPUT_HIST_MAX - 1]); + pfree(&input.history[INPUT_HIST_MAX - 1]); memmove(input.history + 1, input.history, (sizeof(input.history) / INPUT_HIST_MAX) * (INPUT_HIST_MAX - 1)); input.history[0] = str; input.string[0] = '\0'; @@ -659,26 +658,26 @@ getcmd: len = strlen(stem); ui_complete_get_cmds(stem, len, &found, &fullcomplete); - free(stem); + pfree(&stem); if (found) { len = strlen(found) + 2; p = emalloc(len); snprintf(p, len, "/%s", found); - free(found); + pfree(&found); found = p; wp = stowc(found); - free(found); + pfree(&found); ui_complete_stitch(str, size, &input.counter, coff, NULL, 0, wp, toks + 1, tokn - 1, fullcomplete); - free(wp); + pfree(&wp); goto end; } - free(found); + pfree(&found); found = NULL; } @@ -705,7 +704,7 @@ getcmd: if (type == 1) ui_complete_get_cmds(stem, len, &found, &fullcomplete); ui_complete_get_settings(stem, len, &found, &fullcomplete); - free(stem); + pfree(&stem); if (found) { if (type == 3) @@ -718,11 +717,11 @@ getcmd: wp, toks + 2, tokn - 2, fullcomplete); - free(wp); - free(found); + pfree(&wp); + pfree(&found); goto end; } - free(found); + pfree(&found); found = NULL; } } @@ -734,7 +733,7 @@ getcmd: len = strlen(stem); ui_complete_get_nicks(selected.channel, stem, len, &found, &fullcomplete); - free(stem); + pfree(&stem); if (found) { if (ctok == 0) { @@ -742,7 +741,7 @@ getcmd: len = strlen(found) + strlen(hchar) + 1; p = emalloc(len); snprintf(p, len, "%s%s", found, hchar); - free(found); + pfree(&found); found = p; } wp = stowc(found); @@ -751,18 +750,18 @@ getcmd: wp, toks + ctok + 1, tokn - ctok - 1, fullcomplete); - free(wp); - free(found); + pfree(&wp); + pfree(&found); goto end; } - free(found); + pfree(&found); found = NULL; } end: - free(_toks); + pfree(&_toks); /* elements in _toks are pointers to dup */ - free(dup); + pfree(&dup); return; } @@ -865,7 +864,7 @@ ui_redraw(void) { if (selected.history) { for (p = selected.history->history; p; p = p->next) { if (p->format) { - free(p->format); + pfree(&p->format); p->format = NULL; } } @@ -1134,7 +1133,7 @@ ui_wprintc(struct Window *window, int lines, char *format, ...) { elc -= 1; wcs = stowc(str); - free(str); + pfree(&str); for (ret = cc = lc = 0, s = wcs; s && *s; s++) { switch (*s) { @@ -1396,7 +1395,7 @@ ui_select(struct Server *server, struct Channel *channel) { if (selected.history->unread) { for (i = 0, hp = selected.history->history; hp && hp->next; hp = hp->next, i++); if (i == (HIST_MAX-1)) { - free(hp->next); + pfree(&hp->next); hp->next = NULL; } @@ -1503,7 +1502,7 @@ ui_format_(struct Window *window, char *format, struct History *hist, int recurs {NULL, NULL}, }; - free(ret); + pfree(&ret); ret = emalloc(rs); subs[sub_channel].val = selected.channel ? selected.channel->name : NULL; @@ -1688,7 +1687,7 @@ outcont: save = estrdup(ret); rc = snprintf(ret, rs, "%1$*3$s%2$s", save, config_gets("divider.string"), config_getl("divider.margin") + (strlen(ret) - ui_strlenc(window, ret, NULL))); - free(save); + pfree(&save); format = strchr(format, '}') + 1; continue; } else if (*(content+1) == '\0') { @@ -1710,11 +1709,11 @@ outcont: ret = NULL; ui_format_(NULL, content, hist, 1); rc += snprintf(&save[rc], rs - rc, "%1$*2$s", ret, pn); - free(ret); + pfree(&ret); ret = save; format = strchr(format+2+strlen("pad:"), ',') + strlen(content) + 2; - free(content); + pfree(&content); continue; } @@ -1727,9 +1726,9 @@ outcont: rc += snprintf(&save[rc], rs - rc, "%s", strrdate((time_t)pn)); format += 3 + strlen("rdate:") + strlen(content); - free(ret); + pfree(&ret); ret = save; - free(content); + pfree(&content); } if (strncmp(content, "time:", strlen("time:")) == 0 && strchr(content, ',')) { @@ -1743,9 +1742,9 @@ outcont: rc += strftime(&save[rc], rs - rc, p, gmtime((time_t *)&pn)); format = strchr(format+2+strlen("time:"), ',') + strlen(content) + 2; - free(ret); + pfree(&ret); ret = save; - free(content); + pfree(&content); continue; } @@ -1771,9 +1770,9 @@ outcont: strchr(format+2+strlen("split:"), ',') + 1, ',') + strlen(content) + 2; - free(ret); + pfree(&ret); ret = save; - free(content); + pfree(&content); continue; } @@ -1786,10 +1785,10 @@ outcont: rc += snprintf(&save[rc], rs - rc, "%c%02d", 3 /* ^C */, nick_getcolour(nick)); format += 3 + strlen("nick:") + strlen(content); - free(ret); + pfree(&ret); ret = save; nick_free(nick); - free(content); + pfree(&content); continue; } } @@ -1824,12 +1823,12 @@ outcont: if (!recursive && divider && !rhs) { save = estrdup(ret); rc = snprintf(ret, rs, "%1$*4$s%2$s%3$s", "", config_gets("divider.string"), save, config_getl("divider.margin")); - free(save); + pfree(&save); } save = estrdup(ret); rc = snprintf(ret, rs, "%s%s", ts, save); - free(save); + pfree(&save); if (!recursive && window) { for (p = ret, pc = 0; p && p <= (ret + rs); p++) { @@ -1875,7 +1874,7 @@ outcont: p += snprintf(p, rs - ((size_t)(p - ret)), "%1$*3$s %2$s", "", save, ui_strlenc(NULL, ts, NULL)); } - free(save); + pfree(&save); pc = 0; } } @@ -1883,9 +1882,9 @@ outcont: } if (subs[sub_time].val) - free(subs[sub_time].val); + pfree(&subs[sub_time].val); if (ts[0] != '\0') - free(ts); + pfree(&ts); return ret; } @@ -1898,7 +1897,7 @@ ui_rectrl(char *str) { char c; if (rp) { - free(rp); + pfree(&rp); rp = NULL; } @@ -1934,7 +1933,7 @@ ui_unctrl(char *str) { int rc; if (rp) { - free(rp); + pfree(&rp); rp = NULL; } @@ -1997,10 +1996,10 @@ ui_unbind(char *binding) { if (p->next) p->next->prev = p->prev; - free(p->binding); - free(p->wbinding); - free(p->cmd); - free(p); + pfree(&p->binding); + pfree(&p->wbinding); + pfree(&p->cmd); + pfree(&p); return 0; } }