When Perl and RPM don’t get along.

August 13, 2008 – 3:37 pm by William

Sometimes when building rpm packages you will get an rpm that requires a file that it already contains. This seems pretty lame (which it is) but here is an example and a workaround.

Building a package for freepbx we see this output:

rpmbuild -ba freepbx.spec
--------snip-----------------
Provides: config(freepbx) = 2.4.0-0
Requires(interp): /bin/sh /bin/sh
Requires(rpmlib): rpmlib(CompressedFileNames) <= 3.0.4-1 rpmlib(PayloadFilesHavePrefix) <= 4.0-1
Requires(post): /bin/sh
Requires(postun): /bin/sh
Requires: /bin/bash /usr/bin/env /usr/bin/perl /usr/bin/php config(freepbx) = 2.4.0-0 perl(DBI) perl(FindBin) perl(retrieve_parse_amportal_conf.pl)

The file we don’t want is: “perl(retrieve_parse_amportal_conf.pl)”

What rpmbuild does is go through the list of files and run “ldd” against all executables to find required libraries.
It also goes through each perl file and looks for “use / require” flags to pull out required perl modules.
When a developer does a legitimate thing like ‘require “retrieve_parse_amportal_conf.pl“‘ to include functions and such into their program, rpmbuild sees that this file is needed adds it too it’s list of required files.

Now rpmbuild also goes through and looks for what packages/files perl programs provide. It does this by scanning through the files and looking for “package“. If you just have an include file with functions, you don’t have a complete module and won’t have the package statement either. Thus rpmbuild will never see your file provides itself! Fortunatly there are a couple work arounds.

In your perl file that rpmbuild is requiring you can define ‘ our $RPM_Provides = “yourfilename.pl” ‘. rpmbuild will pick this up and happily add it to the provided file list. The other method is slightly more complicated but works well if you don’t want to patch the source code.

In your rpm spec file under the %prep section after the %setup add the following code:

cat << \EOF > %{name}-req
#!/bin/sh
%{__perl_requires} $* |\
sed -e ‘/perl(yourperlfile.pl)/d’
EOF
%define __perl_requires %{_builddir}/%{name}-%{version}/%{name}-req
chmod 755 %{__perl_requires}

Where yourperlfile.pl is the file you want to exclude from the rpm requires check.
This should make your rpm build hapily and exlude that file from the requires check.

If you want to see the actuall files rpmbuild runs take a look at:
/usr/lib/rpm/perl.prov
and
/usr/lib/rpm/perl.req

Share and Enjoy:
  • Digg
  • del.icio.us
  • Pownce
  • Slashdot
  • StumbleUpon
  • Technorati
  • TwitThis

The recent DNS vulnerability and the impact on Sonic.net.

July 11, 2008 – 5:35 pm by Augie Schwer

Earlier this week US-CERT announced a very serious DNS Cache Poisoning vulnerability which affects a large number of DNS servers across the Internet.

Thankfully we here at Sonic.net run PowerDNS on our Authoritative and Recursive servers which has been hardened against this type of attack for years (official PowerDNS statement on the vulnerability).

The vulnerability would allow an attacker to inject incorrect answers into the recursive server, which would then send clients to a potentially malicious web site or redirect email, or any other network traffic; all of which would be un-detected by the user or the host running the name server.

It is highly recommended that you update your DNS name server software; all major vendors will have patches and updates available; of course if you were running PowerDNS, then you wouldn’t need to do any patching. :)

Share and Enjoy:
  • Digg
  • del.icio.us
  • Pownce
  • Slashdot
  • StumbleUpon
  • Technorati
  • TwitThis

How to write a WordPress plugin to notify your customers via Twitter.

July 3, 2008 – 4:02 pm by Augie Schwer

Wordpress has a page on “Writing a Plugin” that you can refer to for all the gory details; this post is a quick demonstration of how you too can notify people of updates to your Blog via Twitter.

Add your handlers:

add_action('edit_form_advanced','notify_customers_checkbox');
add_action('save_post','notify_customers');

Add some check boxes to the “Write Post” interface:

function notify_customers_checkbox()
{
?>
<fieldset id="notify_customers" class="dbx-box">
<h3 class="dbx-handle">Notify Customers:</h3>
<div class="dbx-content">
<input type="checkbox" name="send_to_twitter" id="send_to_twitter" checked="checked" /> twitter
<input type="checkbox" name="send_to_list" id="send_to_list" checked="checked" /> email
<input type="checkbox" name="send_to_nntp" id="send_to_nntp" checked="checked" /> nntp
</div>
</fieldset>
<?php
}

Check the status of those check boxes:

function notify_customers($post_id)
{
if ( isset ( $_POST['send_to_twitter'] ) )
{ send_to_twitter($post_id); }

if (isset ( $_POST['send_to_list'] ) )
{ send_to_list($post_id); }

if (isset ( $_POST['send_to_nntp'] ) )
{ send_to_nntp($post_id); }
}

Write a method to take your post, clean it up a bit and send it off to Twitter:

function send_to_twitter($post_id)
{
$twitter_user = 'sonicnet_status';
$twitter_pass = '';

$post_url     = get_permalink($post_id);
$post_title    = stripslashes($_POST['post_title']);
$post_title    = html_entity_decode($post_title);
$post_content    = stripslashes($_POST['post_content']);
$post_content    = strip_tags($post_content);
$post_content    = html_entity_decode($post_content);

$twitter_message = "$post_title: $post_content";

// We only care about published posts.
// If it's an old post being updated prepend "Update" to the post.

if ( $_POST['prev_status'] == 'draft' ) //new post.
{
if($_POST['publish'] == 'Publish')
{
$xrl = file_get_contents("http://metamark.net/api/rest/simple?long_url=$post_url");

$twitter_message = substr($twitter_message , 0 , 117);
$twitter_message = "$twitter_message... $xrl";
$twitter_message = urlencode($twitter_message);

$url = 'http://twitter.com/statuses/update.xml';
$curl_handle = curl_init();
curl_setopt($curl_handle, CURLOPT_URL, "$url");
curl_setopt($curl_handle, CURLOPT_CONNECTTIMEOUT, 2);
curl_setopt($curl_handle, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl_handle, CURLOPT_POST, 1);
curl_setopt($curl_handle, CURLOPT_POSTFIELDS, "status=$twitter_message");
curl_setopt($curl_handle, CURLOPT_USERPWD, "$twitter_user:$twitter_pass");
$buffer = curl_exec($curl_handle);
curl_close($curl_handle);
}
}
}

And there you have it; you’ve just told all your Twitter followers about your latest Blog post.

You’ll note we do some other cool stuff to keep our customers in the loop; like send them E-Mail and post to Usenet, but that’s another Blog post.

Share and Enjoy:
  • Digg
  • del.icio.us
  • Pownce
  • Slashdot
  • StumbleUpon
  • Technorati
  • TwitThis

Our contribution to the community: CPAN PowerDNS modules released.

June 24, 2008 – 4:01 pm by Augie Schwer

We have released several PowerDNS modules to CPAN:

http://search.cpan.org/~augie/

PowerDNS::Backend::MySQL Provides an interface to manipulate PowerDNS data in the MySQL Backend.

PowerDNS::Control::Client Provides an interface to control the PowerDNS daemon.

PowerDNS::Control::Server Provides an interface to control the PowerDNS daemon.

Share and Enjoy:
  • Digg
  • del.icio.us
  • Pownce
  • Slashdot
  • StumbleUpon
  • Technorati
  • TwitThis

Perl , $SIG{CHLD} = ‘IGNORE’ , system() and you.

June 24, 2008 – 3:45 pm by Augie Schwer

At first blush you probably would not expect the following to print “-1″; as you probably expect “system” to execute and return the return code from “echo”.

$SIG{CHLD} = 'IGNORE';
print system('echo');

This stumped me too, so I did some research.

From the Perl PIC Documentation:

On most Unix platforms, the CHLD (sometimes also known as CLD) signal has special behavior with respect to a value of ‘IGNORE’. Setting $SIG{CHLD} to ‘IGNORE’ on such a platform has the effect of not creating zombie processes when the parent process fails to wait() on its child processes (i.e. child processes are automatically reaped). Calling wait() with $SIG{CHLD} set to ‘IGNORE’ usually returns -1 on such platforms.

And perldoc -f system:

The return value is the exit status of the program as returned by the wait call. … Return value of -1 indicates a failure to start the program or an error of the wait(2) system call (inspect $! for the reason).

And wait(2):

POSIX.1-2001 specifies that if the disposition of SIGCHLD is set to SIG_IGN or the SA_NOCLDWAIT flag is set for SIGCHLD (see sigaction(2)), then children that terminate do not become zombies and a call to wait() or waitpid() will block until all children have terminated, and then fail with errno set to ECHILD. (The original POSIX standard left the behaviour of setting SIGCHLD to SIG_IGN unspecified.) Linux 2.6 conforms to this specification. However, Linux 2.4 (and earlier) does not: if a wait() or waitpid() call is made while SIGCHLD is being ignored, the call behaves just as though SIGCHLD were not being ignored, that is, the call blocks until the next child terminates and then returns the process ID and status of that child.

So on Linux 2.6 kernels if you auto. reap zombies by setting $SIG{CHLD} to ‘IGNORE’, then you can’t trust the return code from ’system’ as it will always be ‘-1′.

One solution would be to reap your own zombies with one of the popular zombie reaping code snipets.

sub REAPER { 1 until waitpid(-1 , WNOHANG) == -1 };
$SIG{CHLD} = \&REAPER;
print system('echo');

Be careful when using the special Perl variable ‘$?’ because it will have been altered by the call to ‘waitpid’ in your REAPER.

This is because when a child exits a SIG_CHLD is sent to its parent to see this in action try the code below:

sub REAPER
{ print "REAPER\n"; waitpid(-1 , WNOHANG); }
$SIG{CHLD} = \&REAPER;
system('echo');
print "RV: $?\n";

Share and Enjoy:
  • Digg
  • del.icio.us
  • Pownce
  • Slashdot
  • StumbleUpon
  • Technorati
  • TwitThis

Procmail Tips: How to forward your email.

June 24, 2008 – 2:56 pm by Augie Schwer

Not that you would ever want to forward your email away from Sonic.net, but maybe you like the idea of archiving and searching your E-Mail at a secondary E-Mail location; to that end the post below details how you should be forwarding your E-Mail in any UNIX environment.

You know that looping your mail is a bad idea; that is forwarding your email to Gmail and then forwarding that back to yourself, ad infinitum, you get the idea. It’s equally a bad idea to forward DSNs or bounce messages to Gmail (or anywhere really); as it causes the same sort of loop and the same kind of aggravation for your System Administrator. The following is a procmail recipe that works for me; just drop this into your .procmailrc in your home directory.

SENDMAIL=/usr/sbin/sendmail
FORMAIL=/usr/bin/formail

:0
* ^X-Loop: Your_Email_Address@sonic.net
/dev/null

:0E
* ^TO_Your_Email_Address\+0×96rds@sonic\.net
$DEFAULT

:0cE
| $FORMAIL -A “X-Loop: Your_Email_Address@sonic.net” | $SENDMAIL -f Your_Email_Address+0×96rds@sonic.net -oi Your_Email_Address@gmail.com

In detail:

SENDMAIL=/usr/sbin/sendmail
FORMAIL=/usr/bin/formail

Sets up some variables.

:0
* ^X-Loop: Your_Email_Address@sonic.net
/dev/null

Discards the message if it has the “X-Loop” header in it; this stops circular mail loops; for example if you forwarded Your_Email_Address@sonic.net to Your_Email_Address@gmail.com and then forwarded that back to Your_Email_Address@sonic.net.

:0E
* ^TO_Your_Email_Address\+0×96rds@sonic\.net
$DEFAULT

Places the message in your Inbox and does not forward it on if the “To” header contains our address plus the special string. This stops you from forwarding those nasty bounce messages to the server that just sent you the bounce, thus causing a ping pong affect.

Little known fact: your_user_name+anything@sonic.net will go to your_user_name@sonic.net, so you can utilize that little “+anything” to do special filtering like in this script.

:0cE
| $FORMAIL -A “X-Loop: Your_Email_Address@sonic.net” | $SENDMAIL -f Your_Email_Address+0×96rds@sonic.net -oi Your_Email_Address@gmail.com

Finally this bit adds the above conditions to your message before forwarding it on to your “other” E-Mail provider.

Share and Enjoy:
  • Digg
  • del.icio.us
  • Pownce
  • Slashdot
  • StumbleUpon
  • Technorati
  • TwitThis

Hello world!

May 30, 2008 – 10:59 am by Augie Schwer

Welcome to the Sonic.net “Internals” blog. Here you’ll find technical postings from real Sonic.net employees (mostly System and Network Administrators) about how we keep things working at your favorite ISP; stay tuned as we will have content up real soon.

Share and Enjoy:
  • Digg
  • del.icio.us
  • Pownce
  • Slashdot
  • StumbleUpon
  • Technorati
  • TwitThis