rssfeeder 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. #!/usr/bin/perl -w
  2. # (c) 2007 S. Smeenk <ssmeenk@freshdot.net>
  3. # GPLv2
  4. use strict;
  5. use POSIX qw/setsid getpid strftime/;
  6. use Unix::Syslog qw/:macros :subs/;
  7. use LWP;
  8. use LWP::UserAgent;
  9. use Digest::MD5 qw(md5_hex);
  10. ## Config stuff :)
  11. my $SERVICE = "rssfeeder";
  12. my $PIDFILE = $ENV{'HOME'} . '/.irssi/irssi-rss/rssfeeder.pid';
  13. my $FEEDSFILE = $ENV{'HOME'} . '/.irssi/irssi-rss/rssfeeder.lst';
  14. my $FEEDSTMP = $ENV{'HOME'} . '/.irssi/irssi-rss/';
  15. my $DELAY = 300; # seconds between rss retrieval
  16. ## Internals :)
  17. my $UA = LWP::UserAgent->new; $UA->agent('irssi-rss');
  18. my $NOISY = 1; # Default to printing stuff on STOUD/STDERR
  19. $0 = $SERVICE;
  20. if ( ! -d $FEEDSTMP ) {
  21. mkdir $FEEDSTMP || die "Sorry, $FEEDSTMP doesn't exist, and mkdir failed: $!\n";
  22. }
  23. checkargs();
  24. checkself();
  25. daemonize();
  26. opensyslog();
  27. writepid();
  28. while (1) { main(); sleep $DELAY; }
  29. exit 0;
  30. # ###
  31. ## ##
  32. ### #
  33. sub main {
  34. if (open (FD, "<$FEEDSFILE")) {
  35. while (my $feed = <FD>) {
  36. chomp($feed);
  37. my ($feedtag, $feedurl) = $feed =~ /^(.+?)\s(.+?)$/;
  38. my $filename = $FEEDSTMP . "rssfeeder_" . md5_hex($feedurl);
  39. my $result = $UA->mirror($feedurl, $filename);
  40. if ($result->code == 200) {
  41. # Everything OK, file saved by $UA->mirror()
  42. } elsif ($result->code == 304) {
  43. # Everything OK, just not modified :)
  44. } else {
  45. syslog LOG_WARNING, "rss feed $feedtag on $feedurl returned ".$result->code;
  46. }
  47. }
  48. } else {
  49. syslog LOG_NOTICE, "unable to read from $FEEDSFILE: $!";
  50. }
  51. }
  52. sub opensyslog {
  53. my $OPTIONS = LOG_CONS | LOG_PID;
  54. my $FACILITY = LOG_DAEMON;
  55. openlog $SERVICE, $OPTIONS, $FACILITY;
  56. syslog LOG_NOTICE, "$SERVICE starting.";
  57. }
  58. sub suicide {
  59. open (FD, "<$PIDFILE") or die "($$) cannot open $PIDFILE: $!\n";
  60. my $childpid = <FD>;
  61. close (FD);
  62. if (!$childpid || ($childpid !~ /^\d+$/)) {
  63. print "($$) incorrect format $PIDFILE. bailing out.\n" if $NOISY;
  64. exit 0;
  65. }
  66. if (not kill(0, $childpid)) {
  67. print "($$) stale $PIDFILE. no process '$childpid'.\n" if $NOISY;
  68. print "($$) unlinking $PIDFILE. nothing to kill.\n" if $NOISY;
  69. unlink $PIDFILE or die "($$) cannot unlink $PIDFILE: $!\n" if $NOISY;
  70. exit 0;
  71. } else {
  72. print "($$) found active process '$childpid' from $PIDFILE.\n" if $NOISY;
  73. if (not kill(9, $childpid)) {
  74. die "($$) no process '$childpid'. this is weird mm'kay?\n";
  75. } else {
  76. print "($$) killed $childpid. unlinking $PIDFILE.\n" if $NOISY;
  77. unlink $PIDFILE or die "($$) cannot unlink $PIDFILE: $!\n";
  78. }
  79. }
  80. }
  81. sub checkargs {
  82. foreach my $ARG (@ARGV) {
  83. if ($ARG =~ /--kill/) {
  84. print "($$) killing $SERVICE.\n" if $NOISY;
  85. suicide(); exit;
  86. } elsif ($ARG =~ /--cron/) {
  87. $NOISY = 0; # No more output from this point. only syslog.
  88. } elsif ($ARG !~ /--(kill|cron)/) {
  89. showhelp(); exit;
  90. }
  91. }
  92. print "($$) $SERVICE starting.\n" if $NOISY;
  93. }
  94. sub showhelp {
  95. my $basename = reverse(substr(reverse($0),0,index(reverse($0),'/')));
  96. print "($$) $SERVICE\n";
  97. print "($$)\n";
  98. print "($$) usage: $basename [args]\n";
  99. print "($$)\n";
  100. print "($$) where [args] can be a combination of:\n";
  101. print "($$) --kill : Kills a possibly running pptp checker by looking\n";
  102. print "($$) up the pid from $PIDFILE\n";
  103. print "($$) --cron : Silent operation. Only syslog output\n";
  104. print "($$)\n";
  105. print "($$) reads rss feeds from file $FEEDSFILE\n";
  106. }
  107. sub writepid {
  108. if (open (FD, ">$PIDFILE")) {
  109. print FD getpid();
  110. close (FD);
  111. } else {
  112. syslog(LOG_WARNING, "could not write pidfile $PIDFILE: %m");
  113. }
  114. }
  115. sub daemonize {
  116. chdir '/' or die "($$) Can't chdir to /: $!\n";
  117. # open STDIN, '/dev/null' or die "($$) Can't read /dev/null: $!\n";
  118. # open STDOUT, '/dev/null' or die "($$) Can't write to /dev/null: $!\n";
  119. print STDERR "($$) ready to fork. closed stdin & stdout.\n" if $NOISY;
  120. defined(my $pid = fork) or die "($$) Can't fork(): $!\n";
  121. print STDERR "($$) forked process $pid. take care!\n" if ($pid && $NOISY);
  122. exit if $pid;
  123. my $c = getpid();
  124. print STDERR "($c) thanks! child taking over, have a nice day.\n" if $NOISY;
  125. setsid() or die "($$) Can't start a new session: $!\n";
  126. # open STDERR, '>&STDOUT' or die "($$) Can't redirect STDERR: $!\n";
  127. }
  128. sub checkself {
  129. my $pid = "empty";
  130. if (open (FD, $PIDFILE)) {
  131. $pid = <FD>;
  132. close (FD);
  133. }
  134. if (($pid && ($pid =~ /^\d+$/)) && (kill (0, $pid))) {
  135. print "($$) already active as process '$pid'\n" if $NOISY;
  136. exit 0;
  137. }
  138. if (($pid && ($pid =~ /^\d+$/)) && (not kill (0, $pid))) {
  139. print "($$) stale $PIDFILE. '$pid' no longer active!\n" if $NOISY;
  140. print "($$) unlinking $PIDFILE and doing normal startup.\n" if $NOISY;
  141. unlink $PIDFILE or die "($$) Can't unlink $PIDFILE: $!\n";
  142. }
  143. }