URI: 
       tplan9.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       tplan9.c (5463B)
       ---
            1 #include <u.h>
            2 #include <sys/types.h>
            3 #include <sys/stat.h>
            4 #include <errno.h>
            5 
            6 #include <u.h>
            7 #include <libc.h>
            8 #include <draw.h>
            9 #include <thread.h>
           10 #include <mouse.h>
           11 #include <cursor.h>
           12 #include <keyboard.h>
           13 #include <frame.h>
           14 #define Tversion Tversion9p
           15 #define Twrite Twrite9p
           16 #include <fcall.h>
           17 #undef Tversion
           18 #undef Twrite
           19 #include <9pclient.h>
           20 #include <plumb.h>
           21 #include "flayer.h"
           22 #include "samterm.h"
           23 
           24 static char *exname;
           25 
           26 #define STACK 16384
           27 
           28 void
           29 usage(void)
           30 {
           31         fprint(2, "usage: samterm -a -W winsize\n");
           32         threadexitsall("usage");
           33 }
           34 
           35 void
           36 getscreen(int argc, char **argv)
           37 {
           38         char *t;
           39 
           40         ARGBEGIN{
           41         case 'a':
           42                 autoindent = 1;
           43                 break;
           44         case 'W':
           45                 winsize = EARGF(usage());
           46                 break;
           47         default:
           48                 usage();
           49         }ARGEND
           50 
           51         if(initdraw(panic1, nil, "sam") < 0){
           52                 fprint(2, "samterm: initdraw: %r\n");
           53                 threadexitsall("init");
           54         }
           55         t = getenv("tabstop");
           56         if(t != nil){
           57                 maxtab = strtoul(t, nil, 0);
           58                 free(t);
           59         }
           60         draw(screen, screen->clipr, display->white, nil, ZP);
           61 }
           62 
           63 int
           64 screensize(int *w, int *h)
           65 {
           66         int fd, n;
           67         char buf[5*12+1];
           68 
           69         fd = open("/dev/screen", OREAD);
           70         if(fd < 0)
           71                 return 0;
           72         n = read(fd, buf, sizeof(buf)-1);
           73         close(fd);
           74         if (n != sizeof(buf)-1)
           75                 return 0;
           76         buf[n] = 0;
           77         if (h) {
           78                 *h = atoi(buf+4*12)-atoi(buf+2*12);
           79                 if (*h < 0)
           80                         return 0;
           81         }
           82         if (w) {
           83                 *w = atoi(buf+3*12)-atoi(buf+1*12);
           84                 if (*w < 0)
           85                         return 0;
           86         }
           87         return 1;
           88 }
           89 
           90 int
           91 snarfswap(char *fromsam, int nc, char **tosam)
           92 {
           93         char *s;
           94 
           95         s = getsnarf();
           96         putsnarf(fromsam);
           97         *tosam = s;
           98         return s ? strlen(s) : 0;
           99 }
          100 
          101 void
          102 dumperrmsg(int count, int type, int count0, int c)
          103 {
          104         fprint(2, "samterm: host mesg: count %d %ux %ux %ux %s...ignored\n",
          105                 count, type, count0, c, rcvstring());
          106 }
          107 
          108 void
          109 removeextern(void)
          110 {
          111         remove(exname);
          112 }
          113 
          114 Readbuf        hostbuf[2];
          115 Readbuf        plumbbuf[2];
          116 
          117 void
          118 extproc(void *argv)
          119 {
          120         Channel *c;
          121         int i, n, which, fd;
          122         void **arg;
          123 
          124         arg = argv;
          125         c = arg[0];
          126         fd = (int)(uintptr)arg[1];
          127 
          128         i = 0;
          129         for(;;){
          130                 i = 1-i;        /* toggle */
          131                 n = read(fd, plumbbuf[i].data, sizeof plumbbuf[i].data);
          132 if(0) fprint(2, "ext %d\n", n);
          133                 if(n <= 0){
          134                         fprint(2, "samterm: extern read error: %r\n");
          135                         threadexits("extern");        /* not a fatal error */
          136                 }
          137                 plumbbuf[i].n = n;
          138                 which = i;
          139                 send(c, &which);
          140         }
          141 }
          142 
          143 void
          144 extstart(void)
          145 {
          146         char *user, *disp;
          147         int fd, flags;
          148         static void *arg[2];
          149 
          150         user = getenv("USER");
          151         if(user == nil)
          152                 return;
          153         disp = getenv("DISPLAY");
          154         if(disp){
          155                 exname = smprint("/tmp/.sam.%s.%s", user, disp);
          156                 free(disp);
          157         }
          158         else
          159                 exname = smprint("/tmp/.sam.%s", user);
          160         free(user);
          161         if(exname == nil){
          162                 fprint(2, "not posting for B: out of memory\n");
          163                 return;
          164         }
          165 
          166         if(mkfifo(exname, 0600) < 0){
          167                 struct stat st;
          168                 if(errno != EEXIST || stat(exname, &st) < 0)
          169                         return;
          170                 if(!S_ISFIFO(st.st_mode)){
          171                         removeextern();
          172                         if(mkfifo(exname, 0600) < 0)
          173                                 return;
          174                 }
          175         }
          176 
          177         fd = open(exname, OREAD|ONONBLOCK);
          178         if(fd == -1){
          179                 removeextern();
          180                 return;
          181         }
          182 
          183         /*
          184          * Turn off no-delay and provide ourselves as a lingering
          185          * writer so as not to get end of file on read.
          186          */
          187         flags = fcntl(fd, F_GETFL, 0);
          188         if(flags<0 || fcntl(fd, F_SETFL, flags&~O_NONBLOCK)<0
          189         ||open(exname, OWRITE) < 0){
          190                 close(fd);
          191                 removeextern();
          192                 return;
          193         }
          194 
          195         plumbc = chancreate(sizeof(int), 0);
          196         chansetname(plumbc, "plumbc");
          197         arg[0] = plumbc;
          198         arg[1] = (void*)(uintptr)fd;
          199         proccreate(extproc, arg, STACK);
          200         atexit(removeextern);
          201 }
          202 
          203 int
          204 plumbformat(Plumbmsg *m, int i)
          205 {
          206         char *addr, *data, *act;
          207         int n;
          208 
          209         data = (char*)plumbbuf[i].data;
          210         n = m->ndata;
          211         if(n == 0 || 2+n+2 >= READBUFSIZE){
          212                 plumbfree(m);
          213                 return 0;
          214         }
          215         act = plumblookup(m->attr, "action");
          216         if(act!=nil && strcmp(act, "showfile")!=0){
          217                 /* can't handle other cases yet */
          218                 plumbfree(m);
          219                 return 0;
          220         }
          221         addr = plumblookup(m->attr, "addr");
          222         if(addr){
          223                 if(addr[0] == '\0')
          224                         addr = nil;
          225                 else
          226                         addr = strdup(addr);        /* copy to safe storage; we'll overwrite data */
          227         }
          228         memmove(data, "B ", 2);        /* we know there's enough room for this */
          229         memmove(data+2, m->data, n);
          230         n += 2;
          231         if(data[n-1] != '\n')
          232                 data[n++] = '\n';
          233         if(addr != nil){
          234                 if(n+strlen(addr)+1+1 <= READBUFSIZE)
          235                         n += sprint(data+n, "%s\n", addr);
          236                 free(addr);
          237         }
          238         plumbbuf[i].n = n;
          239         plumbfree(m);
          240         return 1;
          241 }
          242 
          243 void
          244 plumbproc(void *arg)
          245 {
          246         CFid *fid;
          247         int i;
          248         Plumbmsg *m;
          249 
          250         fid = arg;
          251         i = 0;
          252         for(;;){
          253                 m = plumbrecvfid(fid);
          254                 if(m == nil){
          255                         fprint(2, "samterm: plumb read error: %r\n");
          256                         threadexits("plumb");        /* not a fatal error */
          257                 }
          258                 if(plumbformat(m, i)){
          259                         send(plumbc, &i);
          260                         i = 1-i;        /* toggle */
          261                 }
          262         }
          263 }
          264 
          265 int
          266 plumbstart(void)
          267 {
          268         CFid *fid;
          269 
          270         plumbfd = plumbopen("send", OWRITE|OCEXEC);        /* not open is ok */
          271         fid = plumbopenfid("edit", OREAD|OCEXEC);
          272         if(fid == nil)
          273                 return -1;
          274         plumbc = chancreate(sizeof(int), 0);
          275         chansetname(plumbc, "plumbc");
          276         if(plumbc == nil){
          277                 fsclose(fid);
          278                 return -1;
          279         }
          280         threadcreate(plumbproc, fid, STACK);
          281         return 1;
          282 }
          283 
          284 void
          285 hostproc(void *arg)
          286 {
          287         Channel *c;
          288         int i, n, which;
          289 
          290         c = arg;
          291 
          292         i = 0;
          293         for(;;){
          294                 i = 1-i;        /* toggle */
          295                 n = read(hostfd[0], hostbuf[i].data, sizeof hostbuf[i].data);
          296 if(0) fprint(2, "hostproc %d\n", n);
          297                 if(n <= 0){
          298                         if(n == 0){
          299                                 if(exiting)
          300                                         threadexits(nil);
          301                                 werrstr("unexpected eof");
          302                         }
          303                         fprint(2, "samterm: host read error: %r\n");
          304                         threadexitsall("host");
          305                 }
          306                 hostbuf[i].n = n;
          307                 which = i;
          308 if(0) fprint(2, "hostproc send %d\n", which);
          309                 send(c, &which);
          310         }
          311 }
          312 
          313 void
          314 hoststart(void)
          315 {
          316         hostc = chancreate(sizeof(int), 0);
          317         chansetname(hostc, "hostc");
          318         proccreate(hostproc, hostc, STACK);
          319 }