home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / x / volume21 / sxpc / part01 < prev    next >
Encoding:
Text File  |  1993-10-10  |  21.9 KB  |  852 lines

  1. Newsgroups: comp.sources.x
  2. From: rr2b+@andrew.cmu.edu (Robert Andrew Ryan)
  3. Subject: v21i012:  sxpc - Silly X Protocol Compressor, Part01/01
  4. Message-ID: <1993Oct10.155202.14791@sparky.sterling.com>
  5. X-Md4-Signature: 28690f5dd607092e7117cea564a05db8
  6. Sender: chris@sparky.sterling.com (Chris Olson)
  7. Organization: Sterling Software
  8. Date: Sun, 10 Oct 1993 15:52:02 GMT
  9. Approved: chris@sterling.com
  10.  
  11. Submitted-by: rr2b+@andrew.cmu.edu (Robert Andrew Ryan)
  12. Posting-number: Volume 21, Issue 12
  13. Archive-name: sxpc/part01
  14. Environment: X11, ANSI
  15.  
  16. [ This compiles, I didn't run any other tests on it... ]
  17. [                -- chris           ]
  18.  
  19. The Silly X protocol compressor gateway. (A Really Gross Hack) 
  20.  
  21. This program provides upto 75% compression of the X protocol stream. 
  22. It is intended to be used to improve the performance of X applications 
  23. over a slow internet connection.  (e.g. slip,cslip. or term)  It assumes 
  24. a Unix operating system at  both ends of the link. 
  25.  
  26.  WARNING WARNING  DANGER DANGER 
  27.  If you use this program use xauth to provide SECURITY, since 
  28.  host-based security will be BYPASSED. 
  29.  
  30. #!/bin/sh
  31. echo x - Imakefile
  32. sed -e 's/^X//' > Imakefile << '!Funky!Stuff!'
  33. X#ifndef XCOMM
  34. X#define XCOMM #
  35. X#endif
  36. XXCOMM The Silly X Protocol Compressor
  37. XXCOMM robr@cmu.edu
  38. XDEPLIBS=
  39. XSimpleProgramTarget(sxpc)
  40. !Funky!Stuff!
  41. echo x - Makefile
  42. sed -e 's/^X//' > Makefile << '!Funky!Stuff!'
  43. X# Makefile for the Silly X Protocol Compressor
  44. X# Rob Ryan (robr@cmu.edu)
  45. X# this assumes that cc can handle simple prototypes.
  46. X# if your compiler can't edit the sxpc.c to put
  47. X# all the function definitions in the old style.
  48. X# For generic BSD systems  (IBM RT, Decstation)
  49. Xsxpc:
  50. X    $(CC) -o sxpc sxpc.c
  51. X
  52. X# for RS/6000
  53. X#sxpc:
  54. X#    cc -D_BSD -o sxpc sxpc.c -lbsd
  55. X
  56. X# for HP
  57. X#sxpc:
  58. X#     c89 -D_INCLUDE_POSIX_SOURCE -D_INCLUDE_ANSI_SOURCE
  59. -D_INCLUDE_HPUX_SOURCE -D_INCLUDE_AES_SOURCE -DPOSIX -o sxpc sxpc.c
  60. !Funky!Stuff!
  61. echo x - README
  62. sed -e 's/^X//' > README << '!Funky!Stuff!'
  63. XThe Silly X protocol compressor gateway. (A Really Gross Hack) 
  64. X
  65. XThis program provides upto 75% compression of the X protocol stream. 
  66. XIt is intended to be used to improve the performance of X applications 
  67. Xover a slow internet connection.  (e.g. slip,cslip. or term)  It assumes 
  68. Xa Unix operating system at  both ends of the link. 
  69. X
  70. X WARNING WARNING  DANGER DANGER 
  71. X If you use this program use xauth to provide SECURITY, since 
  72. X host-based security will be BYPASSED. 
  73. X
  74. XCompilation: 
  75. Xxmkmf 
  76. Xmake 
  77. XIf this doesn't work you may have to compile it manually, if your compiler 
  78. Xclaims to be ANSI, but you don't have stdlib.h use -DNOSTDLIBPLEASE, if 
  79. Xyour system is POSIX try -D_POSIX_SOURCE.  If your system is vanilla BSD 
  80. Xcc -o sxpc sxpc.c should just work. 
  81. X
  82. XUsage: 
  83. X
  84. XOn X server host: 
  85. Xsxpc local $DISPLAY 
  86. X
  87. XOn X clients' host:
  88. XFor csh based shells:
  89. Xsetenv DISPLAY `sxpc remote $DISPLAY `
  90. X
  91. XFor sh based shells:
  92. XDISPLAY=`sxpc remote $DISPLAY`
  93. Xexport DISPLAY
  94. X(where $DISPLAY is the display setting you would normally use
  95. Xto connect to the X server from the clients' host.) 
  96. X
  97. X-Rob Ryan 
  98. Xrobr@cmu.edu 
  99. X/* 
  100. XCopyright Rob Ryan and Carnegie Mellon University 1993  - All Rights Reserved 
  101. X
  102. XPermission to use, copy, modify, and distribute this software and its    
  103. Xdocumentation for any purpose is hereby granted without fee, provided 
  104. Xthat the above copyright notice appear in all copies and that both that 
  105. Xcopyright notice, this permission notice, and the following disclaimer 
  106. Xappear in supporting documentation, and that the name Carnegie Mellon 
  107. XUniversity, not be used in advertising or publicity pertaining to 
  108. Xdistribution of the software without specific, written prior permission. 
  109. X                                  
  110. XCARNEGIE MELLON UNIVERSITY AND ROB RYAN 
  111. XDISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 
  112. XINCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 
  113. XAND FITNESS FOR ANY PARTICULAR PURPOSE.  
  114. XIN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY, OR 
  115. XROB RYAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR 
  116. XCONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER 
  117. XRESULTING FROM LOSS OF USE, DATA, OR PROFITS, 
  118. XWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE, OR 
  119. XOTHER TORTIOUS ACTION, ARISING OUT OF OR IN 
  120. XCONNECTION WITH THE USE OR PERFORMANCE OF THIS 
  121. XSOFTWARE.    
  122. X*/ 
  123. !Funky!Stuff!
  124. echo x - patchlevel.h
  125. sed -e 's/^X//' > patchlevel.h << '!Funky!Stuff!'
  126. X#define VersionString "Version 0.9"
  127. !Funky!Stuff!
  128. echo x - sxpc.1
  129. sed -e 's/^X//' > sxpc.1 << '!Funky!Stuff!'
  130. X.TH sxpc 1 "09sep1993" "X" "X"
  131. X.SH NAME
  132. XThe Silly X protocol compressor gateway. (A Really Gross Hack)
  133. X.SH SYNOPSIS
  134. XThis program provides upto 75% compression of the X protocol stream. It
  135. is intended to be used to improve the performance of X applications over
  136. a slow internet connection.  (e.g. slip, cslip, or term) It assumes a
  137. Unix operating system at  both ends of the link. 
  138. X
  139. X
  140. XWARNING WARNING  DANGER DANGER
  141. X
  142. XIf you use this program, use xauth to provide SECURITY, since 
  143. host-based security will be BYPASSED.  (If somebody knows you are
  144. running sxpc they will be able to connect to your server and watch what
  145. you type, what shows up on your screen, or type for you... A BAD THING
  146. :-()
  147. X
  148. X.SH DESCRIPTION
  149. XOn the X clients' host:
  150. X.PP
  151. XFor csh based shells:
  152. X.PP
  153. Xsetenv DISPLAY `sxpc remote $DISPLAY `
  154. X
  155. XFor sh based shells:
  156. X.PP
  157. XDISPLAY=`sxpc remote $DISPLAY`
  158. X.PP
  159. Xexport DISPLAY
  160. X.PP
  161. X(where $DISPLAY is the display setting you would normally use to
  162. connect to the X server from the clients' host.) 
  163. XOn the X server host:
  164. X sxpc local $DISPLAY
  165. X
  166. X.SH ENVIRONMENT VARIABLES
  167. X.PP
  168. XXCLIENTGATEPORT
  169. X.PP
  170. XSets the base port on which clients will connect to the  X server. 
  171. This will be added to the display number to get the final port number. 
  172. The default is 6008 so that by default the DISPLAY setting to connect to
  173. sxpc will be localhost:DisplayNumber+8:0.0 
  174. X
  175. XXCOMPGATEPORT
  176. X.PP
  177. XSets the base port on which the sxpc running on the X server host will
  178. listen for connections. This will be added to the display number to get
  179. the final port number.  The default is 4000 so that the sxpc on the X
  180. server host will listen on port 4000 (if it is directed to display on
  181. display 0.)
  182. X
  183. X.SH AUTHOR
  184. XRob Ryan (robr@cmu.edu)
  185. !Funky!Stuff!
  186. echo x - sxpc.c
  187. sed -e 's/^X//' > sxpc.c << '!Funky!Stuff!'
  188. X/*
  189. XCopyright Rob Ryan and Carnegie Mellon University 1993  - All Rights Reserved
  190. X
  191. XPermission to use, copy, modify, and distribute this software and its    
  192. Xdocumentation for any purpose is hereby granted without fee, provided
  193. Xthat the above copyright notice appear in all copies and that both that 
  194. Xcopyright notice, this permission notice, and the following disclaimer 
  195. Xappear in supporting documentation, and that the name Carnegie Mellon
  196. XUniversity, not be used in advertising or publicity pertaining to
  197. Xdistribution of the software without specific, written prior permission.
  198. X                                  
  199. XCARNEGIE MELLON UNIVERSITY AND ROB RYAN
  200. XDISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 
  201. XINCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 
  202. XAND FITNESS FOR ANY PARTICULAR PURPOSE.  
  203. XIN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY, OR
  204. XROB RYAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  205. XCONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
  206. XRESULTING FROM LOSS OF USE, DATA, OR PROFITS,
  207. XWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE, OR
  208. XOTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  209. XCONNECTION WITH THE USE OR PERFORMANCE OF THIS
  210. XSOFTWARE.    
  211. X*/
  212. X
  213. X/* The Silly X protocol compressor gateway. (A Really Gross Hack)
  214. X
  215. X TODO:
  216. XThis program compresses the X protocol by replacing repeated occurrences
  217. Xof 4 byte values with a one or two byte index into the most recent values
  218. Xsent.  The lookup for recent values is a simple linear search, this limits
  219. Xthe amount of history which can be kept without making computation the
  220. Xdominating time factor.  A possible solution for this is to switch to a
  221. Xcircular history buffer, with a hash table of the longs which contains
  222. Xthe index of each long in the history list  (This proposal also calls
  223. Xfor bringing old values to the most recent position without copying all
  224. Xthe values which WERE more recent than the old value down.  Thus a gap
  225. Xwill be left, making values older than that age more quickly.  Thus it
  226. Xwill require twice as much history space to ensure the same number of
  227. Xhistoric values are available.)
  228. X
  229. X Find and use a real compression algorithm.
  230. X
  231. X Allow for different blocking factors.  (Otherwise there is a pause before
  232. X a redraw while most or all of the data is sent over.)  ~250 is probably
  233. X good for cslip. 
  234. X -Rob Ryan (robr@cmu.edu)
  235. X Sept, 1993.
  236. X */
  237. X
  238. X/* use -DMAXPACKET=1022 or whatever if you want a larger or smaller
  239. X packet size over the slow link.  Note that a 2 byte header will be sent in
  240. X addition to upto MAXPACKET bytes of data. */
  241. X#ifndef MAXPACKET
  242. X#define MAXPACKET 254
  243. X#endif
  244. X
  245. X#include "patchlevel.h"
  246. X
  247. X#include <X11/Xos.h>
  248. X
  249. X#if defined(__STDC__) && !defined(ibm032) && !defined(NOSTDLIBPLEASE)
  250. X#include <stdlib.h>
  251. X#else
  252. X#ifdef _POSIX_SOURCE
  253. X#include <unistd.h>
  254. X#else
  255. Xextern char *getenv();
  256. X#endif
  257. X#endif
  258. X
  259. X#include <stdio.h>
  260. X#include <sys/types.h>
  261. X#include <sys/socket.h>
  262. X#include <netinet/in.h>
  263. X#include <sys/file.h>
  264. X#include <netdb.h>
  265. X#if defined(_IBMR2) || defined(AIXV3)
  266. X#include <sys/select.h>
  267. X#endif
  268. X#include <errno.h>
  269. X#include <string.h>
  270. X#include <signal.h>
  271. X#include <sys/resource.h>
  272. X#include <sys/wait.h>
  273. X#include <ctype.h>
  274. X
  275. Xint compression=0; /* -1 uncompress, 0 no compression, 1 compress */
  276. Xstruct sockaddr_in servaddr; 
  277. Xextern int errno;
  278. X
  279. X
  280. X#if defined(__hpux) || defined(hpux)
  281. Xint getdtablesize() {
  282. X    return 32; /* should do the right thing here, but I don't have the
  283. POSIX book handy */
  284. X}
  285. X#endif
  286. X
  287. X
  288. Xint client()
  289. X{
  290. X    int sock;
  291. X    unsigned char *iaddr=(unsigned char *)&servaddr.sin_addr;
  292. X    if ((sock = socket(AF_INET, SOCK_STREAM, PF_UNSPEC)) == -1) {
  293. X    perror("socket");
  294. X    return -1;
  295. X    }
  296. X
  297. X    if (connect(sock, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1) {
  298. X    fprintf(stderr, "port:%d\n",ntohs(servaddr.sin_port));
  299. X    fprintf(stderr, "addr:%d.%d.%d.%d\n", iaddr[0], iaddr[1], iaddr[2],
  300. iaddr[3]);
  301. X    perror("connect");
  302. X    return -1;
  303. X    }
  304. X
  305. X    return sock;
  306. X}
  307. X
  308. X#define MAXTRANBUF 65536
  309. X
  310. Xint reallywrite(fd, buf, len)
  311. Xint fd;
  312. Xunsigned char *buf;
  313. Xint len;
  314. X{
  315. X    int r;
  316. X    while(len>0) {
  317. X    r=write(fd, buf, len);
  318. X    if(r<0) {
  319. X        perror("write");
  320. X        exit(-1);
  321. X    }
  322. X    buf+=r;
  323. X    len-=r;
  324. X    }
  325. X}
  326. X
  327. Xtypedef unsigned long thet;
  328. X#define NTOH(x) ntohl(x)
  329. X#define HTON(x) htonl(x)
  330. X#define WRITE(x) OUTBYTE((x)&0xff);OUTBYTE((x)>>8);OUTBYTE((x)>>16);OUTBYTE((x)>>24);
  331. X#define READ(w,x,y,z) (((thet)w)|(((thet)x)<<8)|(((thet)y)<<16)|(((thet)z)<<24))
  332. X
  333. X#define HISTORY 2048
  334. X#define SCOUNTMAX 128
  335. X#define COUNTBASE 192
  336. Xstatic thet chistory[HISTORY];
  337. Xstatic int cnext=0;
  338. Xstatic thet uhistory[HISTORY];
  339. Xstatic int unext=0;
  340. X
  341. X#define OUTBYTE(blah)  do { *out++=((blah)&0xff); csize--, size++;} while (0)
  342. Xint scompress(cbuf, csize, buf, len)
  343. Xunsigned char *cbuf;
  344. Xint csize;
  345. Xunsigned char **buf;
  346. Xint *len;
  347. X{
  348. X    thet *p=(thet *)*buf;
  349. X    unsigned char *out=cbuf;
  350. X    unsigned char *prev=NULL;
  351. X    int i;
  352. X    int scan=0;
  353. X    int size=0;
  354. X    if(*len&1) {
  355. X    fprintf(stderr, "WARNING WARNING WARNING, odd packet size...\n");
  356. X    exit(-1);
  357. X    }
  358. X#ifdef LOGDATA
  359. X    fprintf(stderr,"sending: ");
  360. X    for(i=0;i<len;i++) fprintf(stderr, "%x ",*buf[i]);
  361. X    fprintf(stderr,"\n");
  362. X#endif
  363. X    
  364. X    while(*len>0 && csize>0) {
  365. X    thet sh=HTON(*p);
  366. X    for(scan=cnext-1;scan>=0;scan--) {
  367. X        if(sh==chistory[scan]) {
  368. X        int scanx=cnext-1-scan;
  369. X        prev=NULL;
  370. X        if(scanx>=SCOUNTMAX) {
  371. X            if(csize<2) return size;
  372. X            OUTBYTE(((scanx>>8)&0x7)+SCOUNTMAX);
  373. X            OUTBYTE(scanx&0xff);
  374. X        } else OUTBYTE(scanx);
  375. X        for(i=scan+1;i<cnext;i++) {
  376. X            chistory[i-1]=chistory[i];
  377. X        }
  378. X        chistory[cnext-1]=sh;
  379. X        p++;
  380. X        *len-=sizeof(thet);
  381. X        *buf+=sizeof(thet);
  382. X        break;
  383. X        }
  384. X    }
  385. X    if(scan>=0) continue;
  386. X    if(csize<sizeof(thet)) return size;
  387. X    if(prev && *prev<0xff) {
  388. X        (*prev)++;
  389. X    } else {
  390. X        if(csize<sizeof(thet)+1) return size;
  391. X        prev=out;
  392. X        OUTBYTE(COUNTBASE);
  393. X    }
  394. X    WRITE(sh);
  395. X    p++;
  396. X    *len-=sizeof(thet);
  397. X    *buf+=sizeof(thet);
  398. X    if(cnext<HISTORY) {
  399. X        chistory[cnext]=sh;
  400. X        cnext++;
  401. X       
  402. X    } else {
  403. X        bcopy(&chistory[1], &chistory[0], sizeof(chistory)-sizeof(chistory[0]));
  404. X        chistory[cnext-1]=sh;
  405. X    }
  406. X    }
  407. X    return size;
  408. X}
  409. X
  410. Xstatic unsigned char c2buf[65538];
  411. Xstatic unsigned char c3buf[65538];
  412. X    
  413. Xint unscompress(src, len, dest)
  414. Xunsigned char *src;
  415. Xint len;
  416. Xunsigned char *dest;
  417. X{
  418. X    int ulen=0;
  419. X    int i;
  420. X#ifdef LOGDATA
  421. X    unsigned char *odest=dest;
  422. X    fprintf(stderr, "uncompressing: ");
  423. X    for(i=0;i<len;i++) {
  424. X    fprintf(stderr, "%x ", src[i]);
  425. X    }
  426. X    fprintf(stderr, "\n");
  427. X#endif
  428. X    while(len>0) {
  429. X    thet sh=0;
  430. X    if(*src>=COUNTBASE) {
  431. X        int shorts=(*src-(COUNTBASE-1));
  432. X        
  433. X        len--;
  434. X        src++;
  435. X
  436. X        while(shorts>0) {
  437. X
  438. X        sh=READ(src[0], src[1], src[2], src[3]);
  439. X        sh=NTOH(sh);
  440. X        if(unext<HISTORY) {
  441. X            uhistory[unext]=sh;
  442. X            unext++;
  443. X        } else {
  444. X            bcopy(&uhistory[1], &uhistory[0], sizeof(uhistory)-sizeof(uhistory[0]));
  445. X            uhistory[unext-1]=sh;
  446. X        }
  447. X        *((thet *)dest)=(sh);
  448. X        ulen+=sizeof(thet);
  449. X        dest+=sizeof(thet);
  450. X        src+=sizeof(thet);
  451. X        len-=sizeof(thet);
  452. X        shorts--;
  453. X        }
  454. X    } else if(*src<SCOUNTMAX+8) {
  455. X        int scanx;
  456. X        if(*src>=SCOUNTMAX) {
  457. X        scanx=(((src[0])-SCOUNTMAX)<<8)+src[1];
  458. X        len--;
  459. X        src++;
  460. X        } else scanx=(*src);
  461. X        scanx=unext-1-scanx;
  462. X        sh=(uhistory[scanx]);
  463. X        *((thet *)dest)=sh;
  464. X        for(i=scanx+1;i<unext;i++) {
  465. X        uhistory[i-1]=uhistory[i];
  466. X        }
  467. X        uhistory[unext-1]=sh;
  468. X        ulen+=sizeof(thet);
  469. X        dest+=sizeof(thet);
  470. X        len--;
  471. X        src++;
  472. X    } else {
  473. X        fprintf(stderr, "Bad data!!! %d\n", *src);
  474. X    }
  475. X    }
  476. X
  477. X#ifdef LOGDATA
  478. X    fprintf(stderr, "received: ");
  479. X    for(i=0;i<ulen;i++) fprintf(stderr, "%x ", odest[i]);
  480. X    fprintf(stderr, "\n");
  481. X#endif
  482. X    return ulen;
  483. X}
  484. X
  485. Xstatic unsigned char mbuf[MAXTRANBUF];
  486. X#undef MAX
  487. X#define MAX(x,y) ((x<y)?(y):(x))
  488. X
  489. Xint dosstuff(fd)
  490. Xint fd;
  491. X{
  492. X    fd_set rfs;
  493. X    int xfd;
  494. X    xfd=client();
  495. X    if(xfd<0) {
  496. X    perror("client");
  497. X    exit(-1);
  498. X    }
  499. X    while(1) {
  500. X    int nfds;
  501. X    FD_ZERO(&rfs);
  502. X    FD_SET(fd, &rfs);
  503. X    FD_SET(xfd, &rfs);
  504. X#if defined(__hpux) || defined(hpux)
  505. X#define CASTREADMASK(x) ((int *)(x))
  506. X#else
  507. X#define CASTREADMASK(x) (x)
  508. X#endif
  509. X    
  510. X    nfds=select(MAX(fd, xfd)+1, CASTREADMASK(&rfs), NULL, NULL, NULL);
  511. X    if(nfds==0) continue;
  512. X    if(nfds<0) {
  513. X        if(errno==EINTR) continue;
  514. X        perror("select");
  515. X        continue;
  516. X    }
  517. X    if(FD_ISSET(fd, &rfs)) {
  518. X        if(compression==-1) {
  519. X        unsigned short readlen;
  520. X        int len=0;
  521. X        while(len<2) {
  522. X            int r=read(fd, ((char *)&readlen)+len, 2-len);
  523. X            if(r<=0) {
  524. X            exit(-1);
  525. X            }
  526. X            len+=r;
  527. X        }
  528. X        len=0;
  529. X        readlen=ntohs(readlen);
  530. X        while(len<readlen) {
  531. X            int r=read(fd, mbuf+len, readlen-len);
  532. X            if(r<=0) {
  533. X            exit(-1);
  534. X            }
  535. X            len+=r;
  536. X        }
  537. X        len=unscompress(mbuf, len, c2buf);
  538. X        reallywrite(xfd, c2buf, len);
  539. X
  540. X        } else if(compression==1) {
  541. X        unsigned char *ptr=mbuf;
  542. X        int len=read(fd, mbuf, sizeof(mbuf));
  543. X        int j;
  544. X        if(len<=0) {
  545. X            exit(-1);
  546. X        }
  547. X        while(len>0) {
  548. X            int oldlen=len;
  549. X            j=scompress(c3buf+2, MAXPACKET, &ptr, &len);
  550. X        /* printf("compressed %d to %d\n", oldlen-len, j+2); */
  551. X            *((unsigned short *)c3buf)=htons(j);
  552. X            reallywrite(xfd, c3buf, j+2);
  553. X        }
  554. X        }
  555. X    }
  556. X    if(FD_ISSET(xfd, &rfs)) {
  557. X        if(compression==1) {
  558. X        unsigned short readlen;
  559. X        int len=0;
  560. X        while(len<2) {
  561. X            int r=read(xfd, ((char *)&readlen)+len, 2-len);
  562. X            if(r<=0) {
  563. X            exit(-1);
  564. X            }
  565. X            len+=r;
  566. X        }
  567. X        len=0;
  568. X        readlen=ntohs(readlen);
  569. X        while(len<readlen) {
  570. X            int r=read(xfd, mbuf+len, readlen-len);
  571. X            if(r<=0) {
  572. X            exit(-1);
  573. X            }
  574. X            len+=r;
  575. X        }
  576. X        len=unscompress(mbuf, len, c2buf);
  577. X        reallywrite(fd, c2buf, len);
  578. X        } else if(compression==-1) {
  579. X        unsigned char *ptr=mbuf;
  580. X        int len=read(xfd, mbuf, sizeof(mbuf));
  581. X        int j;
  582. X        if(len<=0) {
  583. X            exit(-1);
  584. X        }
  585. X        while(len>0) {
  586. X            int oldlen=len;
  587. X            j=scompress(c3buf+2, MAXPACKET, &ptr, &len);
  588. X        /* printf("compressed %d to %d\n", oldlen-len, j+2); */
  589. X            *((unsigned short *)c3buf)=htons(j);
  590. X            reallywrite(fd, c3buf, j+2);
  591. X        }
  592. X        }
  593. X        
  594. X    }
  595. X    }   
  596. X}
  597. X
  598. X#ifdef SO_LINGER
  599. Xstruct linger blah={
  600. X    0,
  601. X    0
  602. X};
  603. X#endif
  604. X
  605. Xint server(portnum)
  606. Xshort portnum;
  607. X{
  608. X    int one=1;
  609. X    int servsock, clientsock;
  610. X    struct sockaddr_in servsockaddr, clientsockaddr;
  611. X    int clientsockaddrlen;
  612. X    int pid;
  613. X
  614. X    if ((servsock = socket(AF_INET, SOCK_STREAM, PF_UNSPEC)) == -1) {
  615. X    perror("socket");
  616. X    return -1;
  617. X    }
  618. X
  619. X#ifdef SO_REUSEADDR
  620. X    setsockopt(servsock,SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
  621. X#endif
  622. X
  623. X#ifdef SO_LINGER
  624. X    setsockopt(servsock, SOL_SOCKET, SO_LINGER, &blah, sizeof(blah));
  625. X#endif
  626. X
  627. X    servsockaddr.sin_family = AF_INET;
  628. X    servsockaddr.sin_port = htons(portnum);
  629. X    servsockaddr.sin_addr.s_addr = 0;
  630. X
  631. X    if (bind(servsock, (struct sockaddr *)&servsockaddr,
  632. sizeof(servsockaddr)) == -1) {
  633. X    perror("bind");
  634. X    return -1;
  635. X    }
  636. X
  637. X    if (listen(servsock, 5) == -1) {
  638. X    perror("listen");
  639. X    return -1;
  640. X    }
  641. X
  642. X    if(pid=fork()) {
  643. X    if(pid<0) perror("fork");
  644. X    else exit(0);
  645. X    }
  646. X    close(1);
  647. X    close(0);
  648. X    dup2(2, 1);
  649. X    for (;;) {
  650. X    clientsockaddrlen = sizeof(clientsockaddr);
  651. X    clientsock = accept(servsock, &clientsockaddr, &clientsockaddrlen);
  652. X    if (clientsock == -1) {
  653. X        if(errno!=EINTR) perror("accept");
  654. X        continue;
  655. X    }
  656. X    if(fork()==0) {
  657. X        int i;
  658. X        int count=getdtablesize();
  659. X        for(i=3;i<count;i++) {
  660. X        if(i!=clientsock) close(i);
  661. X        }
  662. X        dosstuff(clientsock);
  663. X    } else close(clientsock);
  664. X    }
  665. X}
  666. X
  667. Xstatic int GetXServAddr(dname)
  668. Xchar *dname;
  669. X{
  670. X    struct hostent *hp;
  671. X    char *hostname;
  672. X    char *p;
  673. X    unsigned char inetaddr[4];
  674. X    int dnum=0;
  675. X    int count=0;
  676. X    
  677. X    p=strchr(dname, ':');
  678. X    if(p==NULL || !(isascii(*(p+1)) && isdigit(*(p+1)))) {
  679. X    fprintf(stderr, "DISPLAY must be of the form:
  680. [HostnameOrUnix]:DisplayNumber[.ScreenNumber]\n");
  681. X    exit(-1);
  682. X    }
  683. X    *p='\0';
  684. X    dnum=atoi(p+1);
  685. X    
  686. X    if(dname[0]=='\0' || strcmp(dname, "unix")==0) hostname="localhost";
  687. X    else hostname=dname;
  688. X    if(isascii(hostname[0]) && isdigit(hostname[0])) {
  689. X    inetaddr[0]=atoi(hostname);
  690. X    count++;
  691. X    p=strchr(hostname, '.');
  692. X    if(p) {
  693. X        inetaddr[1]=atoi(p+1);
  694. X        count++;
  695. X        p=strchr(p+1, '.');
  696. X        if(p) {
  697. X        inetaddr[2]=atoi(p+1);
  698. X        count++;
  699. X        p=strchr(p+1, '.');
  700. X        if(p) {
  701. X            inetaddr[3]=atoi(p+1);
  702. X            count++;
  703. X        }
  704. X        }
  705. X    }
  706. X    if(count!=4) {
  707. X        fprintf(stderr, "Badly formed IP address %s\n", hostname);
  708. X        exit(-1);
  709. X    }
  710. X    bcopy(inetaddr, (char *)&servaddr.sin_addr, sizeof(servaddr.sin_addr));
  711. X    } else {
  712. X    hp = gethostbyname(hostname);
  713. X    if (hp == NULL) {
  714. X        fprintf(stderr, "Can't find address for host %s\n", hostname);
  715. X        exit(-1);
  716. X    }
  717. X    bcopy(hp->h_addr, (char *)&servaddr.sin_addr, sizeof(servaddr.sin_addr));
  718. X    }
  719. X
  720. X    servaddr.sin_family = AF_INET;
  721. X    servaddr.sin_port = htons(6000 + dnum);
  722. X    return dnum;
  723. X}
  724. X
  725. Xstatic int GetGatewayServAddr(dname, clientbase, serverbase)
  726. Xchar *dname;
  727. Xint clientbase;
  728. Xint serverbase;
  729. X{
  730. X    struct hostent *hp;
  731. X    char *hostname;
  732. X    char *p;
  733. X    unsigned char inetaddr[4];
  734. X    int dnum=0;
  735. X    int count=0;
  736. X    int snum=0;
  737. X        
  738. X    p=strchr(dname, ':');
  739. X    if(p==NULL || !(isascii(*(p+1)) && isdigit(*(p+1)))) {
  740. X    fprintf(stderr, "DISPLAY must be of the form:
  741. [HostnameOrUnix]:DisplayNumber[.ScreenNumber]\n");
  742. X    exit(-1);
  743. X    }
  744. X    *p='\0';
  745. X    dnum=atoi(p+1);
  746. X    p=strchr(p+1, '.');
  747. X    if(p) snum=atoi(p+1);
  748. X    
  749. X    if(dname[0]=='\0' || strcmp(dname, "unix")==0) hostname="localhost";
  750. X    else hostname=dname;
  751. X    if(isascii(hostname[0]) && isdigit(hostname[0])) {
  752. X    inetaddr[0]=atoi(hostname);
  753. X    count++;
  754. X    p=strchr(hostname, '.');
  755. X    if(p) {
  756. X        inetaddr[1]=atoi(p+1);
  757. X        count++;
  758. X        p=strchr(p+1, '.');
  759. X        if(p) {
  760. X        inetaddr[2]=atoi(p+1);
  761. X        count++;
  762. X        p=strchr(p+1, '.');
  763. X        if(p) {
  764. X            inetaddr[3]=atoi(p+1);
  765. X            count++;
  766. X        }
  767. X        }
  768. X    }
  769. X    if(count!=4) {
  770. X        fprintf(stderr, "Badly formed IP address %s\n", hostname);
  771. X        exit(-1);
  772. X    }
  773. X    bcopy(inetaddr, (char *)&servaddr.sin_addr, sizeof(servaddr.sin_addr));
  774. X    } else {
  775. X    hp = gethostbyname(hostname);
  776. X    if (hp == NULL) {
  777. X        fprintf(stderr, "Can't find address for host %s\n", hostname);
  778. X        exit(-1);
  779. X    }
  780. X    bcopy(hp->h_addr, (char *)&servaddr.sin_addr, sizeof(servaddr.sin_addr));
  781. X    }
  782. X    printf("localhost:%d.%d\n",clientbase-6000+dnum, snum);
  783. X    servaddr.sin_family = AF_INET;
  784. X    servaddr.sin_port = htons(serverbase + dnum);
  785. X    return dnum;
  786. X}
  787. X
  788. X#if defined(_POSIX_SOURCE) || defined(SYSV)
  789. Xvoid Reaper(n)
  790. Xint n;
  791. X{
  792. X    while(waitpid(-1, NULL, WNOHANG)>0);
  793. X#ifdef SYSV
  794. X    signal(SIGCHLD, Reaper);
  795. X#endif
  796. X}
  797. X#else
  798. Xint Reaper(n)
  799. Xint n;
  800. X{
  801. X    union wait status;
  802. X    while(wait3(&status, WNOHANG, NULL)>0);
  803. X    return 0;
  804. X}
  805. X#endif
  806. X
  807. Xint main(argc, argv)
  808. Xint argc;
  809. Xchar **argv;
  810. X{
  811. X    char *p=getenv("XCOMPGATEPORT");
  812. X    char *q=getenv("XCLIENTGATEPORT");
  813. X    int clientbase=6008;
  814. X    int serverbase=4000;
  815. X
  816. X    if(p) serverbase=atoi(p);
  817. X    if(serverbase==0) serverbase=4000;
  818. X
  819. X    if(q) clientbase=atoi(q);
  820. X    if(clientbase==0) clientbase=6008;
  821. X    
  822. X    signal(SIGCHLD, Reaper);
  823. X    
  824. X    if(argc<3) {
  825. X    fprintf(stderr, "%s\n", VersionString);
  826. X    fprintf(stderr, "On the X server host:\n\tsxpc local $DISPLAY\nOn the
  827. X clients' host:\n\tsetenv DISPLAY `sxpc remote $REMOTEDISPLAY`\n(Where
  828. $REMOTEDISPLAY is the DISPLAY variable setting which would otherwise be
  829. used.)\n");
  830. X    exit(-1);
  831. X    }
  832. X    
  833. X    compression=(argv[1][0]=='l')?-1:1;
  834. X    if(compression==-1) {
  835. X    server(GetXServAddr(argv[2])+serverbase);
  836. X    } else {
  837. X    server(clientbase+GetGatewayServAddr(argv[2], clientbase, serverbase));
  838. X    }
  839. X}
  840. X
  841. !Funky!Stuff!
  842. exit
  843.  
  844. exit 0 # Just in case...
  845. -- 
  846.   // chris@Sterling.COM           | Send comp.sources.x submissions to:
  847. \X/  Amiga - The only way to fly! |    sources-x@sterling.com
  848.  "It's intuitively obvious to the |
  849.   most casual observer..."        | GCS d+/-- p+ c++ l+ m+ s++/+ g+ w+ t+ r+ x+
  850.