ddrawex: Use CRT allocation functions.
[wine.git] / programs / ping / ping_main.c
blob0615dd65054ed12da57f3ec6fbfc373cc2015585
1 /*
2 * ping program
4 * Copyright (C) 2010 Trey Hunner
5 * Copyright (C) 2018 Isira Seneviratne
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "winsock2.h"
23 #include "ws2tcpip.h"
24 #include "iphlpapi.h"
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <icmpapi.h>
30 #include <limits.h>
32 #include <windows.h>
34 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(ping);
38 static void usage(void)
40 printf("Usage: ping [-n count] [-w timeout] [-l buffer_length] target_name\n\n"
41 "Options:\n"
42 " -n Number of echo requests to send.\n"
43 " -w Timeout in milliseconds to wait for each reply.\n"
44 " -l Length of send buffer.\n");
47 int __cdecl main(int argc, char** argv)
49 unsigned int n = 4, i, w = 4000, l = 32;
50 int res;
51 int rec = 0, lost = 0, min = INT_MAX, max = 0;
52 WSADATA wsa;
53 HANDLE icmp_file;
54 unsigned long ipaddr;
55 DWORD retval, reply_size;
56 char *send_data, ip[100], *hostname = NULL, rtt[16];
57 void *reply_buffer;
58 struct in_addr addr;
59 ICMP_ECHO_REPLY *reply;
60 float avg = 0;
61 struct hostent *remote_host;
63 if (argc == 1)
65 usage();
66 exit(1);
69 for (i = 1; i < argc; i++)
71 if (argv[i][0] == '-' || argv[i][0] == '/')
73 switch (argv[i][1])
75 case 'n':
76 if (i == argc - 1)
78 printf( "Missing value for option %s\n", argv[i] );
79 exit(1);
81 n = atoi(argv[++i]);
82 if (n == 0)
84 printf("Bad value for option -n, valid range is from 1 to 4294967295.\n");
85 exit(1);
87 break;
88 case 'w':
89 if (i == argc - 1)
91 printf( "Missing value for option %s\n", argv[i] );
92 exit(1);
94 w = atoi(argv[++i]);
95 if (w == 0)
97 printf("Bad value for option -w.\n");
98 exit(1);
100 break;
101 case 'l':
102 if (i == argc - 1)
104 printf( "Missing value for option %s\n", argv[i] );
105 exit(1);
107 l = atoi(argv[++i]);
108 if (l == 0)
110 printf("Bad value for option -l.\n");
111 exit(1);
113 break;
114 case '?':
115 usage();
116 exit(1);
117 default:
118 usage();
119 WINE_FIXME( "this command currently only supports the -n, -w and -l parameters.\n" );
120 exit(1);
123 else
125 if (hostname)
127 printf( "Bad argument %s\n", argv[i] );
128 exit(1);
130 hostname = argv[i];
134 if (!hostname)
136 printf("Pass a host name.\n");
137 return 1;
140 res = WSAStartup(MAKEWORD(2, 2), &wsa);
141 if (res != 0)
143 printf("WSAStartup failed: %d\n", res);
144 return 1;
147 remote_host = gethostbyname(hostname);
148 if (remote_host == NULL)
150 printf("Ping request could not find host %s. Please check the name and try again.\n",
151 hostname);
152 return 1;
155 addr.s_addr = *(u_long *) remote_host->h_addr_list[0];
156 strcpy(ip, inet_ntoa(addr));
157 ipaddr = inet_addr(ip);
158 if (ipaddr == INADDR_NONE)
160 printf("Could not get IP address of host %s.", hostname);
161 return 1;
164 icmp_file = IcmpCreateFile();
166 send_data = calloc(1, l);
167 reply_size = sizeof(ICMP_ECHO_REPLY) + l + 8;
168 /* The buffer has to hold 8 more bytes of data (the size of an ICMP error message). */
169 reply_buffer = malloc(reply_size);
170 if (reply_buffer == NULL)
172 printf("Unable to allocate memory to reply buffer.\n");
173 return 1;
176 printf("Pinging %s [%s] with %d bytes of data:\n", hostname, ip, l);
177 for (i = 0; i < n; i++)
179 SetLastError(0);
180 retval = IcmpSendEcho(icmp_file, ipaddr, send_data, l,
181 NULL, reply_buffer, reply_size, w);
182 if (retval != 0)
184 reply = (ICMP_ECHO_REPLY *) reply_buffer;
185 if (reply->RoundTripTime >= 1)
186 sprintf(rtt, "=%ld", reply->RoundTripTime);
187 else
188 strcpy(rtt, "<1");
189 printf("Reply from %s: bytes=%d time%sms TTL=%d\n", ip, l,
190 rtt, reply->Options.Ttl);
191 if (reply->RoundTripTime > max)
192 max = reply->RoundTripTime;
193 if (reply->RoundTripTime < min)
194 min = reply->RoundTripTime;
195 avg += reply->RoundTripTime;
196 rec++;
198 else
200 if (GetLastError() == IP_REQ_TIMED_OUT)
201 puts("Request timed out.");
202 else
203 puts("PING: transmit failed. General failure.");
204 lost++;
206 if (i < n - 1) Sleep(1000);
209 printf("\nPing statistics for %s\n", ip);
210 printf("\tPackets: Sent = %d, Received = %d, Lost = %d (%.0f%% loss)\n",
211 n, rec, lost, (float) lost / n * 100);
212 if (rec != 0)
214 avg /= rec;
215 printf("Approximate round trip times in milli-seconds:\n");
216 printf("\tMinimum = %dms, Maximum = %dms, Average = %.0fms\n",
217 min, max, avg);
220 free(reply_buffer);
221 return 0;