-
Notifications
You must be signed in to change notification settings - Fork 4
/
common.c
151 lines (128 loc) · 2.71 KB
/
common.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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
/*
* Serial port over Telnet common routines
* Lubomir Rintel <[email protected]>
* License: GPL
*/
#define _POSIX_C_SOURCE 201112L
#define _XOPEN_SOURCE
#define _XOPEN_SOURCE_EXTENDED
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#include <stdio.h>
#include <unistd.h>
#include "common.h"
static void
com_port_option (const unsigned char *buf, int size, com_port_option_callback callback)
{
union com_port_option_value value;
if (size < 6) {
fprintf (stderr, "too short: %d\n", size);
return;
}
switch (buf[3] - 100) {
case SET_BAUDRATE:
if (size < 10)
return;
value.baudrate = (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | (buf[7] << 0);
callback (SET_BAUDRATE, &value);
break;
case SET_DATASIZE:
value.datasize = buf[4];
callback (SET_DATASIZE, &value);
break;
case SET_PARITY:
value.parity = buf[4];
callback (SET_PARITY, &value);
break;
case SET_STOPSIZE:
value.stopsize = buf[4];
callback (SET_STOPSIZE, &value);
break;
case SET_CONTROL:
value.control = buf[4];
callback (SET_CONTROL, &value);
break;
}
}
int
get_esc (const unsigned char *buf, int size, com_port_option_callback callback)
{
int i;
if (size < 2)
return 0;
if (buf[0] != IAC)
return 0;
switch (buf[1]) {
case IAC:
/* If we leave IAC IAC, then it's considered as IAC data. */
return 0;
case WILL:
if (size < 3)
return 0;
return 3;
case DO:
if (size < 3)
return 0;
return 3;
case SB:
for (i = 2; i < size; i++) {
if (i + 1 <= size && buf[i] == IAC && buf[i + 1] == SE)
break;
}
if (i == size)
return 0;
i += 2;
if (i < 5)
return i;
if (buf[2] == COM_PORT_OPTION && callback)
com_port_option (buf, i, callback);
return i;
}
/* Unknown code. Just consume the IAC and command. */
return 2;
}
/* If the first character is an IAC after the previous get_esc() call
* it is not a command. */
int
get_data (const unsigned char *buf, int size)
{
int i;
if (size == 0)
return 0;
if (size >= 2 && buf[0] == IAC && buf[1] == IAC)
return 1;
for (i = 0; i < size; i++) {
if (buf[i] == IAC)
break;
}
return i;
}
int
get_socket (const char *host, const char *service)
{
int fd;
int res;
struct addrinfo hints = { .ai_socktype = SOCK_STREAM };
struct addrinfo *ai;
struct addrinfo *p;
res = getaddrinfo (host, service, &hints, &ai);
if (res != 0) {
fprintf (stderr, "%s:%s: %s\n", host, service, gai_strerror (res));
return -1;
}
for (p = ai; p; p = p->ai_next) {
fd = socket (p->ai_family, p->ai_socktype, p->ai_protocol);
if (fd == -1)
continue;
res = connect (fd, p->ai_addr, p->ai_addrlen);
if (res != -1)
break;
close (fd);
fd = -1;
}
if (p == NULL)
perror ("connect");
freeaddrinfo (ai);
return fd;
}