pup_event_frontend_d.bac 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. REM (c) Copyright Barry Kauler, June 2013, bkhome.org
  2. REM License GPL3 (refer: /usr/share/doc/legal)
  3. REM libc ref: http://www.gnu.org/software/libc/manual/html_node/Function-Index.html#Function-Index
  4. REM this little daemon reads kernel uevents.
  5. REM vovchik: compile like this, reduces executable 34K to 9K...
  6. REM bacon -o -s -o -Os -o -fdata-sections -o -ffunction-sections -o -Wl,--gc-sections -d /tmp $myfile
  7. REM 130614 forgot to detect sr0/sr1 devices.
  8. REM 130629 support clients in new pup_event IPC mechanism.
  9. REM initialization script... note, RETVAL has exit status.
  10. SYSTEM "/usr/local/pup_event/frontend_startup"
  11. IF RETVAL!=0 THEN END 9
  12. '130629 for reading contents of /tmp/pup_event_ipc...
  13. PROTO opendir, readdir
  14. DECLARE dir1 TYPE DIR*
  15. DECLARE ent1 TYPE struct dirent*
  16. REM from linux/netlink.h...
  17. CONST NETLINK_KOBJECT_UEVENT=15
  18. REM linux/poll.h, only includes asm/poll.h, which only includes asm-generic/poll.h...
  19. CONST POLLIN=1
  20. REM C functions, in libc.so. note, I originally used IMPORT, but PROTO is simpler...
  21. PROTO getpid, socket, bind, poll, recv, printf, strlen, strcmp
  22. REM struct sockaddr_nl, defined in linux/netlink.h...
  23. RECORD nls
  24. LOCAL nl_family TYPE unsigned short
  25. LOCAL nl_pad TYPE unsigned short
  26. LOCAL nl_pid TYPE unsigned int
  27. LOCAL nl_groups TYPE unsigned int
  28. END RECORD
  29. REM struct pollfd, defined in asm-generic/poll.h...
  30. RECORD pfd
  31. LOCAL fd TYPE int
  32. LOCAL events TYPE short
  33. LOCAL revents TYPE short
  34. END RECORD
  35. DECLARE buf TYPE char ARRAY 512
  36. DECLARE eventstatus TYPE int
  37. DECLARE bufin TYPE char*
  38. size_char=SIZEOF(char)
  39. size_buf=size_char*512
  40. size_us=SIZEOF(unsigned short)
  41. size_ui=SIZEOF(unsigned int)
  42. size_nls=(2*size_us)+(2*size_ui)
  43. REM initialise the nls structure...
  44. nls.nl_family = AF_NETLINK
  45. nls.nl_pad = 0
  46. nls.nl_pid = getpid()
  47. nls.nl_groups = -1
  48. REM Open hotplug event netlink socket...
  49. pfd.events = POLLIN
  50. pfd.fd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT)
  51. IF pfd.fd == -1 THEN END 1
  52. REM listen to netlink socket...
  53. retval=bind(pfd.fd, (void *)&nls.nl_family, size_nls)
  54. IF retval==-1 THEN END 2
  55. cnt=0
  56. devevents$=""
  57. WHILE TRUE DO
  58. REM 2 second timeout... note, -1 is wait indefinitely.
  59. eventstatus=poll(&pfd.fd, 1, 1000)
  60. IF eventstatus==-1 THEN END 3
  61. IF eventstatus==0 THEN
  62. REM one-second timeout.
  63. REM graceful exit if shutdown X (see /usr/bin/restartwm,wmreboot,wmpoweroff)...
  64. IF FILEEXISTS("/tmp/wmexitmode.txt")==1 THEN END 8
  65. IF devevents$!="" THEN
  66. exe_change$=CONCAT$("/usr/local/pup_event/frontend_change ",devevents$)
  67. SYSTEM exe_change$
  68. '130629 also post block-drive events to any ipc client...
  69. 'look for any files named /tmp/pup_event_ipc/block_* ...
  70. dir1=opendir("/tmp/pup_event_ipc")
  71. IF dir1!=NULL THEN
  72. WHILE TRUE DO
  73. ent1=readdir(dir1)
  74. IF ent1==NULL THEN BREAK
  75. off1=INSTR((*ent1).d_name,"block_")
  76. IF off1!=0 THEN
  77. clientfile$=CONCAT$("/tmp/pup_event_ipc/",(*ent1).d_name)
  78. outmsg$=CONCAT$(devevents$,"\n")
  79. USEC
  80. #define O_WRONLY 00000001
  81. #define O_APPEND 00002000
  82. int clientdescr;
  83. clientdescr=open(clientfile$, O_WRONLY | O_APPEND);
  84. if (clientdescr>0) {
  85. int wr=write(clientdescr,outmsg$,strlen(outmsg$));
  86. close(clientdescr);
  87. }
  88. END USEC
  89. ENDIF
  90. WEND
  91. ENDIF
  92. devevents$=""
  93. ELSE
  94. REM want to call a pup_event script every four seconds...
  95. INCR cnt
  96. IF cnt>=4 THEN
  97. SYSTEM "/usr/local/pup_event/frontend_timeout"
  98. cnt=0
  99. ENDIF
  100. END IF
  101. CONTINUE
  102. END IF
  103. REM get the uevent...
  104. len = recv(pfd.fd, buf, size_buf, MSG_DONTWAIT)
  105. IF len==-1 THEN END 4
  106. REM process the uevent...
  107. REM only add@, remove@, change@ uevents...
  108. devevent$=""
  109. IF buf[0]=='a' THEN
  110. IF buf[1]=='d' THEN
  111. IF buf[2]=='d' THEN devevent$="add:"
  112. END IF
  113. END IF
  114. IF buf[0]=='r' THEN
  115. IF buf[1]=='e' THEN
  116. IF buf[2]=='m' THEN devevent$="rem:"
  117. END IF
  118. END IF
  119. IF buf[0]=='c' THEN
  120. IF buf[1]=='h' THEN
  121. IF buf[2]=='a' THEN devevent$="cha:"
  122. END IF
  123. END IF
  124. IF devevent$=="" THEN CONTINUE
  125. REM want uevents that have "SUBSYSTEM=block"...
  126. REM buf has a sequence of zero-delimited strings...
  127. i=0
  128. flag_block=0
  129. devname$=""
  130. WHILE i<len DO
  131. bufin=buf+i
  132. IF flag_block==1 THEN
  133. REM ex: DEVNAME=sdc DEVTYPE=disk ex2: DEVNAME=sdc1 DEVTYPE=partition
  134. IF INSTR(bufin,"DEVNAME")!=0 THEN
  135. devname$=EXTRACT$(bufin,"DEVNAME=")
  136. REM ignore loop or ram devices... 130614 fix...
  137. IF REGEX(devname$,"^sd|^hd|^mmc|^sr")==0 THEN CONTINUE 2
  138. devevents$=CONCAT$(devevents$,devevent$,devname$," ")
  139. END IF
  140. ELSE
  141. IF strcmp(bufin,"SUBSYSTEM=block")==0 THEN flag_block=1
  142. END IF
  143. i = i+strlen(bufin)+1
  144. WEND
  145. WEND