sources-request@mirror.TMC.COM (03/10/87)
Submitted by: Dave Taylor <hplabs!taylor> Mod.sources: Volume 9, Issue 13 Archive-name: elm2/Part13 #! /bin/sh # This is a shell archive. Remove anything before this line, # then unpack it by saving it in a file and typing "sh file". # If this archive is complete, you will see the message: # "End of archive 13 (of 19)." # Contents: test/test.notes utils/arepdaemon.c utils/newalias.c PATH=/bin:/usr/bin:/usr/ucb ; export PATH echo shar: Extracting \"test/test.notes\" \(13582 characters\) if test -f test/test.notes ; then echo shar: Will not over-write existing file \"test/test.notes\" else sed "s/^X//" >test/test.notes <<'END_OF_test/test.notes' X/***** hpfloat:net.micro.68K / barrett / 2:39 pm Dec 16, 1985*/ XDoes anyone here at this site know anything about hang-gliding? X XI am thinking of learning to hang-glide, but am afraid of heights. I Xdo fly light planes and love the hairiest roller coaster rides available Xhowever. My main question is "is there a way to learn to hang-glide Xgradually?" I have seen some films of people learning on big sand dunes Xan such before leaping off of cliffs with the things. X XDave Barrett Xhpfcla!barrett X/* ---------- */ X/***** hpcnof:fsd.rec / hpfcla!ajs / 5:57 pm Dec 16, 1985*/ X> Does anyone here at this site know anything about hang-gliding? X XYeah. Don't waste your time, don't waste your money, don't risk your life. X X> I am thinking of learning to hang-glide, but am afraid of heights. X XI wasn't, but it still got me a broken arm. X X> My main question is "is there a way to learn to hang-glide gradually?" X XProbably not (yet). Five years ago, simulators were in practice non- Xexistent. We got twenty seconds hanging in a triangular control bar Xwith a person pushing. Next stop, rocky slopes, real gliders, and cheap Xwalkie-talkies. X XYou'd be amazed how easy it is to injure yourself. It's the nature of Xthe hobby. People with plenty of experience die doing it every day, Xdue to circumstances often beyond their control. There are better ways Xto get thrills. X XAlan X/* ---------- */ X/***** hpcnof:fsd.rec / hpfcms!mpm / 8:58 pm Dec 16, 1985*/ X X>You'd be amazed how easy it is to injure yourself. It's the nature of X>the hobby. People with plenty of experience die doing it every day, X>due to circumstances often beyond their control. There are better ways X>to get thrills. X>Alan X X I haven't done any hang-gliding myself, but I would like to try it Xsome day. (I have a moderate fear of heights; it depends on the altitude Xand the apparent stability of my "perch".) X X I read (or heard) that MOST hang-gliding accidents fall into two Xcategories: X X 1) novices attempt something beyond their experience (like jumping X off a tall building after one lesson on a gently sloped hill), X X 2) experts attempt VERY dramatic stuff (like jumping off El X Capitan in unpredictable thermal up- and down- drafts). X X Please note: Alan Silverstein doesn't fall in EITHER category. I Xtook some sport parachuting lessons a few years ago. It turned out to be Xquite safe GIVEN ADEQUATE TRAINING as I had at the time. I suspect the Xsame would hold true for hang-gliding (or rapelling, or ice climbing, or X...). The best way to find out if you can overcome your fears is by con- Xfronting them in a safe and supportive environment. X X My recommendation: check out any "school" before you sign up. Ask Xabout their safety record, the terrain where they offer lessons, amount of X"ground school" training before first "flight", etc. Above all, make sure Xthat you TRUST any prospective teacher. Even if you have no logical reason Xto distrust someone, don't try something like this unless you trust them. X(This is where your rational mind needs to work with your intuition.) XOtherwise you could easily get hurt. X X This is likely to be unknown territory for you, so be prepared and Xyou will likely have a more enjoyable (and safe) experience. Of course, Xthere is ALWAYS the chance for an accident. X X -- Mike "no I wasn't crazy at the time; I WANTED to do it" McCarthy X hpfcla!mpm X/* ---------- */ X/***** hpcnof:fsd.rec / dat / 12:12 pm Dec 19, 1985*/ X>> Does anyone here at this site know anything about hang-gliding? X>Yeah. Don't waste your time, don't waste your money, don't risk your life. X X Strong stuff! I think you're out on a limb this time, Alan. XI've known lots of people who've hang-glided and never gotten hurt. X(and we're talking the La Jolla cliffs in San Diego!!) (they also Xthink it's the best 'high' in the world (and they've tried some Xpretty strange things to compare!)) X X>> I am thinking of learning to hang-glide, but am afraid of heights. X>I wasn't, but it still got me a broken arm. X X Fine. So I broke my arm a long time ago jumping off a bunk Xbed. Does this mean that bunk beds are too dangerous and that I Xshouldn't ever sleep in one??? X X The point is that anything you do is dangerous and that the Xway to minimize the danger is to take things gradually and only Xprogress when you feel comfortable with your current level of learning. XAt the same time realize that even sitting in a chair in a warm room Xcould be dangerous, so don't be so foolishly optimistic to think that Xyou cannot get seriously hurt hang-gliding. X X On the other hand - if you want to go for it - GO FOR IT!!! X X -- Dave "Cheap Thrills, Inc." Taylor X/* ---------- */ X/***** hpcnof:fsd.rec / hpfcmp!rjn / 11:33 pm Dec 16, 1985*/ Xre: hang gliding X XI am a licensed [so what] pilot in powered aircraft and sailplanes. I was Xtaking hang gliding (HG) instruction four years ago (prior to moving to XColorado). I gave it up when I moved here. My impressions: X X* If your introduction to piloting flying machines is via HG, you will not X have enough understanding of aerodynamics to safely operate your craft in X calm or steady-wind conditions. X X* HGs which are controlled by weight shifting do not have adequate control X authority for normal conditions, unless you have lots of the X aforementioned understanding and fly only in ideal conditions. HGs with X 3-axis control offer a little more margin. X X* HGs are typically operated close to the ground. No HG designs have enough X control authority to handle gusty conditions. You can safely land a X parachute in conditions which are dangerous for HG operation. Flying in X gusty conditions is the most popular way to crash a HG. If you think X jumping is dangerous, don't take up HG. (I used to room with a jumpmaster X and have made one jump myself. I think jumping is safer.) X X* HGs operated at higher altitudes (away from ground reference) suffer from X lack of instrumentation. It is easy to enter a spiral dive, spin or deep X stall (luff the sail on Rogallo machines) without instruments or lots of X experience. Spiral dives usually overstress the airframe; the resulting X collection of parts crashes. X XIf you insist on K-Mart aviating, I suggest a 2-place ultra-light (with Xparachute), a good instructor and a calm day. At least the ground is level. XBring earplugs. X XBob Niland TN-226-4014 HP-UX: hpfcla!rjn DESK: rjn (hpfcla) /HP4000/UX X/* ---------- */ X/***** hpcnof:fsd.rec / hpfloat!jim / 9:10 am Dec 17, 1985*/ XTry flying across the waves on a windsurfer! I once met a guy from XDenver who said he had tried them all--hang gliding, sky diving. Windsurfing Xoffered just as much thrill with almost no risk. X XThe crash landings are rather painless. I've gotten 5 feet of air right Xhere in Colorado. X X "Jumping Jim" Tear X X/* ---------- */ X/***** hpcnof:fsd.rec / hpfcmt!ron / 7:56 am Dec 17, 1985*/ X X XI also am a "regular" aircraft (and sailplane) pilot. X XI have not tried hang gliding however I have a fairly close friend who Xwas into it before he totally demolished his craft. He was only bruised Xby the impact but came away considerably more careful about his sports. X XBesides the previously mentioned drawbacks I would like to mention the Xfollowing: X XA perfect landing consists of X X (a) Correct airspeed X (b) Level wings ( tolerance to prevent wingtip dragging) X (c) Correct yaw alignment (within tolerance of landing gear) X (d) Correct pitch X (e) Correct rate of descent (within tolerance of landing gear) X (f) Correct altitude X (g) Correct groundspeed (within tolerance of landing gear) X XConsider that the landing gear on an HG is your legs and gear collapse Xis fairly common due to the low maximum speed for the gear and the Xairspeed being right in that range at touchdown. XConsider also that even calm air has some "breezes" going. XAdd to the "breezes" the fact that your control authority relative to the Xvelocity of the breezes is poor and you can wind up with all the ingredients Xfor a face plant. X XNow to moderate the above, the idea of simple flight appeals greatly to Xme. Unfortunately my personal risk-taking threshold is below the minimum Xrisk for this sport. XI agree with Bob, try ultra-lights if you MUST . At least they have wheels. X X XRon Miller X X X"Show me a country where the newspapers are filled with good news Xand I'll show you a country where the jails are filled with good people." X -<I forgot> X XService Engineering (Hardware Support) XHewlett-Packard Co. XFt. Collins Systems Div. Home of the HP 9000 Series 200,300 & 500 XFt. Collins Colorado X303-226-3800 X Xat: {ihnp4}hpfcla!ron X/* ---------- */ X/***** hpcnof:fsd.rec / hpfcla!ajs / 6:36 pm Dec 19, 1985*/ X> Strong stuff! I think you're out on a limb this time, Alan. X> I've known lots of people who've hang-glided and never gotten hurt. X XYes, but, -- X X> Fine. So I broke my arm a long time ago jumping off a bunk X> bed. Does this mean that bunk beds are too dangerous and that I X> shouldn't ever sleep in one??? X XI'll be more explicit (and just as strong). Let's say sleeping is a Xzero (epsilon?) on the risk scale, and flying in a commercial aircraft Xis 1, and driving a car, oh, I'd guess about a 4, and parachuting maybe Xa 6, and SCUBA diving must be maybe a 7 or 8 then, comparable (?) with Xclimbing Fourteeners. Based on my experience with it, I'd rank hang Xgliding at around a 12 or 15. Don't risk your life. X XOne thing I discovered is that being under a "kite" feels very different Xfrom how you might guess while watching someone fly. Not nearly as Xcomfortable (until airborne); very exposed. Some people are naturals at Xit; some (like me) are not. If you are the former, and you are lucky, Xand it appeals to you, you'll go do it anyway, no matter what I or Dave Xsay about it; good luck to you. X XBut, if you are the latter, you'll likely injure yourself seriously Xtrying to learn, because there isn't much margin for error outside a Xsimulator. Look, I was gung-ho, being trained by a "professional" Xtraining school, determined to overcome inexperience, ignored warnings Xfrom concerned friends, was certain I could do it safely, paid close Xattention to instructions, studied the subject intensely, and when I Xcrashed, I'd been in the air about five seconds, was about ten feet off Xthe ground, and was amazed that I'd actually broken anything. A very Xsobering experience. X XOn the way to the hospital, the trainer doing the driving informed me Xthat someone was seriously injured in their classes about once a month. X XGee, Dave, I guess I must be "out on a limb", incapable of giving advice Xon the subject, because I survived the crash. :-) X XAlan X/* ---------- */ X/***** hpcnof:fsd.rec / hpfcde!anny / 2:28 pm Dec 31, 1985*/ XWARNING: Severe Base Note D r i f t X X<. . . and driving a car, oh, I'd guess about a 4, and parachuting maybe X<a 6, and SCUBA diving must be maybe a 7 or 8 then, . . . X XCome on Alan! SCUBA diving more dangerous than parachuting? Maybe if your Xparachuting off a jump tower versus SCUBA diving alone on the Great Barrier XReef at night carring shark bait making wounded fish sounds. . . ;-) X XAfter all, the FIRST time you parachute, you have to jump out of a PLANE! (/.\) XIn the SKY! You can SCUBA dive in a pool or a shallow lake or inlet. XIf something goes wrong in the water, your buddy's there to help. If Xsomething goes wrong in the sky, so long . . . X XJust defending what I consider to be a fun and safe sport! X XAnny (low altitude (4' or less) sports for me!) Randel X/* ---------- */ X/***** hpcnof:fsd.rec / hpfcla!ajs / 9:27 am Jan 2, 1986*/ X> Come on Alan! SCUBA diving more dangerous than parachuting? X XForgive me, I was just guessing, to make a point. I don't know the Xactual statistics, but you're probably right -- if you measure accidents Xper hour. On the other hand, if you measure accidents per jump or dive, Xit wouldn't surprise me if the rates were similar. Lotsa people go Xdiving without enough training, but skydiving requires decent training Xand the accident rate is surprisingly low. X XAlan "pick your poison" Silverstein X/* ---------- */ X/***** hpcnof:fsd.rec / hpfcdc!donn / 9:32 am Jan 3, 1986*/ XThe problem with SCUBA diving is the fact that "fly by nites" can Xafford to get into the business. A reputable dive shop will not Xlet you rent a tank unless you have a NAUI card (or ==) (and they'll hold Xit while you have the tanks). However there are always some who Xwill not do this, and some clown tries diving without essentially Xany training ("Gee, I can swim, so I can dive.") and gets into Xtrouble. It's much tougher to be a "fly by night" (or anytime) Xwhen you need an airplane and a pilot's license. Actually, the Xaccident rate for people with any significant training *and* who Xare doing something more-or-less reasonable is not bad. (Diving Xbelow 150ft (or maybe less) is like starting a jump at 50000 feet: Xit might work, but good luck unless you know what you're doing. XThe problem is that there isn't much reason to start at 50000 feet, Xbut there's a lot of interesting and valuable stuff below 150.) X XI like to dive (tropical saltwater only, so I don't do it much), Xand since one of the graduation exercises is diving while someone Xis *trying* to make you screw up (albeit in a pool where there's Xsomeone to fish you out), you learn to handle problems. If you're Xgutsy, try the NAUI *instructors* class: the graduation from that Xis a open-water dive with known defective equipment! X XDonn X/* ---------- */ END_OF_test/test.notes if test 13582 -ne `wc -c <test/test.notes`; then echo shar: \"test/test.notes\" unpacked with wrong size!? fi # end of overwriting check fi echo shar: Extracting \"utils/arepdaemon.c\" \(13412 characters\) if test -f utils/arepdaemon.c ; then echo shar: Will not over-write existing file \"utils/arepdaemon.c\" else sed "s/^X//" >utils/arepdaemon.c <<'END_OF_utils/arepdaemon.c' X/** arepdaemon.c **/ X X/** (C) Copyright 1986 Dave Taylor **/ X X/** Keep track of mail as it arrives, and respond by sending a 'recording' X file to the sender as new mail is received. X X Note: the user program that interacts with this program is the X 'autoreply' program and that should be consulted for further X usage information. X X This program is part of the 'autoreply' system, and is designed X to run every hour and check all mailboxes listed in the file X "/etc/autoreply.data", where the data is in the form: X X username replyfile current-mailfile-size X X To avoid a flood of autoreplies, this program will NOT reply to mail X that contains header "X-Mailer: fastmail". Further, each time the X program responds to mail, the 'mailfile size' entry is updated in X the file /etc/autoreply.data to allow the system to be brought X down and rebooted without any loss of data or duplicate messages. X X This daemon also uses a lock semaphore file, /usr/spool/uucp/LCK..arep, X to ensure that more than one copy of itself is never running. For this X reason, it is recommended that this daemon be started up each morning X from cron, since it will either start since it's needed or simply see X that the file is there and disappear. X X Since this particular program is the main daemon answering any X number of different users, it must be run with uid root. X X (C) 1985, Dave Taylor, HP Colorado Networks Operation X**/ X X#include <stdio.h> X X#ifdef BSD X# include <sys/time.h> X#else X# include <time.h> X#endif X X#include <sys/types.h> X#include <sys/stat.h> X X#include "defs.h" X Xstatic char ident[] = { WHAT_STRING }; X X#define arep_lock_file "/usr/spool/uucp/LCK..arep" X X#define autoreply_file "/etc/autoreply.data" X#define fastmail "/usr/local/bin/fastmail" X X#define logfile "/etc/autoreply.log" /* first choice */ X#define logfile2 "/tmp/autoreply.log" /* second choice */ X X#define BEGINNING 0 /* see fseek(3S) for info */ X#define SLEEP_TIME 3600 /* run once an hour */ X#define MAX_PEOPLE 20 /* max number in program */ X X#define EXISTS 00 /* lock file exists?? */ X#define MODE 0777 /* lockfile creation mode */ X X#define remove_return(s) if (strlen(s) > 0) { \ X if (s[strlen(s)-1] == '\n') \ X s[strlen(s)-1] = '\0'; \ X } X Xstruct replyrec { X char username[NLEN]; /* login name of user */ X char mailfile[SLEN]; /* name of mail file */ X char replyfile[SLEN]; /* name of reply file */ X long mailsize; /* mail file size */ X int in_list; /* for new replies */ X } reply_table[MAX_PEOPLE]; X XFILE *logfd; /* logfile (log action) */ Xlong autoreply_size = 0L; /* size of autoreply file */ Xint active = 0; /* # of people 'enrolled' */ X XFILE *open_logfile(); /* forward declaration */ X Xlong bytes(); /* ditto */ X Xmain() X{ X long size; X int person, data_changed; X X if (! lock()) X exit(0); /* already running! */ X X while (1) { X X logfd = open_logfile(); /* open the log */ X X /* 1. check to see if autoreply table has changed.. */ X X if ((size = bytes(autoreply_file)) != autoreply_size) { X read_autoreply_file(); X autoreply_size = size; X } X X /* 2. now for each active person... */ X X data_changed = 0; X X for (person = 0; person < active; person++) { X if ((size = bytes(reply_table[person].mailfile)) != X reply_table[person].mailsize) { X if (size > reply_table[person].mailsize) X read_newmail(person); X /* else mail removed - resync */ X reply_table[person].mailsize = size; X data_changed++; X } X } X X /* 3. if data changed, update autoreply file */ X X if (data_changed) X update_autoreply_file(); X X close_logfile(); /* close the logfile again */ X X /* 4. Go to sleep... */ X X sleep(SLEEP_TIME); X } X} X Xint Xread_autoreply_file() X{ X /** We're here because the autoreply file has changed size!! It X could either be because someone has been added or because X someone has been removed...since the list will always be in X order (nice, eh?) we should have a pretty easy time of it... X **/ X X FILE *file; X char username[SLEN], replyfile[SLEN]; X int person; X long size; X X log("Autoreply data file has changed! Reading..."); X X if ((file = fopen(autoreply_file,"r")) == NULL) { X log("No-one is using autoreply..."); X return(0); X } X X for (person = 0; person < active; person++) X reply_table[person].in_list = 0; X X while (fscanf(file, "%s %s %dl", username, replyfile, &size) != EOF) { X /* check to see if this person is already in the list */ X if ((person = in_list(username)) != -1) { X reply_table[person].in_list = 1; X reply_table[person].mailsize = size; /* sync */ X } X else { /* if not, add them */ X if (active == MAX_PEOPLE) { X unlock(); X exit(log("Couldn't add %s - already at max people!", X username)); X } X log("adding %s to the active list", username); X strcpy(reply_table[active].username, username); X sprintf(reply_table[active].mailfile, "/usr/mail/%s", username); X strcpy(reply_table[active].replyfile, replyfile); X reply_table[active].mailsize = size; X reply_table[active].in_list = 1; /* obviously! */ X active++; X } X } X X /** now check to see if anyone has been removed... **/ X X for (person = 0; person < active; person++) X if (reply_table[person].in_list == 0) { X log("removing %s from the active list", X reply_table[person].username); X strcpy(reply_table[person].username, X reply_table[active-1].username); X strcpy(reply_table[person].mailfile, X reply_table[active-1].mailfile); X strcpy(reply_table[person].replyfile, X reply_table[active-1].replyfile); X reply_table[person].mailsize = reply_table[active-1].mailsize; X active--; X } X} X Xupdate_autoreply_file() X{ X /** update the entries in the autoreply file... **/ X X FILE *file; X register int person; X X if ((file = fopen(autoreply_file,"w")) == NULL) { X log("Couldn't update autoreply file!"); X return; X } X X for (person = 0; person < active; person++) X fprintf(file, "%s %s %ld\n", X reply_table[person].username, X reply_table[person].replyfile, X reply_table[person].mailsize); X X fclose(file); X X printf("updated autoreply file\n"); X autoreply_size = bytes(autoreply_file); X} X Xint Xin_list(name) Xchar *name; X{ X /** search the current active reply list for the specified username. X return the index if found, or '-1' if not. **/ X X register int index; X X for (index = 0; index < active; index++) X if (strcmp(name, reply_table[index].username) == 0) X return(index); X X return(-1); X} X Xread_newmail(person) Xint person; X{ X /** Read the new mail for the specified person. **/ X X X FILE *mailfile; X char from_whom[LONG_SLEN], subject[SLEN]; X int sendit; X X log("New mail for %s", reply_table[person].username); X X if ((mailfile = fopen(reply_table[person].mailfile,"r")) == NULL) X return(log("can't open mailfile for user %s", X reply_table[person].username)); X X if (fseek(mailfile, reply_table[person].mailsize, BEGINNING) == -1) X return(log("couldn't seek to %ld in mail file!", X reply_table[person].mailsize)); X X while (get_return(mailfile, person, from_whom, subject, &sendit) != -1) X if (sendit) X reply_to_mail(person, from_whom, subject); X X return; X} X Xint Xget_return(file, person, from, subject, sendit) XFILE *file; Xint person, *sendit; Xchar *from, *subject; X{ X /** Reads the new message and return the from and subject lines. X sendit is set to true iff it isn't a machine generated msg X **/ X X char name1[SLEN], name2[SLEN], lastname[SLEN]; X char buffer[LONG_SLEN], hold_return[NLEN]; X int done = 0, in_header = 0; X X from[0] = '\0'; X *sendit = 1; X X while (! done) { X X if (fgets(buffer, LONG_SLEN, file) == NULL) X return(-1); X X if (first_word(buffer, "From ")) { X in_header++; X sscanf(buffer, "%*s %s", hold_return); X } X else if (in_header) { X if (first_word(buffer, ">From")) { X sscanf(buffer,"%*s %s %*s %*s %*s %*s %*s %*s %*s %s", name1, name2); X add_site(from, name2, lastname); X } X else if (first_word(buffer,"Subject:")) { X remove_return(buffer); X strcpy(subject, (char *) (buffer + 8)); X } X else if (first_word(buffer,"X-Mailer: fastmail")) X *sendit = 0; X else if (strlen(buffer) == 1) X done = 1; X } X } X X if (from[0] == '\0') X strcpy(from, hold_return); /* default address! */ X else X add_site(from, name1, lastname); /* get the user name too! */ X X return(0); X} X Xadd_site(buffer, site, lastsite) Xchar *buffer, *site, *lastsite; X{ X /** add site to buffer, unless site is 'uucp', or the same as X lastsite. If not, set lastsite to site. X **/ X X char local_buffer[LONG_SLEN], *strip_parens(); X X if (strcmp(site, "uucp") != 0) X if (strcmp(site, lastsite) != 0) { X if (buffer[0] == '\0') X strcpy(buffer, strip_parens(site)); /* first in list! */ X else { X sprintf(local_buffer,"%s!%s", buffer, strip_parens(site)); X strcpy(buffer, local_buffer); X } X strcpy(lastsite, strip_parens(site)); /* don't want THIS twice! */ X } X} X Xremove_first_word(string) Xchar *string; X{ /** removes first word of string, ie up to first non-white space X following a white space! **/ X X register int loc; X X for (loc = 0; string[loc] != ' ' && string[loc] != '\0'; loc++) X ; X X while (string[loc] == ' ' || string[loc] == '\t') X loc++; X X move_left(string, loc); X} X Xmove_left(string, chars) Xchar string[]; Xint chars; X{ X /** moves string chars characters to the left DESTRUCTIVELY **/ X X register int i; X X chars--; /* index starting at zero! */ X X for (i=chars; string[i] != '\0' && string[i] != '\n'; i++) X string[i-chars] = string[i]; X X string[i-chars] = '\0'; X} X Xreply_to_mail(person, from, subject) Xint person; Xchar *from, *subject; X{ X /** Respond to the message from the specified person with the X specified subject... **/ X X char buffer[SLEN]; X X if (strlen(subject) == 0) X strcpy(subject, "Auto-reply Mail"); X else if (! first_word(subject,"Auto-reply")) { X sprintf(buffer, "Auto-reply to:%s", subject); X strcpy(subject, buffer); X } X X log("auto-replying to '%s'", from); X X mail(from, subject, reply_table[person].replyfile, person); X} X Xreverse(string) Xchar *string; X{ X /** reverse string... pretty trivial routine, actually! **/ X X char buffer[SLEN]; X register int i, j = 0; X X for (i = strlen(string)-1; i >= 0; i--) X buffer[j++] = string[i]; X X buffer[j] = '\0'; X X strcpy(string, buffer); X} X Xlong Xbytes(name) Xchar *name; X{ X /** return the number of bytes in the specified file. This X is to check to see if new mail has arrived.... **/ X X int ok = 1; X extern int errno; /* system error number! */ X struct stat buffer; X X if (stat(name, &buffer) != 0) X if (errno != 2) { X unlock(); X exit(fprintf(stderr,"Error %d attempting fstat on %s", errno, name)); X } X else X ok = 0; X X return(ok ? buffer.st_size : 0); X} X Xmail(to, subject, filename, person) Xchar *to, *subject, *filename; Xint person; X{ X /** Mail 'file' to the user from person... **/ X X char buffer[VERY_LONG_STRING]; X X sprintf(buffer, "%s -f '%s [autoreply]' -s '%s' %s %s", X fastmail, reply_table[person].username, X subject, filename, to); X X system(buffer); X} X Xlog(message, arg) Xchar *message; Xchar *arg; X{ X /** Put log entry into log file. Use the format: X date-time: <message> X **/ X X struct tm *localtime(), *thetime; X long time(), clock; X char buffer[SLEN]; X X /** first off, get the time and date **/ X X clock = time((long *) 0); /* seconds since ??? */ X thetime = localtime(&clock); /* and NOW the time... */ X X /** then put the message out! **/ X X sprintf(buffer, message, arg); X X fprintf(logfd,"%d/%d-%d:%02d: %s\n", X thetime->tm_mon+1, thetime->tm_mday, X thetime->tm_hour, thetime->tm_min, X buffer); X} X XFILE *open_logfile() X{ X /** open the logfile. returns a valid file descriptor **/ X X FILE *fd; X X if ((fd = fopen(logfile, "a")) == 0) X if ((fd = fopen(logfile2, "a")) == 0) { X unlock(); X exit(1); /* give up! */ X } X X return( (FILE *) fd); X} X Xclose_logfile() X{ X /** Close the logfile until needed again. **/ X X fclose(logfd); X} X Xchar *strip_parens(string) Xchar *string; X{ X /** Return string with all parenthesized information removed. X This is a non-destructive algorithm... **/ X X static char buffer[LONG_SLEN]; X register int i, depth = 0, buffer_index = 0; X X for (i=0; i < strlen(string); i++) { X if (string[i] == '(') X depth++; X else if (string[i] == ')') X depth--; X else if (depth == 0) X buffer[buffer_index++] = string[i]; X } X X buffer[buffer_index] = '\0'; X X return( (char *) buffer); X} X X/*** LOCK and UNLOCK - ensure only one copy of this daemon running at any X given time by using a file existance semaphore (wonderful stuff!) ***/ X Xlock() X{ X /** Try to create the lock file. If it's there, or we can't X create it for some stupid reason, return zero, otherwise, X a non-zero return code indicates success in locking this X process in. **/ X X if (access(arep_lock_file, EXISTS) == 0) X return(0); /* file already exists!! */ X X if (creat(arep_lock_file, MODE) == -1) X return(0); /* can't create file!! */ X X return(1); X} X Xunlock() X{ X /** remove lock file if it's there! **/ X X (void) unlink(arep_lock_file); X} END_OF_utils/arepdaemon.c if test 13412 -ne `wc -c <utils/arepdaemon.c`; then echo shar: \"utils/arepdaemon.c\" unpacked with wrong size!? fi # end of overwriting check fi echo shar: Extracting \"utils/newalias.c\" \(13123 characters\) if test -f utils/newalias.c ; then echo shar: Will not over-write existing file \"utils/newalias.c\" else sed "s/^X//" >utils/newalias.c <<'END_OF_utils/newalias.c' X/** newalias.c **/ X X/** (C) Copyright 1986 Dave Taylor **/ X X/** Install a new set of aliases for the 'Elm' mailer. X X If invoked with a specific filename, it assumes that X it is working with an individual users alias tables, and X generates the .alias.hash and .alias.data files in their X home directory. X If, however, it is invoked with no arguments, then X it assumes that the user is updating the system alias X file and uses the defaults for everything. X X The format for the input file is; X alias1, alias2, ... : username : address Xor alias1, alias2, ... : groupname: member, member, member, ... X member, member, member, ... X X "-q" flag added: 6/17/86 X**/ X X#ifdef BSD X# include <sys/file.h> X#else X# include <fcntl.h> X#endif X X#include <stdio.h> X#include "defs.h" /* ELM system definitions */ X Xstatic char ident[] = { WHAT_STRING }; X X#ifndef TAB X# define TAB '\t' /* TAB character! */ X#endif X X#define alias_hash ".alias_hash" X#define alias_data ".alias_data" X#define alias_text ".alias_text" X X#define group(string) (strpbrk(string,", ") != NULL) X Xstruct alias_rec Xshash_table[MAX_SALIASES]; /* the actual hash table */ X Xstruct alias_rec Xuhash_table[MAX_UALIASES]; /* the actual hash table */ X Xint hash_table_loaded=0; /* is system table actually loaded? */ X Xint buff_loaded; /* for file input overlap... */ Xint error= 0; /* if errors, don't save! */ Xint system=0; /* system file updating? */ Xint count=0; /* how many aliases so far? */ Xlong offset = 0L; /* data file line offset! */ X Xmain(argc, argv) Xint argc; Xchar *argv[]; X{ X FILE *in, *data; X char inputname[SLEN], hashname[SLEN], dataname[SLEN]; X char home[SLEN], buffer[LONG_STRING]; X int hash, count = 0, owner, quiet = 0; X X if (argc != 1) X if (strcmp(argv[1], "-q") == 0) X quiet++; X else X exit(printf("Usage: %s\n", argv[0])); X X owner = getuid(); X X if (owner == 0 && ! quiet) { /* being run by root! */ X printf("Would you like to update the system aliases? (y/n)"); X gets(buffer, 2); X if (buffer[0] == 'y' || buffer[0] == 'Y') { X printf("Updating the system alias file...\n"); X X sprintf(inputname, "%s/%s", mailhome, alias_text); X sprintf(hashname, "%s/%s", mailhome, alias_hash); X sprintf(dataname, "%s/%s", mailhome, alias_data); X system++; X init_table(shash_table, MAX_SALIASES); X } X else X printf("Updating your personal alias file...\n"); X } X X if (! system) { X if (strcpy(home, getenv("HOME")) == NULL) X exit(printf("Confused: No HOME variable in environment!\n")); X X sprintf(inputname, "%s/%s", home, alias_text); X sprintf(hashname, "%s/%s", home, alias_hash); X sprintf(dataname, "%s/%s", home, alias_data); X X init_table(uhash_table, MAX_UALIASES); X X read_in_system(shash_table, sizeof shash_table); X } X X if ((in = fopen(inputname,"r")) == NULL) X exit(printf("Couldn't open %s for input!\n", inputname)); X X if ((hash = open(hashname, O_WRONLY | O_CREAT, 0644)) == -1) X exit(printf("Couldn't open %s for output!\n", hashname)); X X if ((data = fopen(dataname,"w")) == NULL) X exit(printf("Couldn't open %s for output!\n", dataname)); X X buff_loaded = 0; /* file buffer empty right now! */ X X while (get_alias(in, buffer) != -1) { X if (system) X put_alias(data, buffer, shash_table, MAX_SALIASES); X else X put_alias(data, buffer, uhash_table, MAX_UALIASES); X count++; X } X X if (error) { X printf("\n** Not saving tables! Please fix and re-run %s!\n", X argv[0]); X exit(1); X } X else { X if (system) X write(hash, shash_table, sizeof shash_table); X else X write(hash, uhash_table, sizeof uhash_table); X X close(hash); X fclose(data); X close(in); X X printf("Processed %d aliases\n", count); X exit(0); X } X} X Xint Xget_alias(file, buffer) XFILE *file; Xchar *buffer; X{ X /* load buffer with the next complete alias from the file. X (this can include reading in multiple lines and appending X them all together!) Returns EOF after last entry in file. X X Lines that start with '#' are assumed to be comments and are X ignored. White space as the first field of a line is taken X to indicate that this line is a continuation of the previous. */ X X static char mybuffer[SLEN]; X int done = 0, first_read = 1; X X /** get the first line of the entry... **/ X X buffer[0] = '\0'; /* zero out line */ X X do { X if (get_line(file, mybuffer, first_read) == -1) X return(-1); X first_read = 0; X if (mybuffer[0] != '#') X strcpy(buffer, mybuffer); X } while (strlen(buffer) == 0); X X /** now read in the rest (if there is any!) **/ X X do { X if (get_line(file, mybuffer, first_read) == -1) { X buff_loaded = 0; /* force a read next pass! */ X return(0); /* okay. let's just hand 'buffer' back! */ X } X done = (mybuffer[0] != ' ' && mybuffer[0] != TAB); X if (mybuffer[0] != '#' && ! done) X strcat(buffer, mybuffer); X done = (done && mybuffer[0] != '#'); X } while (! done); X X return(0); /* no sweat! */ X} X Xput_alias(data, buffer, table, size) XFILE *data; Xchar *buffer; Xstruct alias_rec table[]; Xint size; X{ X /** break buffer down into three pieces: aliases, comment, and address. X Make the appropriate entries in the table (size) X **/ X X char aliases[LONG_STRING], address[LONG_STRING]; X char comment[LONG_STRING]; X int first, last, i = 0, j = 0; X X remove_all(' ', TAB, buffer); X X for (i=0; buffer[i] != ':' && i < LONG_STRING; i++) X aliases[i] = buffer[i]; X aliases[i] = '\0'; X X for (i=strlen(buffer)-1; buffer[i] != ':' && i > 0; i--) X address[j++] = buffer[i]; X address[j] = '\0'; X X comment[0] = '\0'; /* default to nothing at all... */ X X if ((first=strlen(aliases)+1) < (last=(strlen(buffer) - j))) { X extract_comment(comment, buffer, first, last); X } X X reverse(address); X X add_to_table(data, aliases, comment, address, table, size); X} X Xint Xget_line(file, buffer, first_line) XFILE *file; Xchar *buffer; Xint first_line; X{ X /** read line from file. If first_line and buff_loaded, X then just return! **/ X int stat; X X if (first_line && buff_loaded) { X buff_loaded = 1; X return; X } X X buff_loaded = 1; /* we're going to get SOMETHING in the buffer */ X X stat = fgets(buffer, SLEN, file) == NULL ? -1 : 0; X X if (stat != -1) X no_ret(buffer); X X return(stat); X} X Xreverse(string) Xchar *string; X{ X /** reverse the order of the characters in string... X uses a bubble-sort type of algorithm! **/ X X register int f, l; X char c; X X f = 0; X l = strlen(string) - 1; X X while (f < l) { X c = string[f]; X string[f] = string[l]; X string[l] = c; X f++; X l--; X } X} X Xadd_to_table(data, aliases, comment, address, table, size) XFILE *data; Xchar *aliases, *comment, *address; Xstruct alias_rec table[]; Xint size; X{ X /** add address + comment to datafile, incrementing offset count X (bytes), then for each alias in the aliases string, add to the X hash table, with the associated pointer value! **/ X X static char buf[SLEN], *word; X long additive = 1L; X X word = buf; /* use the allocated space! */ X X if (group(address)) { X check_group(address, aliases); X if (error) return; /* don't do work if we aren't to save it! */ X fprintf(data, "!%s\n", address); X additive = 2L; X } X else { X if (error) return; /* don't do work if we aren't to save it! */ X if (strlen(comment) > 0) { X fprintf(data, "%s (%s)\n", address, comment); X additive = (long) (strlen(comment) + 4); X } X else X fprintf(data, "%s\n", address, comment); X } X X while ((word = (char *) strtok(aliases,", ")) != NULL) { X add_to_hash_table(word, offset, table, size); X aliases = NULL; /* let's get ALL entries via 'strtok' */ X count++; X } X X if ( system ? count > MAX_SALIASES-35 : count > MAX_UALIASES-21) { X printf("** Too many aliases in file! **\n"); X error++; X } X X offset = (offset + (long) strlen(address) + additive); X} X Xremove_all(c1, c2, string) Xchar c1, c2, *string; X{ X /* Remove all occurances of character 'c1' or 'c2' from the string. X Hacked (literally) to NOT remove ANY characters from within the X colon fields. This will only be used if the line contains TWO X colons (and comments with colons in them are the kiss of death!) X */ X X char buffer[LONG_STRING]; X register int i = 0, j = 0, first_colon = -1, last_colon = -1; X X for (i = 0; string[i] != '\0' && i < LONG_STRING; i++) { X if (string[i] != c1 && string[i] != c2) X buffer[j++] = string[i]; X X if (first_colon == -1 && string[i] == ':') { X first_colon = i; X for (last_colon=strlen(string);string[last_colon] != ':'; X last_colon--) ; X } X else if (i > first_colon && i < last_colon) X if (string[i] == c1 || string[i] == c2) X buffer[j++] = string[i]; X } X X buffer[j] = '\0'; X strcpy(string, buffer); X} X Xadd_to_hash_table(word, offset, table, size) Xchar *word; Xlong offset; Xstruct alias_rec table[]; Xint size; X{ X /** add word and offset to current hash table. **/ X register int loc; X X if (strlen(word) > 20) X exit(printf("Bad alias name: %s. Too long.\n", word)); X X loc = hash_it(word, size); X X while (table[loc].name[0] != '\0' && strcmp(table[loc].name, word) != 0) X loc = loc + 1 % size; X X if (table[loc].name[0] == '\0') { X strcpy(table[loc].name, word); X table[loc].byte = offset; X } X else X printf("** Duplicate alias '%s' in file. Multiples ignored.\n", X word); X} X Xint Xhash_it(string, table_size) Xchar *string; X{ X /** compute the hash function of the string, returning X it (mod table_size) **/ X X register int i, sum = 0; X X for (i=0; string[i] != '\0'; i++) X sum += (int) string[i]; X X return(sum % table_size); X} X Xinit_table(table, size) Xstruct alias_rec table[]; Xint size; X{ X /** initialize hash table! **/ X X register int i; X X for (i=0; i < size; i++) X table[i].name[0] = '\0'; X} X Xread_in_system(table, size) Xstruct alias_rec table[]; Xint size; X{ X /** read in the system hash table...to check for group aliases X from the user alias file (to ensure that there are no names X in the user group files that are not purely contained within X either alias table) **/ X X int fd; X char fname[SLEN]; X X sprintf(fname, "%s/%s", mailhome, alias_hash); X X if ((fd = open(fname, O_RDONLY)) == -1) X return; /* no sweat: flag 'hash_table_loaded' not set! */ X X (void) read(fd, table, size); X close(fd); X hash_table_loaded++; X} X Xcheck_group(names, groupname) Xchar *names, *groupname; X{ X /** one by one make sure each name in the group is defined X in either the system alias file or the user alias file. X This search is linearly dependent, so all group aliases X in the source file should appear LAST, after all the user X aliases! **/ X X char *word, *bufptr, buffer[LONG_STRING]; X X strcpy(buffer, names); X bufptr = (char *) buffer; X X while ((word = (char *) strtok(bufptr,", ")) != NULL) { X if (! can_find(word)) X if (! valid_name(word)) { X error++; X printf("** Alias %s in group %s is bad!\n", word, groupname); X } X bufptr = NULL; X } X} X Xint Xcan_find(name) Xchar *name; X{ X /** find name in either hash table...use 'system' variable to X determine if we should look in both or just system.... **/ X X register int loc; X X if (strlen(name) > 20) { X error++; X printf("** Bad alias name: %s. Too long.\n", name); X return(1); /* fake out: don't want 2 error messages! */ X } X X /** system alias table... **/ X if (hash_table_loaded || system) { X loc = hash_it(name, MAX_SALIASES); X X while (strcmp(name, shash_table[loc].name) != 0 && X shash_table[loc].name[0] != '\0') X loc = (loc + 1) % MAX_SALIASES; X X if (strcmp(name, shash_table[loc].name) == 0) X return(1); /* found it! */ X } X X if (! system) { /* okay! Let's check the user alias file! */ X loc = hash_it(name, MAX_UALIASES); X X while (strcmp(name, uhash_table[loc].name) != 0 && X uhash_table[loc].name[0] != '\0') X loc = (loc + 1) % MAX_UALIASES; X X if (strcmp(name, uhash_table[loc].name) == 0) X return(1); /* found it! */ X } X X return(0); X} X Xextract_comment(comment, buffer, first, last) Xchar *comment, *buffer; Xint first, last; X{ X /** Buffer contains a comment, located between the first and last X values. Copy that into 'comment', but remove leading and X trailing white space. Note also that it doesn't copy past X a comma, so `unpublishable' comments can be of the form; X dave: Dave Taylor, HP Labs : taylor@hplabs X and the output will be "taylor@hplabs (Dave Taylor)". X **/ X X register int loc = 0; X X /** first off, skip the LEADING white space... **/ X X while (buffer[first] == ' ') first++; X X /** now let's backup the 'last' value until we hit a non-space **/ X X last -= 2; /* starts at ch AFTER colon.. */ X while (buffer[last] == ' ') last--; X X /** now a final check to make sure we're still talking about a X reasonable string (rather than a "joe :: joe@dec" type string) **/ X X if (first < last) { X /* one more check - let's find the comma, if present... */ X for (loc=first; loc < last; loc++) X if (buffer[loc] == ',') { X last = loc-1; X break; X } X loc = 0; X while (first <= last) X comment[loc++] = buffer[first++]; X comment[loc] = '\0'; X } X} END_OF_utils/newalias.c if test 13123 -ne `wc -c <utils/newalias.c`; then echo shar: \"utils/newalias.c\" unpacked with wrong size!? fi # end of overwriting check fi echo shar: End of archive 13 \(of 19\). cp /dev/null ark13isdone DONE=true for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ; do if test ! -f ark${I}isdone ; then echo shar: You still need to run archive ${I}. DONE=false fi done if test "$DONE" = "true" ; then echo You have unpacked all 19 archives. echo "See the Instructions file" rm -f ark[1-9]isdone ark[1-9][0-9]isdone fi ## End of shell archive. exit 0