2006-05-25 rss feed
Just spent the past couple of hours making an RSS feed for this site. Those who are using firefox should have a little RSS icon in the lower right corner of the window where you can subscribe.
What's the fuss about you might ask. Rightly so, there's little reason to get excited about RSS, but on one hand it does allow people to collaborate their sites. For instance, it's not too much work for me to embed a friend's headlines within my page content.
xb360 hack
A friend of mine is currently fiddling with their xbox360 to play backups. Please note they are backups, not copies. Rightly so, why shouldn't the game owner be able to keep a backup should the original become damaged? Here is a link to the document containing details. xbox 360 backup hack.
2006-05-23 thumbnail resize
We've all been there, wanting to make some thumbnails in a hurry to resize a site's directory or whatever... well, let me save you the work.
#!/usr/bin/perl -w
use strict;
use warnings;
my $tnx = 150;
my $tny = 150;
my $od = "./temp/";
sub resize {
my $file = shift;
my $output = `/usr/bin/identify $file`;
$output =~ s/.*JPEG //;
$output =~ s/ .*//;
if( $output =~ /([0-9]+)x([0-9]+)/ ) {
my $nx = $tnx;
my $ny = $tny;
my $x = $1;
my $y = $2;
if( $x > $y ) {
$nx = $tnx / $x;
$ny = $nx * $y;
$nx = $tnx;
}
else {
$ny = $tny / $y;
$nx = $ny * $x;
$ny = $tny;
}
my $cmd = "/usr/bin/convert -resize ${nx}x${ny} $file ${od}$file";
print( `$cmd` );
}
}
sub processdir {
opendir( DIR, "./" );
while( my $file = readdir( DIR ) ) {
if( $file =~ /.jpg/i ) {
print( $file."\n" );
resize( $file );
}
}
}
processdir();
This requires perl an ImageMagick, but fear not, this is not using the perl library, so it's one less thing to depend on, should run relatively quick, dont worry about the decimal point, that's handled by imagemagick too (if it was not, then I'd strip it out before calling, but there's no need, it's faster for ImageMagick to do that in C).
Oh wow, look, I've been making blod entries for over a year now... For those who are interested (I'm sure it's not many of you) there have been over 6000 paragraphs added (I'm not sure how many exist, that's just the current ID) and 123 articles. For what it's worth, every line of code counts for a paragraph, that's the style I decided to use so hopefully making huge changes to the overall appearance of this site is a bit easier. Perhaps that was a bad choice.. It's hard to tell. What is easier is to have each text block as a paragraph, then I can simply apply a large change to all the articles in one go.
2006-05-20 new interest
I've decided to learn some Russian. It has come to my attention that I should be less ignorant of others in this world and should make a good effort to learn something along the way.
On this note I had a delivery from Amazon today for three books:
- Teach Yourself Russian Complete Course (Book + CD Pack)
- Teach yourself beginners Russian script
- The Cuckoo's Egg: Tracking a Spy Through the Maze of Computer Espionage
So far I am quite pleased with this choice. There isn't enough attention to foriegn languages on the PC! Fortunately there is a gnome application that allows one to switch keyboard layouts in applications that can support it.
2006-05-18 data sync
I spotted a post on usenet tonight which I felt like responding to in comp.unix.programmer:
"I have an application (for trading stocks) that is a transaction processing system, sending out orders using a socket messaging protocol. It logs the messages to a file. The log file gets very large as the day progresses to about 100 Mb or more. Will this large file size cause a performance issue, in terms of sending out and receiving socket messages. I am interested in understanding this at a linux system level as to what happens. My application runs on Solaris and Linux, are the performance impacting factors different on Solaris and linux."
Here is a quick c program that demonstrates FILE stream buffering
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
void logline( char *text ) {
FILE *fp = fopen( "./logfile", "a+" );
if( !fp ) {
fprintf( stderr, "Cannot open logfile for append\n" );
exit( EXIT_FAILURE );
}
fprintf( fp, "%s\n", text );
fclose( fp );
}
int main() {
char *logtext=(char *)malloc(1024);
register int i;
int size;
time_t timer;
for( i=0 ; i<26 ; i++ ) {
logtext[i] = 'a'+i;
logtext[i+26] = 'A'+i;
}
timer = time( NULL );
for( i=0 ; i<1155350 ; i++ ) {
logline( logtext );
if( i % 200 == 0 ) {
fprintf( stdout, "%d seconds %i lines\n", \
time( NULL ) - timer, i );
}
}
free( logtext );
return( EXIT_SUCCESS );
}
One of the benefits of a Unix like kernel is that the writes to disk are nearly always buffered, and dumped to disk later when the kernel feels happy to. This can offer some huge benefits (when you think about where the head might be in relation to the disk, its obviously better to write the data in patches as the head moves in a full sweep from the inner tracks to the outter).
Performance of this program degrades by adding a 'must write to disk' statement after writing:
fdatasync( fp->_fileno );
This single line advises the kernel to flush everything to disk. Unlike the fclose which just frees the file descriptor.
2006-05-14 netmon
Code today to monitor network traffic.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
/* network monitor.c
* Monitors the bytes of traffic on a network device
* 2006-05-14 ed AT s5h DOT net - version 0.1 beta code
* Use at your own risk. Author not responsible for use.
*
* Updates at http://www.s5h.net
*
* Released under GPL version 2 only.
*/
#define PROCNET "/proc/net/dev"
struct interface_line {
struct interface_line *next;
char name[20]; /* over sized */
long long ibytes;
long long obytes;
long long ipackets;
long long opackets;
long long ierr;
long long oerr;
long long idrop;
long long odrop;
long long ififo;
long long ofifo;
long long iframe;
long long oframe;
long long icompressed;
long long ocompressed;
long long imulticast;
long long omulticast;
};
void *if_name( char *name, struct interface_line *il ) {
while( il != NULL ) {
if( strncmp( il->name, name,20 ) == 0 ) {
return( il );
}
il = il->next;
}
return( NULL );
}
struct interface_line *find_last( struct interface_line *ptr ) {
if( ptr == NULL ) {
return( NULL );
}
while( ptr->next != NULL ) {
ptr = ptr->next;
}
return( ptr );
}
void free_list( struct interface_line *i ) {
struct interface_line *p;
while( i != NULL ) {
p = i->next;
free(i);
i = p;
}
}
struct interface_line *parse_line( char *line, struct interface_line *lst ) {
struct interface_line *il;
struct interface_line *ptr;
char *colon;
char *temp = malloc(20);
colon = strstr( line, ":" );
if( colon ) {
*colon = ' ';
}
if( sscanf( line, "%s", temp ) == 0 ) {
fprintf( stderr, "Cannot get interface name\n" );
exit(EXIT_FAILURE);
}
il = if_name( temp, lst );
if( il == NULL ) {
il = malloc( sizeof( struct interface_line ) );
il->next = NULL;
snprintf( il->name, 20, "%s", temp );
ptr = find_last( lst );
if( ptr == NULL ) {
lst = il;
}
else {
ptr->next = il;
}
}
if( sscanf( line, "%s %Ld %Ld %Ld %Ld %Ld %Ld %Ld %Ld %Ld %Ld %Ld %Ld %Ld %Ld %Ld %Ld",
il->name,
&il->ibytes, &il->ipackets, &il->ierr,
&il->idrop, &il->ififo, &il->iframe,
&il->icompressed, &il->imulticast,
&il->obytes, &il->opackets, &il->oerr,
&il->odrop, &il->ofifo, &il->oframe,
&il->ocompressed, &il->omulticast
) == 0 ) {
free(il);
return(NULL);
}
/* else {
printf( "Name %s Bytes in %Ld bytes out %Ld\n", il->name, il->ibytes, il->obytes );
}*/
free(temp);
return(lst);
}
struct interface_line *find_il( struct interface_line *ifname, struct interface_line *linked ) {
struct interface_line *ptr;
while( ptr != NULL && ptr->next != NULL ) {
if( strncmp( ptr->name, ifname->name, 20 ) == 0 ) {
return( ptr );
}
ptr = ptr->next;
}
return( NULL );
}
void print_list( struct interface_line *p, struct interface_line *pp ) {
while( p != NULL ) {
if( pp == NULL ) {
pp = p;
}
printf( "Name: %s In:%LdMiB Out:%LdMiB\t In:%LdKiB Out:%LdKiB\n",
p->name, p->ibytes/1024/1024, p->obytes/1024/1024,
(p->ibytes-pp->ibytes)/1024, (p->obytes-pp->obytes)/1024 );
p=p->next;
pp=pp->next;
}
printf( "\n\n" );
}
void readdev() {
FILE *fp;
char *contents = malloc( 1000 );
struct interface_line *cur_list = NULL;
struct interface_line *last_list = NULL;
if( ( fp = fopen( PROCNET, "r" ) ) == NULL ) {
fprintf( stderr, "cannot open %s\n", PROCNET );
exit(EXIT_FAILURE);
}
while( 1 ) {
if( fseek( fp, 0, SEEK_SET ) ) {
fprintf( stderr, "error seeking in %s\n", PROCNET );
exit(EXIT_FAILURE);
}
while( fgets( contents, 1000, fp ) ) {
if( strstr( contents, ":" ) == NULL ) {
continue;
}
cur_list = parse_line( contents, cur_list );
}
print_list( cur_list, last_list );
free_list( last_list );
last_list = cur_list;
cur_list = NULL;
usleep(1000000);
}
fclose(fp);
free(contents);
}
int main() {
readdev();
return(EXIT_SUCCESS);
}
I had done something similar in BSD for network bandwidth monitoring, but there's a distinct absence of the ifa_data structure on the linux platform, so the only alaternative that I can see is to use the /proc file system. This as you can see from the above adds a real overhead as the file has to be parsed to glean the network device information. Unlike OpenBSD's structure this has one advantage that network aliases are not classed as devices [although that is a real small advantage].
(Hint: beware the usleep(1000) call might be a tad fast for you.)
2006-05-14 gvim7 on debian
I don't know what it is, but I really like gvim. It's great, superb. Bram Moolenaar has released version 7 after much work, and it's just got better. Perhaps the most notable feature is improved ^n^n. There were some obscure dependencies missing for the configure script to compile with GUI support on my debian stable system. Here's a list of what you probably have to get.
apt-get install libatk1.0-dev libglib2.0-dev libgpmg1-dev libgtk2.0-dev xlibs-dev libpango1.0-dev libx11-dev
Once the above is retrived you can then configure (confiugre doesn't tell you much if a required library is missing)
./configure --prefix=/usr --mandir=/usr/share/man --with-compiledby=eneville --enable-gpm --enable-cscope --with-features=big --enable-multibyte --with-x --enable-xim --enable-fontset --enable-gui=gtk2 --enable-rlinterp --disable-pythoninterp --enable-rubyinterp --enable-tclinterp
If that compiles, just go to the source directory and link vim to gvim and it should start up nicely as a GTK app.
2006-05-12 perl sub hashes
Just a short post today. Hashes in perl are teadious, for a lot of information see the man pages, for less information see perldoc perlreftut, for even less information see below for something that just stores a subhash and then calls it back.
#!/usr/bin/perl
use strict;
use warnings;
sub main {
my %hash;
my %hash_element;
$hash_element{"first"} = 1;
$hash_element{"second"} = 1;
# fine
$hash{"num"} = \%hash_element;
# not fine
my $new = $hash{"num"};
my %h = %{$new};
print( $h{"first"} . "\n" );
}
main();
2006-05-11 sitemaps and stuff
A friend pointed out to me that google(tm) uses sitemaps to perhaps help crawl sites. Saves their bandwidth bill if they know before hand which pages have changed and stuff. So, I've gone to some lengths to create a sitemap.xml on demand via the php error page.
It just queries my data base for a list of what html pages it has and then prints today's date against each page. This ensures that the menu on on the left hand side of my page is acurate.
It's just a short function and I welcome all to give it a go.
function write_sitemap( $url ) {
$sql = "select left( dat,7 ) as da from articledate group by da order by da";
$result = mysql_query( $sql );
$dates = array();
$count = 0;
while( $l = mysql_fetch_array( $result ) ) {
$dates[$count++] = $l['da'];
}
$sitemap =
'<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.google.com/schemas/sitemap/0.84">
<url>
<loc>' . $url . '/</loc>
<lastmod>' . date( "Y-m-d" ) . '</lastmod>
<changefreq>daily</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>' . $url . '/dns/</loc>
<changefreq>weekly</changefreq>
</url>' . "\n";
for( $i=0,$s=sizeof($dates); $i<$s; $i++ ) {
$sitemap .=
' <url>
<loc>' . $url . "/" . $dates[$i] . '.html</loc>
<changefreq>daily</changefreq>
<lastmod>' . date( "Y-m-d" ) . "</lastmod>
</url>\n";
}
$sitemap .= "</urlset>";
echo( $sitemap );
}
2006-05-06 amd64 sizeof int
Due to recent hardware problems I had to go and change my motherboard. I previously owned an Athlon Barton CPU (Basically AthlonXP with 512KiB cache). Everything was fine until I added some RAM, the mobo errored when doing memtests, on all conceivable configurations. I had the choice, stick with the current Socket7 or get Socket939. I chose to use 939, which meant upgrading both CPU and motherbaord.
The first mobo was a bit of a mistake, it was an Abit AV8, but it didn't like my CPU and there was a note on their BIOS upgrade page stating that some Version E CPUs need a Flash update... Which was impossible as I didn't have anything that could take the same BIOS chip so it had to go back and I had to get a Gigabyte board instead. Which was great.
So, with new CPU and mobo in place I have a log into my box and everything is fine, the kernel still boots just how it did previously. This is not enough for me... I have a new toy and I want to see where I can take it. So I set the CPU to Opteron/Athlon64 in the kernel, rebuild and see if theres any difference. Everything booted just fine, so I ran the code below:
#include <stdio.h>
int main() {
printf( "CHAR %d\n", sizeof( char )*8 );
printf( "SHORT %d\n", sizeof( short )*8 );
printf( "INT %d\n", sizeof( int )*8 );
printf( "LONG %d\n", sizeof( long )*8 );
printf( "LONG LONG %d\n", sizeof( long long )*8 );
printf( "LONG LONG INT %d\n", sizeof( long long int )*8 );
return(0);
}
I get the following output:
CHAR 8 SHORT 16 INT 32 LONG 32 LONG LONG 64 LONG LONG INT 64
What? I'm running 64bits now, why is long still 32? This is because the /usr/include/limits.h states the size of a long. This should not be fiddled with. It's part of the standard libraies which are linked to. Altering this would pretty much require that you do a LFS 'upgrade'.
So first I try ubuntu-5.10-install-amd64.iso, which is fine, I install this and nearly everything is ok. Zsnes isn't though. One of the obvious differences is that anything I had previously compiled now refuses to run. Well I got thinking about the long debate between using Ubuntu and Debian stable, since FireFox is now unstable as hell, 10% of the pages I visit crash. This is not good enough, I don't want to work Mark Shuttleworth's crank.
Next thing I do is to get the debian 64bit iso, debian-31r2-ia64-businesscard.iso, which I promptly burn to an 8cm CD. This is mistake number 2. My PC goes into a reboot loop before a boot: prompt.
I get likewise reults with debian-31r2-ia64-netinst.iso.
At this point I stuble upon the unofficial debian-31r0a-amd64-netinst.iso. This installs just great. Firefox is stable, I have a lovely system just like I had last year :) I'm over the moon. But wait... All my c programs are broken. Still my c program now (when recompiled) gives the following output:
CHAR 8 SHORT 16 INT 32 LONG 64 LONG LONG 64 LONG LONG INT 64
So, sod all difference, my memory is now fully addressable, system is stable, but somethings that I want to do are just not accessible. So for now, I'm going back to debian stable, and shall have make a dual booting system for amd64.
2006-05-03 jelly legs
Run complete :) I crossed the line at 28:10, I could go on about how I ran out of steam just a bit too early and things, but I'm sure if I had my time again I could improve in many ways. The event raised an estimated 150,000(gbp) for Cancer Research UK.
This was a short event compared to others (3miles) perhaps with a bit more training my stamina could improve and maybe enter for further distances, overall I enjoyed myself. I have a deep feeling of accomplishment.
Info