mesg.c 7.1 KB

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