123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257 |
- REM (c) Copyright Barry Kauler, June 2013, bkhome.org
- REM License GPL3 (refer: /usr/share/doc/legal)
- REM InterProcess Communication for Puppy Linux, CLI utility using inotify.
- REM vovchik: compile like this, reduces executable 34K to 9K...
- REM bacon -o -s -o -Os -o -fdata-sections -o -ffunction-sections -o -Wl,--gc-sections -d /tmp $myfile
- REM 130628 first version.
- DECLARE helpflg,milliseconds TYPE int
- 'parse the commandline...
- helpflg=0
- milliseconds=0
- sendstr$=""
- IF argc==1 THEN helpflg=1
- FOR x=1 TO argc-1
- arg$=argv[x]
- IF arg$=="--help" THEN
- helpflg=1
- CONTINUE
- ENDIF
- IF arg$=="-h" THEN
- helpflg=1
- CONTINUE
- ENDIF
- IF arg$=="-t" THEN
- INCR x
- milliseconds=VAL(argv[x])
- CONTINUE
- END IF
- sendstr$=arg$
- NEXT
- IF helpflg==1 THEN
- PRINT "(c) Copyright Barry Kauler, June 2013, license GPL3 (/usr/share/doc/legal)"
- PRINT "This is a CLI utility that may be used in scripts. Run like this:"
- PRINT " pup_event_ipc \"request:client[:message]\""
- PRINT " request: name of another application to send the message to*. Or,"
- PRINT " request: keyword to request information. Supported keywords:"
- PRINT " block mailbox waitmail"
- PRINT " client: any single-word to identify client (usually sender) application*."
- PRINT " message: any text string (that other side understands), up to 4000 bytes."
- PRINT " any characters allowed, including \":\""
- PRINT "ex: pup_event_ipc \"otherapp:myapp:some data for otherapp\""
- PRINT "ex: pup_event_ipc \"mailbox:otherapp:some data for otherapp\""
- PRINT "ex: pup_event_ipc \"mailbox:myapp\""
- PRINT "ex: pup_event_ipc \"waitmail:myapp\""
- PRINT "ex: pup_event_ipc \"block:myapp\""
- PRINT "pup_event_ipc has an optional timeout (milliseconds),"
- PRINT "ex: pup_event_ipc -t 1000 \"otherapp:myapp:data for you\""
- PRINT "Will exit with non-zero value if an error:"
- PRINT " 1=timeout. 2=wrong msg format. 3-7=message-passing failure. "
- PRINT "*Any unique names that both clients agree on."
- PRINT "PLEASE SEE /usr/local/pup_event/pup_event_ipc-README.htm for more details."
- END 0
- END IF
- PROTO close, ftruncate, inotify_init, inotify_add_watch, inotify_rm_watch, lseek, open, poll, read, sizeof, strlen, write
- DECLARE fd1,len1,leni,size_buf,thiswatchfile,otherwatchfile TYPE int
- DECLARE arr1,thisapp,otherapp TYPE char*
- DECLARE thisdescr,otherdescr TYPE int
- size_char=sizeof(char)
- size_inbuf=size_char*4096
- DECLARE inbuf,bufinotify TYPE char ARRAY size_inbuf
- SUB exitsub(NUMBER i)
- IF watchdir>0 THEN inotify_rm_watch(fd1,watchdir)
- IF fd1>0 THEN close(fd1)
- IF otherdescr>0 THEN close(otherdescr)
- IF thisdescr>0 THEN close(thisdescr)
- END i
- END SUB
- 'struct pollfd, defined in asm-generic/poll.h...
- RECORD pfd
- LOCAL fd TYPE int
- LOCAL events TYPE short
- LOCAL revents TYPE short
- END RECORD
- 'linux/poll.h, only includes asm/poll.h, which only includes asm-generic/poll.h...
- CONST POLLIN=1
- pfd.events = POLLIN
- SUB waitsub()
- 'note, there is a very slight possibility of deadlocking, if reply comes in between the lseek and read/poll...
- offt=lseek(thisdescr,0,SEEK_END)
- IF offt==0 THEN
- IF milliseconds==0 THEN
- 'this will block until the file is modified...
- leni=read(fd1,bufinotify,size_inbuf)
- ELSE
- pfd.fd=fd1
- eventstatus=poll(&pfd.fd,1,milliseconds)
- IF eventstatus==0 THEN exitsub(1)
- IF eventstatus<0 THEN exitsub(7)
- ENDIF
- ENDIF
- offt=lseek(thisdescr,0,SEEK_SET)
- numr=read(thisdescr,inbuf,size_inbuf)
- ft=ftruncate(thisdescr,0)
- IF numr>1 THEN
- 'get rid of carriage-return char...
- inbuf[numr-1]=0
- inbuf$=inbuf
- PRINT inbuf$
- ENDIF
- END SUB
- 'parse the message...
- 'SPLIT sendstr$ BY ":" TO fields$ SIZE dims
- 'IF dims==0 THEN exitsub(2)
- field1$=""
- field2$=""
- field3$=""
- field4$=""
- message$=""
- arr1=sendstr$
- off1=INSTR(arr1,":")
- IF off1=0 THEN exitsub(2)
- arr1[off1-1]=0
- field1$=arr1
- off2=INSTR(arr1+off1,":")
- arr1[off1+off2-1]=0
- field2$=arr1+off1
- IF off2>0 THEN
- off3=INSTR(arr1+off1+off2,":")
- 'the message-part can have ":" chars in it...
- message$=arr1+off1+off2
- arr1[off1+off2+off3-1]=0
- field3$=arr1+off1+off2
- IF off3>0 THEN
- off4=INSTR(arr1+off1+off2+off3,":")
- arr1[off1+off2+off3+off4-1]=0
- field4$=arr1+off1+off2+off3
- ENDIF
- ENDIF
- 'need to extract names of this-app and other-app...
- otherapp=0
- thisapp=0
- thiscreateflag=1
- SELECT field1$
- CASE "mailbox"
- IF message$!="" THEN
- otherapp=field2$
- ELSE
- thisapp=field2$
- ENDIF
- CASE "waitmail"
- thisapp=field2$
- CASE "block"
- thisapp$=CONCAT$("block_",field2$)
- thisapp=thisapp$
- ' 'thisfile$ is not created here, it is created by a daemon that monitors kernel uevents...
- ' thiscreateflag=0
- DEFAULT
- otherapp=field1$
- thisapp=field2$
- END SELECT
- 'create the files...
- otherdescr=0
- thisdescr=0
- watchdir=0
- IF FILEEXISTS("/tmp/pup_event_ipc")==0 THEN MAKEDIR "/tmp/pup_event_ipc"
- IF otherapp!=0 THEN
- otherfile$=CONCAT$("/tmp/pup_event_ipc/",otherapp)
- USEC
- /*defined in /usr/include/asm-generic/fcntl.h, and i386-linux-gnu/bits/fcntl-linux.h...*/
- #define O_WRONLY 00000001
- #define O_CREAT 00000100
- # define O_SYNC 04010000
- #define O_FSYNC O_SYNC
- #define O_APPEND 00002000
- /*otherdescr=open(otherfile$,O_WRONLY | O_CREAT, O_FSYNC);*/
- /*otherdescr=open(otherfile$, O_WRONLY | O_CREAT, O_APPEND);*/
- otherdescr=open(otherfile$, O_WRONLY | O_CREAT | O_APPEND);
- END USEC
- IF otherdescr<=0 THEN exitsub(3)
- ENDIF
- IF thisapp!=0 THEN
- closedflag=0
- thisfile$=CONCAT$("/tmp/pup_event_ipc/",thisapp)
- IF thiscreateflag=1 THEN
- USEC
- #define O_RDONLY 00000000
- #define O_CREAT 00000100
- #define O_RDWR 00000002
- thisdescr=open(thisfile$,O_RDWR | O_CREAT);
- END USEC
- ELSE
- IF FILEEXISTS(thisfile$)==1 THEN
- USEC
- #define O_RDONLY 00000000
- #define O_RDWR 00000002
- thisdescr=open(thisfile$,O_RDWR);
- END USEC
- ELSE
- closedflag=1
- ENDIF
- ENDIF
- IF closedflag==0 THEN
- IF thisdescr<=0 THEN exitsub(4)
- fd1=inotify_init()
- IF fd1<=0 THEN exitsub(5)
- CONST IN_MODIFY=2
- watchdir=inotify_add_watch(fd1,thisfile$,IN_MODIFY)
- IF watchdir<=0 THEN exitsub(6)
- ENDIF
- ENDIF
- 'now decide what to do...
- SELECT field1$
- CASE "mailbox"
- IF otherapp!=0 THEN
- 'need to post message to otherapp... format: "mailbox:otherapp:message"
- outstr$=CONCAT$(message$,"\n")
- 'position to end of file, so msgs can queue...
- 'lseek(otherdescr,0,SEEK_END)
- wr=write(otherdescr,outstr$,strlen(outstr$))
- PRINT "Mailbox acknowledge"
- ELSE
- 'need to check if waiting mail for thisapp...
- offt=lseek(thisdescr,0,SEEK_END)
- IF offt==0 THEN
- PRINT "Mailbox empty"
- ELSE
- offt=lseek(thisdescr,0,SEEK_SET)
- numr=read(thisdescr,inbuf,size_inbuf)
- ft=ftruncate(thisdescr,0)
- IF numr>1 THEN
- 'get rid of carriage-return char...
- inbuf[numr-1]=0
- inbuf$=inbuf
- PRINT inbuf$
- ENDIF
- ENDIF
- ENDIF
- CASE "waitmail"
- 'need to wait for mail for thisapp... format: "waitmail:thisapp"
- waitsub()
- CASE "block"
- 'need to wait for block-drive hotplug event, for thisapp... format: "block:thisapp"
- IF FILEEXISTS(thisfile$)==0 THEN
- PRINT "Not implemented"
- ELSE
- waitsub()
- ENDIF
- DEFAULT
- 'post msg to otherapp, wait for reply to thisapp... format: "otherapp:thisapp:message"
- outstr$=CONCAT$(message$,"\n")
- wr=write(otherdescr,outstr$,strlen(outstr$))
- waitsub()
- END SELECT
- exitsub(0)
|