mesg.c 6.9 KB

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