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 $