October 2005
Working as a multi-customer facing administrator and programmer, there
come times when something needed - isn't there. Earlier texts here
have mentioned some shell script bits, the text will revisit those
and discuss C and Perl bits that have
proven to come in handy time and again. The bits discussed
are not exclusive, just some examples. The usual simple constructs
like if/else ladders, for, while, unless loops
as well as referencing are generally easy to remember.
Examples of fast and easy to use shell bits can be surprisingly hard
to find, especially when a script needs to be finished yesterday.
In the following, some simple constructs are shown as well as a
generic bomb() routine.
bomb() RoutineThe syntax for it while simple is quite forgettable. The following shows the routine itself with an example that calls it:
bomb()
{
cat >&2 <<ERRORMESSAGE
ERROR: $@
*** ${progname} aborted ***
ERRORMESSAGE
kill ${toppid}
exit 1
}
# Shell test
if ! type getopts >/dev/null 2>&1; then
bomb "/bin/sh shell is too old; try ksh or bash"
fi
Additionally, keeping a copy of switch case and
redirect based usage() examples have also come in handy:
progname=${0##*/}
...
usage()
{
cat << _usage_
${progname} opt arg
${progname} help
_usage_
exit 0
}
while getopts e:g:u: ch; do
case ${ch} in
e)
example=${OPTARG}
;;
g)
good=${OPTARG}
;;
u)
usage
return 0
;;
esac
done
shift $((${OPTIND} - 1))
Going between different systems has proven one thing to most administrators and programmers - the only guarantee about perl is the core might be installed. Not unlike the shell examples, a good starting point is interrupt handling:
$SIG{'INT' } = 'interrupt';
$SIG{'HUP' } = 'interrupt';
$SIG{'ABRT'} = 'interrupt';
$SIG{'QUIT'} = 'interrupt';
$SIG{'TRAP'} = 'interrupt';
$SIG{'STOP'} = 'interrupt';
$SIG{'TERM'} = 'interrupt';
...
sub interrupt
{
print "Caught @_ exiting\n";
die;
}
Very generic - but enough to start with. The next few are a set of bare bones generic routines:
$LOG="/tmp/foo";
...
sub logit
{
my ($msg) = shift;
my $date = longfmt();
appendfile($LOG, "$PROGRAM: $date $msg");
}
sub insert0
{
my ($date) = shift;
if ($date < 10) {
return "0$date";
}
return $date;
}
sub longfmt
{
my ($sec,$min,$hour,$mday,$mon,$year,
$wday,$yday,$iddst) = localtime(time);
my $datestring;
$year += 1900;
$mon++;
$mon = insert0($mon);
$mday = insert0($mday);
$min = insert0($min);
$datestring = "$year-$mon-$mday $hour:$min";
return($datestring);
}
Finally, an anonymous hash which is always handy to have around:
my @items;
for (my $j = 0; $j < @init_list; $j++) {
push @items, { name => $init_list[$j], tics => 0, alarm => none
};
}
Other things that might be good to keep around in perl might be:
Last and not least, some ideas about C bits that are handy to have
within reach. To start, a copy of the strl* functions which
are often not on a variety of UNIX systems and Linux distributions:
/* strlcat based on OpenBSDs strlcat */
#include <sys/types.h>
size_t strlcat(char *, const char *, size_t);
size_t
strlcat (char *dst, const char *src, size_t dst_sz)
{
size_t len = strlen(dst);
if (dst_sz < len)
return len + strlen(src);
return len + strlcpy (dst + len, src, dst_sz - len);
}
The same can be done for strlcpy():
/* strlcpy based on OpenBSDs strlcpy */
#include <stdio.h>
#include <sys/types.h>
size_t strlcpy(char *, const char *, size_t);
strlcpy(char *dst, const char *src, size_t siz)
{
char *d = dst;
const char *s = src;
size_t n = siz;
/* Copy as many bytes as will fit */
if (n != 0 && --n != 0) {
do {
if ((*d++ = *s++) == 0)
break;
} while (--n != 0);
}
/* Not enough room in dst, add NUL and traverse rest of src */
if (n == 0) {
if (siz != 0)
*d = '\0'; /* NUL-terminate dst */
while (*s++)
;
}
return(s - src - 1); /* count does not include NUL */
}
Some other useful C-bits to keep handy might be:
In some cases - a laptop. Or - in a place where the bits can be easily retrieved. Some people even setup their own CVS or subversion repositories that they can access from anyplace they can run their laptop or have access to the commands. Last and not least - a copy on a USB stick never hurts.
The article was not meant to be a tutorial as much as to make readers think about how it can be when moving from system to system, company to company, or even customer to customer. Keeping a working copy of what one knows - even if they are just templates - is a very good idea.
(based on last 2 months log reports)