mesg.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include <u.h>
  10. #include <libc.h>
  11. #include "plumb.h"
  12. int
  13. plumbopen(char *name, int omode)
  14. {
  15. int fd, f;
  16. char *s, *plumber;
  17. char buf[128], err[ERRMAX];
  18. if(name[0] == '/')
  19. return open(name, omode);
  20. /* find elusive plumber */
  21. if(access("/mnt/plumb/send", AWRITE) >= 0)
  22. plumber = "/mnt/plumb";
  23. else if(access("/mnt/term/mnt/plumb/send", AWRITE) >= 0)
  24. plumber = "/mnt/term/mnt/plumb";
  25. else{
  26. /* last resort: try mounting service */
  27. plumber = "/mnt/plumb";
  28. s = getenv("plumbsrv");
  29. if(s == nil)
  30. return -1;
  31. f = open(s, ORDWR);
  32. free(s);
  33. if(f < 0)
  34. return -1;
  35. if(mount(f, -1, "/mnt/plumb", MREPL, "", 'M') < 0){
  36. close(f);
  37. return -1;
  38. }
  39. if(access("/mnt/plumb/send", AWRITE) < 0)
  40. return -1;
  41. }
  42. snprint(buf, sizeof buf, "%s/%s", plumber, name);
  43. fd = open(buf, omode);
  44. if(fd >= 0)
  45. return fd;
  46. /* try creating port; used by non-standard plumb implementations */
  47. rerrstr(err, sizeof err);
  48. fd = create(buf, omode, 0600);
  49. if(fd >= 0)
  50. return fd;
  51. errstr(err, sizeof err);
  52. return -1;
  53. }
  54. static int
  55. Strlen(char *s)
  56. {
  57. if(s == nil)
  58. return 0;
  59. return strlen(s);
  60. }
  61. static char*
  62. Strcpy(char *s, char *t)
  63. {
  64. if(t == nil)
  65. return s;
  66. return strcpy(s, t) + strlen(t);
  67. }
  68. /* quote attribute value, if necessary */
  69. static char*
  70. quote(char *s, char *buf, char *bufe)
  71. {
  72. char *t;
  73. int c;
  74. if(s == nil){
  75. buf[0] = '\0';
  76. return buf;
  77. }
  78. if(strpbrk(s, " '=\t") == nil)
  79. return s;
  80. t = buf;
  81. *t++ = '\'';
  82. while(t < bufe-2){
  83. c = *s++;
  84. if(c == '\0')
  85. break;
  86. *t++ = c;
  87. if(c == '\'')
  88. *t++ = c;
  89. }
  90. *t++ = '\'';
  91. *t = '\0';
  92. return buf;
  93. }
  94. char*
  95. plumbpackattr(Plumbattr *attr)
  96. {
  97. int n;
  98. Plumbattr *a;
  99. char *s, *t, *buf, *bufe;
  100. if(attr == nil)
  101. return nil;
  102. if((buf = malloc(4096)) == nil)
  103. return nil;
  104. bufe = buf + 4096;
  105. n = 0;
  106. for(a=attr; a!=nil; a=a->next)
  107. n += Strlen(a->name) + 1 + Strlen(quote(a->value, buf, bufe)) + 1;
  108. s = malloc(n);
  109. if(s == nil) {
  110. free(buf);
  111. return nil;
  112. }
  113. t = s;
  114. *t = '\0';
  115. for(a=attr; a!=nil; a=a->next){
  116. if(t != s)
  117. *t++ = ' ';
  118. strcpy(t, a->name);
  119. strcat(t, "=");
  120. strcat(t, quote(a->value, buf, bufe));
  121. t += strlen(t);
  122. }
  123. if(t > s+n)
  124. abort();
  125. free(buf);
  126. return s;
  127. }
  128. char*
  129. plumblookup(Plumbattr *attr, char *name)
  130. {
  131. while(attr){
  132. if(strcmp(attr->name, name) == 0)
  133. return attr->value;
  134. attr = attr->next;
  135. }
  136. return nil;
  137. }
  138. char*
  139. plumbpack(Plumbmsg *m, int *np)
  140. {
  141. int n, ndata;
  142. char *buf, *p, *attr;
  143. ndata = m->ndata;
  144. if(ndata < 0)
  145. ndata = Strlen(m->data);
  146. attr = plumbpackattr(m->attr);
  147. n = Strlen(m->src)+1 + Strlen(m->dst)+1 + Strlen(m->wdir)+1 +
  148. Strlen(m->type)+1 + Strlen(attr)+1 + 16 + ndata;
  149. buf = malloc(n+1); /* +1 for '\0' */
  150. if(buf == nil){
  151. free(attr);
  152. return nil;
  153. }
  154. p = Strcpy(buf, m->src);
  155. *p++ = '\n';
  156. p = Strcpy(p, m->dst);
  157. *p++ = '\n';
  158. p = Strcpy(p, m->wdir);
  159. *p++ = '\n';
  160. p = Strcpy(p, m->type);
  161. *p++ = '\n';
  162. p = Strcpy(p, attr);
  163. *p++ = '\n';
  164. p += sprint(p, "%d\n", ndata);
  165. memmove(p, m->data, ndata);
  166. *np = (p-buf)+ndata;
  167. buf[*np] = '\0'; /* null terminate just in case */
  168. if(*np >= n+1)
  169. abort();
  170. free(attr);
  171. return buf;
  172. }
  173. int
  174. plumbsend(int fd, Plumbmsg *m)
  175. {
  176. char *buf;
  177. int n;
  178. buf = plumbpack(m, &n);
  179. if(buf == nil)
  180. return -1;
  181. n = write(fd, buf, n);
  182. free(buf);
  183. return n;
  184. }
  185. static int
  186. plumbline(char **linep, char *buf, int i, int n, int *bad)
  187. {
  188. int starti;
  189. char *p;
  190. starti = i;
  191. while(i<n && buf[i]!='\n')
  192. i++;
  193. if(i == n)
  194. *bad = 1;
  195. else{
  196. p = malloc((i-starti) + 1);
  197. if(p == nil)
  198. *bad = 1;
  199. else{
  200. memmove(p, buf+starti, i-starti);
  201. p[i-starti] = '\0';
  202. }
  203. *linep = p;
  204. i++;
  205. }
  206. return i;
  207. }
  208. void
  209. plumbfree(Plumbmsg *m)
  210. {
  211. Plumbattr *a, *next;
  212. free(m->src);
  213. free(m->dst);
  214. free(m->wdir);
  215. free(m->type);
  216. for(a=m->attr; a!=nil; a=next){
  217. next = a->next;
  218. free(a->name);
  219. free(a->value);
  220. free(a);
  221. }
  222. free(m->data);
  223. free(m);
  224. }
  225. Plumbattr*
  226. plumbunpackattr(char *p)
  227. {
  228. Plumbattr *attr, *prev, *a;
  229. char *q, *v, *buf, *bufe;
  230. int c, quoting;
  231. buf = malloc(4096);
  232. if(buf == nil)
  233. return nil;
  234. bufe = buf + 4096;
  235. attr = prev = nil;
  236. while(*p!='\0' && *p!='\n'){
  237. while(*p==' ' || *p=='\t')
  238. p++;
  239. if(*p == '\0')
  240. break;
  241. for(q=p; *q!='\0' && *q!='\n' && *q!=' ' && *q!='\t'; q++)
  242. if(*q == '=')
  243. break;
  244. if(*q != '=')
  245. break; /* malformed attribute */
  246. a = malloc(sizeof(Plumbattr));
  247. if(a == nil)
  248. break;
  249. a->name = malloc(q-p+1);
  250. if(a->name == nil){
  251. free(a);
  252. break;
  253. }
  254. memmove(a->name, p, q-p);
  255. a->name[q-p] = '\0';
  256. /* process quotes in value */
  257. q++; /* skip '=' */
  258. v = buf;
  259. quoting = 0;
  260. while(*q!='\0' && *q!='\n'){
  261. if(v >= bufe)
  262. break;
  263. c = *q++;
  264. if(quoting){
  265. if(c == '\''){
  266. if(*q == '\'')
  267. q++;
  268. else{
  269. quoting = 0;
  270. continue;
  271. }
  272. }
  273. }else{
  274. if(c==' ' || c=='\t')
  275. break;
  276. if(c == '\''){
  277. quoting = 1;
  278. continue;
  279. }
  280. }
  281. *v++ = c;
  282. }
  283. a->value = malloc(v-buf+1);
  284. if(a->value == nil){
  285. free(a->name);
  286. free(a);
  287. break;
  288. }
  289. memmove(a->value, buf, v-buf);
  290. a->value[v-buf] = '\0';
  291. a->next = nil;
  292. if(prev == nil)
  293. attr = a;
  294. else
  295. prev->next = a;
  296. prev = a;
  297. p = q;
  298. }
  299. free(buf);
  300. return attr;
  301. }
  302. Plumbattr*
  303. plumbaddattr(Plumbattr *attr, Plumbattr *new)
  304. {
  305. Plumbattr *l;
  306. l = attr;
  307. if(l == nil)
  308. return new;
  309. while(l->next != nil)
  310. l = l->next;
  311. l->next = new;
  312. return attr;
  313. }
  314. Plumbattr*
  315. plumbdelattr(Plumbattr *attr, char *name)
  316. {
  317. Plumbattr *l, *prev;
  318. prev = nil;
  319. for(l=attr; l!=nil; l=l->next){
  320. if(strcmp(name, l->name) == 0)
  321. break;
  322. prev = l;
  323. }
  324. if(l == nil)
  325. return nil;
  326. if(prev)
  327. prev->next = l->next;
  328. else
  329. attr = l->next;
  330. free(l->name);
  331. free(l->value);
  332. free(l);
  333. return attr;
  334. }
  335. Plumbmsg*
  336. plumbunpackpartial(char *buf, int n, int *morep)
  337. {
  338. Plumbmsg *m;
  339. int i, bad;
  340. char *ntext, *attr;
  341. m = malloc(sizeof(Plumbmsg));
  342. if(m == nil)
  343. return nil;
  344. memset(m, 0, sizeof(Plumbmsg));
  345. if(morep != nil)
  346. *morep = 0;
  347. bad = 0;
  348. i = plumbline(&m->src, buf, 0, n, &bad);
  349. i = plumbline(&m->dst, buf, i, n, &bad);
  350. i = plumbline(&m->wdir, buf, i, n, &bad);
  351. i = plumbline(&m->type, buf, i, n, &bad);
  352. i = plumbline(&attr, buf, i, n, &bad);
  353. i = plumbline(&ntext, buf, i, n, &bad);
  354. if(bad){
  355. plumbfree(m);
  356. return nil;
  357. }
  358. m->attr = plumbunpackattr(attr);
  359. free(attr);
  360. m->ndata = atoi(ntext);
  361. if(m->ndata != n-i){
  362. bad = 1;
  363. if(morep!=nil && m->ndata>n-i)
  364. *morep = m->ndata - (n-i);
  365. }
  366. free(ntext);
  367. if(!bad){
  368. m->data = malloc(n-i+1); /* +1 for '\0' */
  369. if(m->data == nil)
  370. bad = 1;
  371. else{
  372. memmove(m->data, buf+i, m->ndata);
  373. m->ndata = n-i;
  374. /* null-terminate in case it's text */
  375. m->data[m->ndata] = '\0';
  376. }
  377. }
  378. if(bad){
  379. plumbfree(m);
  380. m = nil;
  381. }
  382. return m;
  383. }
  384. Plumbmsg*
  385. plumbunpack(char *buf, int n)
  386. {
  387. return plumbunpackpartial(buf, n, nil);
  388. }
  389. Plumbmsg*
  390. plumbrecv(int fd)
  391. {
  392. char *buf;
  393. Plumbmsg *m;
  394. int n, more;
  395. buf = malloc(8192);
  396. if(buf == nil)
  397. return nil;
  398. n = read(fd, buf, 8192);
  399. m = nil;
  400. if(n > 0){
  401. m = plumbunpackpartial(buf, n, &more);
  402. if(m==nil && more>0){
  403. /* we now know how many more bytes to read for complete message */
  404. buf = realloc(buf, n+more);
  405. if(buf == nil)
  406. return nil;
  407. if(readn(fd, buf+n, more) == more)
  408. m = plumbunpackpartial(buf, n+more, nil);
  409. }
  410. }
  411. free(buf);
  412. return m;
  413. }