combase: Add stub for RoRegisterForApartmentShutdown.
[wine.git] / programs / ping / ping_main.c
blob9c4f23959ea7972e04c6c4d1f01434277dda1987
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 "config.h"
23 #include "wine/port.h"
24 #include "winsock2.h"
25 #include "ws2tcpip.h"
26 #include "iphlpapi.h"
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <icmpapi.h>
32 #include <limits.h>
33 #ifdef HAVE_UNISTD_H
34 #include <unistd.h>
35 #endif
37 #include <windows.h>
39 #include "wine/debug.h"
40 #include "wine/heap.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(ping);
44 static void usage(void)
46 printf("Usage: ping [-n count] [-w timeout] [-l buffer_length] target_name\n\n"
47 "Options:\n"
48 " -n Number of echo requests to send.\n"
49 " -w Timeout in milliseconds to wait for each reply.\n"
50 " -l Length of send buffer.\n");
53 int main(int argc, char** argv)
55 unsigned int n = 4, i = 0, w = 4000, l = 32;
56 int optc, res;
57 int rec = 0, lost = 0, min = INT_MAX, max = 0;
58 WSADATA wsa;
59 HANDLE icmp_file;
60 unsigned long ipaddr;
61 DWORD retval, reply_size;
62 char *send_data, ip[100], *hostname, rtt[16];
63 void *reply_buffer;
64 struct in_addr addr;
65 ICMP_ECHO_REPLY *reply;
66 float avg = 0;
67 struct hostent *remote_host;
69 if (argc == 1)
71 usage();
72 exit(1);
75 while ((optc = getopt( argc, argv, "n:w:l:tal:fi:v:r:s:j:k:" )) != -1)
77 switch(optc)
79 case 'n':
80 n = atoi(optarg);
81 if (n == 0)
83 printf("Bad value for option -n, valid range is from 1 to 4294967295.\n");
84 exit(1);
86 break;
87 case 'w':
88 w = atoi(optarg);
89 if (w == 0)
91 printf("Bad value for option -w.\n");
92 exit(1);
94 break;
95 case 'l':
96 l = atoi(optarg);
97 if (l == 0)
99 printf("Bad value for option -l.\n");
100 exit(1);
102 break;
103 case '?':
104 usage();
105 exit(1);
106 default:
107 usage();
108 WINE_FIXME( "this command currently only supports the -n, -w and -l parameters.\n" );
109 exit(1);
113 if (argv[optind] != NULL)
114 hostname = argv[optind];
115 else
117 printf("Pass a host name.\n");
118 return 1;
121 res = WSAStartup(MAKEWORD(2, 2), &wsa);
122 if (res != 0)
124 printf("WSAStartup failed: %d\n", res);
125 return 1;
128 remote_host = gethostbyname(hostname);
129 if (remote_host == NULL)
131 printf("Ping request could not find host %s. Please check the name and try again.\n",
132 hostname);
133 return 1;
136 addr.s_addr = *(u_long *) remote_host->h_addr_list[0];
137 strcpy(ip, inet_ntoa(addr));
138 ipaddr = inet_addr(ip);
139 if (ipaddr == INADDR_NONE)
141 printf("Could not get IP address of host %s.", hostname);
142 return 1;
145 icmp_file = IcmpCreateFile();
147 send_data = heap_alloc_zero(l);
148 reply_size = sizeof(ICMP_ECHO_REPLY) + l + 8;
149 /* The buffer has to hold 8 more bytes of data (the size of an ICMP error message). */
150 reply_buffer = heap_alloc(reply_size);
151 if (reply_buffer == NULL)
153 printf("Unable to allocate memory to reply buffer.\n");
154 return 1;
157 printf("Pinging %s [%s] with %d bytes of data:\n", hostname, ip, l);
158 for (;;)
160 SetLastError(0);
161 retval = IcmpSendEcho(icmp_file, ipaddr, send_data, l,
162 NULL, reply_buffer, reply_size, w);
163 if (retval != 0)
165 reply = (ICMP_ECHO_REPLY *) reply_buffer;
166 if (reply->RoundTripTime >= 1)
167 sprintf(rtt, "=%d", reply->RoundTripTime);
168 else
169 strcpy(rtt, "<1");
170 printf("Reply from %s: bytes=%d time%sms TTL=%d\n", ip, l,
171 rtt, reply->Options.Ttl);
172 if (reply->RoundTripTime > max)
173 max = reply->RoundTripTime;
174 if (reply->RoundTripTime < min)
175 min = reply->RoundTripTime;
176 avg += reply->RoundTripTime;
177 rec++;
179 else
181 if (GetLastError() == IP_REQ_TIMED_OUT)
182 puts("Request timed out.");
183 else
184 puts("PING: transmit failed. General failure.");
185 lost++;
187 i++;
188 if (i == n)
189 break;
190 Sleep(1000);
193 printf("\nPing statistics for %s\n", ip);
194 printf("\tPackets: Sent = %d, Received = %d, Lost = %d (%.0f%% loss)\n",
195 n, rec, lost, (float) lost / n * 100);
196 if (rec != 0)
198 avg /= rec;
199 printf("Approximate round trip times in milli-seconds:\n");
200 printf("\tMinimum = %dms, Maximum = %dms, Average = %.0fms\n",
201 min, max, avg);
204 heap_free(reply_buffer);
205 return 0;