home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / languages / perl / scripts-osu / snoop.shar < prev    next >
Encoding:
Internet Message Format  |  1991-02-11  |  10.6 KB

  1. Path: tut.cis.ohio-state.edu!VAX1.CC.UAKRON.EDU!mcs.kent.edu!usenet.ins.cwru.edu!gatech!mcnc!uvaarpa!mmdf
  2. From: ted@evi.com (Ted Stefanik)
  3. Newsgroups: comp.lang.perl
  4. Subject: Here's a poor man's "remote perl debugger"
  5. Message-ID: <1991Feb12.181225.21121@uvaarpa.Virginia.EDU>
  6. Date: 12 Feb 91 18:12:25 GMT
  7. Sender: mmdf@uvaarpa.Virginia.EDU (Uvaarpa Mail System)
  8. Reply-To: ted@evi.com
  9. Organization: The Internet
  10. Lines: 276
  11.  
  12. This year at the X Technical Conference, a paper called Tcl/Tk was presented.
  13. Tcl is "an embeddable command language intended for interactive applicaitons."
  14. One of the interesting things about Tcl is its send command, "which allows any
  15. [Tcl] application to invoke arbitrary Tcl operations in any other application."
  16. The send command "allows applications to work together so that a collection
  17. of small reusable programs can be used to solve problems that previously
  18. would have required a single monolithic application."
  19.  
  20. I was intrigued by this feature, particulary after seeing it demonstrated in an
  21. Tk/X11 interface control-panel application which was used to interactively tune
  22. another running application.  So... I implemented the beginnings of a send
  23. feature for Perl, in hopeful anticipation of an X11 interface for Perl.
  24.  
  25. Until then, I have found this feature quite useful anyway!  We have several
  26. long-running (2+ CPU hour) data manipulation scripts written in Perl, and it is
  27. nice to keep tabs on them, and sometimes debug them.  This would be great to
  28. debug daemons, too.  A send-like feature serves as a poor man's remote
  29. debugger or attach feature.  Therefore I named the package "snoop".
  30.  
  31. The shar (included herein) file includes three items:
  32.    1) snoop.pl - The snoop package
  33.    2) snoopme  - A sample application willing to be snooped on
  34.    3) snoop    - A simple snooper.
  35.  
  36. For an example of how it works, try the following commands:
  37.  
  38.    snoopme
  39.    snoop snoopme
  40.    $inc += 20;
  41.    ^C
  42.  
  43. Caveats:
  44.    1) The sample application does not invoke snoop() with the issolate feature;
  45.       therefore any snooper can modify the application in any way.  If this
  46.       scares you, be sure to invoke snoop with the issolate argument set true.
  47.  
  48.    2) The snoop package requires socket IPC.  Systems without sockets are out
  49.       of luck (and I don't know how to implement it in System V IPC).
  50.  
  51.    3) The snoop package uses a fcntl(F_ASYNC) which causes the IPC socket
  52.       generate a SIGIO signal when a new connection is ready.  (If your
  53.       application alreay uses SIGIO, snoop will probably not work.)
  54.  
  55.    4) The code to save and restore the application's context around snoop
  56.       events was stolen from perldb.  I have no idea if it is all that is
  57.       necessary and sufficient to preserve context, but it seems to work.
  58.  
  59.    5) The snoop package was developed and tested on a DECStation 2100 with
  60.       Ultrix 3.1 and Perl 3.044.  Your mileage may vary.
  61.  
  62.    6) You have the right to freely copy and distribute this code (but if you
  63.       do it in a wildly profitable way, throw some crumbs to the author!)
  64.  
  65.    7) Because it is free, snoop has no warranty, either expressed or implied.
  66.  
  67.    8) Security: What security?  When X11-Perl comes around, I'll probably
  68.       include the "magic cookie" security and a more appropriate mechanism
  69.       to name the target.  Until then, you better trust the other users or
  70.       add some mechanism to authenticate the snoopers.
  71.  
  72. #--------------------------------CUT HERE-------------------------------------
  73. #! /bin/sh
  74. #
  75. # This is a shell archive.  Save this into a file, edit it
  76. # and delete all lines above this comment.  Then give this
  77. # file to sh by executing the command "sh file".  The files
  78. # will be extracted into the current directory owned by
  79. # you with default permissions.
  80. #
  81. # The files contained herein are:
  82. #
  83. # -rwxr-x---  1 ted           172 Feb 12 12:05 snoop
  84. # -rw-r--r--  1 ted          5304 Feb 12 12:16 snoop.pl
  85. # -rwxr-x---  1 ted           195 Feb 12 12:05 snoopme
  86. #
  87. echo 'x - snoop'
  88. if test -f snoop; then echo 'shar: not overwriting snoop'; else
  89. sed 's/^X//' << '________This_Is_The_END________' > snoop
  90. X#!/usr/local/gbin/perl
  91. X
  92. Xrequire 'snoop.pl';
  93. X
  94. X@names = @ARGV;
  95. Xundef @ARGV;
  96. X
  97. Xwhile (<>)
  98. X{
  99. X   @result = &snoop($_, @names);
  100. X   print "The answer is: @result\n\n";
  101. X}
  102. X
  103. Xexit(0);
  104. ________This_Is_The_END________
  105. if test `wc -l < snoop` -ne 14; then
  106.     echo 'shar: snoop was damaged during transit (should have been 14 bytes)'
  107. fi
  108. fi        ; : end of overwriting check
  109. echo 'x - snoop.pl'
  110. if test -f snoop.pl; then echo 'shar: not overwriting snoop.pl'; else
  111. sed 's/^X//' << '________This_Is_The_END________' > snoop.pl
  112. X#
  113. X# snoop.pl allows a process to send perl commands to another for evaluation
  114. X#
  115. X# By Ted Stefanik (ted@evi.com)
  116. X#    February 12, 1991
  117. X#
  118. X
  119. Xpackage SNOOP;
  120. X
  121. Xrequire 'sys/socket.ph';
  122. Xrequire 'fcntl.ph';
  123. X
  124. X
  125. Xsub main'snoopon
  126. X{
  127. X   local($isolate,                                  # Issolate snoops with fork
  128. X         @names) = @_;                              # Socket address name(s)
  129. X
  130. X   local($filename, $line);
  131. X   ($package, $filename, $line) = caller;           # Grab $package for correct
  132. X                                                    #   context during snoops
  133. X
  134. X   local($addr);                                    # Make socket address,
  135. X   ($sock, $addr) = &makeaddr(@names);              #   then open master socket
  136. X
  137. X   socket(S, &AF_UNIX,&SOCK_STREAM,&PF_UNSPEC) || die("socket: $!\n");
  138. X   (! -e $sock || unlink($sock))               || die("unlink \"$sock\"\n");
  139. X   bind(S, $addr)                              || die("bind($sock): $!\n");
  140. X   fcntl(S, &F_SETFL, &FASYNC + 0)             || die("fcntl(FASYNC): $!\n");
  141. X   fcntl(S, &F_SETOWN, $$ + 0)                 || die("fcntl(F_SETOWN): $!\n");
  142. X   listen(S, 5)                                || die("bind: $!\n");
  143. X
  144. X   $sv = '';                                        # Set up bit vector for
  145. X   vec($sv, fileno(S), 1) = 1;                      #   catch's select
  146. X
  147. X   $snoopbyfork = $isolate;
  148. X   $SIG{'IO'} = "SNOOP'catch";                      # Catch new connections
  149. X
  150. X   return(undef);
  151. X}
  152. X
  153. Xsub main'snoopoff
  154. X{
  155. X   unlink($sock)                               || die("unlink($sock): $!\n");
  156. X   return(undef);
  157. X}
  158. X
  159. Xsub main'snoop
  160. X{
  161. X   local($request,                                  # The snooping command
  162. X         @names) = @_;                              # Socket address name(s)
  163. X
  164. X   local($sock, $addr) = &makeaddr(@names);
  165. X
  166. X#  local(*S);                                       # Can't due to Perl bug???
  167. X   socket(S, &AF_UNIX,&SOCK_STREAM,&PF_UNSPEC) || die("socket: $!\n");
  168. X   setsockopt(S, &SOL_SOCKET, &SO_LINGER, undef);   # Open a connection socket,
  169. X   local($oldfh) = select(S);                       #   set to linger on close
  170. X   $| = 1;                                          #   and unbuffered I/O
  171. X   select($oldfh);
  172. X
  173. X   connect(S, $addr)                           || die("connect($sock): $!\n");
  174. X   send(S, $request, 0)                        || die("send(snoop): $!\n");
  175. X   send(S, "__SOCKETEND__\n", 0)               || die("send(EOF): $!\n");
  176. X
  177. X   local(@result) = <S>;                            # Get the reply
  178. X   close(S);
  179. X   return (@result);                                #   and return it
  180. X}
  181. X
  182. X
  183. Xsub catch
  184. X{
  185. X   local(@saved) = ($_, $@, $!, $[, $,, $/, $\);    # Save context
  186. X                                                    #   (Stolen from perldb)
  187. X   local($sig) = @_;                                # Make sure we caught the
  188. X   die("Erroneously caught a SIG$sig\n")            #   correct signal
  189. X      if ($sig != "IO");
  190. X
  191. X   local($j);
  192. X   return (undef)                                   # Make sure the signal
  193. X      if (select($j=$sv, $j=$sv, $j=$sv, 0) == 0);  #   came from master
  194. X
  195. X   &docatch()                                       # Handle the signal
  196. X      if (!$snoopbyfork || fork() == 0);            #   (maybe fork first)
  197. X
  198. X   ($_, $@, $!, $[, $,, $/, $\) = @saved;           # Restore context
  199. X
  200. X   return(undef);
  201. X}
  202. X
  203. Xsub docatch
  204. X{
  205. X   $[ = 0; $, = ""; $/ = "\n"; $\ = "";
  206. X
  207. X   local($usercontext) = '($_, $@, $!, $[, $,, $/, $\) = @saved;' .
  208. X      "package $package;";
  209. X
  210. X   accept(NS,S) || die("accept: $!\n");             # Open new connection
  211. X   setsockopt(S, &SOL_SOCKET, &SO_LINGER, undef);   #   set to linger on close
  212. X   local($oldfh) = select(NS);                      #   and unbuffered I/O
  213. X   $| = 1;
  214. X   select($oldfh);
  215. X
  216. X   undef $command;                                  # Receive command from
  217. X   NSloop: while(<NS>)                              #   socket connection
  218. X   {                                                #   until the hack EOF mark
  219. X      last NSloop
  220. X         if ($_ eq "__SOCKETEND__\n");
  221. X      $command .=  $_;
  222. X   }
  223. X
  224. X   $result = eval("$usercontext $command");         # Evaluate the command in
  225. X   $result = $@                                     #   snoopon() caller's pkg
  226. X      if ($@ ne '');                                #   with current context
  227. X
  228. X   send(NS, $result, 0);                            # Send the results back
  229. X   close(NS);
  230. X
  231. X   kill(9, $$)                                      # Exit just hangs???
  232. X      if ($snoopbyfork);
  233. X
  234. X   return(undef);
  235. X}
  236. X
  237. Xsub makeaddr
  238. X{
  239. X   local(@names) = @_;                              # Take a list of names
  240. X   local($sock, $addr);                             #   and convert it to a
  241. X                                                    #   file system socket
  242. X   $sock="/tmp/";                                   #   address located in
  243. X                                                    #   /tmp.  The names are
  244. X   foreach $name (@names)                           #   joined with ".",
  245. X   {                                                #   and have any "/"s
  246. X      $name =~ s|/|!|go;                            #   converted to "!".
  247. X      $sock .= "$name.";
  248. X   }
  249. X
  250. X   $addr = pack('Sa*', &AF_UNIX, $sock);            # An address suitable for
  251. X                                                    #   use with bind(2).
  252. X   return ($sock, $addr);
  253. X}
  254. X
  255. X1;
  256. ________This_Is_The_END________
  257. if test `wc -l < snoop.pl` -ne 144; then
  258.     echo 'shar: snoop.pl was damaged during transit (should have been 144 bytes)'
  259. fi
  260. fi        ; : end of overwriting check
  261. echo 'x - snoopme'
  262. if test -f snoopme; then echo 'shar: not overwriting snoopme'; else
  263. sed 's/^X//' << '________This_Is_The_END________' > snoopme
  264. X#!/usr/local/gbin/perl
  265. X
  266. Xrequire 'snoop.pl';
  267. X
  268. X&snoopon(0, $0);
  269. X$SIG{'INT'} = "done";
  270. X
  271. Xwhile(1)
  272. X{
  273. X   print "Dum dee dum... " . $inc++ . "\n";
  274. X   sleep(1);
  275. X}
  276. X
  277. Xsub done
  278. X{
  279. X   &snoopoff;
  280. X   exit(0);
  281. X}
  282. ________This_Is_The_END________
  283. if test `wc -l < snoopme` -ne 18; then
  284.     echo 'shar: snoopme was damaged during transit (should have been 18 bytes)'
  285. fi
  286. fi        ; : end of overwriting check
  287. exit 0
  288.  
  289.