Man pages tell you "how," but they usually don't give enough "what" and
rarely (if ever) give any "why." This file is an attempt to remedy that.

First, some general information: My work involves Unix and Unix-like
systems of all flavors (Solaris, Linux, *BSD, HP-UX, AIX, and others);
even my Linux work crosses several different distros. I also work in
"restricted" environments -- things like installers and embedded
systems; these environments often have significant space limitations
that preclude things like Perl or Python. Finally, I hate having to port
my tools every time I have to work in a new environment. As a result,
I've chosen to stick to small programs, written mostly in C and the
POSIX shell language (with the odd bit of Perl thrown in), and to the
greatest extent possible, to stick to the ISO/IEEE/POSIX standards.

Some of my programs have the same name as or are very similar to
programs found on certain distros of Linux (but never the same name as
POSIX programs); other of my programs implement features found in Perl
(but as I said, Perl is not always available to me). In most cases, my
reasons for writing a given program fall into one of two categories:
first, I need to have the *identical* program available to me across
*all* platforms (and yes, some of my work involves multiple operating
systems); second, I need access from inside a shell program to a feature
or function or capability found in the kernel or a C library. In the
other cases, I needed functionality that just wasn't available in any
other program I could find (or in a program that I could easily port to
lots of o/s versions).

Now then, the programs themselves . . .

addrtool
    Rather than fire up dc(1) every time I need to deal with subnet
    masks, CIDR blocks, IP addresses, etc., I wrote addrtool to do the
    bit-fiddling for me. It's not as flexible as some similar tools, but
    it does everything I've ever needed.

asm2install
    Many systems have a program called "install," but like so many other
    programs I deal with, it either isn't installed on every system I
    need or it works differently on different systems. Also, I don't
    believe any version I've ever seen supports creating links to the
    target program. I don't expect people to use this but my software
    uses it to install itself.

baseconv
    I often find myself wanting to use large integers like "epoch
    seconds" or MD5 checksums as part of a filename or job ID or some
    such thing; in most cases, those numbers are too large when
    expressed in their "native" base (10 or 16). Still other times I
    simply find it useful to express a number in a different base.
    baseconv is a program that will convert integers between any of the
    following "programmer's" bases: 2, 8, 10, 16, 32, 62, and 64. Since
    I often use the encoded result as part of a file name, I chose a
    version of base 64 that doesn't use "/" as one of the "digits"; I
    then "invented" base 62 for those time when limiting the "digits" to
    only letters and numbers makes things that much easier.

dateops
    Many of my programs involve dates and times, and simple operations
    like calculating tomorrow or yesterday or next month, etc. I wrote
    dateops to perform these calculations and a few more (namely, the
    ability to convert a human-readable date and time to epoch seconds).

dseq
    Once I had dateops, it was a small step to a program that would
    print out sequences of dates -- and that's what dseq does. Like the
    Linux program "seq," dseq understands "step values," thus giving you
    the ability to print a list of, say, the next 12 Wednesdays; like
    the date(1) command, dseq lets you specify the exact format of the
    output.

edate
    This program is similar to and different from the standatd date(1)
    command as follows: First, edate understands all the same conversion
    specifications as date(1) and strftime(3) plus four more: the day of
    the month without a leading space (if a single digit), the English
    suffix for the day of the month, the time as epoch seconds, and the
    current microseconds (as reported by gettimeofday(2)). Next, edate
    can print date information for a date specified in epoch seconds.
    Finally, edate can *not* set the system date. Unlike the GNU version
    of date(1), edate is 100% POSIX-compliant and doesn't require a non-
    standard C library.

getman
    Used with hexify (see below).

hd
    I started programming on an IBM 1130 -- a "mini-computer" that fit
    into a mere 25 square feet of floor space. A common activity for
    people who programmed this beast was to read core dumps, which
    looked something like this:


	00000000  7f 45 4c 46 . . . 00 00 00 00  .ELF............
	00000010  02 00 03 00 . . . 34 00 00 00  ............4...
	00000020  6c 1f 00 00 . . . 07 00 28 00  l.......4.....(.

    Time passed, and I moved on to more modern systems. In 1984, my
    friend and sometimes business partner Peter Jansson wrote the first
    version of a program he called "hd"; I don't remember what machine
    it ran on but it produced the familiar output he and I had both come
    to know. He gave me a copy which I then ported to Unix. Pete and I
    maintained separate copies of hd, ported to this system, modified to
    meet that requirement, etc. Although the core of this program is
    descended from Pete's original version, it's all new code.

    At one time, my version of the program had so many bells and
    whistles you'd have thought it was part of the GNU project. I've
    since gotten rid of some of them, but there are some I can't bring
    myself to remove for those few times I need them. Fortunately,
    nearly all of the options can be ignored for typical use. The man
    page ("hd --man") describes the options in detail.

hexify
    A fairly ugly hack (but a simple one) that gives me an easy way to
    provide built-in (plain ASCII) man pages in my C programs. There are
    many ways I could have done this (including using perldoc), but
    "getman" (above) and hexify don't require any additional programs or
    libraries, either for compilation or execution. I don't really
    expect other people to use these programs, but I include them so my
    C programs can be compiled.

lstat
    The ls(1) command can print most of the contents of an inode, but
    not all of them and often not in a form that's easy to use; worse,
    the form of the output can change based on how old a file is.
    Dealing with this in a shell program is tedious and error-prone.
    Rather than write a collection of shell functions to do the parsing
    and munging, I wrote a C program to give me direct access to the
    contents of the inode via the lstat(2) system call.

    My lstat program accepts 10 options, at least that many arguments to
    some of those options, and about a dozen modifiers to those
    arguments. I've tried to give good explanations in the man page,
    along with some examples. I'll try to provide more examples in
    another file in the release (Real Soon Now).

mkstemp
    As a shell programmer, I frequently need to create temporary files;
    to avoid the most common security flaws along this vector, and to
    minimize the risk of reusing a temp file from a previous run of a
    program (that somehow didn't get deleted), I wrote mkstemp. It's
    nothing more than a very simple wrapper around the ANSI/POSIX
    function of the same name. Some Linux distros come with a similar
    program (mktemp), but as with most of my other software, I needed
    something that was available on all operating systems (and identical
    across all of them).

nthday
    Someone once complained to me that cron(1) didn't have a way to
    specify a job to run on the last Friday of the month. Figuring this
    out by looking at a printed calendar is dead simple, so I wrote
    nthday to parse the output of cal(1). By default, nthday calculates
    a day in the current month, but giving more arguments on the command
    line lets the user specify a given month of the current year or a
    month and year anytime in the past or future.

note
    A very simple program for managing notes to myself. It's crude,
    fast, fairly easy to use, and runs 100% from the command line
    (except when editing files).

numcmp
    I try to avoid doing more than very simple arithmetic in shell
    programs; most of the time, that's all I need. However, I recently
    wrote some programs to deal with spam, and that required me to
    compare two floating-point numbers; to make matters worse, one of
    those numbers was often negative. The shell doesn't deal well with
    either of those so I wrote numcmp to do the hard work for me. To
    make things even easier for the shell, I chose to have the output be
    single words: "less," "equal," or "greater" -- all very easy to deal
    with.

simplePath
    I do a lot of work in "multi-architecture" environments; that is,
    places where a single home directory is shared across different
    types of machines running different operating systems (or different
    versions of the same operating system or different Linux
    distributions or just different kernels). Interpreted programs
    (shell, Perl, Python) work fine but binaries don't fare as well; in
    particular, I needed a scheme to ensure that the right binaries were
    in my path for each machine. Since many of my shell scripts depend
    on those same binaries, I also needed a way to ensure that $PATH
    gets set correctly. simplePath has two branches through the code:
    the one I use and the one the rest of the world should use (unless
    you build your world like I build mine). Mostly you can ignore this
    program (it comes configured for the rest of the world), but it is a
    handy place to set whatever $PATH you want for your copy of my shell
    scripts.

st
    A very simple program for compiling and printing status reports.
    Like "note" (above), this runs from the command line. st isn't meant
    for detailed time accounting but there's enough data to calculate
    approximately how much time was spent on any given task (assuming
    you're diligent enough to make frequent entries).

strcmp
strncmp
    Another thing not available in the POSIX versions of sh(1) or
    test(1) is a mechanism to compare two strings and return which of
    them is lexicographically less than the other. The C library
    functions strcmp(3) and strncmp(3) do exactly that. The output of
    these programs is identical to "numcmp" (above); that is, "less,"
    "equal," or "greater."

tester
    There are lots of test *frameworks* and test *harnesses* and test
    *othercomplicatedthings* out there, but I wanted something simple
    and easy to use, and aimed more at integration tests -- or, at
    least, aimed a bit higher than unit tests. tester is the result.
    It's completely self-contained, intended primarily for testing other
    programs, and requires nothing more than a simple text file to set
    up tests and the associated pass/fail criteria.


# $Id: BACKGROUND,v 1.18 2012/01/13 18:38:43 adamm Exp adamm $
