pup_event_ipc.bac 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. REM (c) Copyright Barry Kauler, June 2013, bkhome.org
  2. REM License GPL3 (refer: /usr/share/doc/legal)
  3. REM InterProcess Communication for Puppy Linux, CLI utility using inotify.
  4. REM vovchik: compile like this, reduces executable 34K to 9K...
  5. REM bacon -o -s -o -Os -o -fdata-sections -o -ffunction-sections -o -Wl,--gc-sections -d /tmp $myfile
  6. REM 130628 first version.
  7. DECLARE helpflg,milliseconds TYPE int
  8. 'parse the commandline...
  9. helpflg=0
  10. milliseconds=0
  11. sendstr$=""
  12. IF argc==1 THEN helpflg=1
  13. FOR x=1 TO argc-1
  14. arg$=argv[x]
  15. IF arg$=="--help" THEN
  16. helpflg=1
  17. CONTINUE
  18. ENDIF
  19. IF arg$=="-h" THEN
  20. helpflg=1
  21. CONTINUE
  22. ENDIF
  23. IF arg$=="-t" THEN
  24. INCR x
  25. milliseconds=VAL(argv[x])
  26. CONTINUE
  27. END IF
  28. sendstr$=arg$
  29. NEXT
  30. IF helpflg==1 THEN
  31. PRINT "(c) Copyright Barry Kauler, June 2013, license GPL3 (/usr/share/doc/legal)"
  32. PRINT "This is a CLI utility that may be used in scripts. Run like this:"
  33. PRINT " pup_event_ipc \"request:client[:message]\""
  34. PRINT " request: name of another application to send the message to*. Or,"
  35. PRINT " request: keyword to request information. Supported keywords:"
  36. PRINT " block mailbox waitmail"
  37. PRINT " client: any single-word to identify client (usually sender) application*."
  38. PRINT " message: any text string (that other side understands), up to 4000 bytes."
  39. PRINT " any characters allowed, including \":\""
  40. PRINT "ex: pup_event_ipc \"otherapp:myapp:some data for otherapp\""
  41. PRINT "ex: pup_event_ipc \"mailbox:otherapp:some data for otherapp\""
  42. PRINT "ex: pup_event_ipc \"mailbox:myapp\""
  43. PRINT "ex: pup_event_ipc \"waitmail:myapp\""
  44. PRINT "ex: pup_event_ipc \"block:myapp\""
  45. PRINT "pup_event_ipc has an optional timeout (milliseconds),"
  46. PRINT "ex: pup_event_ipc -t 1000 \"otherapp:myapp:data for you\""
  47. PRINT "Will exit with non-zero value if an error:"
  48. PRINT " 1=timeout. 2=wrong msg format. 3-7=message-passing failure. "
  49. PRINT "*Any unique names that both clients agree on."
  50. PRINT "PLEASE SEE /usr/local/pup_event/pup_event_ipc-README.htm for more details."
  51. END 0
  52. END IF
  53. PROTO close, ftruncate, inotify_init, inotify_add_watch, inotify_rm_watch, lseek, open, poll, read, sizeof, strlen, write
  54. DECLARE fd1,len1,leni,size_buf,thiswatchfile,otherwatchfile TYPE int
  55. DECLARE arr1,thisapp,otherapp TYPE char*
  56. DECLARE thisdescr,otherdescr TYPE int
  57. size_char=sizeof(char)
  58. size_inbuf=size_char*4096
  59. DECLARE inbuf,bufinotify TYPE char ARRAY size_inbuf
  60. SUB exitsub(NUMBER i)
  61. IF watchdir>0 THEN inotify_rm_watch(fd1,watchdir)
  62. IF fd1>0 THEN close(fd1)
  63. IF otherdescr>0 THEN close(otherdescr)
  64. IF thisdescr>0 THEN close(thisdescr)
  65. END i
  66. END SUB
  67. 'struct pollfd, defined in asm-generic/poll.h...
  68. RECORD pfd
  69. LOCAL fd TYPE int
  70. LOCAL events TYPE short
  71. LOCAL revents TYPE short
  72. END RECORD
  73. 'linux/poll.h, only includes asm/poll.h, which only includes asm-generic/poll.h...
  74. CONST POLLIN=1
  75. pfd.events = POLLIN
  76. SUB waitsub()
  77. 'note, there is a very slight possibility of deadlocking, if reply comes in between the lseek and read/poll...
  78. offt=lseek(thisdescr,0,SEEK_END)
  79. IF offt==0 THEN
  80. IF milliseconds==0 THEN
  81. 'this will block until the file is modified...
  82. leni=read(fd1,bufinotify,size_inbuf)
  83. ELSE
  84. pfd.fd=fd1
  85. eventstatus=poll(&pfd.fd,1,milliseconds)
  86. IF eventstatus==0 THEN exitsub(1)
  87. IF eventstatus<0 THEN exitsub(7)
  88. ENDIF
  89. ENDIF
  90. offt=lseek(thisdescr,0,SEEK_SET)
  91. numr=read(thisdescr,inbuf,size_inbuf)
  92. ft=ftruncate(thisdescr,0)
  93. IF numr>1 THEN
  94. 'get rid of carriage-return char...
  95. inbuf[numr-1]=0
  96. inbuf$=inbuf
  97. PRINT inbuf$
  98. ENDIF
  99. END SUB
  100. 'parse the message...
  101. 'SPLIT sendstr$ BY ":" TO fields$ SIZE dims
  102. 'IF dims==0 THEN exitsub(2)
  103. field1$=""
  104. field2$=""
  105. field3$=""
  106. field4$=""
  107. message$=""
  108. arr1=sendstr$
  109. off1=INSTR(arr1,":")
  110. IF off1=0 THEN exitsub(2)
  111. arr1[off1-1]=0
  112. field1$=arr1
  113. off2=INSTR(arr1+off1,":")
  114. arr1[off1+off2-1]=0
  115. field2$=arr1+off1
  116. IF off2>0 THEN
  117. off3=INSTR(arr1+off1+off2,":")
  118. 'the message-part can have ":" chars in it...
  119. message$=arr1+off1+off2
  120. arr1[off1+off2+off3-1]=0
  121. field3$=arr1+off1+off2
  122. IF off3>0 THEN
  123. off4=INSTR(arr1+off1+off2+off3,":")
  124. arr1[off1+off2+off3+off4-1]=0
  125. field4$=arr1+off1+off2+off3
  126. ENDIF
  127. ENDIF
  128. 'need to extract names of this-app and other-app...
  129. otherapp=0
  130. thisapp=0
  131. thiscreateflag=1
  132. SELECT field1$
  133. CASE "mailbox"
  134. IF message$!="" THEN
  135. otherapp=field2$
  136. ELSE
  137. thisapp=field2$
  138. ENDIF
  139. CASE "waitmail"
  140. thisapp=field2$
  141. CASE "block"
  142. thisapp$=CONCAT$("block_",field2$)
  143. thisapp=thisapp$
  144. ' 'thisfile$ is not created here, it is created by a daemon that monitors kernel uevents...
  145. ' thiscreateflag=0
  146. DEFAULT
  147. otherapp=field1$
  148. thisapp=field2$
  149. END SELECT
  150. 'create the files...
  151. otherdescr=0
  152. thisdescr=0
  153. watchdir=0
  154. IF FILEEXISTS("/tmp/pup_event_ipc")==0 THEN MAKEDIR "/tmp/pup_event_ipc"
  155. IF otherapp!=0 THEN
  156. otherfile$=CONCAT$("/tmp/pup_event_ipc/",otherapp)
  157. USEC
  158. /*defined in /usr/include/asm-generic/fcntl.h, and i386-linux-gnu/bits/fcntl-linux.h...*/
  159. #define O_WRONLY 00000001
  160. #define O_CREAT 00000100
  161. # define O_SYNC 04010000
  162. #define O_FSYNC O_SYNC
  163. #define O_APPEND 00002000
  164. /*otherdescr=open(otherfile$,O_WRONLY | O_CREAT, O_FSYNC);*/
  165. /*otherdescr=open(otherfile$, O_WRONLY | O_CREAT, O_APPEND);*/
  166. otherdescr=open(otherfile$, O_WRONLY | O_CREAT | O_APPEND);
  167. END USEC
  168. IF otherdescr<=0 THEN exitsub(3)
  169. ENDIF
  170. IF thisapp!=0 THEN
  171. closedflag=0
  172. thisfile$=CONCAT$("/tmp/pup_event_ipc/",thisapp)
  173. IF thiscreateflag=1 THEN
  174. USEC
  175. #define O_RDONLY 00000000
  176. #define O_CREAT 00000100
  177. #define O_RDWR 00000002
  178. thisdescr=open(thisfile$,O_RDWR | O_CREAT);
  179. END USEC
  180. ELSE
  181. IF FILEEXISTS(thisfile$)==1 THEN
  182. USEC
  183. #define O_RDONLY 00000000
  184. #define O_RDWR 00000002
  185. thisdescr=open(thisfile$,O_RDWR);
  186. END USEC
  187. ELSE
  188. closedflag=1
  189. ENDIF
  190. ENDIF
  191. IF closedflag==0 THEN
  192. IF thisdescr<=0 THEN exitsub(4)
  193. fd1=inotify_init()
  194. IF fd1<=0 THEN exitsub(5)
  195. CONST IN_MODIFY=2
  196. watchdir=inotify_add_watch(fd1,thisfile$,IN_MODIFY)
  197. IF watchdir<=0 THEN exitsub(6)
  198. ENDIF
  199. ENDIF
  200. 'now decide what to do...
  201. SELECT field1$
  202. CASE "mailbox"
  203. IF otherapp!=0 THEN
  204. 'need to post message to otherapp... format: "mailbox:otherapp:message"
  205. outstr$=CONCAT$(message$,"\n")
  206. 'position to end of file, so msgs can queue...
  207. 'lseek(otherdescr,0,SEEK_END)
  208. wr=write(otherdescr,outstr$,strlen(outstr$))
  209. PRINT "Mailbox acknowledge"
  210. ELSE
  211. 'need to check if waiting mail for thisapp...
  212. offt=lseek(thisdescr,0,SEEK_END)
  213. IF offt==0 THEN
  214. PRINT "Mailbox empty"
  215. ELSE
  216. offt=lseek(thisdescr,0,SEEK_SET)
  217. numr=read(thisdescr,inbuf,size_inbuf)
  218. ft=ftruncate(thisdescr,0)
  219. IF numr>1 THEN
  220. 'get rid of carriage-return char...
  221. inbuf[numr-1]=0
  222. inbuf$=inbuf
  223. PRINT inbuf$
  224. ENDIF
  225. ENDIF
  226. ENDIF
  227. CASE "waitmail"
  228. 'need to wait for mail for thisapp... format: "waitmail:thisapp"
  229. waitsub()
  230. CASE "block"
  231. 'need to wait for block-drive hotplug event, for thisapp... format: "block:thisapp"
  232. IF FILEEXISTS(thisfile$)==0 THEN
  233. PRINT "Not implemented"
  234. ELSE
  235. waitsub()
  236. ENDIF
  237. DEFAULT
  238. 'post msg to otherapp, wait for reply to thisapp... format: "otherapp:thisapp:message"
  239. outstr$=CONCAT$(message$,"\n")
  240. wr=write(otherdescr,outstr$,strlen(outstr$))
  241. waitsub()
  242. END SELECT
  243. exitsub(0)