diff --git a/server/include/file.h b/server/include/file.h index 8c54684b8..c6bfd458b 100644 --- a/server/include/file.h +++ b/server/include/file.h @@ -52,7 +52,7 @@ int file_init(int argc, char *argv[], struct settings *set); int file_deinit(); /** @see node_vtable::print */ -int file_print(struct node *n, char *buf, int len); +char * file_print(struct node *n); /** @see node_vtable::parse */ int file_parse(config_setting_t *cfg, struct node *n); diff --git a/server/include/gtfpga.h b/server/include/gtfpga.h index 5f863a49b..fe20a4192 100644 --- a/server/include/gtfpga.h +++ b/server/include/gtfpga.h @@ -60,7 +60,7 @@ int gtfpga_deinit(); int gtfpga_parse(config_setting_t *cfg, struct node *n); /** @see node_vtable::print */ -int gtfpga_print(struct node *n, char *buf, int len); +char * gtfpga_print(struct node *n); /** @see node_vtable::open */ int gtfpga_open(struct node *n); diff --git a/server/include/hist.h b/server/include/hist.h index 92081cbe9..e1bbdfdcb 100644 --- a/server/include/hist.h +++ b/server/include/hist.h @@ -78,8 +78,11 @@ void hist_print(struct hist *h); /** Print ASCII style plot of histogram */ void hist_plot(struct hist *h); -/** Dump histogram data in Matlab format to buf */ -void hist_dump(struct hist *h, char *buf, int len); +/** Dump histogram data in Matlab format. + * + * @return The string containing the dump. The caller is responsible to free() the buffer. + */ +char * hist_dump(struct hist *h); /** Prints Matlab struct containing all infos to file. */ void hist_matlab(struct hist *h, FILE *f); diff --git a/server/include/ngsi.h b/server/include/ngsi.h index fceb4e2d4..58c13f23c 100644 --- a/server/include/ngsi.h +++ b/server/include/ngsi.h @@ -66,7 +66,7 @@ int ngsi_deinit(); int ngsi_parse(config_setting_t *cfg, struct node *n); /** @see node_vtable::print */ -int ngsi_print(struct node *n, char *buf, int len); +char * ngsi_print(struct node *n); /** @see node_vtable::open */ int ngsi_open(struct node *n); diff --git a/server/include/node.h b/server/include/node.h index 733bd1395..3fb94a8da 100644 --- a/server/include/node.h +++ b/server/include/node.h @@ -28,7 +28,7 @@ /* Helper macros for virtual node type */ #define node_type(n) ((n)->vt->type) -#define node_print(n, b, l) ((n)->vt->print(n, b, l)) +#define node_print(n) ((n)->vt->print(n)) #define node_read(n, p, ps, f, c) ((n)->vt->read(n, p, ps, f, c)) #define node_write(n, p, ps, f, c) ((n)->vt->write(n, p, ps, f, c)) @@ -74,14 +74,12 @@ struct node_type { */ int (*parse)(config_setting_t *cfg, struct node *n); - /** Print details of socket connection + /** Returns a string with a textual represenation of this node. * * @param n A pointer to the node structure - * @param buf The character buffer to be filled. - * @param len The length of the supplied buffer. - * @return The length of the address. + * @return A pointer to a dynamically allocated string. Must be freed(). */ - int (*print)(struct node *n, char *buf, int len); + char * (*print)(struct node *n); /** Create new socket and connect(), bind(), accept(). * diff --git a/server/include/opal.h b/server/include/opal.h index 842618fb1..88994c8e1 100644 --- a/server/include/opal.h +++ b/server/include/opal.h @@ -77,7 +77,7 @@ int opal_deinit(); int opal_parse(config_setting_t *cfg, struct node *n); /** @see node_vtable::print */ -int opal_print(struct node *n, char *buf, int len); +char * opal_print(struct node *n); int opal_print_global(struct opal_global *g); diff --git a/server/include/path.h b/server/include/path.h index 5d1a80601..bf9e918d2 100644 --- a/server/include/path.h +++ b/server/include/path.h @@ -138,10 +138,9 @@ void path_print_stats(struct path *p); * Format: source => [ dest1 dest2 dest3 ] * * @param p A pointer to the path structure. - * @param buf A pointer to the buffer which should be filled. - * @param len The length of buf in bytes. + * @return A pointer to a string containing a textual representation of the path. */ -int path_print(struct path *p, char *buf, int len); +char * path_print(struct path *p); /** Conditionally execute the hooks * diff --git a/server/include/socket.h b/server/include/socket.h index 370f483ac..ee8cb65e7 100644 --- a/server/include/socket.h +++ b/server/include/socket.h @@ -81,19 +81,17 @@ int socket_read(struct node *n, struct msg *pool, int poolsize, int first, int c int socket_parse(config_setting_t *cfg, struct node *n); /** @see node_vtable::print */ -int socket_print(struct node *n, char *buf, int len); +char * socket_print(struct node *n); /** Generate printable socket address depending on the address family * * A IPv4 address is formatted as dotted decimals followed by the port/protocol number * A link layer address is formatted in hexadecimals digits seperated by colons and the inferface name * - * @param buf A buffer to be filled. - * @param len The length of the supplied buffer. * @param sa A pointer to the socket address. - * @retur The length of the address in bytes. + * @return The buffer containing the textual representation of the address. The caller is responsible to free() this buffer! */ -int socket_print_addr(char *buf, int len, struct sockaddr *sa); +char * socket_print_addr(struct sockaddr *saddr); /** Parse a socket address depending on the address family * diff --git a/server/include/tc.h b/server/include/tc.h index a5b460154..0896331f4 100644 --- a/server/include/tc.h +++ b/server/include/tc.h @@ -37,13 +37,10 @@ int tc_parse(config_setting_t *cfg, struct rtnl_qdisc **ne); /** Print network emulator (netem) setting into buffer. * - * @param buf A character buffer to write to. - * @param len The length of the supplied buffer. * @param tc A pointer to the libnl3 qdisc object where settings will be read from. - * @retval 0 Success. Everything went well. - * @retval <0 Error. Something went wrong. + * @return A pointer to a string which must be freed() by the caller. */ -int tc_print(char *buf, size_t len, struct rtnl_qdisc *ne); +char * tc_print(struct rtnl_qdisc *ne); /** Remove all queuing disciplines and filters. * diff --git a/server/include/utils.h b/server/include/utils.h index 2b1d53be9..c9c6fa763 100644 --- a/server/include/utils.h +++ b/server/include/utils.h @@ -84,14 +84,22 @@ double box_muller(float m, float s); /** Double precission uniform random variable */ double randf(); -/** Safely append a format string to an existing string. +/** Concat formatted string to an existing string. * - * This function is similar to strlcat() from BSD. + * This function uses realloc() to resize the destination. + * Please make sure to only on dynamic allocated destionations!!! + * + * @param dest A pointer to a malloc() allocated memory region + * @param fmt A format string like for printf() + * @param ... Optional parameters like for printf() + * @retval The the new value of the dest buffer. */ -int strap(char *dest, size_t size, const char *fmt, ...); +char * strcatf(char **dest, const char *fmt, ...) + __attribute__ ((format(printf, 2, 3))); -/** Variadic version of strap() */ -int vstrap(char *dest, size_t size, const char *fmt, va_list va); +/** Variadic version of strcatv() */ +char * vstrcatf(char **dest, const char *fmt, va_list va) + __attribute__ ((format(printf, 2, 0))); /** Convert integer to cpu_set_t. * diff --git a/server/src/cfg.c b/server/src/cfg.c index 992678d23..a16d9a227 100644 --- a/server/src/cfg.c +++ b/server/src/cfg.c @@ -168,10 +168,10 @@ int config_parse_path(config_setting_t *cfg, list_push(paths, p); } else { - char buf[128]; - path_print(p, buf, sizeof(buf)); - + char *buf = path_print(p); warn("Path %s is not enabled", buf); + free(buf); + path_destroy(p); } diff --git a/server/src/file.c b/server/src/file.c index 4ac657680..d25028c97 100644 --- a/server/src/file.c +++ b/server/src/file.c @@ -26,11 +26,12 @@ int file_deinit() return 0; /* nothing todo here */ } -int file_print(struct node *n, char *buf, int len) +char * file_print(struct node *n) { struct file *f = n->file; + char *buf = NULL; - return snprintf(buf, len, "in=%s, out=%s, mode=%s, rate=%.1f, epoch_mode=%u, epoch=%.0f", + return strcatf(&buf, "in=%s, out=%s, mode=%s, rate=%.1f, epoch_mode=%u, epoch=%.0f", f->path_in, f->path_out, f->file_mode, f->rate, f->epoch_mode, time_to_double(&f->epoch)); } diff --git a/server/src/gtfpga.c b/server/src/gtfpga.c index 105490dd7..e6b9b4ac8 100644 --- a/server/src/gtfpga.c +++ b/server/src/gtfpga.c @@ -100,18 +100,19 @@ int gtfpga_parse(config_setting_t *cfg, struct node *n) return 0; } -int gtfpga_print(struct node *n, char *buf, int len) +char * gtfpga_print(struct node *n) { struct gtfpga *g = n->gtfpga; + char *buf = NULL; if (g->dev) { - return snprintf(buf, len, "rate=%.1f slot=%04"PRIx16":%02"PRIx8":%02"PRIx8".%"PRIx8 + return strcatf(&buf, "rate=%.1f slot=%04"PRIx16":%02"PRIx8":%02"PRIx8".%"PRIx8 " id=%04"PRIx16":%04"PRIx16" class=%04"PRIx16" irq=%d (%s)", g->rate, g->dev->domain, g->dev->bus, g->dev->dev, g->dev->func, g->dev->vendor_id, g->dev->device_id, g->dev->device_class, g->dev->irq, g->name); } else { - return snprintf(buf, len, "rate=%.1f slot=%02"PRIx8":%02"PRIx8".%"PRIx8" id=%04"PRIx16":%04"PRIx16, g->rate, + return strcatf(&buf, "rate=%.1f slot=%02"PRIx8":%02"PRIx8".%"PRIx8" id=%04"PRIx16":%04"PRIx16, g->rate, g->filter.bus, g->filter.device, g->filter.func, g->filter.vendor, g->filter.device); } diff --git a/server/src/hist.c b/server/src/hist.c index 672b1d1dd..9d8cb9a76 100644 --- a/server/src/hist.c +++ b/server/src/hist.c @@ -115,9 +115,9 @@ void hist_print(struct hist *h) if (h->total - h->higher - h->lower > 0) { hist_plot(h); - char buf[(h->length + 1) * 8]; - hist_dump(h, buf, sizeof(buf)); + char *buf = hist_dump(h); info(buf); + free(buf); } } @@ -145,22 +145,23 @@ void hist_plot(struct hist *h) } } -void hist_dump(struct hist *h, char *buf, int len) +char * hist_dump(struct hist *h) { - *buf = 0; - - strap(buf, len, "[ "); + char *buf = alloc(128); + + strcatf(&buf, "[ "); for (int i = 0; i < h->length; i++) - strap(buf, len, "%u ", h->data[i]); + strcatf(&buf, "%u ", h->data[i]); - strap(buf, len, "]"); + strcatf(&buf, "]"); + + return buf; } void hist_matlab(struct hist *h, FILE *f) { - char buf[h->length * 8]; - hist_dump(h, buf, sizeof(buf)); + char *buf = hist_dump(h); fprintf(f, "%lu = struct( ", time(NULL)); fprintf(f, "'min', %f, 'max', %f, ", h->low, h->high); @@ -171,4 +172,6 @@ void hist_matlab(struct hist *h, FILE *f) fprintf(f, "'stddev', %f, ", hist_stddev(h)); fprintf(f, "'hist', %s ", buf); fprintf(f, "),\n"); + + free(buf); } diff --git a/server/src/hooks.c b/server/src/hooks.c index 986e09028..733d2ba9b 100644 --- a/server/src/hooks.c +++ b/server/src/hooks.c @@ -107,12 +107,12 @@ int hook_restart(struct path *p) { if (p->current->sequence == 0 && p->previous->sequence <= UINT32_MAX - 32) { - char buf[33]; - path_print(p, buf, sizeof(buf)); + char *buf = path_print(p); warn("Simulation for path %s restarted (prev->seq=%u, current->seq=%u)", buf, p->previous->sequence, p->current->sequence); + free(buf); - path_reset(p); + path_reset(p); } return 0; diff --git a/server/src/if.c b/server/src/if.c index 60f89fd1d..03687a793 100644 --- a/server/src/if.c +++ b/server/src/if.c @@ -93,10 +93,10 @@ int if_start(struct interface *i, int affinity) if (ret) error("Failed to setup FW mark classifier: %s", nl_geterror(ret)); - char buf[256]; - tc_print(buf, sizeof(buf), s->tc_qdisc); + char *buf = tc_print(s->tc_qdisc); debug(5, "Starting network emulation on interface '%s' for FW mark %u: %s", rtnl_link_get_name(i->nl_link), s->mark, buf); + free(buf); ret = tc_netem(i, &s->tc_qdisc, TC_HANDLE(0x1000+s->mark, 0), TC_HANDLE(1, s->mark)); if (ret) diff --git a/server/src/log.c b/server/src/log.c index 4a7b96073..015a9388d 100644 --- a/server/src/log.c +++ b/server/src/log.c @@ -71,30 +71,32 @@ void log_print(const char *lvl, const char *fmt, ...) void log_vprint(const char *lvl, const char *fmt, va_list ap) { struct timespec ts; - char buf[512] = ""; - + char *buf = alloc(512); + /* Timestamp */ clock_gettime(CLOCK_REALTIME, &ts); - strap(buf, sizeof(buf), "%10.3f ", time_delta(&epoch, &ts)); + strcatf(&buf, "%10.3f ", time_delta(&epoch, &ts)); /* Severity */ - strap(buf, sizeof(buf), BLD("%5s "), lvl); + strcatf(&buf, "%5s ", lvl); /* Indention */ #ifdef __GNUC__ for (int i = 0; i < indent; i++) - strap(buf, sizeof(buf), ACS_VERTICAL " "); - strap(buf, sizeof(buf), ACS_VERTRIGHT " "); + strcatf(&buf, ACS_VERTICAL " "); + + strcatf(&buf, ACS_VERTRIGHT " "); #endif /* Format String */ - vstrap(buf, sizeof(buf), fmt, ap); + vstrcatf(&buf, fmt, ap); /* Output */ #ifdef ENABLE_OPAL_ASYNC OpalPrint("S2SS: %s\n", buf); #endif fprintf(stderr, "\r%s\n", buf); + free(buf); } void line() @@ -148,23 +150,25 @@ void error(const char *fmt, ...) void serror(const char *fmt, ...) { va_list ap; - char buf[1024]; + char *buf = NULL; va_start(ap, fmt); - vsnprintf(buf, sizeof(buf), fmt, ap); + vstrcatf(&buf, fmt, ap); va_end(ap); log_print(ERROR, "%s: %m (%u)", buf, errno); + + free(buf); die(); } void cerror(config_setting_t *cfg, const char *fmt, ...) { va_list ap; - char buf[1024]; + char *buf = NULL; va_start(ap, fmt); - vsnprintf(buf, sizeof(buf), fmt, ap); + vstrcatf(&buf, fmt, ap); va_end(ap); log_print(ERROR, "%s in %s:%u", buf, @@ -172,5 +176,7 @@ void cerror(config_setting_t *cfg, const char *fmt, ...) ? config_setting_source_file(cfg) : "(stdio)", config_setting_source_line(cfg)); + + free(buf); die(); } diff --git a/server/src/ngsi.c b/server/src/ngsi.c index 4f28a6643..83e1d27d3 100644 --- a/server/src/ngsi.c +++ b/server/src/ngsi.c @@ -235,11 +235,12 @@ int ngsi_parse(config_setting_t *cfg, struct node *n) return 0; } -int ngsi_print(struct node *n, char *buf, int len) +char * ngsi_print(struct node *n) { struct ngsi *i = n->ngsi; - - return snprintf(buf, len, "endpoint=%s, timeout=%.3f secs", + char *buf = NULL; + + return strcatf(&buf, "endpoint=%s, timeout=%.3f secs", i->endpoint, i->timeout); } diff --git a/server/src/node.c b/server/src/node.c index 745ab1152..034ac2d61 100644 --- a/server/src/node.c +++ b/server/src/node.c @@ -66,10 +66,9 @@ int node_start(struct node *n) return -1; } - char str[256]; - node_print(n, str, sizeof(str)); - - debug(1, "Starting node '%s' of type '%s' (%s)", n->name, n->vt->name, str); + char *buf = node_print(n); + debug(1, "Starting node '%s' of type '%s' (%s)", n->name, n->vt->name, buf); + free(buf); { INDENT return n->vt->open(n); diff --git a/server/src/opal.c b/server/src/opal.c index 9405fd00a..5304a2b79 100644 --- a/server/src/opal.c +++ b/server/src/opal.c @@ -104,17 +104,21 @@ int opal_deinit() int opal_print_global(struct opal_global *g) { INDENT - char sbuf[512] = ""; - char rbuf[512] = ""; + debug(2, "Controller ID: %u", og->params.controllerID); + + char *sbuf = alloc(og->send_icons * 5); + char *rbuf = alloc(og->recv_icons * 5); for (int i = 0; i < og->send_icons; i++) - strap(sbuf, sizeof(sbuf), "%u ", og->send_ids[i]); + strcatf(&sbuf, "%u ", og->send_ids[i]); for (int i = 0; i < og->recv_icons; i++) - strap(rbuf, sizeof(rbuf), "%u ", og->recv_ids[i]); + strcatf(&rbuf, "%u ", og->recv_ids[i]); - debug(2, "Controller ID: %u", og->params.controllerID); debug(2, "Send Blocks: %s", sbuf); debug(2, "Receive Blocks: %s", rbuf); + + free(sbuf); + free(rbuf); debug(2, "Control Block Parameters:"); for (int i=0; iopal; + char *buf = NULL; /** @todo: Print send_params, recv_params */ - return snprintf(buf, len, "send_id=%u, recv_id=%u, reply=%u", + return strcatf(&buf, "send_id=%u, recv_id=%u, reply=%u", o->send_id, o->recv_id, o->reply); } diff --git a/server/src/path.c b/server/src/path.c index 0d764bca5..2143d68b3 100644 --- a/server/src/path.c +++ b/server/src/path.c @@ -115,10 +115,9 @@ static void * path_run(void *arg) int path_start(struct path *p) { INDENT - char buf[33]; - path_print(p, buf, sizeof(buf)); - + char *buf = path_print(p); info("Starting path: %s (poolsize = %u)", buf, p->poolsize); + free(buf); if (path_run_hook(p, HOOK_PATH_START)) return -1; @@ -145,10 +144,9 @@ int path_start(struct path *p) int path_stop(struct path *p) { INDENT - char buf[33]; - path_print(p, buf, sizeof(buf)); - + char *buf = path_print(p); info("Stopping path: %s", buf); + free(buf); pthread_cancel(p->recv_tid); pthread_join(p->recv_tid, NULL); @@ -166,22 +164,22 @@ int path_stop(struct path *p) return 0; } -int path_print(struct path *p, char *buf, int len) +char * path_print(struct path *p) { - *buf = 0; - - strap(buf, len, "%s " MAG("=>"), p->in->name); + char *buf = alloc(32); + + strcatf(&buf, "%s " MAG("=>"), p->in->name); if (list_length(&p->destinations) > 1) { - strap(buf, len, " ["); + strcatf(&buf, " ["); FOREACH(&p->destinations, it) - strap(buf, len, " %s", it->node->name); - strap(buf, len, " ]"); + strcatf(&buf, " %s", it->node->name); + strcatf(&buf, " ]"); } else - strap(buf, len, " %s", p->out->name); + strcatf(&buf, " %s", p->out->name); - return 0; + return buf; } int path_reset(struct path *p) diff --git a/server/src/socket.c b/server/src/socket.c index ba864a746..1f39afa88 100644 --- a/server/src/socket.c +++ b/server/src/socket.c @@ -49,9 +49,9 @@ int socket_init(int argc, char * argv[], struct settings *set) /* Determine outgoing interface */ if (if_get_egress((struct sockaddr *) &s->remote, &link)) { - char buf[128]; - socket_print_addr(buf, sizeof(buf), (struct sockaddr *) &s->remote); + char *buf = socket_print_addr((struct sockaddr *) &s->remote); error("Failed to get interface for socket address '%s'", buf); + free(buf); } int ifindex = rtnl_link_get_ifindex(link); @@ -79,24 +79,26 @@ int socket_deinit() return 0; } -int socket_print(struct node *n, char *buf, int len) +char * socket_print(struct node *n) { struct socket *s = n->socket; - - char local[INET6_ADDRSTRLEN + 16]; - char remote[INET6_ADDRSTRLEN + 16]; - char *layer = NULL; + char *layer = NULL, *buf = NULL; switch (s->layer) { - case LAYER_UDP: layer = "udp"; break; - case LAYER_IP: layer = "ip"; break; - case LAYER_ETH: layer = "eth"; break; + case LAYER_UDP: layer = "udp"; break; + case LAYER_IP: layer = "ip"; break; + case LAYER_ETH: layer = "eth"; break; } - socket_print_addr(local, sizeof(local), (struct sockaddr *) &s->local); - socket_print_addr(remote, sizeof(remote), (struct sockaddr *) &s->remote); + char *local = socket_print_addr((struct sockaddr *) &s->local); + char *remote = socket_print_addr((struct sockaddr *) &s->remote); - return snprintf(buf, len, "layer=%s, local=%s, remote=%s", layer, local, remote); + strcatf(&buf, "layer=%s, local=%s, remote=%s", layer, local, remote); + + free(local); + free(remote); + + return buf; } int socket_open(struct node *n) @@ -319,24 +321,25 @@ int socket_parse(config_setting_t *cfg, struct node *n) return 0; } -int socket_print_addr(char *buf, int len, struct sockaddr *saddr) +char * socket_print_addr(struct sockaddr *saddr) { union sockaddr_union *sa = (union sockaddr_union *) saddr; + char *buf = alloc(64); /* Address */ switch (sa->sa.sa_family) { case AF_INET6: - inet_ntop(AF_INET6, &sa->sin6.sin6_addr, buf, len); + inet_ntop(AF_INET6, &sa->sin6.sin6_addr, buf, 64); break; case AF_INET: - inet_ntop(AF_INET, &sa->sin.sin_addr, buf, len); + inet_ntop(AF_INET, &sa->sin.sin_addr, buf, 64); break; case AF_PACKET: - snprintf(buf, len, "%02x", sa->sll.sll_addr[0]); + strcatf(&buf, "%02x", sa->sll.sll_addr[0]); for (int i = 1; i < sa->sll.sll_halen; i++) - strap(buf, len, ":%02x", sa->sll.sll_addr[i]); + strcatf(&buf, ":%02x", sa->sll.sll_addr[i]); break; default: @@ -347,7 +350,7 @@ int socket_print_addr(char *buf, int len, struct sockaddr *saddr) switch (sa->sa.sa_family) { case AF_INET6: case AF_INET: - strap(buf, len, ":%hu", ntohs(sa->sin.sin_port)); + strcatf(&buf, ":%hu", ntohs(sa->sin.sin_port)); break; case AF_PACKET: { @@ -356,13 +359,13 @@ int socket_print_addr(char *buf, int len, struct sockaddr *saddr) if (!link) error("Failed to get interface for index: %u", sa->sll.sll_ifindex); - strap(buf, len, "%%%s", rtnl_link_get_name(link)); - strap(buf, len, ":%hu", ntohs(sa->sll.sll_protocol)); + strcatf(&buf, "%%%s", rtnl_link_get_name(link)); + strcatf(&buf, ":%hu", ntohs(sa->sll.sll_protocol)); break; } } - return 0; + return buf; } int socket_parse_addr(const char *addr, struct sockaddr *saddr, enum socket_layer layer, int flags) diff --git a/server/src/stats.c b/server/src/stats.c index a06b125ea..7bb2b84dc 100644 --- a/server/src/stats.c +++ b/server/src/stats.c @@ -21,11 +21,9 @@ void stats_header() int stats_line(struct path *p) { - char buf[33]; - path_print(p, buf, sizeof(buf)); - - info("%-32s : %-8u %-8u %-8u %-8u %-8u", buf, - p->sent, p->received, p->dropped, p->skipped, p->invalid); + char *buf = path_print(p); + info("%-32s : %-8u %-8u %-8u %-8u %-8u", buf, p->sent, p->received, p->dropped, p->skipped, p->invalid); + free(buf); return 0; } diff --git a/server/src/tc.c b/server/src/tc.c index 5f2863d8c..2187daf98 100644 --- a/server/src/tc.c +++ b/server/src/tc.c @@ -84,53 +84,53 @@ int tc_parse(config_setting_t *cfg, struct rtnl_qdisc **netem) return 0; } -int tc_print(char *buf, size_t len, struct rtnl_qdisc *ne) +char * tc_print(struct rtnl_qdisc *ne) { - *buf = 0; /* start from the beginning */ - + char *buf = NULL; + if (rtnl_netem_get_limit(ne) > 0) - strap(buf, len, "limit %upkts", rtnl_netem_get_limit(ne)); + strcatf(&buf, "limit %upkts", rtnl_netem_get_limit(ne)); if (rtnl_netem_get_delay(ne) > 0) { - strap(buf, len, "delay %.2fms ", rtnl_netem_get_delay(ne) / 1000.0); + strcatf(&buf, "delay %.2fms ", rtnl_netem_get_delay(ne) / 1000.0); if (rtnl_netem_get_jitter(ne) > 0) { - strap(buf, len, "jitter %.2fms ", rtnl_netem_get_jitter(ne) / 1000.0); + strcatf(&buf, "jitter %.2fms ", rtnl_netem_get_jitter(ne) / 1000.0); if (rtnl_netem_get_delay_correlation(ne) > 0) - strap(buf, len, "%u%% ", rtnl_netem_get_delay_correlation(ne)); + strcatf(&buf, "%u%% ", rtnl_netem_get_delay_correlation(ne)); } } if (rtnl_netem_get_loss(ne) > 0) { - strap(buf, len, "loss %u%% ", rtnl_netem_get_loss(ne)); + strcatf(&buf, "loss %u%% ", rtnl_netem_get_loss(ne)); if (rtnl_netem_get_loss_correlation(ne) > 0) - strap(buf, len, "%u%% ", rtnl_netem_get_loss_correlation(ne)); + strcatf(&buf, "%u%% ", rtnl_netem_get_loss_correlation(ne)); } if (rtnl_netem_get_reorder_probability(ne) > 0) { - strap(buf, len, " reorder%u%% ", rtnl_netem_get_reorder_probability(ne)); + strcatf(&buf, " reorder%u%% ", rtnl_netem_get_reorder_probability(ne)); if (rtnl_netem_get_reorder_correlation(ne) > 0) - strap(buf, len, "%u%% ", rtnl_netem_get_reorder_correlation(ne)); + strcatf(&buf, "%u%% ", rtnl_netem_get_reorder_correlation(ne)); } if (rtnl_netem_get_corruption_probability(ne) > 0) { - strap(buf, len, "corruption %u%% ", rtnl_netem_get_corruption_probability(ne)); + strcatf(&buf, "corruption %u%% ", rtnl_netem_get_corruption_probability(ne)); if (rtnl_netem_get_corruption_correlation(ne) > 0) - strap(buf, len, "%u%% ", rtnl_netem_get_corruption_correlation(ne)); + strcatf(&buf, "%u%% ", rtnl_netem_get_corruption_correlation(ne)); } if (rtnl_netem_get_duplicate(ne) > 0) { - strap(buf, len, "duplication %u%% ", rtnl_netem_get_duplicate(ne)); + strcatf(&buf, "duplication %u%% ", rtnl_netem_get_duplicate(ne)); if (rtnl_netem_get_duplicate_correlation(ne) > 0) - strap(buf, len, "%u%% ", rtnl_netem_get_duplicate_correlation(ne)); + strcatf(&buf, "%u%% ", rtnl_netem_get_duplicate_correlation(ne)); } - return 0; + return buf; } int tc_prio(struct interface *i, struct rtnl_qdisc **qd, tc_hdl_t handle, tc_hdl_t parent, int bands) diff --git a/server/src/utils.c b/server/src/utils.c index 9ff54159f..431c56c3c 100644 --- a/server/src/utils.c +++ b/server/src/utils.c @@ -76,23 +76,29 @@ void die() pthread_kill(_mtid, SIGINT); } -int strap(char *dest, size_t size, const char *fmt, ...) +char * strcatf(char **dest, const char *fmt, ...) { - int ret; - va_list ap; va_start(ap, fmt); - ret = vstrap(dest, size, fmt, ap); + vstrcatf(dest, fmt, ap); va_end(ap); - return ret; + return *dest; } -int vstrap(char *dest, size_t size, const char *fmt, va_list ap) +char * vstrcatf(char **dest, const char *fmt, va_list ap) { - int len = strlen(dest); + char *tmp; + int n = *dest ? strlen(*dest) : 0; + int i = vasprintf(&tmp, fmt, ap); - return vsnprintf(dest + len, size - len, fmt, ap); + *dest = (char *)(realloc(*dest, n + i + 1)); + if (*dest != NULL) + strncpy(*dest+n, tmp, i + 1); + + free(tmp); + + return *dest; } cpu_set_t to_cpu_set(int set)