Added simple netcat client for Akaros
[akaros.git] / tools / apps / snc / snc.c
1
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <errno.h>
6 #include <unistd.h>
7 #include <sys/types.h>
8 #include <sys/stat.h>
9 #include <fcntl.h>
10 #include <sys/socket.h>
11 #include <netinet/in.h>
12 #include <arpa/inet.h>
13 #include <netdb.h>
14
15 #define min(a, b)                               \
16     ({ __typeof__(a) _a = (a);                  \
17                 __typeof__(b) _b = (b);                 \
18                 _a < _b ? _a : _b; })
19 #define max(a, b)                               \
20     ({ __typeof__(a) _a = (a);                  \
21                 __typeof__(b) _b = (b);                 \
22                 _a > _b ? _a : _b; })
23
24 static void usage(const char *prg)
25 {
26         fprintf(stderr, "Use: %s -s SERVER_IP -p PORT -i FILE\n", prg);
27         exit(1);
28 }
29
30 int main(int argc, const char **argv)
31 {
32         int i, sfd, ffd, port = -1;
33         off_t written;
34         const char *sip = NULL, *fpath = NULL;
35         struct sockaddr_in address;
36         struct stat stb;
37         char buffer[4096];
38
39         for (i = 1; i < argc; i++) {
40                 if (strcmp(argv[i], "-s") == 0) {
41                         if (++i < argc)
42                                 sip = argv[i];
43                 } else if (strcmp(argv[i], "-p") == 0) {
44                         if (++i < argc)
45                                 port = atoi(argv[i]);
46                 } else if (strcmp(argv[i], "-i") == 0) {
47                         if (++i < argc)
48                                 fpath = argv[i];
49                 }
50         }
51         if (port < 0 || !sip || !fpath)
52                 usage(argv[0]);
53
54         ffd = open(fpath, O_RDONLY);
55         if (ffd < 0) {
56                 fprintf(stderr, "Unable to open input file '%s': %s\n", fpath,
57                                 strerror(errno));
58                 return 1;
59         }
60         if (fstat(ffd, &stb)) {
61                 fprintf(stderr, "Unable to stat input file '%s': %s\n", fpath,
62                                 strerror(errno));
63                 return 1;
64         }
65
66         memset(&address, 0, sizeof(address));
67         address.sin_family = AF_INET;
68         address.sin_port = htons(port);
69         if (inet_pton(AF_INET, sip, &address.sin_addr) <= 0) {
70                 fprintf(stderr, "Invalid server IP '%s': %s\n", sip, strerror(errno));
71                 return 1;
72         }
73         sfd = socket(AF_INET, SOCK_STREAM, 0);
74         if (sfd < 0) {
75                 fprintf(stderr, "Invalid create stream socket: %s\n", strerror(errno));
76                 return 1;
77         }
78         if (connect(sfd, (struct sockaddr *) &address, sizeof(address)) < 0) {
79                 fprintf(stderr, "Unable to connect to server IP '%s': %s\n", sip,
80                                 strerror(errno));
81                 return 1;
82         }
83
84         written = 0;
85         while (written < stb.st_size) {
86                 size_t csize = min((off_t) sizeof(buffer), stb.st_size - written);
87
88                 if (read(ffd, buffer, csize) != csize) {
89                         fprintf(stderr, "Unable to read input file '%s': %s\n", fpath,
90                                         strerror(errno));
91                         return 1;
92                 }
93                 if (write(sfd, buffer, csize) != csize) {
94                         fprintf(stderr, "Unable to write to server IP '%s': %s\n", sip,
95                                         strerror(errno));
96                         return 1;
97                 }
98
99                 written += csize;
100         }
101
102         close(sfd);
103
104         return 0;
105 }