mesg.c 6.9 KB

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