New Messages
To the Editor,
In Larry Reznick's article, "Multiport Serial Installation,"
in the March/April 1994 issue of Sys Admin magazine,
he includes
an insert listing installable device programs. Therein
he comments
that a few of the programs that he found didn't have
their functionality
documented.
Hopefully, the following information will help. My references
are
the SVR4.2 source code that my company has bought (the
advantages
of working for a fairly large company).
idmkenv: This command is called at boot time by a sysinit entered
in the /etc/inittab file. Its purpose is to update /etc/idrc.d,
/etc/idsd.d,
/etc/inittab, and the device nodes, in /dev. It also
recovers the
kernel environment when a reconfiguration is aborted
due to losing
power or the user hitting the big reset button.
idval: This program is used by the idtune shell script. It
is used to do the actual comparison between the new
tuneable parameter
against its lower and upper bounds. It supports both
decimal and hexadecimal
numbers and therefore is more powerful than performing
such a function
strictly in "shell code."
idmaster: This one I couldn't find at all. I suspect therefore
that it's an add-on by Esix.
Joe Berry
joe@landmark.com
Baltimore, MD
Thanks for the research and clarification. -rlw
To: saletter@rdpub.com
Subject: Reznick's "Time for UNIX"
Larry Reznick requested a program to set up a holidays
file. Listing 1 (E-Media Production Manager's note: Listings referenced within the New
Messages/Letters can be found by
scrolling to the bottom of the current page.)
is one I wrote on January 15, 1992, together with
an input file.
BTW, Larry doesn't say what system he uses, but my Sun
system has
lots of documentation on zic files, etc.
Samuel T Denton
sdenton@world.std.com
Thanks for following up on Larry Reznick's request.
Readers
will no doubt put your program to good use. -rlw
To: saletter@rdpub.com
Subject: A clever use of the TZ environment variable
In the May/June issue of Sys Admin Larry Reznick describes
in great detail the TZ environment variable and how
one might configure
a system to correctly change the time at/around daylight
savings time.
In Arizona, we stay on Mountain Standard time year round.
In the process
of trying to figure out how to make my Apollo DomainOS
systems NOT
automatically adjust the time when everyone else went
on daylight
savings time, I came up with a clever trick that I employ
in scripts
that perform time/day/date calculations.
The trick is to basically retard (shift backwards) the
time in scripts
by 12 hours. This is done by setting the TZ environment
variable in
the beginning of the script to something different than
the default.
In other words, instead of using the default "TZ=MST7MST7",
I use "TZ=BST19BST19" to retard the time 12
hours (BST is
Backward Standard Time) :-)
You may be wondering how this could be useful. Take
backups for example.
You usually start these late at night or even early
in the morning
on the NEXT day. If you are trying to perform date calculations,
starting
things after midnight become a problem because the day
and date are
different than the day you are backing up.
In my situation, I had a script that was checking the
tape in the
drive to make sure it was the correct tape. If I was
doing a Wednesday
backup (early on Thursday morning), the time shift would
cause the
date command to return "Wednesday" so that
it would match
the pre-labeled tape. This is a simple case involving
days, but when
you start performing date calculations involving the
month or the
year (for example Dec. 31, 1993 vs. Jan. 1, 1994), this
makes a complex
calculation easy to perform.
On DomainOS I am able to shift time as many hours backward/forward
as I want just by using ever-increasing/decreasing values.
Check your
UNIX implementation to see if it behaves the same.
Here is a script called "tzdate" I wrote to
replace the "date"
command used in other scripts:
#!/bin/sh
############################################################################
#
# Program to determine what the date is if the TZ is shifted "$1"
# hours. This program is necessary because if a backup occurs after
# midnight on a certain day, the previous day's information is
# usually desired for date calculations required for the backup.
# This script allows for this by shifting the time zone so the
# system thinks it is yesterday, and therefore any date calculations
# are correct (even over day, month or year boundaries.
#
# Usage: tzdate <hours-to-shift> +hours retards time
# -hours advances time
############################################################################
GMTSHIFT=7 # "Our" default shift from GMT
SHIFT=`echo "$GMTSHIFT + $1" | bc` # New shift from GMT
TZ=BST$SHIFT # Shift time-zone setting "$SHIFT" hours
export TZ # Export for child process
date # What does it think date is now
David J. Young
davidy@hwcae.honeywell.com
Phoenix, AZ
That's a cool solution to an interesting problem! Guess
Arizona has so much daylight that there's no need to
save any of it.
--rlw
Listing 1: holidays.conf
# Input file for /usr/local/bin/holidays, which runs in the wee hours of
# the morning of Jan. 1st, and generates /etc/holidays for the new year.
#
# New Year`s Day is Jan. 1st, unless it falls on a weekend
1 1 1-5 New Year's Day
1 2 1 New Year's Day
# Memorial Day is the last Monday in May
5 25-31 1 Memorial Day
# Independence Day is July 4th, unless it falls on a weekend
7 4 1-5 Independence Day
7 5 1 Independence Day
7 3 5 Independence Day
# Labor Day is the first Monday in September
9 1-7 1 Labor Day
# Election Day is the Tuesday after the first Monday in November
#11 2-8 2 Election Day
# Thanksgiving is the fourth Thurday in November
11 21-28 4 Thanksgiving Day
11 22-29 5 day after Thanksgiving
# Christmas Eve is December 24th, unless it falls on a weekend
12 23 4-5 Christmas Eve
12 24 1-5 Christmas Eve
Christmas is December 25th, unless it falls on a weekend
12 25 1-5 Christmas
12 26 1-2 Christmas
# New Year`s Eve, if it falls on a Friday
12 31 5 New Year`s Eve
==> holidays.c <==
#include <stdio.h>
#include <sysexits.h>
#include <time.h>
/*
* Creates /etc/holidays file
*
* Usage: holidays [-year <year>] [-prime <start> <end>]
*
* Input file is of the form:
* <month> <days-of-month> <days-of-week> <holiday name>
* where:
* <month> is in the range 1 through 12
* <days-of-month> is in the range 1 through 31
* <days-of-week> is in the range 0 through 6, where 0 is Sunday
* <holiday-name> is a character string extending to EOL
*
* Output file is the holidays file expected by the accounting system.
*
*/
char *progname;
void
usage()
{
static char *help_message[] = {
"where options include:\n",
"\t-year <year>\t\tyear for which holidays are to be calculated\n",
"\t-prime <start> <end>\tstarting and ending times for prime time\n",
"\n",
"Options may be abbreviated to the shortest unambiguous prefix.\n",
"\n",
NULL
}, **cpp;
fprintf (stderr, "usage: %s [-options ...]\n\n", progname);
for (cpp = help_message; *cpp; cpp++) {
fputs (*cpp, stderr);
}
exit(EX_USAGE);
}
void
dataerr(errmsg)
char *errmsg;
{
fprintf(stderr,"%s: %s\n",progname,errmsg);
exit(EX_DATAERR);
}
main(argc,argv)
int argc;
char **argv;
{
int i,j,n,mday_start,mday_end,wday_start,wday_end;
long t;
char buffer[1024],mdays[93],wdays[14];
char *name, *prime, *non_prime;
struct tm date, *u;
progname = argv[0];
/* default to current year; except in December, when we assume next year */
t = time(NULL);
memcpy(&date,gmtime(&t),sizeof date);
if (date.tm_mon == 11) date.tm_year += 1;
/* prime time defaults to 8:00 AM to 5:00 PM */
prime = "0800";
non_prime = "1700";
/* process arguments */
for (i=1;i<argc;i++) {
char *arg = argv[i];
if (arg[0] == '-') { /* process command line switches */
switch (arg[1]) {
case 'y': /* -year <year> */
if (++i >= argc) usage();
date.tm_year = atoi(argv[i]);
if (date.tm_year >= 1000) date.tm_year -= 1900;
if (date.tm_year <= 0) usage();
continue;
case 'p': /* -prime <start> <end> */
if (i+2 >= argc) usage();
prime = argv[++i];
non_prime = argv[++i];
continue;
default:
usage();
/* NOTREACHED */
}
} else {
usage();
/* NOTREACHED */
}
} /* end argv for-loop */
fputs("*\n* Curr\tPrime\tNon-Prime\n* Year\tStart\tStart\n*\n",stdout);
fprintf(stdout," %4d %s %s\n",1900+date.tm_year,prime,non_prime);
fputs("*\n* Day of\tCalendar\tCompany\n* Year\t\tDate\t\tHoliday\n*\n",
stdout);
while ( 1 ) {
fgets(buffer,sizeof buffer,stdin);
if (feof(stdin)) break;
if (buffer[0] == '#') continue; /* comment to ignore */
if (buffer[0] == '*') { /* comment to pass along */
fputs(buffer,stdout);
continue;
}
n = sscanf(buffer,"%d %92s %13s %n",&date.tm_mon,mdays,wdays,&i);
if (n != 3) dataerr("data error in input file");
if ((date.tm_mon < 1) || (date.tm_mon > 12)) exit (1);
date.tm_mon -= 1;
name = &buffer[i];
n = sscanf(mdays,"%d-%d",&mday_start,&mday_end);
if (n == 0) dataerr("bad days-of-month field in input file");
if (n == 1) mday_end = mday_start;
n = sscanf(wdays,"%d-%d",&wday_start,&wday_end);
if (n == 0) dataerr("bad days-of-week field in input file");
if (n == 1) wday_end = wday_start;
for (date.tm_mday=mday_start;date.tm_mday<=mday_end;date.tm_mday++) {
t = timegm(&date);
u = gmtime(&t);
if ((u->tm_wday >= wday_start) && (u->tm_wday <= wday_end)) {
char prefix[20];
strftime(prefix,sizeof prefix,"%j\t\t%b %d",u);
printf(" %s\t\t%s",prefix,name);
}
}
}
exit(EX_OK);
}
|