Saturday, November 16, 2013

Unix shell environment pro tip:

Something I'm doing now that I have just way to many machine on different networks...

 1) Setup a Dropbox or Google Drive account (probably dropbox since google drive isn't well supported in other unixes at the moment)
 2) Make directory called something like myprofile
 3) Initialize Git repositories (using git --bare):
   a) shell_profile
   b) vim (or emacs)
   c) ssh
 4) clone respective repositories into ~/.{profile,vim,ssh}
 5) Setup gitignore for private files (for example your ssh private key)
 6) Install your ssh_config, custom shell functions/aliases/prompts, vim syntax files, et cetera into respective directories and git add & push files
 7) write a function into custom profile (bash) to iterate to through git commits for shell workflow files call it something like sync_profile; remember to call this when you edit files or hook it your logout
 8) write a simple shell script in your remote drive (dropbox) that automates the directory cloning process

Now, when you get a new shell account/virtual-machine et cetera all you have to do get your "unified shell environment" is:
 a) Install/Mount dropbox
 b) run ~/Dropbox/setup_shell.sh

Upside is that if you screw up a config file, or something you also get all the benefits of version control via git.

Saturday, September 24, 2011

Add Try::Tiny to Mouse or Moose


Here is a little snippet that shows how to extend Mouse (lightweight version of Moose) with Try::Tiny for better exception handling.

Here would be your application class:

package MyApp::Mouse;

use Mouse ();
use Mouse::Exporter;
use Try::Tiny;

Mouse::Exporter->setup_import_methods( 
	as_is => [qw[try catch finally]],
	also  => 'Mouse'
);

1;

Then you simply use MyApp::Mouse in place of the Mouse module for your classes:

package Foo;

use MyApp:::Mouse;

sub t {
	my ($self,$d) = @_;
	
	my $v = try {
		die "testing" if $d;
		'no';
	} catch {
		$_;
	}; 

	return $v;
}

1;

A simple test?

package Foo;

~$ perl -Mfeature=:5.12 -MFoo -e say Foo->new->t;
no

Of course this recipe works with Moose, simply replace the Mouse namespace with the Moose namespace and your in business.

Friday, September 23, 2011

Experimenting with #mojolicious experimental groups block

In the course of discussion via IRC in #mojo the groups block was added as an experimental feature to Mojolicious::Lite (originally called routes but shortly after renamed), here is the result of me playing with it in the context of a authentication and authorization:


use Mojolicious::Lite;

under sub { 
  my $self = shift;
  my ($user) = split /:/, $self->req->url->to_abs->userinfo;
  
  unless ($user) {
    $self->res->headers->www_authenticate('Basic realm=test');
    $self->render_text('You must log in', status => 401);
    return;
  } else {
    $self->stash( user => $user );
    return 1;
  }
};

helper greet => sub {
  sprintf(
    "Hello %s would you like to play a game",
    shift->stash('user')
  );
};

get '/' => sub { shift->greet; };

group {
  under '/gtw' => sub { shift->stash('user') eq 'david' };

  get sub {
    shift->render_text('The only way to win is to not play at all');
  };
};

get '/chess' => sub { shift->render_text('checkmate'); };
get '/bye'   => sub { shift->render_text('Bye!', status => 401); };

app->start;


Friday, September 9, 2011

Implementation of Pascal's Triangle with Perl and Moose

Probably not the best way to do it, but I thought I would give it a hack:




#!/usr/bin/perl

package Row;

use Moose;

has triangle => (
is => 'ro',
isa => 'Triangle',
);

has prev => (
is => 'ro',
isa => 'Row',
);

has members => (
is => 'rw',
isa => 'ArrayRef[Int]',
lazy_build => 1,
);

sub _build_members {
my $self = shift;

return [1] unless $self->prev;

my @prev = @{ $self->prev->members };

my @values = (1);

for(my $i = 0; $i < ( scalar(@prev) - 1 ); $i++) {
my $c = $prev[ $i ];
my $n = $prev[ $i + 1 ] || 1;

push @values, $c + $n;
}

push @values, 1;

return \@values;
}

sub print {
my $self = shift;
print join ' ', @{ $self->members },"\n";
return $self;
}

__PACKAGE__->meta->make_immutable;

no Moose;

package Triangle;

use Moose;

has rows => (
is => 'rw',
isa => 'ArrayRef[Row]',
default => sub { [ Row->new({}) ] },
);

sub first {
my $self = shift;
return $self->rows->[0];
}

sub last {
my $self = shift;
return $self->rows->[ $#{ $self->rows } ];
}

sub next {
my $self = shift;
my $row = Row->new( prev => $self->last );
push @{ $self->rows }, $row;
return $self->last;
}

__PACKAGE__->meta->make_immutable;

package main;

die "Usage: $0 \n"
unless $ARGV[0] > 1;


my $t = Triangle->new;

$t->next->prev->print foreach(1..$ARGV[0]);

Wednesday, August 31, 2011

Some more C musings

Still working on getting my C mojo back both for school and for a application project. Here is an example of some (attempting to be overrun safe) dynamic memory alocation:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>


char *speak ( char *bs, unsigned int counter ) {
	char *str    = "Hello %d: %s";

	size_t bs_l  = strlen( bs );
	size_t str_l = strlen( str ) - 2;
	size_t c_l   = counter == 0? 1 : log(counter) / log(10) + 1;
	size_t alloc = str_l + c_l + bs_l;

	char *ptr    = malloc( alloc );
	int written  = snprintf( ptr, alloc, str, counter, bs );

	printf( "(%zd + %zd + %zd) = %zd <> %i: ", str_l, c_l, bs_l, alloc, written );

	return ptr;
}

int main ( void ) {

	unsigned int c;

	for( c = 0; c == c; c = c + 5 ) {
		char *foo = speak("Have a nice day!", c);
		printf("%s\r", foo);
		free( foo );
	} 

	exit(0);
}

Wednesday, August 24, 2011

Example of libxslt transform from a libcurl fetch

I've written various programs/network services that perform this function for one purpose or another. In light of some performance needs of one of these services I've been considering porting it from Perl to C in order to get the most performance possible. Being as I haven't written anything in C in a very long time I thought I would implement one aspect of the service as a simple command line tool.

This is the result:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <curl/curl.h>

#include <libxml/xmlmemory.h>

#include <libxslt/xslt.h>
#include <libxslt/xsltInternals.h>
#include <libxslt/transform.h>
#include <libxslt/xsltutils.h>

struct fetch {
	char *buffer;
	size_t size;
};

static size_t write_fetch ( void *chunk, size_t size, size_t nmemb, void *data ) {
	size_t realsize = size * nmemb;
	struct fetch *f = (struct fetch *)data;
	
	f->buffer = realloc( f->buffer, f->size + realsize + 1 );
	
	if ( f->buffer == NULL ) {
		fprintf( stderr, "Out of memory (realloc returned NULL)\n" );
		exit( EXIT_FAILURE );
	}

	memcpy( &( f->buffer[ f->size ] ), chunk, realsize );
	f->size += realsize;
	f->buffer[ f->size ] = 0;

	return realsize;
}

CURLcode get_curl_xml ( char *url, void *chunk ) {
	CURL *curl;
	CURLcode result;

	if ( curl = curl_easy_init() ) {
		curl_easy_setopt( curl, CURLOPT_URL, url );
		curl_easy_setopt( curl, CURLOPT_WRITEFUNCTION, write_fetch );
		curl_easy_setopt( curl, CURLOPT_WRITEDATA, chunk );

		if ( ( result = curl_easy_perform( curl ) ) != 0 ) {
			fprintf( stderr, "Error %i: %s\n", result, curl_easy_strerror( result ) );
			return result;	
		}
		
		curl_easy_cleanup( curl );
	} else {
		return -1;
	}

}

int main (int argc, char *argv[]) {

	struct fetch data;
	xsltStylesheetPtr xslt = NULL;
	xmlDocPtr source, normalized;
	
	data.buffer = malloc( 1 );
	data.size   = 0;

	if ( argc < 2 ) {
		fprintf( stderr, "Usage: %s <stylesheet> <url>\n", argv[0] );
		return 0;
	}


	get_curl_xml( argv[2], (void *)&data );

	fprintf( stderr, "Fetched %lu bytes\n", (long)data.size);
	fprintf( stderr, "Buffer size %lu\n", sizeof( data.buffer ) );

	if ( source = xmlReadMemory( data.buffer, data.size, "memory.xml", NULL, 0 ) ) {
		xslt       = xsltParseStylesheetFile( (const xmlChar *)argv[1] );
		normalized = xsltApplyStylesheet( xslt, source, NULL );
		
		fprintf( stderr, "Normlized XML data\n" );

		xmlSaveFile( "-", normalized );

	} else {
		fprintf( stderr, "Failed to parse XML document\n" );
	}

	xmlFreeDoc( source );
	xmlFreeDoc( normalized );
	xmlCleanupParser();

	free( data.buffer );

	return 0;
}

Sunday, May 29, 2011

Send prowl notifications upon Irssi highlight.

Here is a script I wrote using WebService::Prowl to send prowl notifications when someone highlights my nickname in any of the channels I'm in when using Irssi.