From 4b62b1d16caec36c4c843108c40cde25f9aa64e4 Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Wed, 25 Jul 2007 23:13:18 +0000 Subject: [PATCH] Sync with fdm. --- Makefile | 28 +++--- buffer.c | 38 ++++---- local.c | 50 +++++----- log.c | 50 +++++----- screen.c | 114 ++++++++++++++--------- server.c | 78 ++++++++-------- session.c | 4 +- tmux.c | 10 +- tmux.h | 23 ++++- window.c | 24 ++--- xmalloc-debug.c | 238 ++++++++++++++++++++++++++++++++++++++++++++++++ xmalloc.c | 96 ++++++++----------- 12 files changed, 511 insertions(+), 242 deletions(-) create mode 100644 xmalloc-debug.c diff --git a/Makefile b/Makefile index 60f38ac3..39d1f1e3 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ -# $Id: Makefile,v 1.1.1.1 2007-07-09 19:03:33 nicm Exp $ +# $Id: Makefile,v 1.2 2007-07-25 23:13:18 nicm Exp $ -.SUFFIXES: .c .o .y .l .h +.SUFFIXES: .c .o .y .h .PHONY: clean PROG= tmux @@ -10,19 +10,22 @@ OS!= uname REL!= uname -r DATE!= date +%Y%m%d-%H%M -SRCS= tmux.c server.c buffer.c buffer-poll.c xmalloc.c input.c screen.c \ - window.c session.c local.c log.c command.c -HDRS= tmux.h +# This must be empty as OpenBSD includes it in default CFLAGS. +DEBUG= + +SRCS= tmux.c server.c buffer.c buffer-poll.c xmalloc.c xmalloc-debug.c \ + input.c screen.c window.c session.c local.c log.c command.c -LEX= lex YACC= yacc -d CC= cc INCDIRS+= -I. -I- -I/usr/local/include CFLAGS+= -DBUILD="\"$(VERSION) ($(DATE))\"" +.ifdef DEBUG CFLAGS+= -g -ggdb -DDEBUG +LDFLAGS+= -Wl,-E +.endif #CFLAGS+= -pedantic -std=c99 -#CFLAGS+= -Wredundant-decls -Wdisabled-optimization -Wendif-labels CFLAGS+= -Wno-long-long -Wall -W -Wnested-externs -Wformat=2 CFLAGS+= -Wmissing-prototypes -Wstrict-prototypes -Wmissing-declarations CFLAGS+= -Wwrite-strings -Wshadow -Wpointer-arith -Wcast-qual -Wsign-compare @@ -35,29 +38,22 @@ INSTALLMAN= install -g bin -o root -m 444 LDFLAGS+= -L/usr/local/lib LIBS+= -lutil -lncurses -OBJS= ${SRCS:S/.c/.o/:S/.y/.o/:S/.l/.o/} +OBJS= ${SRCS:S/.c/.o/:S/.y/.o/} CLEANFILES= ${PROG} *.o .depend *~ ${PROG}.core *.log .c.o: ${CC} ${CFLAGS} ${INCDIRS} -c ${.IMPSRC} -o ${.TARGET} -.l.o: - ${LEX} ${.IMPSRC} - ${CC} ${CFLAGS} ${INCDIRS} -c lex.yy.c -o ${.TARGET} - .y.o: ${YACC} ${.IMPSRC} ${CC} ${CFLAGS} ${INCDIRS} -c y.tab.c -o ${.TARGET} -all: .depend ${PROG} +all: ${PROG} ${PROG}: ${OBJS} ${CC} ${LDFLAGS} -o ${PROG} ${LIBS} ${OBJS} -.depend: ${HDRS} - -mkdep ${CFLAGS} ${INCDIRS} ${SRCS:M*.c} - depend: mkdep ${CFLAGS} ${INCDIRS} ${SRCS:M*.c} diff --git a/buffer.c b/buffer.c index 3166088c..05ae7084 100644 --- a/buffer.c +++ b/buffer.c @@ -1,4 +1,4 @@ -/* $Id: buffer.c,v 1.1.1.1 2007-07-09 19:03:33 nicm Exp $ */ +/* $Id: buffer.c,v 1.2 2007-07-25 23:13:18 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -29,7 +29,7 @@ buffer_create(size_t size) struct buffer *b; if (size == 0) - log_fatalx("buffer_create: zero size"); + fatalx("zero size"); b = xcalloc(1, sizeof *b); @@ -60,7 +60,7 @@ void buffer_ensure(struct buffer *b, size_t size) { if (size == 0) - log_fatalx("buffer_ensure: zero size"); + fatalx("zero size"); if (BUFFER_FREE(b) >= size) return; @@ -79,9 +79,9 @@ void buffer_add(struct buffer *b, size_t size) { if (size == 0) - log_fatalx("buffer_add: zero size"); + fatalx("zero size"); if (size > b->space - b->size) - log_fatalx("buffer_add: overflow"); + fatalx("overflow"); b->size += size; } @@ -91,9 +91,9 @@ void buffer_reverse_add(struct buffer *b, size_t size) { if (size == 0) - log_fatalx("buffer_reverse_add: zero size"); + fatalx("zero size"); if (size > b->size) - log_fatalx("buffer_reverse_add: underflow"); + fatalx("underflow"); b->size -= size; } @@ -103,9 +103,9 @@ void buffer_remove(struct buffer *b, size_t size) { if (size == 0) - log_fatalx("buffer_remove: zero size"); + fatalx("zero size"); if (size > b->size) - log_fatalx("buffer_remove: underflow"); + fatalx("underflow"); b->size -= size; b->off += size; @@ -116,9 +116,9 @@ void buffer_reverse_remove(struct buffer *b, size_t size) { if (size == 0) - log_fatalx("buffer_reverse_remove: zero size"); + fatalx("zero size"); if (size > b->off) - log_fatalx("buffer_reverse_remove: overflow"); + fatalx("overflow"); b->size += size; b->off -= size; @@ -129,9 +129,9 @@ void buffer_insert_range(struct buffer *b, size_t base, size_t size) { if (size == 0) - log_fatalx("buffer_insert_range: zero size"); + fatalx("zero size"); if (base > b->size) - log_fatalx("buffer_insert_range: range overflows buffer"); + fatalx("range outside buffer"); buffer_ensure(b, size); memmove(b->base + b->off + base + size, @@ -144,11 +144,11 @@ void buffer_delete_range(struct buffer *b, size_t base, size_t size) { if (size == 0) - log_fatalx("buffer_delete_range: zero size"); + fatalx("zero size"); if (size > b->size) - log_fatalx("buffer_delete_range: size too big"); + fatalx("size too big"); if (base + size > b->size) - log_fatalx("buffer_delete_range: range overflows buffer"); + fatalx("range outside buffer"); memmove(b->base + b->off + base, b->base + b->off + base + size, b->size - base - size); @@ -160,7 +160,7 @@ void buffer_write(struct buffer *b, const void *data, size_t size) { if (size == 0) - log_fatalx("buffer_write: zero size"); + fatalx("zero size"); buffer_ensure(b, size); memcpy(BUFFER_IN(b), data, size); @@ -172,9 +172,9 @@ void buffer_read(struct buffer *b, void *data, size_t size) { if (size == 0) - log_fatalx("buffer_read: zero size"); + fatalx("zero size"); if (size > b->size) - log_fatalx("buffer_read: underflow"); + fatalx("underflow"); memcpy(data, BUFFER_OUT(b), size); buffer_remove(b, size); diff --git a/local.c b/local.c index e85a6c2d..eaa42cf8 100644 --- a/local.c +++ b/local.c @@ -1,4 +1,4 @@ -/* $Id: local.c,v 1.3 2007-07-09 19:39:47 nicm Exp $ */ +/* $Id: local.c,v 1.4 2007-07-25 23:13:18 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -214,13 +214,13 @@ local_init(struct buffer **in, struct buffer **out) struct local_key *lk; if ((tty = ttyname(STDOUT_FILENO)) == NULL) - log_fatal("ttyname"); + fatal("ttyname failed"); if ((local_fd = open(tty, O_RDWR)) == -1) - log_fatal("open(\"%s\")", tty); + fatal("open failed"); if ((mode = fcntl(local_fd, F_GETFL)) == -1) - log_fatal("fcntl"); + fatal("fcntl failed"); if (fcntl(local_fd, F_SETFL, mode|O_NONBLOCK) == -1) - log_fatal("fcntl"); + fatal("fcntl failed"); *in = local_in = buffer_create(BUFSIZ); *out = local_out = buffer_create(BUFSIZ); @@ -228,13 +228,13 @@ local_init(struct buffer **in, struct buffer **out) setupterm(NULL, STDOUT_FILENO, NULL); if (tcgetattr(local_fd, &local_tio) != 0) - log_fatal("tcgetattr"); + fatal("tcgetattr failed"); memcpy(&tio, &local_tio, sizeof tio); tio.c_iflag &= ~(IXON|IXOFF|ICRNL|INLCR); tio.c_oflag &= ~(OPOST|ONLCR|OCRNL|ONLRET); tio.c_lflag &= ~(IEXTEN|ICANON|ECHO|ECHOE|ECHOKE|ECHOCTL|ISIG); if (tcsetattr(local_fd, TCSANOW, &tio) != 0) - log_fatal("tcsetattr"); + fatal("tcsetattr failed"); if (enter_ca_mode != NULL) local_putp(enter_ca_mode); @@ -281,7 +281,7 @@ local_done(void) xfree(local_out); if (tcsetattr(local_fd, TCSANOW, &local_tio) != 0) - log_fatal("tcsetattr"); + fatal("tcsetattr failed"); close(local_fd); if (keypad_local != NULL) @@ -303,7 +303,7 @@ local_putc(int c) u_char ch = c; if (c < 0 || c > (int) UCHAR_MAX) - log_fatalx("local_putc: invalid character"); + fatalx("invalid character"); if (debug_level > 1) { f = fopen("tmux-out.log", "a+"); @@ -320,7 +320,7 @@ void local_putp(const char *s) { if (s == NULL) - log_fatalx("local_putp: null pointer"); + fatalx("null pointer"); tputs(s, 1, local_putc); } @@ -402,7 +402,7 @@ local_output(struct buffer *b, size_t size) } if (size < 1) - log_fatalx("local_output: underflow"); + fatalx("underflow"); size--; ch = input_extract8(b); @@ -410,7 +410,7 @@ local_output(struct buffer *b, size_t size) switch (ch) { case CODE_CURSORUP: if (size < 2) - log_fatalx("local_output: underflow"); + fatalx("underflow"); size -= 2; ua = input_extract16(b); if (parm_up_cursor == NULL) { @@ -421,7 +421,7 @@ local_output(struct buffer *b, size_t size) break; case CODE_CURSORDOWN: if (size < 2) - log_fatalx("local_output: underflow"); + fatalx("underflow"); size -= 2; ua = input_extract16(b); if (parm_down_cursor == NULL) { @@ -432,7 +432,7 @@ local_output(struct buffer *b, size_t size) break; case CODE_CURSORRIGHT: if (size < 2) - log_fatalx("local_output: underflow"); + fatalx("underflow"); size -= 2; ua = input_extract16(b); if (parm_right_cursor == NULL) { @@ -443,7 +443,7 @@ local_output(struct buffer *b, size_t size) break; case CODE_CURSORLEFT: if (size < 2) - log_fatalx("local_output: underflow"); + fatalx("underflow"); size -= 2; ua = input_extract16(b); if (parm_left_cursor == NULL) { @@ -454,7 +454,7 @@ local_output(struct buffer *b, size_t size) break; case CODE_CURSORMOVE: if (size < 4) - log_fatalx("local_output: underflow"); + fatalx("underflow"); size -= 4; ua = input_extract16(b); ub = input_extract16(b); @@ -501,7 +501,7 @@ local_output(struct buffer *b, size_t size) break; case CODE_INSERTLINE: if (size < 2) - log_fatalx("local_output: underflow"); + fatalx("underflow"); size -= 2; ua = input_extract16(b); if (parm_insert_line == NULL) { @@ -512,7 +512,7 @@ local_output(struct buffer *b, size_t size) break; case CODE_DELETELINE: if (size < 2) - log_fatalx("local_output: underflow"); + fatalx("underflow"); size -= 2; ua = input_extract16(b); if (parm_delete_line == NULL) { @@ -523,7 +523,7 @@ local_output(struct buffer *b, size_t size) break; case CODE_INSERTCHARACTER: if (size < 2) - log_fatalx("local_output: underflow"); + fatalx("underflow"); size -= 2; ua = input_extract16(b); if (parm_ich == NULL) { @@ -534,7 +534,7 @@ local_output(struct buffer *b, size_t size) break; case CODE_DELETECHARACTER: if (size < 2) - log_fatalx("local_output: underflow"); + fatalx("underflow"); size -= 2; ua = input_extract16(b); if (parm_dch == NULL) { @@ -573,7 +573,7 @@ local_output(struct buffer *b, size_t size) break; case CODE_SCROLLREGION: if (size < 4) - log_fatalx("local_output: underflow"); + fatalx("underflow"); size -= 4; ua = input_extract16(b); ub = input_extract16(b); @@ -631,18 +631,18 @@ local_output(struct buffer *b, size_t size) break; case CODE_TITLE: if (size < 2) - log_fatalx("local_output: underflow"); + fatalx("underflow"); size -= 2; ua = input_extract16(b); if (size < ua) - log_fatalx("local_output: underflow"); + fatalx("underflow"); size -= ua; buffer_remove(b, ua); break; case CODE_ATTRIBUTES: if (size < 2) - log_fatalx("local_output: underflow"); + fatalx("underflow"); size -= 2; ua = input_extract16(b); @@ -657,7 +657,7 @@ local_output(struct buffer *b, size_t size) while (ua-- != 0) { if (size < 2) - log_fatalx("local_output: underflow"); + fatalx("underflow"); size -= 2; ub = input_extract16(b); diff --git a/log.c b/log.c index 476eb189..06e1e5a8 100644 --- a/log.c +++ b/log.c @@ -1,4 +1,4 @@ -/* $Id: log.c,v 1.1.1.1 2007-07-09 19:03:33 nicm Exp $ */ +/* $Id: log.c,v 1.2 2007-07-25 23:13:18 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -35,11 +35,14 @@ FILE *log_stream; /* Debug level. */ int log_level; -/* Open log. */ +/* Open logging. */ void log_open(FILE *f, int facility, int level) { log_stream = f; + if (f != NULL) + setlinebuf(f); + log_level = level; if (f == NULL) @@ -61,32 +64,37 @@ log_close(void) /* Write a log message. */ void -log_write(FILE *f, int priority, const char *fmt, ...) +log_write(FILE *f, int priority, const char *msg, ...) { va_list ap; - va_start(ap, fmt); - log_vwrite(f, priority, fmt, ap); + va_start(ap, msg); + log_vwrite(f, priority, msg, ap); va_end(ap); } /* Write a log message. */ void -log_vwrite(FILE *f, int priority, const char *fmt, va_list ap) +log_vwrite(FILE *f, int priority, const char *msg, va_list ap) { + char *fmt; + if (!log_enabled) return; + if (f == NULL) + f = log_stream; if (f == NULL) { - vsyslog(priority, fmt, ap); + vsyslog(priority, msg, ap); return; } + if (asprintf(&fmt, "%s\n", msg) == -1) + exit(1); if (vfprintf(f, fmt, ap) == -1) exit(1); - if (fputc('\n', f) == EOF) - exit(1); - fflush(log_stream); + fflush(f); + free(fmt); } /* Log a warning with error string. */ @@ -102,8 +110,8 @@ log_warn(const char *msg, ...) va_start(ap, msg); if (asprintf(&fmt, "%s: %s", msg, strerror(errno)) == -1) exit(1); - log_vwrite(log_stream, LOG_CRIT, fmt, ap); - xfree(fmt); + log_vwrite(NULL, LOG_CRIT, fmt, ap); + free(fmt); va_end(ap); } @@ -114,7 +122,7 @@ log_warnx(const char *msg, ...) va_list ap; va_start(ap, msg); - log_vwrite(log_stream, LOG_CRIT, msg, ap); + log_vwrite(NULL, LOG_CRIT, msg, ap); va_end(ap); } @@ -126,10 +134,10 @@ log_info(const char *msg, ...) if (log_level > -1) { va_start(ap, msg); - if (log_stream == stderr) + if (log_stream == stderr) /* XXX */ log_vwrite(stdout, LOG_INFO, msg, ap); else - log_vwrite(log_stream, LOG_INFO, msg, ap); + log_vwrite(NULL, LOG_INFO, msg, ap); va_end(ap); } } @@ -142,7 +150,7 @@ log_debug(const char *msg, ...) if (log_level > 0) { va_start(ap, msg); - log_vwrite(log_stream, LOG_DEBUG, msg, ap); + log_vwrite(NULL, LOG_DEBUG, msg, ap); va_end(ap); } } @@ -155,7 +163,7 @@ log_debug2(const char *msg, ...) if (log_level > 1) { va_start(ap, msg); - log_vwrite(log_stream, LOG_DEBUG, msg, ap); + log_vwrite(NULL, LOG_DEBUG, msg, ap); va_end(ap); } } @@ -168,7 +176,7 @@ log_debug3(const char *msg, ...) if (log_level > 2) { va_start(ap, msg); - log_vwrite(log_stream, LOG_DEBUG, msg, ap); + log_vwrite(NULL, LOG_DEBUG, msg, ap); va_end(ap); } } @@ -185,13 +193,13 @@ log_vfatal(const char *msg, va_list ap) if (errno != 0) { if (asprintf(&fmt, "fatal: %s: %s", msg, strerror(errno)) == -1) exit(1); - log_vwrite(log_stream, LOG_CRIT, fmt, ap); + log_vwrite(NULL, LOG_CRIT, fmt, ap); } else { if (asprintf(&fmt, "fatal: %s", msg) == -1) exit(1); - log_vwrite(log_stream, LOG_CRIT, fmt, ap); + log_vwrite(NULL, LOG_CRIT, fmt, ap); } - xfree(fmt); + free(fmt); exit(1); } diff --git a/screen.c b/screen.c index fdc21258..850ec334 100644 --- a/screen.c +++ b/screen.c @@ -1,4 +1,4 @@ -/* $Id: screen.c,v 1.2 2007-07-10 10:21:58 nicm Exp $ */ +/* $Id: screen.c,v 1.3 2007-07-25 23:13:18 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -59,6 +59,12 @@ void screen_delete_characters(struct screen *, u_int, u_int, u_int); #define screen_last_y(s) ((s)->sy - 1) #define screen_last_x(s) ((s)->sx - 1) +#define screen_range_y(lx, rx) (((rx) - (lx)) + 1) +#define screen_range_x(ux, lx) (((lx) - (ux)) + 1) + +#define screen_offset_y(py, ny) ((py) + (ny) - 1) +#define screen_offset_x(px, nx) ((px) + (nx) - 1) + /* Create a new screen. */ void screen_create(struct screen *s, u_int sx, u_int sy) @@ -180,7 +186,7 @@ screen_draw(struct screen *s, struct buffer *b, u_int uy, u_int ly) uint16_t n; if (uy > screen_last_y(s) || ly > screen_last_y(s) || ly < uy) - log_fatalx("screen_draw_lines: bad range"); + fatalx("bad range"); /* XXX. This is naive and rough right now. */ attr = 0; @@ -303,7 +309,7 @@ screen_make_lines(struct screen *s, u_int uy, u_int ly) log_debug("making lines %u:%u", uy, ly); if (uy > screen_last_y(s) || ly > screen_last_y(s) || ly < uy) - log_fatalx("screen_make_lines: bad range"); + fatalx("bad range"); for (i = uy; i <= ly; i++) { s->grid_data[i] = xmalloc(s->sx); @@ -321,7 +327,7 @@ screen_free_lines(struct screen *s, u_int uy, u_int ly) log_debug("freeing lines %u:%u", uy, ly); if (uy > screen_last_y(s) || ly > screen_last_y(s) || ly < uy) - log_fatalx("screen_free_lines: bad range"); + fatalx("bad range"); for (i = uy; i <= ly; i++) { xfree(s->grid_data[i]); @@ -344,18 +350,20 @@ screen_move_lines(struct screen *s, u_int dy, u_int uy, u_int ly) ny = (ly - uy) + 1; if (uy > screen_last_y(s) || ly > screen_last_y(s) || ly < uy) - log_fatalx("screen_move_lines: bad range"); + fatalx("bad range"); if (dy > screen_last_y(s)) - log_fatalx("screen_move_lines: bad destination"); + fatalx("bad destination"); if (dy + ny - 1 > screen_last_y(s)) - log_fatalx("screen_move_lines: bad destination"); + fatalx("bad size"); + if (dy == uy) + fatalx("null move"); memmove( - s->grid_data + dy, s->grid_data + uy, ny * (sizeof *s->grid_data)); + &s->grid_data[dy], &s->grid_data[uy], ny * (sizeof *s->grid_data)); memmove( - s->grid_attr + dy, s->grid_attr + uy, ny * (sizeof *s->grid_attr)); + &s->grid_attr[dy], &s->grid_attr[uy], ny * (sizeof *s->grid_attr)); memmove( - s->grid_colr + dy, s->grid_colr + uy, ny * (sizeof *s->grid_colr)); + &s->grid_colr[dy], &s->grid_colr[uy], ny * (sizeof *s->grid_colr)); } /* Fill a range of lines. */ @@ -368,7 +376,7 @@ screen_fill_lines( log_debug("filling lines %u:%u", uy, ly); if (uy > screen_last_y(s) || ly > screen_last_y(s) || ly < uy) - log_fatalx("screen_fill_lines: bad range"); + fatalx("bad range"); for (i = uy; i <= ly; i++) screen_fill_line(s, i, data, attr, colr); @@ -391,7 +399,7 @@ screen_character(struct screen *s, u_char ch) break; default: if (ch < ' ') - log_fatalx("screen_character: bad control: %hhu", ch); + fatalx("bad control"); screen_write_character(s, ch); break; } @@ -662,7 +670,7 @@ screen_scroll_up(struct screen *s, u_int ny) return; } - log_fatalx("screen_scroll_up: %u %u", s->ry_upper, s->ry_lower); + fatalx("unimplemented"); } /* Scroll screen down. */ @@ -674,7 +682,7 @@ screen_scroll_down(struct screen *s, u_int ny) return; } - log_fatalx("screen_scroll_down: %u %u", s->ry_upper, s->ry_lower); + fatalx("unimplemented"); } /* Fill entire screen. */ @@ -722,9 +730,9 @@ screen_fill_end_of_line( if (py > screen_last_y(s)) return; - memset(s->grid_data[py] + px, data, s->sx - px); - memset(s->grid_attr[py] + px, attr, s->sx - px); - memset(s->grid_colr[py] + px, colr, s->sx - px); + memset(&s->grid_data[py][px], data, s->sx - px); + memset(&s->grid_attr[py][px], attr, s->sx - px); + memset(&s->grid_colr[py][px], colr, s->sx - px); } /* Fill to start of line. */ @@ -787,44 +795,64 @@ screen_delete_lines(struct screen *s, u_int py, u_int ny) void screen_insert_characters(struct screen *s, u_int px, u_int py, u_int nx) { - if (px >= s->sx || py >= s->sy) + u_int lx, rx; + + if (px > screen_last_x(s) || py > screen_last_y(s)) return; - if (px + nx > s->sx) - nx = s->sx - px; + lx = px; + rx = screen_offset_x(px, nx); + if (rx > screen_last_x(s)) + rx = screen_last_x(s); - if (px - nx != s->sx) { - memmove(s->grid_data[py] + px + nx, - s->grid_data[py] + px, s->sx - px - nx); - memmove(s->grid_attr[py] + px + nx, - s->grid_attr[py] + px, s->sx - px - nx); - memmove(s->grid_colr[py] + px + nx, - s->grid_colr[py] + px, s->sx - px - nx); + /* + * Inserting a range from lx to rx, inclusive. + * + * - If rx is not the last x, move from lx to rx + 1. + * - Clear the range from lx to rx. + */ + if (rx != screen_last_x(s)) { + nx = screen_range_x(rx + 1, screen_last_x(s)); + memmove(&s->grid_data[py][rx + 1], &s->grid_data[py][lx], nx); + memmove(&s->grid_attr[py][rx + 1], &s->grid_attr[py][lx], nx); + memmove(&s->grid_colr[py][rx + 1], &s->grid_colr[py][lx], nx); } - memset(s->grid_data[py] + px, SCREEN_DEFDATA, nx); - memset(s->grid_attr[py] + px, SCREEN_DEFATTR, nx); - memset(s->grid_colr[py] + px, SCREEN_DEFCOLR, nx); + memset(&s->grid_data[py][lx], SCREEN_DEFDATA, screen_range_x(lx, rx)); + memset(&s->grid_attr[py][lx], SCREEN_DEFATTR, screen_range_x(lx, rx)); + memset(&s->grid_colr[py][lx], SCREEN_DEFCOLR, screen_range_x(lx, rx)); } /* Delete characters. */ void screen_delete_characters(struct screen *s, u_int px, u_int py, u_int nx) { - if (px >= s->sx || py >= s->sy) + u_int lx, rx; + + if (px > screen_last_x(s) || py > screen_last_y(s)) return; - if (px + nx > s->sx) - nx = s->sx - px; + lx = px; + rx = screen_offset_x(px, nx); + if (rx > screen_last_x(s)) + rx = screen_last_x(s); - if (px - nx != s->sx) { - memmove(s->grid_data[py] + px, - s->grid_data[py] + px + nx, s->sx - px - nx); - memmove(s->grid_attr[py] + px, - s->grid_attr[py] + px + nx, s->sx - px - nx); - memmove(s->grid_colr[py] + px, - s->grid_colr[py] + px + nx, s->sx - px - nx); + /* + * Deleting the range from lx to rx, inclusive. + * + * - If rx is not the last x, move the range from rx + 1 to lx. + * - Clear the range from the last x - (rx - lx) to the last x. + */ + + if (rx != screen_last_x(s)) { + nx = screen_range_x(rx + 1, screen_last_x(s)); + memmove(&s->grid_data[py][lx], &s->grid_data[py][rx + 1], nx); + memmove(&s->grid_attr[py][lx], &s->grid_attr[py][rx + 1], nx); + memmove(&s->grid_colr[py][lx], &s->grid_colr[py][rx + 1], nx); } - memset(s->grid_data[py] + px + nx, SCREEN_DEFDATA, s->sx - px - nx); - memset(s->grid_attr[py] + px + nx, SCREEN_DEFATTR, s->sx - px - nx); - memset(s->grid_colr[py] + px + nx, SCREEN_DEFCOLR, s->sx - px - nx); + + /* If lx == rx, then nx = 1. */ + nx = screen_range_x(lx, rx); + memset(&s->grid_data[py][s->sx - nx], SCREEN_DEFDATA, nx); + memset(&s->grid_attr[py][s->sx - nx], SCREEN_DEFATTR, nx); + memset(&s->grid_colr[py][s->sx - nx], SCREEN_DEFCOLR, nx); } diff --git a/server.c b/server.c index 5d6204dd..b1a10e35 100644 --- a/server.c +++ b/server.c @@ -1,4 +1,4 @@ -/* $Id: server.c,v 1.1.1.1 2007-07-09 19:03:42 nicm Exp $ */ +/* $Id: server.c,v 1.2 2007-07-25 23:13:18 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -114,27 +114,27 @@ server_start(void) sz = strlcpy(sa.sun_path, socket_path, sizeof sa.sun_path); if (sz >= sizeof sa.sun_path) { errno = ENAMETOOLONG; - log_fatal("socket"); + fatal("socket failed"); } unlink(sa.sun_path); if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) - log_fatal("socket"); + fatal("socket failed"); mode = umask(S_IXUSR|S_IRWXG|S_IRWXO); if (bind(fd, (struct sockaddr *) &sa, SUN_LEN(&sa)) == -1) - log_fatal("bind"); + fatal("bind failed"); umask(mode); if (listen(fd, 16) == -1) - log_fatal("listen"); + fatal("listen failed"); /* * Detach into the background. This means the PID changes which will * have to be fixed in some way at some point... XXX */ if (daemon(1, 1) != 0) - log_fatal("daemon"); + fatal("daemon failed"); log_debug("server daemonised, pid now %ld", (long) getpid()); setproctitle("server (%s)", socket_path); @@ -154,24 +154,24 @@ server_main(int srv_fd) act.sa_handler = SIG_IGN; if (sigaction(SIGPIPE, &act, NULL) != 0) - log_fatal("sigaction"); + fatal("sigaction failed"); if (sigaction(SIGUSR1, &act, NULL) != 0) - log_fatal("sigaction"); + fatal("sigaction failed"); if (sigaction(SIGUSR2, &act, NULL) != 0) - log_fatal("sigaction"); + fatal("sigaction failed"); if (sigaction(SIGINT, &act, NULL) != 0) - log_fatal("sigaction"); + fatal("sigaction failed"); if (sigaction(SIGQUIT, &act, NULL) != 0) - log_fatal("sigaction"); + fatal("sigaction failed"); ARRAY_INIT(&windows); ARRAY_INIT(&clients); ARRAY_INIT(&sessions); if ((mode = fcntl(srv_fd, F_GETFL)) == -1) - log_fatal("fcntl"); + fatal("fcntl failed"); if (fcntl(srv_fd, F_SETFL, mode|O_NONBLOCK) == -1) - log_fatal("fcntl"); + fatal("fcntl failed"); pfds = NULL; while (!sigterm) { @@ -193,13 +193,13 @@ server_main(int srv_fd) if (poll(pfds, nfds, INFTIM) == -1) { if (errno == EAGAIN || errno == EINTR) continue; - log_fatal("poll"); + fatal("poll failed"); } pfd = pfds; /* Handle server socket. */ if (pfd->revents & (POLLERR|POLLNVAL|POLLHUP)) - log_fatalx("lost server socket"); + fatalx("lost server socket"); if (pfd->revents & POLLIN) { accept_client(srv_fd); continue; @@ -319,12 +319,12 @@ accept_client(int srv_fd) if (client_fd == -1) { if (errno == EAGAIN || errno == EINTR || errno == ECONNABORTED) return (NULL); - log_fatal("accept"); + fatal("accept failed"); } if ((mode = fcntl(client_fd, F_GETFL)) == -1) - log_fatal("fcntl"); + fatal("fcntl failed"); if (fcntl(client_fd, F_SETFL, mode|O_NONBLOCK) == -1) - log_fatal("fcntl"); + fatal("fcntl failed"); c = xmalloc(sizeof *c); c->fd = client_fd; @@ -477,7 +477,7 @@ user_input(struct client *c, size_t in) key = input_extract8(c->in); if (key == '\e') { if (in < 2) - log_fatalx("user_input: underflow"); + fatalx("underflow"); in -= 2; key = (int16_t) input_extract16(c->in); } @@ -762,7 +762,7 @@ process_identify_msg(struct client *c, struct hdr *hdr) struct identify_data data; if (hdr->size != sizeof data) - log_fatalx("bad MSG_IDENTIFY size"); + fatalx("bad MSG_IDENTIFY size"); buffer_read(c->in, &data, hdr->size); c->sx = data.sx; @@ -779,7 +779,7 @@ process_identify_msg(struct client *c, struct hdr *hdr) session_create(data.name, "/bin/ksh -l", c->sx, c->sy); } if (c->session == NULL) - log_fatalx("process_identify_msg: session_create failed"); + fatalx("session_create failed"); draw_client(c, 0, c->sy - 1); } @@ -789,12 +789,12 @@ void process_create_msg(struct client *c, struct hdr *hdr) { if (c->session == NULL) - log_fatalx("MSG_CREATE before identified"); + fatalx("MSG_CREATE before identified"); if (hdr->size != 0) - log_fatalx("bad MSG_CREATE size"); + fatalx("bad MSG_CREATE size"); if (session_new(c->session, "/bin/ksh -l", c->sx, c->sy) != 0) - log_fatalx("process_create_msg: session_new failed"); + fatalx("session_new failed"); draw_client(c, 0, c->sy - 1); } @@ -804,9 +804,9 @@ void process_next_msg(struct client *c, struct hdr *hdr) { if (c->session == NULL) - log_fatalx("MSG_NEXT before identified"); + fatalx("MSG_NEXT before identified"); if (hdr->size != 0) - log_fatalx("bad MSG_NEXT size"); + fatalx("bad MSG_NEXT size"); if (session_next(c->session) == 0) changed_window(c); @@ -819,9 +819,9 @@ void process_previous_msg(struct client *c, struct hdr *hdr) { if (c->session == NULL) - log_fatalx("MSG_PREVIOUS before identified"); + fatalx("MSG_PREVIOUS before identified"); if (hdr->size != 0) - log_fatalx("bad MSG_PREVIOUS size"); + fatalx("bad MSG_PREVIOUS size"); if (session_previous(c->session) == 0) changed_window(c); @@ -836,9 +836,9 @@ process_size_msg(struct client *c, struct hdr *hdr) struct size_data data; if (c->session == NULL) - log_fatalx("MSG_SIZE before identified"); + fatalx("MSG_SIZE before identified"); if (hdr->size != sizeof data) - log_fatalx("bad MSG_SIZE size"); + fatalx("bad MSG_SIZE size"); buffer_read(c->in, &data, hdr->size); c->sx = data.sx; @@ -857,7 +857,7 @@ void process_input_msg(struct client *c, struct hdr *hdr) { if (c->session == NULL) - log_fatalx("MSG_INPUT before identified"); + fatalx("MSG_INPUT before identified"); if (c->prompt == NULL) window_input(c->session->window, c->in, hdr->size); @@ -872,9 +872,9 @@ process_refresh_msg(struct client *c, struct hdr *hdr) struct refresh_data data; if (c->session == NULL) - log_fatalx("MSG_REFRESH before identified"); + fatalx("MSG_REFRESH before identified"); if (hdr->size != 0 && hdr->size != sizeof data) - log_fatalx("bad MSG_REFRESH size"); + fatalx("bad MSG_REFRESH size"); draw_client(c, 0, c->sy - 1); } @@ -886,9 +886,9 @@ process_select_msg(struct client *c, struct hdr *hdr) struct select_data data; if (c->session == NULL) - log_fatalx("MSG_SELECT before identified"); + fatalx("MSG_SELECT before identified"); if (hdr->size != sizeof data) - log_fatalx("bad MSG_SELECT size"); + fatalx("bad MSG_SELECT size"); buffer_read(c->in, &data, hdr->size); if (c->session == NULL) @@ -909,7 +909,7 @@ process_sessions_msg(struct client *c, struct hdr *hdr) u_int i, j; if (hdr->size != sizeof data) - log_fatalx("bad MSG_SESSIONS size"); + fatalx("bad MSG_SESSIONS size"); buffer_read(c->in, &data, hdr->size); data.sessions = 0; @@ -946,7 +946,7 @@ process_windows_msg(struct client *c, struct hdr *hdr) u_int i; if (hdr->size != sizeof data) - log_fatalx("bad MSG_WINDOWS size"); + fatalx("bad MSG_WINDOWS size"); buffer_read(c->in, &data, hdr->size); s = session_find(data.name); @@ -982,9 +982,9 @@ void process_rename_msg(struct client *c, struct hdr *hdr) { if (c->session == NULL) - log_fatalx("MSG_RENAME before identified"); + fatalx("MSG_RENAME before identified"); if (hdr->size != 0) - log_fatalx("bad MSG_RENAME size"); + fatalx("bad MSG_RENAME size"); user_start(c, "Window name: ", c->session->window->name, MAXNAMELEN, rename_callback); diff --git a/session.c b/session.c index 31b80154..5dee2350 100644 --- a/session.c +++ b/session.c @@ -1,4 +1,4 @@ -/* $Id: session.c,v 1.1.1.1 2007-07-09 19:04:12 nicm Exp $ */ +/* $Id: session.c,v 1.2 2007-07-25 23:13:18 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -76,7 +76,7 @@ session_destroy(struct session *s) u_int i; if (session_index(s, &i) != 0) - log_fatalx("session not found"); + fatalx("session not found"); ARRAY_REMOVE(&sessions, i); while (!ARRAY_EMPTY(&s->windows)) diff --git a/tmux.c b/tmux.c index a5965b22..9a5dffdb 100644 --- a/tmux.c +++ b/tmux.c @@ -1,4 +1,4 @@ -/* $Id: tmux.c,v 1.1.1.1 2007-07-09 19:03:33 nicm Exp $ */ +/* $Id: tmux.c,v 1.2 2007-07-25 23:13:18 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -237,7 +237,7 @@ main(int argc, char **argv) /* Handle SIGWINCH if necessary. */ if (sigwinch) { if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == -1) - log_fatal("ioctl(TIOCGWINSZ)"); + fatal("ioctl failed"); hdr.code = MSG_SIZE; hdr.size = sizeof sd; @@ -263,14 +263,14 @@ main(int argc, char **argv) if (poll(pfds, 2, INFTIM) == -1) { if (errno == EAGAIN || errno == EINTR) continue; - log_fatal("poll"); + fatal("poll failed"); } /* Read/write from sockets. */ if (buffer_poll(&pfds[0], srv_in, srv_out) != 0) goto server_dead; if (buffer_poll(&pfds[1], loc_in, loc_out) != 0) - log_fatalx("lost local socket"); + fatalx("lost local socket"); /* Output flushed; pause if requested. */ if (n) @@ -341,7 +341,7 @@ process_server(struct buffer *srv_in) break; case MSG_PAUSE: if (hdr.size != 0) - log_fatalx("bad MSG_PAUSE size"); + fatalx("bad MSG_PAUSE size"); return (1); case MSG_EXIT: return (-1); diff --git a/tmux.h b/tmux.h index 962ed98c..7a80956c 100644 --- a/tmux.h +++ b/tmux.h @@ -1,4 +1,4 @@ -/* $Id: tmux.h,v 1.1.1.1 2007-07-09 19:03:50 nicm Exp $ */ +/* $Id: tmux.h,v 1.2 2007-07-25 23:13:18 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -20,6 +20,7 @@ #define NSCR_H #include +#include #include #include @@ -30,8 +31,12 @@ extern char *__progname; -#define MAXNAMELEN 32 -#define MAXTITLELEN 192 +#define MAXNAMELEN 32 +#define MAXTITLELEN 192 + +/* Fatal errors. */ +#define fatal(msg) log_fatal("%s: %s", __func__, msg); +#define fatalx(msg) log_fatal("%s: %s", __func__, msg); /* Definition to shut gcc up about unused arguments. */ #define unused __attribute__ ((unused)) @@ -580,4 +585,16 @@ int printflike3 printpath(char *, size_t, const char *, ...); char *xdirname(const char *); char *xbasename(const char *); +/* xmalloc-debug.c */ +#ifdef DEBUG +#define xmalloc_caller() __builtin_return_address(0) + +void xmalloc_clear(void); +void xmalloc_report(pid_t, const char *); + +void xmalloc_new(void *, void *, size_t); +void xmalloc_change(void *, void *, void *, size_t); +void xmalloc_free(void *); +#endif + #endif diff --git a/window.c b/window.c index 47d9e08d..5f3e5092 100644 --- a/window.c +++ b/window.c @@ -1,4 +1,4 @@ -/* $Id: window.c,v 1.1.1.1 2007-07-09 19:04:12 nicm Exp $ */ +/* $Id: window.c,v 1.2 2007-07-25 23:13:18 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -78,23 +78,23 @@ window_create(const char *cmd, u_int sx, u_int sy) return (NULL); case 0: if (setenv("TMUX", pid, 1) != 0) - log_fatal("setenv"); + fatal("setenv failed"); if (setenv("TERM", "screen", 1) != 0) - log_fatal("setenv"); + fatal("setenv failed"); log_close(); execl(_PATH_BSHELL, "sh", "-c", cmd, (char *) NULL); - log_fatal("execl"); + fatal("execl failed"); } if ((mode = fcntl(fd, F_GETFL)) == -1) - log_fatal("fcntl"); + fatal("fcntl failed"); if (fcntl(fd, F_SETFL, mode|O_NONBLOCK) == -1) - log_fatal("fcntl"); + fatal("fcntl failed"); mode = 1; if (ioctl(fd, TIOCPKT, &mode) == -1) - log_fatal("ioctl(TIOCPKT)"); + fatal("ioctl failed"); w = xmalloc(sizeof *w); w->fd = fd; @@ -156,7 +156,7 @@ window_remove(struct windows *ww, struct window *w) u_int i; if (window_index(ww, w, &i) != 0) - log_fatalx("window_remove: window not found"); + fatalx("window not found"); ARRAY_REMOVE(ww, i); w->references--; @@ -184,7 +184,7 @@ window_next(struct windows *ww, struct window *w) u_int i; if (window_index(ww, w, &i) != 0) - log_fatalx("window_next: window not found"); + fatalx("window not found"); if (i == ARRAY_LENGTH(ww) - 1) return (NULL); @@ -204,7 +204,7 @@ window_previous(struct windows *ww, struct window *w) u_int i; if (window_index(ww, w, &i) != 0) - log_fatalx("window_previous: window not found"); + fatalx("window not found"); if (i == 0) return (NULL); do { @@ -241,7 +241,7 @@ window_resize(struct window *w, u_int sx, u_int sy) screen_resize(&w->screen, sx, sy); if (ioctl(w->fd, TIOCSWINSZ, &ws) == -1) - log_fatal("ioctl(TIOCSWINSZ)"); + fatal("ioctl failed"); return (0); } @@ -293,7 +293,7 @@ window_input(struct window *w, struct buffer *b, size_t size) key = input_extract8(b); if (key == '\e') { if (size < 2) - log_fatalx("window_input: underflow"); + fatalx("underflow"); size -= 2; key = (int16_t) input_extract16(b); } diff --git a/xmalloc-debug.c b/xmalloc-debug.c new file mode 100644 index 00000000..051d96b7 --- /dev/null +++ b/xmalloc-debug.c @@ -0,0 +1,238 @@ +/* $Id: xmalloc-debug.c,v 1.1 2007-07-25 23:13:18 nicm Exp $ */ + +/* + * Copyright (c) 2007 Nicholas Marriott + * + * 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 MIND, 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. + */ + +#ifdef DEBUG + +#include + +#include +#include +#include +#include +#include + +#include "tmux.h" + +/* Single xmalloc allocated block. */ +struct xmalloc_blk { + void *caller; + + void *ptr; + size_t size; + + SPLAY_ENTRY(xmalloc_blk) entry; +}; + +/* Splay tree of allocated blocks. */ +SPLAY_HEAD(xmalloc_tree, xmalloc_blk); +struct xmalloc_tree xmalloc_tree = SPLAY_INITIALIZER(&xmalloc_tree); + +/* Various statistics. */ +size_t xmalloc_allocated; +size_t xmalloc_freed; +size_t xmalloc_peak; +u_int xmalloc_frees; +u_int xmalloc_mallocs; +u_int xmalloc_reallocs; + +/* Print function. */ +#define XMALLOC_PRINT log_debug3 + +/* Bytes of unallocated blocks and number of allocated blocks to show. */ +#define XMALLOC_BYTES 8 +#define XMALLOC_LINES 32 + +/* Macro to update peek usage variable. */ +#define XMALLOC_UPDATE() do { \ + if (xmalloc_allocated - xmalloc_freed > xmalloc_peak) \ + xmalloc_peak = xmalloc_allocated - xmalloc_freed; \ +} while (0) + +/* Tree functions. */ +int xmalloc_cmp(struct xmalloc_blk *, struct xmalloc_blk *); +SPLAY_PROTOTYPE(xmalloc_tree, xmalloc_blk, entry, xmalloc_cmp); +SPLAY_GENERATE(xmalloc_tree, xmalloc_blk, entry, xmalloc_cmp); + +/* Compare two blocks. */ +int +xmalloc_cmp(struct xmalloc_blk *blk1, struct xmalloc_blk *blk2) +{ + uintptr_t ptr1 = (uintptr_t) blk1->ptr; + uintptr_t ptr2 = (uintptr_t) blk2->ptr; + + if (ptr1 < ptr2) + return (-1); + if (ptr1 > ptr2) + return (1); + return (0); +} + +/* Clear statistics and block list; used to start fresh after fork(2). */ +void +xmalloc_clear(void) +{ + struct xmalloc_blk *blk; + + xmalloc_allocated = 0; + xmalloc_freed = 0; + xmalloc_peak = 0; + xmalloc_frees = 0; + xmalloc_mallocs = 0; + xmalloc_reallocs = 0; + + while (!SPLAY_EMPTY(&xmalloc_tree)) { + blk = SPLAY_ROOT(&xmalloc_tree); + SPLAY_REMOVE(xmalloc_tree, &xmalloc_tree, blk); + free(blk); + } +} + +/* Print report of statistics and unfreed blocks. */ +void +xmalloc_report(pid_t pid, const char *hdr) +{ + struct xmalloc_blk *blk; + u_char *iptr; + char buf[4 * XMALLOC_BYTES + 1], *optr; + size_t len; + u_int n; + Dl_info info; + + XMALLOC_PRINT("%s: %ld: allocated=%zu, freed=%zu, difference=%zd, " + "peak=%zu", hdr, (long) pid, xmalloc_allocated, xmalloc_freed, + xmalloc_allocated - xmalloc_freed, xmalloc_peak); + XMALLOC_PRINT("%s: %ld: mallocs=%u, reallocs=%u, frees=%u", hdr, + (long) pid, xmalloc_mallocs, xmalloc_reallocs, xmalloc_frees); + + n = 0; + SPLAY_FOREACH(blk, xmalloc_tree, &xmalloc_tree) { + n++; + if (n >= XMALLOC_LINES) + continue; + + len = blk->size; + if (len > XMALLOC_BYTES) + len = XMALLOC_BYTES; + + memset(&info, 0, sizeof info); + if (dladdr(blk->caller, &info) == 0) + info.dli_sname = info.dli_saddr = NULL; + + optr = buf; + iptr = blk->ptr; + for (; len > 0; len--) { + if (isascii(*iptr) && !iscntrl(*iptr)) { + *optr++ = *iptr++; + continue; + } + *optr++ = '\\'; + *optr++ = '0' + ((*iptr >> 6) & 07); + *optr++ = '0' + ((*iptr >> 3) & 07); + *optr++ = '0' + (*iptr & 07); + iptr++; + } + *optr = '\0'; + + XMALLOC_PRINT("%s: %ld: %u, %s+0x%02tx: [%p %zu: %s]", hdr, + (long) pid, n, info.dli_sname, ((u_char *) blk->caller) - + ((u_char *) info.dli_saddr), blk->ptr, blk->size, buf); + } + XMALLOC_PRINT("%s: %ld: %u unfreed blocks", hdr, (long) pid, n); +} + +/* Record a newly created block. */ +void +xmalloc_new(void *caller, void *ptr, size_t size) +{ + struct xmalloc_blk *blk; + + xmalloc_allocated += size; + XMALLOC_UPDATE(); + + if ((blk = malloc(sizeof *blk)) == NULL) + abort(); + + blk->ptr = ptr; + blk->size = size; + + blk->caller = caller; + + SPLAY_INSERT(xmalloc_tree, &xmalloc_tree, blk); + + xmalloc_mallocs++; + XMALLOC_UPDATE(); +} + +/* Record changes to a block. */ +void +xmalloc_change(void *caller, void *oldptr, void *newptr, size_t newsize) +{ + struct xmalloc_blk *blk, key; + ssize_t change; + + if (oldptr == NULL) { + xmalloc_new(caller, newptr, newsize); + return; + } + + key.ptr = oldptr; + blk = SPLAY_FIND(xmalloc_tree, &xmalloc_tree, &key); + if (blk == NULL) + return; + + change = newsize - blk->size; + if (change > 0) + xmalloc_allocated += change; + else + xmalloc_freed -= change; + XMALLOC_UPDATE(); + + SPLAY_REMOVE(xmalloc_tree, &xmalloc_tree, blk); + + blk->ptr = newptr; + blk->size = newsize; + + blk->caller = caller; + + SPLAY_INSERT(xmalloc_tree, &xmalloc_tree, blk); + + xmalloc_reallocs++; + XMALLOC_UPDATE(); +} + +/* Record a block free. */ +void +xmalloc_free(void *ptr) +{ + struct xmalloc_blk *blk, key; + + key.ptr = ptr; + blk = SPLAY_FIND(xmalloc_tree, &xmalloc_tree, &key); + if (blk == NULL) + return; + + xmalloc_freed += blk->size; + + SPLAY_REMOVE(xmalloc_tree, &xmalloc_tree, blk); + free(blk); + + xmalloc_frees++; + XMALLOC_UPDATE(); +} + +#endif /* DEBUG */ diff --git a/xmalloc.c b/xmalloc.c index 228e4381..478e5f0e 100644 --- a/xmalloc.c +++ b/xmalloc.c @@ -1,4 +1,4 @@ -/* $Id: xmalloc.c,v 1.1.1.1 2007-07-09 19:03:33 nicm Exp $ */ +/* $Id: xmalloc.c,v 1.2 2007-07-25 23:13:18 nicm Exp $ */ /* * Copyright (c) 2004 Nicholas Marriott @@ -16,14 +16,10 @@ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include +#include #include #include -#include -#include -#include -#include #include #include @@ -33,10 +29,10 @@ void * ensure_for(void *buf, size_t *len, size_t size, size_t adj) { if (adj == 0) - log_fatalx("ensure_for: zero adj"); + fatalx("zero adj"); if (SIZE_MAX - size < adj) - log_fatalx("ensure_for: size + adj > SIZE_MAX"); + fatalx("size + adj > SIZE_MAX"); size += adj; if (*len == 0) { @@ -56,9 +52,9 @@ void * ensure_size(void *buf, size_t *len, size_t nmemb, size_t size) { if (nmemb == 0 || size == 0) - log_fatalx("ensure_size: zero size"); + fatalx("zero size"); if (SIZE_MAX / nmemb < size) - log_fatalx("ensure_size: nmemb * size > SIZE_MAX"); + fatalx("nmemb * size > SIZE_MAX"); if (*len == 0) { *len = BUFSIZ; @@ -91,25 +87,31 @@ xcalloc(size_t nmemb, size_t size) void *ptr; if (size == 0 || nmemb == 0) - log_fatalx("xcalloc: zero size"); + fatalx("zero size"); if (SIZE_MAX / nmemb < size) - log_fatalx("xcalloc: nmemb * size > SIZE_MAX"); + fatalx("nmemb * size > SIZE_MAX"); if ((ptr = calloc(nmemb, size)) == NULL) - log_fatal("xcalloc"); + fatal("xcalloc failed"); +#ifdef DEBUG + xmalloc_new(xmalloc_caller(), ptr, nmemb * size); +#endif return (ptr); } void * xmalloc(size_t size) { - void *ptr; + void *ptr; if (size == 0) - log_fatalx("xmalloc: zero size"); + fatalx("zero size"); if ((ptr = malloc(size)) == NULL) - log_fatal("xmalloc"); + fatal("xmalloc failed"); +#ifdef DEBUG + xmalloc_new(xmalloc_caller(), ptr, size); +#endif return (ptr); } @@ -120,12 +122,15 @@ xrealloc(void *oldptr, size_t nmemb, size_t size) void *newptr; if (newsize == 0) - log_fatalx("xrealloc: zero size"); + fatalx("zero size"); if (SIZE_MAX / nmemb < size) - log_fatal("xrealloc: nmemb * size > SIZE_MAX"); + fatalx("nmemb * size > SIZE_MAX"); if ((newptr = realloc(oldptr, newsize)) == NULL) - log_fatal("xrealloc"); + fatal("xrealloc failed"); +#ifdef DEBUG + xmalloc_change(xmalloc_caller(), oldptr, newptr, nmemb * size); +#endif return (newptr); } @@ -133,8 +138,12 @@ void xfree(void *ptr) { if (ptr == NULL) - log_fatalx("xfree: null pointer"); + fatalx("null pointer"); free(ptr); + +#ifdef DEBUG + xmalloc_free(ptr); +#endif } int printflike2 @@ -156,10 +165,12 @@ xvasprintf(char **ret, const char *fmt, va_list ap) int i; i = vasprintf(ret, fmt, ap); - if (i < 0 || *ret == NULL) - log_fatal("xvasprintf"); + fatal("xvasprintf failed"); +#ifdef DEBUG + xmalloc_new(xmalloc_caller(), *ret, i + 1); +#endif return (i); } @@ -181,53 +192,24 @@ xvsnprintf(char *buf, size_t len, const char *fmt, va_list ap) { int i; - if (len > INT_MAX) { - errno = EINVAL; - log_fatal("xvsnprintf"); - } + if (len > INT_MAX) + fatalx("len > INT_MAX"); i = vsnprintf(buf, len, fmt, ap); - if (i < 0) - log_fatal("xvsnprintf"); + fatal("vsnprintf failed"); return (i); } /* - * Print a path. Same as xsnprintf, but return ENAMETOOLONG on truncation. - */ -int printflike3 -printpath(char *buf, size_t len, const char *fmt, ...) -{ - va_list ap; - int n; - - if (len > INT_MAX) { - errno = ENAMETOOLONG; - return (1); - } - - va_start(ap, fmt); - n = xvsnprintf(buf, len, fmt, ap); - va_end(ap); - - if ((size_t) n > len) { - errno = ENAMETOOLONG; - return (1); - } - - return (0); -} - -/* - * Some system modify the path in place. This function and xbasename below + * Some systems modify the path in place. This function and xbasename below * avoid that by using a temporary buffer. */ char * xdirname(const char *src) { - char dst[MAXPATHLEN]; + static char dst[MAXPATHLEN]; strlcpy(dst, src, sizeof dst); return (dirname(dst)); @@ -236,7 +218,7 @@ xdirname(const char *src) char * xbasename(const char *src) { - char dst[MAXPATHLEN]; + static char dst[MAXPATHLEN]; strlcpy(dst, src, sizeof dst); return (basename(dst));