To-aviod-buffer-overflow-in-telnet.patch 32 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217
  1. From f09a6460a62aacb87bb8683d16aa3ce55848bf7e Mon Sep 17 00:00:00 2001
  2. From: Li xin <lixin.fnst@cn.fujitsu.com>
  3. Date: Fri, 28 Nov 2014 07:06:24 +0900
  4. Subject: [PATCH 1/2] To aviod buffer overflow in telnet
  5. This patch is from Fedora.
  6. Upstream-Status: Pending
  7. Signed-off-by: Li Xin <lixin.fnst@cn.fujitsu.com>
  8. ---
  9. telnet/Makefile | 4 +-
  10. telnet/commands.cc | 270 +++++++++++++++++++++++++++++++++++-----------------
  11. telnet/defines.h | 2 +
  12. telnet/externs.h | 7 +-
  13. telnet/main.cc | 65 ++++++++++---
  14. telnet/netlink.cc | 78 +++++++++------
  15. telnet/netlink.h | 7 +-
  16. telnet/network.cc | 1 +
  17. telnet/proto.h | 2 +-
  18. telnet/ring.cc | 2 +-
  19. telnet/ring.h | 2 +-
  20. telnet/sys_bsd.cc | 11 +++
  21. telnet/telnet.1 | 37 +++++--
  22. telnet/telnet.cc | 45 +++++----
  23. telnet/terminal.cc | 17 +++-
  24. telnet/utilities.cc | 2 +
  25. 16 files changed, 380 insertions(+), 172 deletions(-)
  26. diff --git a/telnet/Makefile b/telnet/Makefile
  27. index cef866f..39249e1 100644
  28. --- a/telnet/Makefile
  29. +++ b/telnet/Makefile
  30. @@ -7,7 +7,7 @@ include ../MRULES
  31. # -DAUTHENTICATE
  32. CXXFLAGS += -DUSE_TERMIO -DKLUDGELINEMODE
  33. -LIBS += $(LIBTERMCAP)
  34. +LIBS = $(LIBTERMCAP)
  35. SRCS = commands.cc main.cc network.cc ring.cc sys_bsd.cc telnet.cc \
  36. terminal.cc tn3270.cc utilities.cc genget.cc environ.cc netlink.cc
  37. @@ -22,7 +22,7 @@ depend:
  38. $(CXX) $(CXXFLAGS) -MM $(SRCS) >depend.mk
  39. install: telnet
  40. - install -s -m$(BINMODE) telnet $(INSTALLROOT)$(BINDIR)
  41. + install -m$(BINMODE) telnet $(INSTALLROOT)$(BINDIR)
  42. install -m$(MANMODE) telnet.1 $(INSTALLROOT)$(MANDIR)/man1
  43. clean:
  44. diff --git a/telnet/commands.cc b/telnet/commands.cc
  45. index d92bccd..02c593e 100644
  46. --- a/telnet/commands.cc
  47. +++ b/telnet/commands.cc
  48. @@ -86,10 +86,6 @@ char cmd_rcsid[] =
  49. #define HELPINDENT ((int) sizeof ("connect"))
  50. -#ifndef MAXHOSTNAMELEN
  51. -#define MAXHOSTNAMELEN 64
  52. -#endif MAXHOSTNAMELEN
  53. -
  54. #if defined(HAS_IPPROTO_IP) && defined(IP_TOS)
  55. int tos = -1;
  56. #endif /* defined(HAS_IPPROTO_IP) && defined(IP_TOS) */
  57. @@ -98,7 +94,7 @@ static unsigned long sourceroute(char *arg, char **cpp, int *lenp);
  58. char *hostname;
  59. -static char _hostname[MAXHOSTNAMELEN];
  60. +static char *_hostname;
  61. //typedef int (*intrtn_t)(int argc, const char *argv[]);
  62. @@ -161,7 +157,7 @@ class command_entry {
  63. assert(argc>=1);
  64. if (nargs>=0 && argc!=nargs+1) {
  65. fprintf(stderr, "Wrong number of arguments for command.\n");
  66. - fprintf(stderr, "Try %s ? for help\n", argv[0]);
  67. + fprintf(stderr, "Try ? %s for help\n", argv[0]);
  68. return 0; /* is this right? */
  69. }
  70. if (nargs==-2) {
  71. @@ -480,6 +476,7 @@ static int send_wontcmd(const char *name, const char *) {
  72. int send_tncmd(int (*func)(int, int), const char *cmd, const char *name) {
  73. char **cpp;
  74. extern char *telopts[];
  75. + long opt;
  76. if (isprefix(name, "help") || isprefix(name, "?")) {
  77. register int col, len;
  78. @@ -506,16 +503,23 @@ int send_tncmd(int (*func)(int, int), const char *cmd, const char *name) {
  79. name, cmd);
  80. return 0;
  81. }
  82. +
  83. + opt = cpp - telopts;
  84. if (cpp == 0) {
  85. - fprintf(stderr, "'%s': unknown argument ('send %s ?' for help).\n",
  86. + char *end;
  87. +
  88. + opt = strtol(name, &end, 10);
  89. + if (*end || opt < 0 || opt > 255) {
  90. + fprintf(stderr, "'%s': unknown argument ('send %s ?' for help).\n",
  91. name, cmd);
  92. - return 0;
  93. + return 0;
  94. + }
  95. }
  96. if (!connected) {
  97. printf("?Need to be connected first.\n");
  98. return 0;
  99. }
  100. - (*func)(cpp - telopts, 1);
  101. + (*func)(opt, 1);
  102. return 1;
  103. }
  104. @@ -689,9 +693,9 @@ static struct togglelist Togglelist[] = {
  105. "print encryption debugging information" },
  106. #endif
  107. - { "skiprc", "don't read ~/.telnetrc file",
  108. + { "skiprc", "don't read the telnetrc files",
  109. NULL, &skiprc,
  110. - "read ~/.telnetrc file" },
  111. + "read the telnetrc files" },
  112. { "binary",
  113. "sending and receiving of binary data",
  114. togbinary, NULL,
  115. @@ -1615,15 +1619,20 @@ void ayt_status(int) {
  116. #endif
  117. int tn(int argc, const char *argv[]) {
  118. - register struct hostent *host = 0;
  119. struct sockaddr_in sn;
  120. - struct servent *sp = 0;
  121. char *srp = NULL;
  122. int srlen;
  123. -
  124. - const char *cmd, *volatile user = 0;
  125. + int family = 0;
  126. + const char *cmd, *volatile user = 0, *srchostp = 0;
  127. const char *portp = NULL;
  128. char *hostp = NULL;
  129. + char *resolv_hostp;
  130. + struct addrinfo hints;
  131. + struct addrinfo *hostaddr = 0;
  132. + int res;
  133. + char name[NI_MAXHOST];
  134. + char service[NI_MAXSERV];
  135. + struct addrinfo *tmpaddr;
  136. /* clear the socket address prior to use */
  137. memset(&sn, 0, sizeof(sn));
  138. @@ -1632,6 +1641,10 @@ int tn(int argc, const char *argv[]) {
  139. printf("?Already connected to %s\n", hostname);
  140. return 0;
  141. }
  142. + if (_hostname) {
  143. + delete[] _hostname;
  144. + _hostname = 0;
  145. + }
  146. if (argc < 2) {
  147. (void) strcpy(line, "open ");
  148. printf("(to) ");
  149. @@ -1657,11 +1670,33 @@ int tn(int argc, const char *argv[]) {
  150. --argc;
  151. continue;
  152. }
  153. + if (strcmp(*argv, "-b") == 0) {
  154. + --argc; ++argv;
  155. + if (argc == 0)
  156. + goto usage;
  157. + srchostp = *argv++;
  158. + --argc;
  159. + continue;
  160. + }
  161. if (strcmp(*argv, "-a") == 0) {
  162. --argc; ++argv;
  163. autologin = 1;
  164. continue;
  165. }
  166. + if (strcmp(*argv, "-6") == 0) {
  167. + --argc; ++argv;
  168. +#ifdef AF_INET6
  169. + family = AF_INET6;
  170. +#else
  171. + puts("IPv6 unsupported");
  172. +#endif
  173. + continue;
  174. + }
  175. + if (strcmp(*argv, "-4") == 0) {
  176. + --argc; ++argv;
  177. + family = AF_INET;
  178. + continue;
  179. + }
  180. if (hostp == 0) {
  181. /* this leaks memory - FIXME */
  182. hostp = strdup(*argv++);
  183. @@ -1680,6 +1715,8 @@ int tn(int argc, const char *argv[]) {
  184. if (hostp == 0)
  185. goto usage;
  186. + resolv_hostp = hostp;
  187. +
  188. #if defined(IP_OPTIONS) && defined(HAS_IPPROTO_IP)
  189. if (hostp[0] == '@' || hostp[0] == '!') {
  190. if ((hostname = strrchr(hostp, ':')) == NULL)
  191. @@ -1696,78 +1733,122 @@ int tn(int argc, const char *argv[]) {
  192. } else {
  193. sn.sin_addr.s_addr = temp;
  194. sn.sin_family = AF_INET;
  195. + /*
  196. + * For source route we just make sure to get the IP given
  197. + * on the command line when looking up the port.
  198. + */
  199. + resolv_hostp = inet_ntoa(sn.sin_addr);
  200. }
  201. }
  202. - else {
  203. -#endif
  204. - if (inet_aton(hostp, &sn.sin_addr)) {
  205. - sn.sin_family = AF_INET;
  206. - strcpy(_hostname, hostp);
  207. - hostname = _hostname;
  208. - }
  209. - else {
  210. - host = gethostbyname(hostp);
  211. - if (host) {
  212. - sn.sin_family = host->h_addrtype;
  213. - if (host->h_length > (int)sizeof(sn.sin_addr)) {
  214. - host->h_length = sizeof(sn.sin_addr);
  215. - }
  216. -#if defined(h_addr) /* In 4.3, this is a #define */
  217. - memcpy((caddr_t)&sn.sin_addr,
  218. - host->h_addr_list[0], host->h_length);
  219. -#else /* defined(h_addr) */
  220. - memcpy((caddr_t)&sn.sin_addr, host->h_addr, host->h_length);
  221. -#endif /* defined(h_addr) */
  222. - strncpy(_hostname, host->h_name, sizeof(_hostname));
  223. - _hostname[sizeof(_hostname)-1] = '\0';
  224. - hostname = _hostname;
  225. - } else {
  226. - herror(hostp);
  227. - return 0;
  228. - }
  229. - }
  230. -#if defined(IP_OPTIONS) && defined(HAS_IPPROTO_IP)
  231. - }
  232. #endif
  233. +
  234. + /* User port or the default name of telnet. */
  235. if (portp) {
  236. if (*portp == '-') {
  237. portp++;
  238. telnetport = 1;
  239. - } else
  240. + } else {
  241. telnetport = 0;
  242. - sn.sin_port = atoi(portp);
  243. - if (sn.sin_port == 0) {
  244. - sp = getservbyname(portp, "tcp");
  245. - if (sp)
  246. - sn.sin_port = sp->s_port;
  247. - else {
  248. - printf("%s: bad port number\n", portp);
  249. - return 0;
  250. + if (*portp >='0' && *portp<='9') {
  251. + char *end;
  252. + long int p;
  253. +
  254. + p=strtol(portp, &end, 10);
  255. + if (ERANGE==errno && (LONG_MIN==p || LONG_MAX==p)) {
  256. + fprintf(stderr, "telnet: port %s overflows\n", portp);
  257. + return 0;
  258. + } else if (p<=0 || p>=65536) {
  259. + fprintf(stderr, "telnet: port %s out of range\n", portp);
  260. + return 0;
  261. + }
  262. }
  263. - }
  264. - else {
  265. - sn.sin_port = htons(sn.sin_port);
  266. }
  267. - }
  268. + }
  269. else {
  270. - if (sp == 0) {
  271. - sp = getservbyname("telnet", "tcp");
  272. - if (sp == 0) {
  273. - fprintf(stderr, "telnet: tcp/telnet: unknown service\n");
  274. - return 0;
  275. - }
  276. - sn.sin_port = sp->s_port;
  277. - }
  278. + portp = "telnet";
  279. telnetport = 1;
  280. }
  281. - printf("Trying %s...\n", inet_ntoa(sn.sin_addr));
  282. +
  283. + /* We only understand SOCK_STREAM sockets. */
  284. + memset(&hints, 0, sizeof(hints));
  285. + hints.ai_socktype = SOCK_STREAM;
  286. + hints.ai_flags = AI_NUMERICHOST;
  287. + hints.ai_family = family;
  288. +
  289. + if (srchostp) {
  290. + res = getaddrinfo(srchostp, "0", &hints, &hostaddr);
  291. + if (res) {
  292. + fprintf(stderr, "telnet: could not resolve %s: %s\n", srchostp,
  293. + gai_strerror(res));
  294. + return 0;
  295. + }
  296. + hints.ai_family = hostaddr->ai_family;
  297. + res = nlink.bind(hostaddr);
  298. + freeaddrinfo(hostaddr);
  299. + if (res < 0)
  300. + return 0;
  301. + }
  302. +
  303. + /* Resolve both the host and service simultaneously. */
  304. + res = getaddrinfo(resolv_hostp, portp, &hints, &hostaddr);
  305. + if (res == EAI_NONAME) {
  306. + hints.ai_flags = AI_CANONNAME;
  307. + res = getaddrinfo(resolv_hostp, portp, &hints, &hostaddr);
  308. + } else if (hostaddr) {
  309. + hostaddr->ai_canonname = 0;
  310. + }
  311. + if (res || !hostaddr) {
  312. + fprintf(stderr, "telnet: could not resolve %s/%s: %s\n", resolv_hostp, portp, gai_strerror(res));
  313. + return 0;
  314. + }
  315. +
  316. + /* Try to connect to every listed round robin IP. */
  317. + tmpaddr = hostaddr;
  318. + errno = 0;
  319. do {
  320. - int x = nlink.connect(debug, host, &sn, srp, srlen, tos);
  321. - if (!x) return 0;
  322. - else if (x==1) continue;
  323. + int x;
  324. +
  325. + if (!tmpaddr) {
  326. + if (errno)
  327. + perror("telnet: Unable to connect to remote host");
  328. + else
  329. + fputs("telnet: Unable to connect to remote host: "
  330. + "Bad port number\n", stderr);
  331. +err:
  332. + freeaddrinfo(hostaddr);
  333. + return 0;
  334. + }
  335. +
  336. + if (tmpaddr->ai_family == AF_UNIX) {
  337. +nextaddr:
  338. + tmpaddr = tmpaddr->ai_next;
  339. + continue;
  340. + }
  341. +
  342. + getnameinfo(tmpaddr->ai_addr, tmpaddr->ai_addrlen,
  343. + name, sizeof(name), service, sizeof(service),
  344. + NI_NUMERICHOST | NI_NUMERICSERV);
  345. +
  346. + printf("Trying %s...\n", name);
  347. + x = nlink.connect(debug, tmpaddr, srp, srlen, tos);
  348. + if (!x)
  349. + goto err;
  350. + else if (x==1)
  351. + goto nextaddr;
  352. +
  353. connected++;
  354. } while (connected == 0);
  355. - cmdrc(hostp, hostname);
  356. + if (tmpaddr->ai_canonname == 0) {
  357. + hostname = new char[strlen(hostp)+1];
  358. + strcpy(hostname, hostp);
  359. + }
  360. + else {
  361. + hostname = new char[strlen(tmpaddr->ai_canonname)+1];
  362. + strcpy(hostname, tmpaddr->ai_canonname);
  363. + }
  364. +
  365. + cmdrc(hostp, hostname, portp);
  366. + freeaddrinfo(hostaddr);
  367. if (autologin && user == NULL) {
  368. struct passwd *pw;
  369. @@ -2013,30 +2094,21 @@ static int help(command_table *tab, int argc, const char *argv[]) {
  370. return 0;
  371. }
  372. -static char *rcname = 0;
  373. -static char rcbuf[128];
  374. -
  375. -void cmdrc(const char *m1, const char *m2) {
  376. +static void readrc(const char *m1, const char *m2, const char *port,
  377. + const char *rcname)
  378. +{
  379. FILE *rcfile;
  380. int gotmachine = 0;
  381. int l1 = strlen(m1);
  382. int l2 = strlen(m2);
  383. - char m1save[64];
  384. -
  385. - if (skiprc) return;
  386. + int lport = strlen(port);
  387. + char m1save[l1 + 1];
  388. + char portsave[lport + 1];
  389. strcpy(m1save, m1);
  390. m1 = m1save;
  391. -
  392. - if (rcname == 0) {
  393. - rcname = getenv("HOME");
  394. - if (rcname)
  395. - strcpy(rcbuf, rcname);
  396. - else
  397. - rcbuf[0] = '\0';
  398. - strcat(rcbuf, "/.telnetrc");
  399. - rcname = rcbuf;
  400. - }
  401. + strcpy(portsave, port);
  402. + port = portsave;
  403. rcfile = fopen(rcname, "r");
  404. if (!rcfile) return;
  405. @@ -2061,6 +2133,13 @@ void cmdrc(const char *m1, const char *m2) {
  406. strncpy(line, &line[7], sizeof(line) - 7);
  407. else
  408. continue;
  409. +
  410. + if (line[0] == ':') {
  411. + if (!strncasecmp(&line[1], port, lport))
  412. + continue;
  413. + strncpy(line, &line[lport + 1], sizeof(line) - lport - 1);
  414. + }
  415. +
  416. if (line[0] != ' ' && line[0] != '\t' && line[0] != '\n')
  417. continue;
  418. gotmachine = 1;
  419. @@ -2073,6 +2152,21 @@ void cmdrc(const char *m1, const char *m2) {
  420. fclose(rcfile);
  421. }
  422. +void cmdrc(const char *m1, const char *m2, const char *port) {
  423. + char *rcname = NULL;
  424. +
  425. + if (skiprc) return;
  426. +
  427. + readrc(m1, m2, port, "/etc/telnetrc");
  428. + if (asprintf (&rcname, "%s/.telnetrc", getenv ("HOME")) == -1)
  429. + {
  430. + perror ("asprintf");
  431. + return;
  432. + }
  433. + readrc(m1, m2, port, rcname);
  434. + free (rcname);
  435. +}
  436. +
  437. #if defined(IP_OPTIONS) && defined(HAS_IPPROTO_IP)
  438. /*
  439. diff --git a/telnet/defines.h b/telnet/defines.h
  440. index 2784400..d5edc46 100644
  441. --- a/telnet/defines.h
  442. +++ b/telnet/defines.h
  443. @@ -50,3 +50,5 @@
  444. #define MODE_COMMAND_LINE(m) ((m)==-1)
  445. #define CONTROL(x) ((x)&0x1f) /* CTRL(x) is not portable */
  446. +
  447. +#define MODE_OUT8 0x8000 /* binary mode sans -opost */
  448. diff --git a/telnet/externs.h b/telnet/externs.h
  449. index 955df79..0730e8a 100644
  450. --- a/telnet/externs.h
  451. +++ b/telnet/externs.h
  452. @@ -48,9 +48,7 @@
  453. typedef unsigned char cc_t;
  454. #endif
  455. -#ifdef __linux__
  456. #include <unistd.h> /* get _POSIX_VDISABLE */
  457. -#endif
  458. #ifndef _POSIX_VDISABLE
  459. #error "Please fix externs.h to define _POSIX_VDISABLE"
  460. @@ -60,7 +58,8 @@ typedef unsigned char cc_t;
  461. extern int autologin; /* Autologin enabled */
  462. extern int skiprc; /* Don't process the ~/.telnetrc file */
  463. -extern int eight; /* use eight bit mode (binary in and/or out */
  464. +extern int eight; /* use eight bit mode (binary in and/or out) */
  465. +extern int binary; /* use binary option (in and/or out) */
  466. extern int flushout; /* flush output */
  467. extern int connected; /* Are we connected to the other side? */
  468. extern int globalmode; /* Mode tty should be in */
  469. @@ -225,6 +224,8 @@ cc_t *tcval(int);
  470. //#if 0
  471. extern struct termios new_tc;
  472. +extern struct termios old_tc;
  473. +
  474. #define termEofChar new_tc.c_cc[VEOF]
  475. #define termEraseChar new_tc.c_cc[VERASE]
  476. diff --git a/telnet/main.cc b/telnet/main.cc
  477. index b67f2ce..b626e54 100644
  478. --- a/telnet/main.cc
  479. +++ b/telnet/main.cc
  480. @@ -45,7 +45,10 @@ char main_rcsid[] =
  481. #include <sys/types.h>
  482. #include <getopt.h>
  483. +#include <stdlib.h>
  484. #include <string.h>
  485. +#include <netdb.h>
  486. +#include <errno.h>
  487. #include "ring.h"
  488. #include "externs.h"
  489. @@ -80,12 +83,13 @@ tninit(void)
  490. void usage(void) {
  491. fprintf(stderr, "Usage: %s %s%s%s%s\n",
  492. prompt,
  493. - " [-8] [-E] [-L] [-a] [-d] [-e char] [-l user] [-n tracefile]",
  494. - "\n\t",
  495. + "[-4] [-6] [-8] [-E] [-L] [-a] [-d] [-e char] [-l user]",
  496. + "\n\t[-n tracefile] [ -b addr ]",
  497. #ifdef TN3270
  498. + "\n\t"
  499. "[-noasynch] [-noasynctty] [-noasyncnet] [-r] [-t transcom]\n\t",
  500. #else
  501. - "[-r] ",
  502. + " [-r] ",
  503. #endif
  504. "[host-name [port]]"
  505. );
  506. @@ -102,7 +106,8 @@ main(int argc, char *argv[])
  507. extern char *optarg;
  508. extern int optind;
  509. int ch;
  510. - char *user;
  511. + char *user, *srcaddr;
  512. + int family;
  513. tninit(); /* Clear out things */
  514. #if defined(CRAY) && !defined(__STDC__)
  515. @@ -110,21 +115,38 @@ main(int argc, char *argv[])
  516. #endif
  517. TerminalSaveState();
  518. + if ((old_tc.c_cflag & (CSIZE|PARENB)) != CS8)
  519. + eight = 0;
  520. if ((prompt = strrchr(argv[0], '/'))!=NULL)
  521. ++prompt;
  522. else
  523. prompt = argv[0];
  524. - user = NULL;
  525. + user = srcaddr = NULL;
  526. + family = 0;
  527. rlogin = (strncmp(prompt, "rlog", 4) == 0) ? '~' : _POSIX_VDISABLE;
  528. autologin = -1;
  529. - while ((ch = getopt(argc, argv, "8EKLS:X:ade:k:l:n:rt:x")) != EOF) {
  530. + while ((ch = getopt(argc, argv,
  531. + "4678EKLS:X:ab:de:k:l:n:rt:x")) != EOF) {
  532. switch(ch) {
  533. + case '4':
  534. + family = AF_INET;
  535. + break;
  536. + case '6':
  537. +#ifdef AF_INET6
  538. + family = AF_INET6;
  539. +#else
  540. + fputs("IPv6 unsupported\n", stderr);
  541. +#endif
  542. + break;
  543. + case '7':
  544. + eight = 0; /* 7-bit ouput and input */
  545. + break;
  546. case '8':
  547. - eight = 3; /* binary output and input */
  548. + binary = 3; /* binary output and input */
  549. break;
  550. case 'E':
  551. rlogin = escapechar = _POSIX_VDISABLE;
  552. @@ -133,23 +155,26 @@ main(int argc, char *argv[])
  553. //autologin = 0;
  554. break;
  555. case 'L':
  556. - eight |= 2; /* binary output only */
  557. + binary |= 2; /* binary output only */
  558. break;
  559. case 'S':
  560. {
  561. -#ifdef HAS_GETTOS
  562. extern int tos;
  563. + int num;
  564. - if ((tos = parsetos(optarg, "tcp")) < 0)
  565. +#ifdef HAS_GETTOS
  566. + if ((num = parsetos(optarg, "tcp")) < 0) {
  567. +#else
  568. + errno = 0;
  569. + num = strtol(optarg, 0, 0);
  570. + if (errno) {
  571. +#endif
  572. fprintf(stderr, "%s%s%s%s\n",
  573. prompt, ": Bad TOS argument '",
  574. optarg,
  575. "; will try to use default TOS");
  576. -#else
  577. - fprintf(stderr,
  578. - "%s: Warning: -S ignored, no parsetos() support.\n",
  579. - prompt);
  580. -#endif
  581. + } else
  582. + tos = num;
  583. }
  584. break;
  585. case 'X':
  586. @@ -210,6 +235,9 @@ main(int argc, char *argv[])
  587. "%s: -x ignored, no encryption support.\n",
  588. prompt);
  589. break;
  590. + case 'b':
  591. + srcaddr = optarg;
  592. + break;
  593. case '?':
  594. default:
  595. usage();
  596. @@ -233,6 +261,13 @@ main(int argc, char *argv[])
  597. *argp++ = "-l";
  598. *argp++ = user;
  599. }
  600. + if (srcaddr) {
  601. + *argp++ = "-b";
  602. + *argp++ = srcaddr;
  603. + }
  604. + if (family) {
  605. + *argp++ = family == AF_INET ? "-4" : "-6";
  606. + }
  607. *argp++ = argv[0]; /* host */
  608. if (argc > 1)
  609. *argp++ = argv[1]; /* port */
  610. diff --git a/telnet/netlink.cc b/telnet/netlink.cc
  611. index f439cff..f839747 100644
  612. --- a/telnet/netlink.cc
  613. +++ b/telnet/netlink.cc
  614. @@ -79,22 +79,61 @@ void netlink::close(int doshutdown) {
  615. shutdown(net, 2);
  616. }
  617. ::close(net);
  618. + net = -1;
  619. }
  620. -int netlink::connect(int debug, struct hostent *host,
  621. - struct sockaddr_in *sn,
  622. - char *srcroute, int srlen, int tos)
  623. +int netlink::bind(struct addrinfo *addr)
  624. {
  625. - int on=1;
  626. + int res;
  627. +
  628. + res = socket(addr->ai_family);
  629. + if (res < 2) {
  630. + if (res == 1)
  631. + perror("telnet: socket");
  632. + return -1;
  633. + }
  634. +
  635. + if (::bind(net, addr->ai_addr, addr->ai_addrlen) < 0) {
  636. + perror("telnet: bind");
  637. + return -1;
  638. + }
  639. +
  640. + return 0;
  641. +}
  642. +
  643. +int netlink::socket(int family)
  644. +{
  645. + if (this->family != family)
  646. + close(0);
  647. - net = socket(AF_INET, SOCK_STREAM, 0);
  648. if (net < 0) {
  649. - perror("telnet: socket");
  650. - return 0;
  651. + this->family = family;
  652. + net = ::socket(family, SOCK_STREAM, 0);
  653. + if (net < 0) {
  654. + if (errno == EAFNOSUPPORT)
  655. + return 1;
  656. + perror("telnet: socket");
  657. + return 0;
  658. + }
  659. }
  660. + return 2;
  661. +}
  662. +
  663. +int netlink::connect(int debug, struct addrinfo *addr,
  664. + char *srcroute, int srlen, int tos)
  665. +{
  666. + int on=1;
  667. + int res;
  668. +
  669. + res = socket(addr->ai_family);
  670. + if (res < 2)
  671. + return res;
  672. +
  673. #if defined(IP_OPTIONS) && defined(HAS_IPPROTO_IP)
  674. if (srcroute) {
  675. + if (addr->ai_family != AF_INET)
  676. + fputs("Source route is only supported for IPv4\n", stderr);
  677. if (setsockopt(net, IPPROTO_IP, IP_OPTIONS, srcroute, srlen) < 0)
  678. perror("setsockopt (IP_OPTIONS)");
  679. }
  680. @@ -108,7 +147,7 @@ int netlink::connect(int debug, struct hostent *host,
  681. #endif
  682. if (tos < 0) tos = 020; /* Low Delay bit */
  683. if (tos && (setsockopt(net, IPPROTO_IP, IP_TOS, &tos, sizeof(int)) < 0)
  684. - && (errno != ENOPROTOOPT))
  685. + && (errno != ENOPROTOOPT) && (errno != EOPNOTSUPP))
  686. perror("telnet: setsockopt (IP_TOS) (ignored)");
  687. #endif /* defined(IPPROTO_IP) && defined(IP_TOS) */
  688. @@ -116,27 +155,8 @@ int netlink::connect(int debug, struct hostent *host,
  689. perror("setsockopt (SO_DEBUG)");
  690. }
  691. - if (::connect(net, (struct sockaddr *)sn, sizeof(*sn)) < 0) {
  692. -#if defined(h_addr) /* In 4.3, this is a #define */
  693. - if (host && host->h_addr_list[1]) {
  694. - int oerrno = errno;
  695. -
  696. - fprintf(stderr, "telnet: connect to address %s: ",
  697. - inet_ntoa(sn->sin_addr));
  698. - errno = oerrno;
  699. - perror(NULL);
  700. - host->h_addr_list++;
  701. - if (host->h_length > (int)sizeof(sn->sin_addr)) {
  702. - host->h_length = sizeof(sn->sin_addr);
  703. - }
  704. - memcpy(&sn->sin_addr, host->h_addr_list[0], host->h_length);
  705. - close(net);
  706. - return 1;
  707. - }
  708. -#endif /* defined(h_addr) */
  709. -
  710. - perror("telnet: Unable to connect to remote host");
  711. - return 0;
  712. + if (::connect(net, addr->ai_addr, addr->ai_addrlen) < 0) {
  713. + return 1;
  714. }
  715. return 2;
  716. }
  717. diff --git a/telnet/netlink.h b/telnet/netlink.h
  718. index 9852b30..0ac8a08 100644
  719. --- a/telnet/netlink.h
  720. +++ b/telnet/netlink.h
  721. @@ -1,13 +1,16 @@
  722. class netlink {
  723. + private:
  724. + int family;
  725. protected:
  726. int net;
  727. public:
  728. netlink();
  729. ~netlink();
  730. - int connect(int debug, struct hostent *host,
  731. - struct sockaddr_in *sin,
  732. + int bind(struct addrinfo *hostaddr);
  733. + int socket(int family);
  734. + int connect(int debug, struct addrinfo *hostaddr,
  735. char *srcroute, int srlen,
  736. int tos);
  737. void close(int doshutdown);
  738. diff --git a/telnet/network.cc b/telnet/network.cc
  739. index 6a2c374..0dcf3e2 100644
  740. --- a/telnet/network.cc
  741. +++ b/telnet/network.cc
  742. @@ -40,6 +40,7 @@ char net_rcsid[] =
  743. #include <sys/types.h>
  744. #include <sys/socket.h>
  745. #include <sys/time.h>
  746. +#include <stdlib.h>
  747. #include <errno.h>
  748. #include <arpa/telnet.h>
  749. diff --git a/telnet/proto.h b/telnet/proto.h
  750. index 8be4a39..92f2419 100644
  751. --- a/telnet/proto.h
  752. +++ b/telnet/proto.h
  753. @@ -13,7 +13,7 @@ int TerminalWindowSize(long *rows, long *cols);
  754. void auth_encrypt_user(char *);
  755. void auth_name(unsigned char *, int);
  756. void auth_printsub(unsigned char *, int, unsigned char *, int);
  757. -void cmdrc(const char *m1, const char *m2);
  758. +void cmdrc(const char *, const char *, const char *);
  759. void env_init(void);
  760. int getconnmode(void);
  761. void init_network(void);
  762. diff --git a/telnet/ring.cc b/telnet/ring.cc
  763. index be57396..772c6c5 100644
  764. --- a/telnet/ring.cc
  765. +++ b/telnet/ring.cc
  766. @@ -165,7 +165,7 @@ int ringbuf::flush() {
  767. /////////////////////////////////////////////////// supply //////////////
  768. -void ringbuf::printf(const char *format, ...) {
  769. +void ringbuf::xprintf(const char *format, ...) {
  770. char xbuf[256];
  771. va_list ap;
  772. va_start(ap, format);
  773. diff --git a/telnet/ring.h b/telnet/ring.h
  774. index 15d3f3f..049377e 100644
  775. --- a/telnet/ring.h
  776. +++ b/telnet/ring.h
  777. @@ -83,7 +83,7 @@ class ringbuf {
  778. // manual supply
  779. void putch(char c) { write(&c, 1); }
  780. void write(const char *buffer, int ct);
  781. - void printf(const char *format, ...);
  782. + void xprintf(const char *format, ...);
  783. int empty_count() { return size - count; }
  784. // automatic supply
  785. diff --git a/telnet/sys_bsd.cc b/telnet/sys_bsd.cc
  786. index 93fba7e..a8c9aab 100644
  787. --- a/telnet/sys_bsd.cc
  788. +++ b/telnet/sys_bsd.cc
  789. @@ -189,18 +189,25 @@ void NetSetPgrp(int fd) {
  790. * Various signal handling routines.
  791. */
  792. +#if 0
  793. static void deadpeer(int /*sig*/) {
  794. setcommandmode();
  795. siglongjmp(peerdied, -1);
  796. }
  797. +#endif
  798. static void intr(int /*sig*/) {
  799. if (localchars) {
  800. intp();
  801. }
  802. else {
  803. +#if 0
  804. setcommandmode();
  805. siglongjmp(toplevel, -1);
  806. +#else
  807. + signal(SIGINT, SIG_DFL);
  808. + raise(SIGINT);
  809. +#endif
  810. }
  811. }
  812. @@ -214,6 +221,8 @@ static void intr2(int /*sig*/) {
  813. sendabort();
  814. return;
  815. }
  816. + signal(SIGQUIT, SIG_DFL);
  817. + raise(SIGQUIT);
  818. }
  819. #ifdef SIGWINCH
  820. @@ -238,7 +247,9 @@ void ayt(int sig) {
  821. void sys_telnet_init(void) {
  822. signal(SIGINT, intr);
  823. signal(SIGQUIT, intr2);
  824. +#if 0
  825. signal(SIGPIPE, deadpeer);
  826. +#endif
  827. #ifdef SIGWINCH
  828. signal(SIGWINCH, sendwin);
  829. #endif
  830. diff --git a/telnet/telnet.1 b/telnet/telnet.1
  831. index 54a47fb..8365e42 100644
  832. --- a/telnet/telnet.1
  833. +++ b/telnet/telnet.1
  834. @@ -42,8 +42,9 @@
  835. protocol
  836. .Sh SYNOPSIS
  837. .Nm telnet
  838. -.Op Fl 8ELadr
  839. +.Op Fl 468ELadr
  840. .Op Fl S Ar tos
  841. +.Op Fl b Ar address
  842. .Op Fl e Ar escapechar
  843. .Op Fl l Ar user
  844. .Op Fl n Ar tracefile
  845. @@ -68,6 +69,10 @@ command implicitly; see the description below.
  846. .Pp
  847. Options:
  848. .Bl -tag -width indent
  849. +.It Fl 4
  850. +Force IPv4 address resolution.
  851. +.It Fl 6
  852. +Force IPv6 address resolution.
  853. .It Fl 8
  854. Request 8-bit operation. This causes an attempt to negotiate the
  855. .Dv TELNET BINARY
  856. @@ -89,6 +94,8 @@ of the
  857. option if supported by the remote system. The username is retrieved
  858. via
  859. .Xr getlogin 3 .
  860. +.It Fl b Ar address
  861. +Use bind(2) on the local socket to bind it to a specific local address.
  862. .It Fl d
  863. Sets the initial value of the
  864. .Ic debug
  865. @@ -474,17 +481,29 @@ protocol without making a mess. Protocol negotiation can be forced by
  866. placing a dash before the port number.
  867. .Pp
  868. After establishing a connection, any commands associated with the
  869. -remote host in the user's
  870. +remote host in
  871. +.Pa /etc/telnetrc
  872. +and the user's
  873. .Pa .telnetrc
  874. -file are executed.
  875. +file are executed, in that order.
  876. .Pp
  877. -The format of the .telnetrc file is as follows: Lines beginning with a
  878. +The format of the telnetrc files is as follows: Lines beginning with a
  879. #, and blank lines, are ignored. The rest of the file should consist
  880. of hostnames and sequences of
  881. .Nm telnet
  882. commands to use with that host. Commands should be one per line,
  883. indented by whitespace; lines beginning without whitespace are
  884. -interpreted as hostnames. Upon connecting to a particular host, the
  885. +interpreted as hostnames. Lines beginning with the special hostname
  886. +.Ql DEFAULT
  887. +will apply to all hosts. Hostnames including
  888. +.Ql DEFAULT
  889. +may be followed immediately by a colon and a port number or string.
  890. +If a port is specified it must match exactly with what is specified
  891. +on the command line. If no port was specified on the command line,
  892. +then the value
  893. +.Ql telnet
  894. +is used.
  895. +Upon connecting to a particular host, the
  896. commands associated with that host are executed.
  897. .It Ic quit
  898. Close any open session and exit
  899. @@ -1184,9 +1203,7 @@ escape sequences are preceded by a '*' to aid in locating them.
  900. When the skiprc toggle is
  901. .Dv TRUE ,
  902. .Tn telnet
  903. -does not read the
  904. -.Pa \&.telnetrc
  905. -file. The initial value for this toggle is
  906. +does not read the telnetrc files. The initial value for this toggle is
  907. .Dv FALSE.
  908. .It Ic termdata
  909. Toggles the display of all terminal data (in hexadecimal format).
  910. @@ -1239,7 +1256,9 @@ to the other side via the
  911. .Dv TELNET ENVIRON
  912. option.
  913. .Sh FILES
  914. -.Bl -tag -width ~/.telnetrc -compact
  915. +.Bl -tag -width /etc/telnetrc -compact
  916. +.It Pa /etc/telnetrc
  917. +global telnet startup values
  918. .It Pa ~/.telnetrc
  919. user customized telnet startup values
  920. .El
  921. diff --git a/telnet/telnet.cc b/telnet/telnet.cc
  922. index 4fc3b1f..7eca811 100644
  923. --- a/telnet/telnet.cc
  924. +++ b/telnet/telnet.cc
  925. @@ -88,7 +88,8 @@ char do_dont_resp[256];
  926. char will_wont_resp[256];
  927. int
  928. -eight = 0,
  929. + eight = 3,
  930. + binary = 0,
  931. autologin = 0, /* Autologin anyone? */
  932. skiprc = 0,
  933. connected,
  934. @@ -639,14 +640,14 @@ static const char *gettermname(void) {
  935. if (resettermname) {
  936. resettermname = 0;
  937. tname = env_getvalue("TERM", 0);
  938. - if (!tname || my_setupterm(tname, 1, &err)) {
  939. + if (!tname /* || my_setupterm(tname, 1, &err) */) {
  940. termbuf[0] = 0;
  941. tname = "UNKNOWN";
  942. }
  943. mklist(termbuf, tname, termtypes);
  944. next = 0;
  945. }
  946. - if (next==termtypes.num()) next = 0;
  947. + if (next==termtypes.num()-1) next = 0;
  948. return termtypes[next++];
  949. }
  950. /*
  951. @@ -681,7 +682,7 @@ static void suboption(void) {
  952. }
  953. #endif /* TN3270 */
  954. name = gettermname();
  955. - netoring.printf("%c%c%c%c%s%c%c", IAC, SB, TELOPT_TTYPE,
  956. + netoring.xprintf("%c%c%c%c%s%c%c", IAC, SB, TELOPT_TTYPE,
  957. TELQUAL_IS, name, IAC, SE);
  958. }
  959. break;
  960. @@ -693,7 +694,7 @@ static void suboption(void) {
  961. if (SB_GET() == TELQUAL_SEND) {
  962. long oospeed, iispeed;
  963. TerminalSpeeds(&iispeed, &oospeed);
  964. - netoring.printf("%c%c%c%c%ld,%ld%c%c", IAC, SB, TELOPT_TSPEED,
  965. + netoring.xprintf("%c%c%c%c%ld,%ld%c%c", IAC, SB, TELOPT_TSPEED,
  966. TELQUAL_IS, oospeed, iispeed, IAC, SE);
  967. }
  968. break;
  969. @@ -780,7 +781,7 @@ static void suboption(void) {
  970. send_wont(TELOPT_XDISPLOC, 1);
  971. break;
  972. }
  973. - netoring.printf("%c%c%c%c%s%c%c", IAC, SB, TELOPT_XDISPLOC,
  974. + netoring.xprintf("%c%c%c%c%s%c%c", IAC, SB, TELOPT_XDISPLOC,
  975. TELQUAL_IS, dp, IAC, SE);
  976. }
  977. break;
  978. @@ -798,7 +799,7 @@ void lm_will(unsigned char *cmd, int len) {
  979. return;
  980. }
  981. - netoring.printf("%c%c%c%c%c%c%c", IAC, SB, TELOPT_LINEMODE,
  982. + netoring.xprintf("%c%c%c%c%c%c%c", IAC, SB, TELOPT_LINEMODE,
  983. DONT, cmd[0], IAC, SE);
  984. }
  985. @@ -815,7 +816,7 @@ void lm_do(unsigned char *cmd, int len) {
  986. /*@*/ printf("lm_do: no command!!!\n"); /* Should not happen... */
  987. return;
  988. }
  989. - netoring.printf("%c%c%c%c%c%c%c", IAC, SB, TELOPT_LINEMODE,
  990. + netoring.xprintf("%c%c%c%c%c%c%c", IAC, SB, TELOPT_LINEMODE,
  991. WONT, cmd[0], IAC, SE);
  992. }
  993. @@ -838,7 +839,7 @@ void lm_mode(unsigned char *cmd, int len, int init) {
  994. k |= MODE_ACK;
  995. }
  996. - netoring.printf("%c%c%c%c%c%c%c", IAC, SB, TELOPT_LINEMODE, LM_MODE,
  997. + netoring.xprintf("%c%c%c%c%c%c%c", IAC, SB, TELOPT_LINEMODE, LM_MODE,
  998. k, IAC, SE);
  999. setconnmode(0); /* set changed mode */
  1000. @@ -933,11 +934,11 @@ void slc_mode_import(int def) {
  1001. void slc_import(int def) {
  1002. if (def) {
  1003. - netoring.printf("%c%c%c%c%c%c%c%c%c", IAC, SB, TELOPT_LINEMODE,
  1004. + netoring.xprintf("%c%c%c%c%c%c%c%c%c", IAC, SB, TELOPT_LINEMODE,
  1005. LM_SLC, 0, SLC_DEFAULT, 0, IAC, SE);
  1006. }
  1007. else {
  1008. - netoring.printf("%c%c%c%c%c%c%c%c%c", IAC, SB, TELOPT_LINEMODE,
  1009. + netoring.xprintf("%c%c%c%c%c%c%c%c%c", IAC, SB, TELOPT_LINEMODE,
  1010. LM_SLC, 0, SLC_VARIABLE, 0, IAC, SE);
  1011. }
  1012. }
  1013. @@ -1050,6 +1051,7 @@ void slc_check(void) {
  1014. unsigned char slc_reply[128];
  1015. +unsigned char const * const slc_reply_eom = &slc_reply[sizeof(slc_reply)];
  1016. unsigned char *slc_replyp;
  1017. void slc_start_reply(void) {
  1018. @@ -1061,6 +1063,14 @@ void slc_start_reply(void) {
  1019. }
  1020. void slc_add_reply(int func, int flags, int value) {
  1021. + /* A sequence of up to 6 bytes my be written for this member of the SLC
  1022. + * suboption list by this function. The end of negotiation command,
  1023. + * which is written by slc_end_reply(), will require 2 additional
  1024. + * bytes. Do not proceed unless there is sufficient space for these
  1025. + * items.
  1026. + */
  1027. + if (&slc_replyp[6+2] > slc_reply_eom)
  1028. + return;
  1029. if ((*slc_replyp++ = func) == IAC)
  1030. *slc_replyp++ = IAC;
  1031. if ((*slc_replyp++ = flags) == IAC)
  1032. @@ -1142,6 +1152,7 @@ void env_opt(unsigned char *buf, int len) {
  1033. }
  1034. }
  1035. +/* OPT_REPLY_SIZE must be a multiple of 2. */
  1036. #define OPT_REPLY_SIZE 256
  1037. unsigned char *opt_reply;
  1038. unsigned char *opt_replyp;
  1039. @@ -1173,6 +1184,7 @@ void env_opt_start_info(void) {
  1040. void env_opt_add(const char *ep) {
  1041. const char *vp;
  1042. + const unsigned char *tp;
  1043. unsigned char c;
  1044. if (opt_reply == NULL) /*XXX*/
  1045. @@ -1185,11 +1197,12 @@ void env_opt_add(const char *ep) {
  1046. return;
  1047. }
  1048. vp = env_getvalue(ep, 1);
  1049. - if (opt_replyp + (vp ? strlen(vp) : 0) + strlen(ep) + 6 > opt_replyend)
  1050. + tp = opt_replyp + (vp ? strlen(vp) * 2 : 0) + strlen(ep) * 2 + 6;
  1051. + if (tp > opt_replyend)
  1052. {
  1053. register int len;
  1054. - opt_replyend += OPT_REPLY_SIZE;
  1055. - len = opt_replyend - opt_reply;
  1056. + len = ((tp - opt_reply) + OPT_REPLY_SIZE - 1) & ~(OPT_REPLY_SIZE - 1);
  1057. + opt_replyend = opt_reply + len;
  1058. opt_reply = (unsigned char *)realloc(opt_reply, len);
  1059. if (opt_reply == NULL) {
  1060. /*@*/ printf("env_opt_add: realloc() failed!!!\n");
  1061. @@ -1740,8 +1753,8 @@ void telnet(const char * /*user*/) {
  1062. send_do(TELOPT_STATUS, 1);
  1063. if (env_getvalue("DISPLAY", 0))
  1064. send_will(TELOPT_XDISPLOC, 1);
  1065. - if (eight)
  1066. - tel_enter_binary(eight);
  1067. + if (binary)
  1068. + tel_enter_binary(binary);
  1069. }
  1070. #endif /* !defined(TN3270) */
  1071. diff --git a/telnet/terminal.cc b/telnet/terminal.cc
  1072. index 9eb47ae..764f18f 100644
  1073. --- a/telnet/terminal.cc
  1074. +++ b/telnet/terminal.cc
  1075. @@ -45,6 +45,8 @@ char terminal_rcsid[] =
  1076. #include <signal.h>
  1077. #include <errno.h>
  1078. #include <stdio.h>
  1079. +#include <string.h>
  1080. +#include <stdlib.h>
  1081. #include "ring.h"
  1082. #include "defines.h"
  1083. @@ -155,9 +157,11 @@ int getconnmode(void) {
  1084. if (localflow)
  1085. mode |= MODE_FLOW;
  1086. - if (my_want_state_is_will(TELOPT_BINARY))
  1087. + if ((eight & 1) || my_want_state_is_will(TELOPT_BINARY))
  1088. mode |= MODE_INBIN;
  1089. + if (eight & 2)
  1090. + mode |= MODE_OUT8;
  1091. if (his_want_state_is_will(TELOPT_BINARY))
  1092. mode |= MODE_OUTBIN;
  1093. @@ -449,10 +453,13 @@ void TerminalNewMode(int f)
  1094. // breaks SunOS.
  1095. tmp_tc.c_iflag |= ISTRIP;
  1096. }
  1097. - if (f & MODE_OUTBIN) {
  1098. + if (f & (MODE_OUTBIN|MODE_OUT8)) {
  1099. tmp_tc.c_cflag &= ~(CSIZE|PARENB);
  1100. tmp_tc.c_cflag |= CS8;
  1101. - tmp_tc.c_oflag &= ~OPOST;
  1102. + if (f & MODE_OUTBIN)
  1103. + tmp_tc.c_oflag &= ~OPOST;
  1104. + else
  1105. + tmp_tc.c_oflag |= OPOST;
  1106. } else {
  1107. tmp_tc.c_cflag &= ~(CSIZE|PARENB);
  1108. tmp_tc.c_cflag |= old_tc.c_cflag & (CSIZE|PARENB);
  1109. @@ -468,7 +475,7 @@ void TerminalNewMode(int f)
  1110. #ifdef SIGINFO
  1111. signal(SIGINFO, ayt);
  1112. -#endif SIGINFO
  1113. +#endif /* SIGINFO */
  1114. #if defined(NOKERNINFO)
  1115. tmp_tc.c_lflag |= NOKERNINFO;
  1116. @@ -504,7 +511,7 @@ void TerminalNewMode(int f)
  1117. #ifdef SIGINFO
  1118. signal(SIGINFO, ayt_status);
  1119. -#endif SIGINFO
  1120. +#endif /* SIGINFO */
  1121. #ifdef SIGTSTP
  1122. signal(SIGTSTP, SIG_DFL);
  1123. diff --git a/telnet/utilities.cc b/telnet/utilities.cc
  1124. index 0448f0a..66839ab 100644
  1125. --- a/telnet/utilities.cc
  1126. +++ b/telnet/utilities.cc
  1127. @@ -47,6 +47,8 @@ char util_rcsid[] =
  1128. #include <sys/socket.h>
  1129. #include <unistd.h>
  1130. #include <ctype.h>
  1131. +#include <string.h>
  1132. +#include <stdlib.h>
  1133. #include "ring.h"
  1134. #include "defines.h"
  1135. --
  1136. 1.8.4.2