plan9.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <draw.h>
  4. #include <thread.h>
  5. #include <mouse.h>
  6. #include <keyboard.h>
  7. #include <frame.h>
  8. #include <plumb.h>
  9. #include "flayer.h"
  10. #include "samterm.h"
  11. static char exname[64];
  12. void
  13. usage(void)
  14. {
  15. fprint(2, "usage: samterm [-a]\n");
  16. threadexitsall("usage");
  17. }
  18. void
  19. getscreen(int argc, char **argv)
  20. {
  21. char *t;
  22. ARGBEGIN{
  23. case 'a':
  24. autoindent = 1;
  25. break;
  26. default:
  27. usage();
  28. }ARGEND
  29. if(initdraw(panic1, nil, "sam") < 0){
  30. fprint(2, "samterm: initdraw: %r\n");
  31. threadexitsall("init");
  32. }
  33. t = getenv("tabstop");
  34. if(t != nil)
  35. maxtab = strtoul(t, nil, 0);
  36. draw(screen, screen->clipr, display->white, nil, ZP);
  37. }
  38. int
  39. screensize(int *w, int *h)
  40. {
  41. int fd, n;
  42. char buf[5*12+1];
  43. fd = open("/dev/screen", OREAD);
  44. if(fd < 0)
  45. return 0;
  46. n = read(fd, buf, sizeof(buf)-1);
  47. close(fd);
  48. if (n != sizeof(buf)-1)
  49. return 0;
  50. buf[n] = 0;
  51. if (h) {
  52. *h = atoi(buf+4*12)-atoi(buf+2*12);
  53. if (*h < 0)
  54. return 0;
  55. }
  56. if (w) {
  57. *w = atoi(buf+3*12)-atoi(buf+1*12);
  58. if (*w < 0)
  59. return 0;
  60. }
  61. return 1;
  62. }
  63. int
  64. snarfswap(char *fromsam, int nc, char **tosam)
  65. {
  66. char *s1;
  67. int f, n, ss;
  68. f = open("/dev/snarf", 0);
  69. if(f < 0)
  70. return -1;
  71. ss = SNARFSIZE;
  72. if(hversion < 2)
  73. ss = 4096;
  74. *tosam = s1 = alloc(ss);
  75. n = read(f, s1, ss-1);
  76. close(f);
  77. if(n < 0)
  78. n = 0;
  79. if (n == 0) {
  80. *tosam = 0;
  81. free(s1);
  82. } else
  83. s1[n] = 0;
  84. f = create("/dev/snarf", 1, 0666);
  85. if(f >= 0){
  86. write(f, fromsam, nc);
  87. close(f);
  88. }
  89. return n;
  90. }
  91. void
  92. dumperrmsg(int count, int type, int count0, int c)
  93. {
  94. fprint(2, "samterm: host mesg: count %d %ux %ux %ux %s...ignored\n",
  95. count, type, count0, c, rcvstring());
  96. }
  97. void
  98. removeextern(void)
  99. {
  100. remove(exname);
  101. }
  102. Readbuf hostbuf[2];
  103. Readbuf plumbbuf[2];
  104. void
  105. extproc(void *argv)
  106. {
  107. Channel *c;
  108. int i, n, which, *fdp;
  109. void **arg;
  110. arg = argv;
  111. c = arg[0];
  112. fdp = arg[1];
  113. i = 0;
  114. for(;;){
  115. i = 1-i; /* toggle */
  116. n = read(*fdp, plumbbuf[i].data, sizeof plumbbuf[i].data);
  117. if(n <= 0){
  118. fprint(2, "samterm: extern read error: %r\n");
  119. threadexits("extern"); /* not a fatal error */
  120. }
  121. plumbbuf[i].n = n;
  122. which = i;
  123. send(c, &which);
  124. }
  125. }
  126. void
  127. extstart(void)
  128. {
  129. char buf[32];
  130. int fd;
  131. static int p[2];
  132. static void *arg[2];
  133. if(pipe(p) < 0)
  134. return;
  135. sprint(exname, "/srv/sam.%s", getuser());
  136. fd = create(exname, 1, 0600);
  137. if(fd < 0){ /* assume existing guy is more important */
  138. Err:
  139. close(p[0]);
  140. close(p[1]);
  141. return;
  142. }
  143. sprint(buf, "%d", p[0]);
  144. if(write(fd, buf, strlen(buf)) <= 0)
  145. goto Err;
  146. close(fd);
  147. /*
  148. * leave p[0] open so if the file is removed the event
  149. * library won't get an error
  150. */
  151. plumbc = chancreate(sizeof(int), 0);
  152. arg[0] = plumbc;
  153. arg[1] = &p[1];
  154. proccreate(extproc, arg, 1024);
  155. atexit(removeextern);
  156. }
  157. int
  158. plumbformat(int i)
  159. {
  160. Plumbmsg *m;
  161. char *addr, *data, *act;
  162. int n;
  163. data = (char*)plumbbuf[i].data;
  164. m = plumbunpack(data, plumbbuf[i].n);
  165. if(m == nil)
  166. return 0;
  167. n = m->ndata;
  168. if(n == 0){
  169. plumbfree(m);
  170. return 0;
  171. }
  172. act = plumblookup(m->attr, "action");
  173. if(act!=nil && strcmp(act, "showfile")!=0){
  174. /* can't handle other cases yet */
  175. plumbfree(m);
  176. return 0;
  177. }
  178. addr = plumblookup(m->attr, "addr");
  179. if(addr){
  180. if(addr[0] == '\0')
  181. addr = nil;
  182. else
  183. addr = strdup(addr); /* copy to safe storage; we'll overwrite data */
  184. }
  185. memmove(data, "B ", 2); /* we know there's enough room for this */
  186. memmove(data+2, m->data, n);
  187. n += 2;
  188. if(data[n-1] != '\n')
  189. data[n++] = '\n';
  190. if(addr != nil){
  191. if(n+strlen(addr)+1+1 <= READBUFSIZE)
  192. n += sprint(data+n, "%s\n", addr);
  193. free(addr);
  194. }
  195. plumbbuf[i].n = n;
  196. plumbfree(m);
  197. return 1;
  198. }
  199. void
  200. plumbproc(void *argv)
  201. {
  202. Channel *c;
  203. int i, n, which, *fdp;
  204. void **arg;
  205. arg = argv;
  206. c = arg[0];
  207. fdp = arg[1];
  208. i = 0;
  209. for(;;){
  210. i = 1-i; /* toggle */
  211. n = read(*fdp, plumbbuf[i].data, READBUFSIZE);
  212. if(n <= 0){
  213. fprint(2, "samterm: plumb read error: %r\n");
  214. threadexits("plumb"); /* not a fatal error */
  215. }
  216. plumbbuf[i].n = n;
  217. if(plumbformat(i)){
  218. which = i;
  219. send(c, &which);
  220. }
  221. }
  222. }
  223. int
  224. plumbstart(void)
  225. {
  226. static int fd;
  227. static void *arg[2];
  228. plumbfd = plumbopen("send", OWRITE|OCEXEC); /* not open is ok */
  229. fd = plumbopen("edit", OREAD|OCEXEC);
  230. if(fd < 0)
  231. return -1;
  232. plumbc = chancreate(sizeof(int), 0);
  233. if(plumbc == nil){
  234. close(fd);
  235. return -1;
  236. }
  237. arg[0] =plumbc;
  238. arg[1] = &fd;
  239. proccreate(plumbproc, arg, 4096);
  240. return 1;
  241. }
  242. void
  243. hostproc(void *arg)
  244. {
  245. Channel *c;
  246. int i, n, which;
  247. c = arg;
  248. i = 0;
  249. for(;;){
  250. i = 1-i; /* toggle */
  251. n = read(0, hostbuf[i].data, sizeof hostbuf[i].data);
  252. if(n <= 0){
  253. if(n==0){
  254. if(exiting)
  255. threadexits(nil);
  256. werrstr("unexpected eof");
  257. }
  258. fprint(2, "samterm: host read error: %r\n");
  259. threadexitsall("host");
  260. }
  261. hostbuf[i].n = n;
  262. which = i;
  263. send(c, &which);
  264. }
  265. }
  266. void
  267. hoststart(void)
  268. {
  269. hostc = chancreate(sizeof(int), 0);
  270. proccreate(hostproc, hostc, 1024);
  271. }