From: Roger Wolff Date: Fri, 19 Sep 2008 00:00:00 +0000 (+0000) Subject: mtr v0.75 X-Git-Tag: v0.75^0 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ae6cb801f130aad5ce79d5c7317aa3d927f390dc;p=thirdparty%2Fmtr.git mtr v0.75 - Feelgood patch to move sprintf to snprintf. People might think that sprintf might cause a buffer overflow. Now it's clean. cut-paste patches: you can now copy an intermediate host to the clipboard. source: ftp://ftp.bitwizard.nl/mtr/mtr-0.75.tar.gz --- diff --git a/Makefile.am b/Makefile.am index d02920f..3e60cdb 100644 --- a/Makefile.am +++ b/Makefile.am @@ -23,7 +23,7 @@ mtr_LDFLAGS = $(GTK_OBJ) $(CURSES_OBJ) EXTRA_DIST = SECURITY mtr.8 Makefile Makefile.dist distclean-local: - cp Makefile.dist Makefile + (sleep 3; cp Makefile.dist Makefile) & rm -f *.orig DISTCLEANFILES = *~ diff --git a/Makefile.dist b/Makefile.dist index 99680ad..a0ea2d1 100644 --- a/Makefile.dist +++ b/Makefile.dist @@ -4,7 +4,7 @@ # firstrule: - ./configure + ./configure $(MAKE) clean: diff --git a/NEWS b/NEWS index 58de1fb..f4e92dd 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,8 @@ WHAT'S NEW? + v0.75 Feelgood patch to move sprintf to snprintf. People might think + that sprintf might cause a buffer overflow. Now it's clean. + cut-paste patches: you can now copy an intermediate host to the + clipboard. v0.74 Martin Pels' patch to allow UDP probes. KES reported a build problem. Turns out I need to install gtk-1.2 on my development sytem, otherwise my release script causes the diff --git a/TODO b/TODO index ffc0ca3..0673b24 100644 --- a/TODO +++ b/TODO @@ -41,6 +41,14 @@ Oh, Feel free to provide suggestions for this list. - Keep all packets and make the "best" and "worst" columns show the xx-th percentile.... + - Can the reports generated also include any secondary servers? In + the interactive mode, any new servers that are found in the + traceroute are added to the list, but it seems to only include + one set of servers when using the -r option. + + - Being able to expand the "column width" of the hosts listed would + be nice, too. + - Bugs to fix? diff --git a/configure.in b/configure.in index b9b23f8..d73e994 100644 --- a/configure.in +++ b/configure.in @@ -1,5 +1,5 @@ AC_INIT(mtr.c) -AM_INIT_AUTOMAKE(mtr, 0.74) +AM_INIT_AUTOMAKE(mtr, 0.75) AC_SUBST(GTK_OBJ) @@ -15,6 +15,9 @@ AC_CHECK_SIZEOF(unsigned short, 2) AC_CHECK_SIZEOF(unsigned int, 4) AC_CHECK_SIZEOF(unsigned long, 4) +AC_CHECK_HEADERS(ncurses.h ncurses/curses.h curses.h cursesX.h sys/types.h fcntl.h) +AC_CHECK_HEADERS(sys/xti.h) + # Some doc I found somewhere. :-) -- REW # - Macro: AC_CHECK_FUNC (FUNCTION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) # - Macro: AC_CHECK_LIB (LIBRARY, FUNCTION [, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND [, OTHER-LIBRARIES]]]) @@ -32,11 +35,7 @@ AC_CHECK_FUNC(initscr, , AC_DEFINE(NO_CURSES, 1, Define if you don't have the curses libraries available.) CURSES_OBJ=)))) -AC_CHECK_FUNCS(attron) - - -AC_CHECK_HEADERS(ncurses.h ncurses/curses.h curses.h cursesX.h sys/types.h) -AC_CHECK_HEADERS(sys/xti.h) +AC_CHECK_FUNCS(attron fcntl) AC_CHECK_LIB(m, floor, , AC_MSG_ERROR(No math library found)) diff --git a/dns.c b/dns.c index 70ad17f..d33df81 100644 --- a/dns.c +++ b/dns.c @@ -893,7 +893,7 @@ void resendrequest(struct resolve *rp,int type) if (type == T_A) { dorequest(rp->hostname,type,rp->id); if (debug) { - sprintf(tempstring,"Resolver: Sent reverse authentication request for \"%s\".", + snprintf(tempstring, sizeof(tempstring), "Resolver: Sent reverse authentication request for \"%s\".", rp->hostname); restell(tempstring); } @@ -914,7 +914,7 @@ void resendrequest(struct resolve *rp,int type) } dorequest(tempstring,type,rp->id); if (debug) { - sprintf(tempstring,"Resolver: Sent domain lookup request for \"%s\".", + snprintf(tempstring, sizeof(tempstring), "Resolver: Sent domain lookup request for \"%s\".", strlongip( &(rp->ip) )); restell(tempstring); } @@ -950,7 +950,7 @@ void passrp(struct resolve *rp,long ttl) rp->expiretime = sweeptime + (double)ttl; untieresolve(rp); if (debug) { - sprintf(tempstring,"Resolver: Lookup successful: %s\n",rp->hostname); + snprintf(tempstring, sizeof(tempstring), "Resolver: Lookup successful: %s\n",rp->hostname); restell(tempstring); } } @@ -1007,7 +1007,7 @@ void parserespacket(byte *s, int l) case NOERROR: if (hp->ancount) { if (debug) { - sprintf(tempstring,"Resolver: Received nameserver reply. (qd:%u an:%u ns:%u ar:%u)", + snprintf(tempstring, sizeof(tempstring), "Resolver: Received nameserver reply. (qd:%u an:%u ns:%u ar:%u)", hp->qdcount,hp->ancount,hp->nscount,hp->arcount); restell(tempstring); } @@ -1047,14 +1047,14 @@ void parserespacket(byte *s, int l) namestring[strlen(stackstring)] = '\0'; if (strcasecmp(stackstring,namestring)) { if (debug) { - sprintf(tempstring,"Resolver: Unknown query packet dropped. (\"%s\" does not match \"%s\")", + snprintf(tempstring, sizeof(tempstring), "Resolver: Unknown query packet dropped. (\"%s\" does not match \"%s\")", stackstring,namestring); restell(tempstring); } return; } if (debug) { - sprintf(tempstring,"Resolver: Queried domain name: \"%s\"",namestring); + snprintf(tempstring, sizeof(tempstring), "Resolver: Queried domain name: \"%s\"",namestring); restell(tempstring); } c+= r; @@ -1065,7 +1065,7 @@ void parserespacket(byte *s, int l) qdatatype = sucknetword(c); qclass = sucknetword(c); if (qclass != C_IN) { - sprintf(tempstring,"Resolver error: Received unsupported query class: %u (%s)", + snprintf(tempstring, sizeof(tempstring), "Resolver error: Received unsupported query class: %u (%s)", qclass,qclass < ClasstypeCount ? classtypes[qclass] : classtypes[ClasstypeCount]); restell(tempstring); @@ -1079,7 +1079,7 @@ void parserespacket(byte *s, int l) } break; default: - sprintf(tempstring,"Resolver error: Received unimplemented query type: %u (%s)", + snprintf(tempstring, sizeof(tempstring), "Resolver error: Received unimplemented query type: %u (%s)", qdatatype,qdatatype < ResourcetypeCount ? resourcetypes[qdatatype] : resourcetypes[ResourcetypeCount]); restell(tempstring); @@ -1101,7 +1101,7 @@ void parserespacket(byte *s, int l) else usefulanswer = 1; if (debug) { - sprintf(tempstring,"Resolver: answered domain query: \"%s\"",namestring); + snprintf(tempstring, sizeof(tempstring), "Resolver: answered domain query: \"%s\"",namestring); restell(tempstring); } c+= r; @@ -1114,10 +1114,10 @@ void parserespacket(byte *s, int l) ttl = sucknetlong(c); rdatalength = sucknetword(c); if (class != qclass) { - sprintf(tempstring,"query class: %u (%s)",qclass,qclass < ClasstypeCount ? + snprintf(tempstring, sizeof(tempstring), "query class: %u (%s)",qclass,qclass < ClasstypeCount ? classtypes[qclass] : classtypes[ClasstypeCount]); restell(tempstring); - sprintf(tempstring,"rr class: %u (%s)",class,class < ClasstypeCount ? + snprintf(tempstring, sizeof(tempstring), "rr class: %u (%s)",class,class < ClasstypeCount ? classtypes[class] : classtypes[ClasstypeCount]); restell(tempstring); restell("Resolver error: Answered class does not match queried class."); @@ -1133,20 +1133,20 @@ void parserespacket(byte *s, int l) } if (datatype == qdatatype || datatype == T_CNAME) { if (debug) { - sprintf(tempstring,"Resolver: TTL: %s",strtdiff(sendstring,ttl)); + snprintf(tempstring, sizeof(tempstring), "Resolver: TTL: %s",strtdiff(sendstring,ttl)); restell(tempstring); } if (usefulanswer) switch (datatype) { case T_A: if (rdatalength != 4) { - sprintf(tempstring,"Resolver error: Unsupported rdata format for \"A\" type. (%u bytes)", + snprintf(tempstring, sizeof(tempstring), "Resolver error: Unsupported rdata format for \"A\" type. (%u bytes)", rdatalength); restell(tempstring); return; } if ( addrcmp( (void *) &(rp->ip), (void *) c, af ) == 0 ) { - sprintf(tempstring,"Resolver: Reverse authentication failed: %s != ", + snprintf(tempstring, sizeof(tempstring), "Resolver: Reverse authentication failed: %s != ", strlongip( &(rp->ip) )); addrcpy( (void *) &alignedip, (void *) c, af ); strcat(tempstring,strlongip( &alignedip )); @@ -1154,7 +1154,7 @@ void parserespacket(byte *s, int l) res_hostipmismatch++; failrp(rp); } else { - sprintf(tempstring,"Resolver: Reverse authentication complete: %s == \"%s\".", + snprintf(tempstring, sizeof(tempstring), "Resolver: Reverse authentication complete: %s == \"%s\".", strlongip( &(rp->ip) ),nonull(rp->hostname)); restell(tempstring); res_reversesuccess++; @@ -1171,7 +1171,7 @@ void parserespacket(byte *s, int l) return; } if (debug) { - sprintf(tempstring,"Resolver: Answered domain: \"%s\"",namestring); + snprintf(tempstring, sizeof(tempstring), "Resolver: Answered domain: \"%s\"",namestring); restell(tempstring); } if (r > HostnameLength) { @@ -1196,14 +1196,14 @@ void parserespacket(byte *s, int l) } break; default: - sprintf(tempstring,"Resolver error: Received unimplemented data type: %u (%s)", + snprintf(tempstring, sizeof(tempstring), "Resolver error: Received unimplemented data type: %u (%s)", datatype,datatype < ResourcetypeCount ? resourcetypes[datatype] : resourcetypes[ResourcetypeCount]); restell(tempstring); } } else { if (debug) { - sprintf(tempstring,"Resolver: Ignoring resource type %u. (%s)", + snprintf(tempstring, sizeof(tempstring), "Resolver: Ignoring resource type %u. (%s)", datatype,datatype < ResourcetypeCount ? resourcetypes[datatype] : resourcetypes[ResourcetypeCount]); restell(tempstring); @@ -1221,7 +1221,7 @@ void parserespacket(byte *s, int l) failrp(rp); break; default: - sprintf(tempstring,"Resolver: Received error response %u. (%s)", + snprintf(tempstring, sizeof(tempstring), "Resolver: Received error response %u. (%s)", getheader_rcode(hp),getheader_rcode(hp) < ResponsecodeCount ? responsecodes[getheader_rcode(hp)] : responsecodes[ResponsecodeCount]); restell(tempstring); @@ -1252,13 +1252,13 @@ void dns_ack(void) (void *) &(from4->sin_addr), AF_INET ) == 0 ) break; if (i == _res.nscount) { - sprintf(tempstring,"Resolver error: Received reply from unknown source: %s", + snprintf(tempstring, sizeof(tempstring), "Resolver error: Received reply from unknown source: %s", inet_ntoa(from4->sin_addr )); restell(tempstring); } else parserespacket((byte *)resrecvbuf,r); } else { - sprintf(tempstring,"Resolver: Socket error: %s",strerror(errno)); + snprintf(tempstring, sizeof(tempstring), "Resolver: Socket error: %s",strerror(errno)); restell(tempstring); } } @@ -1287,7 +1287,7 @@ void dns_events(double *sinterval) case STATE_FINISHED: /* TTL has expired */ case STATE_FAILED: /* Fake TTL has expired */ if (debug) { - sprintf(tempstring,"Resolver: Cache record for \"%s\" (%s) has expired. (state: %u) Marked for expire at: %g, time: %g.", + snprintf(tempstring, sizeof(tempstring), "Resolver: Cache record for \"%s\" (%s) has expired. (state: %u) Marked for expire at: %g, time: %g.", nonull(rp->hostname), strlongip( &(rp->ip) ), rp->state, rp->expiretime, sweeptime); restell(tempstring); @@ -1331,14 +1331,14 @@ char *dns_lookup2(ip_t * ip) if ((rp->state == STATE_FINISHED) || (rp->state == STATE_FAILED)) { if ((rp->state == STATE_FINISHED) && (rp->hostname)) { if (debug) { - sprintf(tempstring,"Resolver: Used cached record: %s == \"%s\".\n", + snprintf(tempstring, sizeof(tempstring), "Resolver: Used cached record: %s == \"%s\".\n", strlongip(ip),rp->hostname); restell(tempstring); } return rp->hostname; } else { if (debug) { - sprintf(tempstring,"Resolver: Used failed record: %s == ???\n", + snprintf(tempstring, sizeof(tempstring), "Resolver: Used failed record: %s == ???\n", strlongip(ip)); restell(tempstring); } diff --git a/gtk.c b/gtk.c index 6a4f8a9..f79aefd 100644 --- a/gtk.c +++ b/gtk.c @@ -42,6 +42,11 @@ #endif gint gtk_ping(gpointer data); +gint Copy_activate(GtkWidget *widget, gpointer data); +gint NewDestination_activate(GtkWidget *widget, gpointer data); +gboolean ReportTreeView_clicked(GtkWidget *Tree, GdkEventButton *event); +gchar* getSelectedHost(GtkTreePath *path); + extern char *Hostname; @@ -49,7 +54,7 @@ extern float WaitTime; extern int af; static int tag; static GtkWidget *Pause_Button; - +static GtkWidget *Entry; void gtk_add_ping_timeout (void) { @@ -170,7 +175,6 @@ void Toolbar_fill(GtkWidget *Toolbar) { GtkWidget *Button; GtkWidget *Label; - GtkWidget *Entry; GtkAdjustment *Adjustment; Button = gtk_button_new_from_stock(GTK_STOCK_QUIT); @@ -278,6 +282,9 @@ void TreeViewCreate(void) ReportTreeView = gtk_tree_view_new_with_model(GTK_TREE_MODEL(ReportStore)); + g_signal_connect(GTK_OBJECT(ReportTreeView), "button_press_event", + G_CALLBACK(ReportTreeView_clicked),NULL); + renderer = gtk_cell_renderer_text_new (); column = gtk_tree_view_column_new_with_attributes ("Hostname", renderer, @@ -536,4 +543,91 @@ void gtk_loop(void) gtk_main(); } +gboolean NewDestination_activate(GtkWidget *widget, gpointer data) +{ + gchar *hostname; + GtkTreePath *path = (GtkTreePath*)data; + + hostname = getSelectedHost(path); + if (hostname) { + gtk_entry_set_text (GTK_ENTRY(Entry), hostname); + Host_activate(Entry, NULL); + g_free(hostname); + } + return TRUE; +} + + +gboolean Copy_activate(GtkWidget *widget, gpointer data) +{ + gchar *hostname; + GtkTreePath *path = (GtkTreePath*)data; + + hostname = getSelectedHost(path); + if (hostname != NULL) { + GtkClipboard *clipboard; + + clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD); + gtk_clipboard_set_text(clipboard, hostname, -1); + + clipboard = gtk_clipboard_get(GDK_SELECTION_PRIMARY); + gtk_clipboard_set_text(clipboard, hostname, -1); + + g_free(hostname); + } + + return TRUE; +} + +gchar *getSelectedHost(GtkTreePath *path) +{ + GtkTreeIter iter; + gchar *name = NULL; + + if (gtk_tree_model_get_iter(GTK_TREE_MODEL(ReportStore), &iter, path)) { + gtk_tree_model_get (GTK_TREE_MODEL(ReportStore), &iter, COL_HOSTNAME, &name, -1); + } + gtk_tree_path_free(path); + return name; +} + + +gboolean ReportTreeView_clicked(GtkWidget *Tree, GdkEventButton *event) +{ + GtkWidget* popup_menu; + GtkWidget* copy_item; + GtkWidget* newdestination_item; + GtkTreePath *path; + + if (event->type != GDK_BUTTON_PRESS || event->button != 3) + return FALSE; + + if(!gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(ReportTreeView), + event->x, event->y, &path, NULL, NULL, NULL)) + return FALSE; + + gtk_tree_view_set_cursor(GTK_TREE_VIEW(ReportTreeView), path, NULL, FALSE); + + // Single right click: prepare and show the popup menu + popup_menu = gtk_menu_new (); + + copy_item = gtk_menu_item_new_with_label ("Copy to clipboard"); + newdestination_item = gtk_menu_item_new_with_label ("Set as new destination"); + + gtk_menu_append (GTK_MENU (popup_menu), copy_item); + gtk_menu_append (GTK_MENU (popup_menu), newdestination_item); + + g_signal_connect(GTK_OBJECT(copy_item),"activate", + GTK_SIGNAL_FUNC(Copy_activate), path); + + g_signal_connect(GTK_OBJECT(newdestination_item),"activate", + GTK_SIGNAL_FUNC(NewDestination_activate), path); + + gtk_widget_show (copy_item); + gtk_widget_show (newdestination_item); + + gtk_menu_popup (GTK_MENU(popup_menu), NULL, NULL, NULL, NULL, + 0, event->time); + return TRUE; +} diff --git a/mtr.8 b/mtr.8 index 30485b2..7321bd9 100644 --- a/mtr.8 +++ b/mtr.8 @@ -20,6 +20,9 @@ mtr \- a network diagnostic tool .B \-\-report\c ] [\c +.B \-\-report-wide\c +] +[\c .B \-\-report\-cycles\ COUNT\c ] [\c @@ -115,6 +118,19 @@ generates a significant amount of network traffic. Using to measure the quality of your network may result in decreased network performance. +.TP +.B \-w +.TP +.B \-\-report-wide +.br +This option puts +.B mtr +into +.B wide report +mode. When in this mode, +.B mtr +will not cut hostnames in the report. + .TP .B \-c\ COUNT .TP diff --git a/mtr.c b/mtr.c index 8849a1c..5ce68ba 100644 --- a/mtr.c +++ b/mtr.c @@ -64,6 +64,7 @@ int dns = 1; int cpacketsize = 64; /* default packet size */ int bitpattern = 0; int tos = 0; +int reportwide = 0; int af = DEFAULT_AF; int mtrtype = IPPROTO_ICMP; /* Use ICMP as default packet type */ @@ -125,6 +126,7 @@ void parse_arg (int argc, char **argv) { "help", 0, 0, 'h' }, { "report", 0, 0, 'r' }, + { "report-wide", 0, 0, 'w' }, { "xml", 0, 0, 'x' }, { "curses", 0, 0, 't' }, { "gtk", 0, 0, 'g' }, @@ -154,7 +156,7 @@ void parse_arg (int argc, char **argv) while(1) { /* added f:m:o: byMin */ opt = getopt_long(argc, argv, - "vhrxtglpo:i:c:s:b:Q:na:f:m:u46", long_options, NULL); + "vhrwxtglpo:i:c:s:b:Q:na:f:m:u46", long_options, NULL); if(opt == -1) break; @@ -169,6 +171,9 @@ void parse_arg (int argc, char **argv) case 'r': DisplayMode = DisplayReport; break; + case 'w': + reportwide = 1; + break; case 't': DisplayMode = DisplayCurses; break; @@ -371,8 +376,8 @@ int main(int argc, char **argv) } if (PrintHelp) { - printf("usage: %s [-hvrctglspniu46] [--help] [--version] [--report]\n" - "\t\t[--report-cycles=COUNT] [--curses] [--gtk]\n" + printf("usage: %s [-hvrwctglspniu46] [--help] [--version] [--report]\n" + "\t\t[--report-wide] [--report-cycles=COUNT] [--curses] [--gtk]\n" "\t\t[--raw] [--split] [--no-dns] [--address interface]\n" /* BL */ "\t\t[--psize=bytes/-s bytes]\n" /* ok */ "\t\t[--interval=SECONDS] HOSTNAME [PACKETSIZE]\n", argv[0]); @@ -395,7 +400,7 @@ int main(int argc, char **argv) bzero( &hints, sizeof hints ); hints.ai_family = af; hints.ai_socktype = SOCK_DGRAM; - error = getaddrinfo( Hostname, "0", &hints, &res ); + error = getaddrinfo( Hostname, NULL, &hints, &res ); if ( error ) { perror( gai_strerror(error) ); exit( EXIT_FAILURE ); diff --git a/mtr.h b/mtr.h index e2efd32..3239b0b 100644 --- a/mtr.h +++ b/mtr.h @@ -20,11 +20,6 @@ /* Typedefs */ -#if 0 - -// Neat trick! However, on my system, "config.h" already defines these types -// so I get a compiler error if I leave this in. -- REW - /* Find the proper type for 8 bits */ #if SIZEOF_UNSIGNED_CHAR == 1 typedef unsigned char uint8; @@ -54,8 +49,6 @@ typedef unsigned long uint32; #error No 32 bit type #endif -#endif - typedef unsigned char byte; typedef unsigned short word; typedef unsigned long dword; diff --git a/net.c b/net.c index ebd3eda..ea583d9 100644 --- a/net.c +++ b/net.c @@ -32,6 +32,9 @@ #include #include #include +#ifdef HAVE_FCNTL_H +#include +#endif #include #include #include @@ -895,6 +898,20 @@ int net_send_batch(void) return 0; } +static void set_fd_flags(int fd) +{ +#if defined(HAVE_FCNTL) && defined(FD_CLOEXEC) + int oldflags; + + oldflags = fcntl(fd, F_GETFD); + if (oldflags == -1) { + perror("Couldn't get fd's flags"); + return; + } + if (fcntl(fd, F_SETFD, oldflags | FD_CLOEXEC)) + perror("Couldn't set fd's flags"); +#endif +} int net_preopen(void) { @@ -925,9 +942,11 @@ int net_preopen(void) recvsock4 = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); if (recvsock4 < 0) return -1; + set_fd_flags(recvsock4); #ifdef ENABLE_IPV6 recvsock6 = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6); #endif + set_fd_flags(recvsock6); return 0; } @@ -956,7 +975,7 @@ int net_selectsocket(void) sendsock6 = sendsock6_udp; break; } - if (sendsock6 < 0) + if ((sendsock6 < 0) && (sendsock4 < 0)) return -1; #endif diff --git a/report.c b/report.c index 8b9fe60..510ef47 100644 --- a/report.c +++ b/report.c @@ -41,6 +41,7 @@ extern int bitpattern; extern int tos; extern int MaxPing; extern int af; +extern int reportwide; void report_open(void) @@ -56,15 +57,41 @@ void report_close(void) char buf[1024]; char fmt[16]; int len=0; + int len_hosts = 33; struct hostent *host; - sprintf(buf, "HOST: %-33s", LocalHostname); + if (reportwide) + { + // get the longest hostname + len_hosts = strlen(LocalHostname); + max = net_max(); + at = net_min(); + for (; at < max; at++) { + addr = net_addr(at); + if( addrcmp( (void *) addr, (void *) &unspec_addr, af ) != 0 ) { + host = dns ? addr2host( (void *) addr, af ) : NULL; + if (host != NULL) { + strncpy( name, host->h_name, (sizeof name) - 1 ); + name[ (sizeof name) - 1 ] = '\0'; + } else { + snprintf(name, sizeof(name), "%s", strlongip( addr ) ); + } + if (len_hosts < strlen(name)) { + len_hosts = strlen(name); + } + } + } + } + + snprintf( fmt, sizeof(fmt), "HOST: %%-%ds", len_hosts); + snprintf(buf, sizeof(buf), fmt, LocalHostname); + len = reportwide ? strlen(buf) : len_hosts; for( i=0; ih_name, (sizeof name) - 1 ); - name[ (sizeof name) - 1 ] = '\0'; + strncpy( name, host->h_name, (sizeof name) - 1 ); + name[ (sizeof name) - 1 ] = '\0'; } else { - sprintf(name, "%s", strlongip( addr ) ); + snprintf(name, sizeof(name), "%s", strlongip( addr ) ); } } - len=0; - sprintf( buf, " %2d. %-33s", at+1, name); + snprintf( fmt, sizeof(fmt), " %%2d. %%-%ds", len_hosts); + snprintf(buf, sizeof(buf), fmt, at+1, name); + len = reportwide ? strlen(buf) : len_hosts; for( i=0; i