-
Notifications
You must be signed in to change notification settings - Fork 17
/
cli.c
114 lines (105 loc) · 2.83 KB
/
cli.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
/*
* tcping command line utility
*
* Copyright (c) 2002-2023 Marc Kirchner
*
*/
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <unistd.h>
#include "tcping.h"
void usage(char *prog)
{
fprintf(stderr,
"error: Usage: %s [-q] [-f <4|6>] [-t timeout_sec] [-u "
"timeout_usec] <host> <port>\n",
prog);
exit(-1);
}
int main(int argc, char *argv[])
{
int force_ai_family = AF_UNSPEC;
long timeout_sec = 0, timeout_usec = 0;
struct timeval timeout;
int verbosity = 1;
if (argc < 3) {
usage(argv[0]);
}
char *cptr;
int c;
while ((c = getopt(argc, argv, "qf:t:u:")) != -1) {
switch (c) {
case 'q':
verbosity = 0;
break;
case 'f':
cptr = NULL;
long fam = strtol(optarg, &cptr, 10);
if (cptr == optarg || (fam != 4 && fam != 6))
usage(argv[0]);
force_ai_family = fam == 4 ? AF_INET : AF_INET6;
break;
case 't':
cptr = NULL;
timeout_sec = strtol(optarg, &cptr, 10);
if (cptr == optarg)
usage(argv[0]);
break;
case 'u':
cptr = NULL;
timeout_usec = strtol(optarg, &cptr, 10);
if (cptr == optarg)
usage(argv[0]);
break;
default:
usage(argv[0]);
break;
}
}
if (!argv[optind + 1]) {
usage(argv[0]);
}
timeout.tv_sec = timeout_sec + timeout_usec / 1000000;
timeout.tv_usec = timeout_usec % 1000000;
struct hostinfo *host;
int err;
int retval = 0;
if ((err = tcping_gethostinfo(argv[optind], argv[optind + 1],
force_ai_family, &host)) != 0) {
log(verbosity, stderr, "error: %s\n", gai_strerror(err));
retval = 255;
goto quit;
}
int sockfd = tcping_socket(host);
int result = tcping_connect(sockfd, host, &timeout);
tcping_close(sockfd);
switch (result) {
case TCPING_ERROR:
log(verbosity, stderr, "error: %s port %s: %s\n", host->name,
host->serv, strerror(errno));
retval = 255;
break;
case TCPING_OPEN:
log(verbosity, stdout, "%s port %s open.\n", host->name, host->serv);
break;
case TCPING_CLOSED:
log(verbosity, stdout, "%s port %s closed.\n", host->name, host->serv);
retval = 1;
break;
case TCPING_TIMEOUT:
log(verbosity, stdout, "%s port %s user timeout.\n", host->name,
host->serv);
retval = 2;
break;
default:
log(verbosity, stderr, "error: invalid return value\n");
retval = 255;
break;
}
quit:
tcping_freehostinfo(host);
return retval;
}